diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 4a15daa5c..f218d9a01 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -7,7 +7,7 @@ - [ ] Only relevant files were touched - [ ] 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.4.9 - - [ ] The code change is tested and works with Tasmota core ESP32 V.2.0.1.1 + - [ ] The code change is tested and works with Tasmota core ESP32 V.2.0.2.1 - [ ] 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**_ diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml index fe3f995d1..8cb8a140e 100644 --- a/.github/workflows/Tasmota_build_devel.yml +++ b/.github/workflows/Tasmota_build_devel.yml @@ -1,4 +1,4 @@ -name: Build_firmware_development_cache +name: Build_development on: workflow_dispatch: # Manually start a workflow @@ -8,1319 +8,80 @@ on: - '.github/**' # Ignore changes towards the .github directory - '**.md' # Do no build if *.md files changes +# Ensures that only one deploy task per branch/environment will run at a time. +concurrency: + group: environment-${{ github.ref }} + cancel-in-progress: true + jobs: - - tasmota: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-minimal: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-minimal - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-lite: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-lite - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-knx: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-knx - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-sensors: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-sensors - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-display: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-display - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-ir: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-ir - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-zbbridge: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-zbbridge - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-zigbee: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-zigbee - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-AF: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-AF - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-BG: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-BG - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-BR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-BR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-CN: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-CN - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-CZ: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-CZ - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-DE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-DE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-ES: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-ES - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-FR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-FR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-FY: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-FY - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-GR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-GR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-HE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-HE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-HU: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-HU - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-IT: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-IT - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-KO: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-KO - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-NL: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-NL - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-PL: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-PL - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-PT: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-PT - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-RO: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-RO - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-RU: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-RU - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-SE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-SE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-SK: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-SK - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-TR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-TR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-TW: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-TW - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-UK: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-UK - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-VN: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-VN - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32 - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32solo1: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32solo1 - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-webcam: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-webcam - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-odroidgo: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-odroidgo - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-core2: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-core2 - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-bluetooth: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-bluetooth - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-display: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-display - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-lvgl: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-lvgl - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-ir: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-ir - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - tasmota32c3: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32c3 - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - tasmota32-AF: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-AF - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-BG: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-BG - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-BR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-BR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-CN: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-CN - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-CZ: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-CZ - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-DE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-DE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-ES: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-ES - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-FR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-FR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-FY: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-FY - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-GR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-GR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-HE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-HE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-HU: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-HU - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-IT: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-IT - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-KO: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-KO - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-NL: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-NL - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-PL: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-PL - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-PT: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-PT - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-RO: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-RO - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-RU: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-RU - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-SE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-SE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-SK: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-SK - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-TR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-TR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-TW: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-TW - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-UK: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-UK - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-VN: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-VN - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - + base-images: + runs-on: ubuntu-latest + if: github.repository == 'arendst/Tasmota' + continue-on-error: true + strategy: + matrix: + variant: + - tasmota + - tasmota-minimal + - tasmota-display + - tasmota-ir + - tasmota-knx + - tasmota-lite + - tasmota-sensors + - tasmota-zbbridge + - tasmota-zigbee + - tasmota32 + - tasmota32-webcam + - tasmota32-bluetooth + - tasmota32-core2 + - tasmota32-display + - tasmota32-ir + - tasmota32-lvgl + - tasmota32-odroidgo + - tasmota32c3 + - tasmota32solo1 + steps: + - uses: actions/checkout@v2 + with: + ref: development + - name: Set up Python + uses: actions/setup-python@v1 + - name: Install dependencies + run: | + pip install -U platformio + - name: Run PlatformIO + run: platformio run -e ${{ matrix.variant }} + - uses: actions/upload-artifact@v2 + with: + name: firmware + path: ./build_output + + language-images: + runs-on: ubuntu-latest + if: github.repository == 'arendst/Tasmota' + continue-on-error: true + strategy: + matrix: + variant: [ tasmota, tasmota32 ] + language: [ AF, BG, BR, CN, CZ, DE, ES, FR, FY, GR, HE, HU, IT, KO, NL, PL, PT, RO, RU, SE, SK, TR, TW, UK, VN ] + steps: + - uses: actions/checkout@v2 + with: + ref: development + - name: Set up Python + uses: actions/setup-python@v1 + - name: Install dependencies + run: | + pip install -U platformio + - name: Run PlatformIO + run: platformio run -e ${{ matrix.variant }}-${{ matrix.language }} + - uses: actions/upload-artifact@v2 + with: + name: firmware + path: ./build_output Upload: - needs: [tasmota-VN, tasmota32-VN, tasmota32-TW, tasmota32-TR] + needs: [base-images, language-images] runs-on: ubuntu-latest continue-on-error: true steps: @@ -1339,7 +100,7 @@ jobs: [ ! -f ./mv_firmware/map/* ] || mv ./mv_firmware/map/* ./firmware/map/ [ ! -f ./mv_firmware/firmware/tasmota.* ] || mv ./mv_firmware/firmware/tasmota.* ./firmware/tasmota/ [ ! -f ./mv_firmware/firmware/tasmota-sensors.* ] || mv ./mv_firmware/firmware/tasmota-sensors.* ./firmware/tasmota/ - [ ! -f ./mv_firmware/firmware/tasmota-minimal.* ] || mv ./mv_firmware/firmware/tasmota-minimal.* ./firmware/tasmota/ + [ ! -f ./mv_firmware/firmware/tasmota-minimal.bin.gz ] || mv ./mv_firmware/firmware/tasmota-minimal.bin.gz ./firmware/tasmota/ [ ! -f ./mv_firmware/firmware/tasmota-lite.* ] || mv ./mv_firmware/firmware/tasmota-lite.* ./firmware/tasmota/ [ ! -f ./mv_firmware/firmware/tasmota-ir*.* ] || mv ./mv_firmware/firmware/tasmota-ir*.* ./firmware/tasmota/ [ ! -f ./mv_firmware/firmware/tasmota-display.* ] || mv ./mv_firmware/firmware/tasmota-display.* ./firmware/tasmota/ diff --git a/.github/workflows/Tasmota_build_master.yml b/.github/workflows/Tasmota_build_master.yml index 4639fde5e..a5e1c3881 100644 --- a/.github/workflows/Tasmota_build_master.yml +++ b/.github/workflows/Tasmota_build_master.yml @@ -5,1320 +5,82 @@ on: branches: master paths-ignore: - '.github/**' # Ignore changes towards the .github directory + - '**.md' # Do no build if *.md files changes + +# Ensures that only one deploy task per branch/environment will run at a time. +concurrency: + group: environment-${{ github.ref }} + cancel-in-progress: true jobs: - - tasmota: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-minimal: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-minimal - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-lite: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-lite - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-knx: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-knx - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-sensors: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-sensors - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-display: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-display - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-ir: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-ir - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-zbbridge: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-zbbridge - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-zigbee: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-zigbee - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-AF: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-AF - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-BG: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-BG - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-BR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-BR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-CN: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-CN - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-CZ: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-CZ - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-DE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-DE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-ES: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-ES - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-FR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-FR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-FY: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-FY - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-GR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-GR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-HE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-HE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-HU: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-HU - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-IT: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-IT - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-KO: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-KO - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-NL: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-NL - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-PL: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-PL - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-PT: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-PT - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-RO: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-RO - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-RU: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-RU - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-SE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-SE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-SK: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-SK - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-TR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-TR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-TW: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-TW - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-UK: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-UK - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-VN: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-VN - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32 - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32solo1: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32solo1 - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-webcam: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-webcam - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-odroidgo: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-odroidgo - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-core2: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-core2 - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-bluetooth: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-bluetooth - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-display: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-display - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-lvgl: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-lvgl - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-ir: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-ir - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - tasmota32c3: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32c3 - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - tasmota32-AF: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-AF - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-BG: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-BG - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-BR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-BR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-CN: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-CN - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-CZ: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-CZ - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-DE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-DE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-ES: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-ES - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-FR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-FR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-FY: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-FY - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-GR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-GR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-HE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-HE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-HU: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-HU - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-IT: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-IT - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-KO: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-KO - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-NL: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-NL - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-PL: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-PL - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-PT: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-PT - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-RO: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-RO - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-RU: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-RU - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-SE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-SE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-SK: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-SK - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-TR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-TR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-TW: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-TW - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-UK: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-UK - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-VN: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-VN - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - + base-images: + runs-on: ubuntu-latest + if: github.repository == 'arendst/Tasmota' + continue-on-error: true + strategy: + matrix: + variant: + - tasmota + - tasmota-minimal + - tasmota-display + - tasmota-ir + - tasmota-knx + - tasmota-lite + - tasmota-sensors + - tasmota-zbbridge + - tasmota-zigbee + - tasmota32 + - tasmota32-webcam + - tasmota32-bluetooth + - tasmota32-core2 + - tasmota32-display + - tasmota32-ir + - tasmota32-lvgl + - tasmota32-odroidgo + - tasmota32c3 + - tasmota32solo1 + steps: + - uses: actions/checkout@v2 + with: + ref: master + - name: Set up Python + uses: actions/setup-python@v1 + - name: Install dependencies + run: | + pip install -U platformio + - name: Run PlatformIO + run: platformio run -e ${{ matrix.variant }} + - uses: actions/upload-artifact@v2 + with: + name: firmware + path: ./build_output + + language-images: + runs-on: ubuntu-latest + if: github.repository == 'arendst/Tasmota' + continue-on-error: true + strategy: + matrix: + variant: [ tasmota, tasmota32 ] + language: [ AF, BG, BR, CN, CZ, DE, ES, FR, FY, GR, HE, HU, IT, KO, NL, PL, PT, RO, RU, SE, SK, TR, TW, UK, VN ] + steps: + - uses: actions/checkout@v2 + with: + ref: master + - name: Set up Python + uses: actions/setup-python@v1 + - name: Install dependencies + run: | + pip install -U platformio + - name: Run PlatformIO + run: platformio run -e ${{ matrix.variant }}-${{ matrix.language }} + - uses: actions/upload-artifact@v2 + with: + name: firmware + path: ./build_output Upload: - needs: [tasmota-VN, tasmota32-VN, tasmota32-TW, tasmota32-TR] + needs: [base-images, language-images] runs-on: ubuntu-latest continue-on-error: true steps: @@ -1346,7 +108,7 @@ jobs: [ ! -f ./mv_firmware/map/* ] || mv ./mv_firmware/map/* ./release-firmware/map/ [ ! -f ./mv_firmware/firmware/tasmota.* ] || mv ./mv_firmware/firmware/tasmota.* ./release-firmware/tasmota/ [ ! -f ./mv_firmware/firmware/tasmota-sensors.* ] || mv ./mv_firmware/firmware/tasmota-sensors.* ./release-firmware/tasmota/ - [ ! -f ./mv_firmware/firmware/tasmota-minimal.* ] || mv ./mv_firmware/firmware/tasmota-minimal.* ./release-firmware/tasmota/ + [ ! -f ./mv_firmware/firmware/tasmota-minimal.bin.gz ] || mv ./mv_firmware/firmware/tasmota-minimal.bin.gz ./release-firmware/tasmota/ [ ! -f ./mv_firmware/firmware/tasmota-lite.* ] || mv ./mv_firmware/firmware/tasmota-lite.* ./release-firmware/tasmota/ [ ! -f ./mv_firmware/firmware/tasmota-ir*.* ] || mv ./mv_firmware/firmware/tasmota-ir*.* ./release-firmware/tasmota/ [ ! -f ./mv_firmware/firmware/tasmota-display.* ] || mv ./mv_firmware/firmware/tasmota-display.* ./release-firmware/tasmota/ diff --git a/.github/workflows/build_all_the_things.yml b/.github/workflows/build_all_the_things.yml index 2ffca53b7..cb41ae85e 100644 --- a/.github/workflows/build_all_the_things.yml +++ b/.github/workflows/build_all_the_things.yml @@ -18,6 +18,7 @@ on: jobs: base-images: runs-on: ubuntu-latest + if: github.repository == 'arendst/Tasmota' strategy: matrix: variant: @@ -59,6 +60,7 @@ jobs: language-images: runs-on: ubuntu-latest + if: github.repository == 'arendst/Tasmota' strategy: matrix: variant: [ tasmota ] diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile index 909bcf681..29d75d19d 100644 --- a/.gitpod.Dockerfile +++ b/.gitpod.Dockerfile @@ -2,4 +2,4 @@ FROM gitpod/workspace-full USER gitpod -RUN pip3 install -U platformio && brew install uncrustify +RUN pip3 install -U platformio diff --git a/BUILDS.md b/BUILDS.md index 975e34d24..77d7d4128 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -76,6 +76,7 @@ Note: `minimal` variant is not listed as it shouldn't be used outside of the [up | USE_MCP39F501 | x | x / - | x | x | - | - | | USE_SDM72 | - | - / x | - | x | - | - | | USE_SDM120 | - | - / x | - | x | - | - | +| USE_SDM230 | - | - / x | - | - | - | - | | USE_SDM630 | - | - / x | - | x | - | - | | USE_DDS2382 | - | - / x | - | x | - | - | | USE_DDSU666 | - | - / x | - | x | - | - | @@ -100,7 +101,7 @@ Note: `minimal` variant is not listed as it shouldn't be used outside of the [up | USE_SHT | - | - / x | - | x | - | - | | USE_HTU | - | - / x | - | x | - | - | | USE_BMP | - | - / x | - | x | - | - | -| USE_BME680 | - | - / x | - | x | - | - | +| USE_BME68X | - | - / x | - | x | - | - | | USE_BH1750 | - | - / x | - | x | - | - | | USE_VEML6070 | - | - / x | - | x | - | - | | USE_ADS1115 | - | - / x | - | x | - | - | diff --git a/CHANGELOG.md b/CHANGELOG.md index e5d9a8633..d245af292 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,105 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - Development -## [10.1.0.1] +## [2022.01.3] +### Added +- Command ``WebTime ,`` to show part of date and/or time in web gui based on "2017-03-07T11:08:02-07:00" +- ESP32 disable serial console when 3 (ESP32) or 2 (Other models) serial interfaces are requested (#14487) +- Support for BME688 with latest Bosch-Sensor-API library (#14513) +- Command ``SetOption44 1..100`` to set base tolerance percentage for matching incoming IR messages (default 25, max 100) (#14555) +- Command ``Json {}`` to enable input of any command as JSON tokens (#14568) +- Rule variable %color% (#14572) +- Command ``SspmDisplay 1`` to display Sonoff SPM energy data in GUI for relays powered on only +- Command ``SspmEnergyTotal`` to (p)reset Sonoff SPM total energy without today's energy +- Command ``SspmHistory`` to retrieve Sonoff SPM daily energy up to last six month (as defined by ARM firmware) +- Command ``SspmIAmHere`` to (faintly) blink Sonoff SPM-4Relay module error light of requested relay +- Command ``SspmLog [x]`` to retrieve Sonoff SPM relay power state change and cause logging +- Command ``SspmScan`` to rescan Sonoff SPM modbus +- Support for MQ analog sensor for air quality by Francesco Adriani (#14581) +- Command ``SetOption134 1`` to disable PWM auto-phasing for lights by default (new behavior) (#14590) + +### Changed +- BME68x-Sensor-API library from v3.5.9 to v4.4.7 +- ESP32 core library from v2.0.2 to v2.0.2.1 (#14553) + +### Fixed +- OneWire-Stickbreaker (DS18x20) library support for ESP32S2 (#14338) + +## [2022.01.2] 20220116 +### Added +- Tasmota favicon to webbrowser tab (#14322) +- Commands for ESP32 ethernet configuration ``EthIpAddress``, ``EthGateway``, ``EthSubnetmask``, ``EthDnsServer1`` and ``EthDnsServer2`` (#14385) +- Support for Eastron SDM230 modBus energy meter (#13443) + +### Changed +- IRremoteESP8266 library from v2.8.0 to v2.8.1 + +## [2022.01.1] 20220107 +### Added +- Experimental ADE7953 (Shelly EM) reset on restart (#14261) +- Command ``SspmMap 2,1,..`` to map Sonoff SPM scanned module to physical module (#14281) +- Solax X1 modbus RTS support and offline status (#14305) +- DDP schemes for light and WS2812 (#14017) +- ESP32 single binary firmware (#14239) +- ESP32 support for USE_PWM_DIMMER as GPIO ``Option E1`` +- Support for Linkind dimmer as GPIO ``Option A6`` (#14004) + +### Changed +- PubSubClient library from v2.8.12 to v2.8.13 +- TasmotaSerial library from v3.3.0 to v3.4.0 +- TasmotaModbus library from v1.2.0 to v3.4.0 +- From Semantic Versioning (SemVer) to Calendar Versioning (CalVer) +- ESP32 Set stack size with ``#define SET_ESP32_STACK_SIZE``, added ``StackLowMark`` metrics +- ESP32 Berry stores compiled bytecode into IRAM, freeing space in heap (#14307) + +### Fixed +- Intermittent exceptions and heap corruption due to PubSubClient library buffer overflow (#13700) +- Scripter memory corruption (#14268) +- Edit file for SD card (#14229) +- Solax X1 negative temperature support (#14278) +- Modbus serial config regression from v10.1.0.3 + +## [10.1.0.3] 20211231 +### Added +- Command ``SSerialConfig `` to change Serial Bridge configuration + +### Fixed +- DHT support negative temperatures on different hardware (#14173) +- ESP32 Provide proper OTA_URL for tasmota32solo1 (#14202) +- Hardware serial parity and stop bits support (#14212) + +### Changed +- LVGL update from 8.0.2 to 8.1.0 + +## [10.1.0.2] 20211225 +### Changed +- TasmotaSerial library from v3.3.0 to v3.4.0 - reverted (#14153) +- Force initial serial configuration even if no serial GPIO's are enabled (#14153) +- Revert change to fix extra flashwrite before QuickPowerDetection (#14153) +- Increase SerialBridge receive buffer from 130 to 256 characters - reverted (#14153) +- ESP8266Audio library from v1.9.2 to v1.9.5 (#14172) +- ESP8266SAM library from v1.0 to v1.0.1 (#14172) + +### Fixed +- Serial broken after #14153 - reverted + +## [10.1.0.1] 20211223 +### Added +- PWM Dimmer two button support (#13993) +- Device Group Send full status item (#14045) +- Support for MAX7219 Dot Matrix displays (#14091) +- ESP32 support for TuyaMcu +- ESP32 Berry features + +### Changed +- Mitsubishi HVAC temperature resolution (#13936) +- Remove restriction of topic must differ from mqttclient (#14019) + +### Fixed +- EZOO2 sensor message format (#14000) +- ESP32 Webcam exception during flashwrites +- ESP32 LedPwmMode exception (#14073) +- ESP32 Compile error when I2S_Audio is enabled (#14095) ## [Released] @@ -893,6 +991,7 @@ All notable changes to this project will be documented in this file. ### Changed - Triple-mode TLS via configuration in a single firmware (TLS AWS IoT, Letsencrypt and No-TLS) +- Berry C mapping moved to a separate ``berry_mapping`` library ### Fixed - ESP32 PWM range diff --git a/FIRMWARE.md b/FIRMWARE.md index 610cc6fba..7373dd131 100644 --- a/FIRMWARE.md +++ b/FIRMWARE.md @@ -18,7 +18,7 @@ See [CHANGELOG.md](https://github.com/arendst/Tasmota/blob/development/tasmota/C ## Development -[![Dev Version](https://img.shields.io/badge/development%20version-v10.1.x.x-blue.svg)](https://github.com/arendst/Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-v2022.01.x-blue.svg)](https://github.com/arendst/Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://ota.tasmota.com/tasmota/) [![Tasmota CI](https://github.com/arendst/Tasmota/workflows/Tasmota%20CI/badge.svg)](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+CI%22) [![Tasmota ESP32 CI](https://github.com/arendst/Tasmota/workflows/Tasmota%20ESP32%20CI/badge.svg)](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+ESP32+CI%22) diff --git a/README.md b/README.md index b41539308..abdc78f58 100644 --- a/README.md +++ b/README.md @@ -23,11 +23,10 @@ Easy initial installation of Tasmota can be performed using the [Tasmota WebInst ## Development -[![Dev Version](https://img.shields.io/badge/development%20version-v10.1.x.x-blue.svg)](https://github.com/arendst/Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-v2022.01.x-blue.svg)](https://github.com/arendst/Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://ota.tasmota.com/tasmota/) -[![Tasmota CI](https://github.com/arendst/Tasmota/workflows/Tasmota%20CI/badge.svg)](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+CI%22) -[![Tasmota ESP32 CI](https://github.com/arendst/Tasmota/workflows/Tasmota%20ESP32%20CI/badge.svg)](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+ESP32+CI%22) -[![Build_firmware](https://github.com/arendst/Tasmota/workflows/Build_firmware/badge.svg)](https://github.com/arendst/Tasmota/actions?query=workflow%3ABuild_firmware) +[![Tasmota CI](https://github.com/arendst/Tasmota/actions/workflows/build_all_the_things.yml/badge.svg)](https://github.com/arendst/Tasmota/actions/workflows/build_all_the_things.yml) +[![Build_development](https://github.com/arendst/Tasmota/actions/workflows/Tasmota_build_devel.yml/badge.svg)](https://github.com/arendst/Tasmota/actions/workflows/Tasmota_build_devel.yml) See [CHANGELOG.md](CHANGELOG.md) for detailed change information. diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e7b2dcdb3..2135624e8 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -100,13 +100,67 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo [Complete list](BUILDS.md) of available feature and sensors. -## Changelog v10.1.0.1 +## Changelog v2022.01.3 ### Added +- Command ``Json {}`` to enable input of any command as JSON tokens [#14568](https://github.com/arendst/Tasmota/issues/14568) +- Command ``SetOption44 1..100`` to set base tolerance percentage for matching incoming IR messages (default 25, max 100) [#14555](https://github.com/arendst/Tasmota/issues/14555) +- Command ``SetOption134 1`` to disable PWM auto-phasing for lights by default (new behavior) [#14590](https://github.com/arendst/Tasmota/issues/14590) +- Command ``SSerialConfig `` to change Serial Bridge configuration +- Command ``SspmDisplay 1`` to display Sonoff SPM energy data in GUI for relays powered on only +- Command ``SspmEnergyTotal`` to (p)reset Sonoff SPM total energy without today's energy +- Command ``SspmHistory`` to retrieve Sonoff SPM daily energy up to last six month (as defined by ARM firmware) +- Command ``SspmIAmHere`` to (faintly) blink Sonoff SPM-4Relay module error light of requested relay +- Command ``SspmLog [x]`` to retrieve Sonoff SPM relay power state change and cause logging +- Command ``SspmMap 2,1,..`` to map Sonoff SPM scanned module to physical module [#14281](https://github.com/arendst/Tasmota/issues/14281) +- Command ``SspmScan`` to rescan Sonoff SPM modbus +- Command ``WebTime ,`` to show part of date and/or time in web gui based on "2017-03-07T11:08:02-07:00" +- Commands for ESP32 ethernet configuration ``EthIpAddress``, ``EthGateway``, ``EthSubnetmask``, ``EthDnsServer1`` and ``EthDnsServer2`` [#14385](https://github.com/arendst/Tasmota/issues/14385) +- Support for Eastron SDM230 modBus energy meter [#13443](https://github.com/arendst/Tasmota/issues/13443) +- PWM Dimmer two button support [#13993](https://github.com/arendst/Tasmota/issues/13993) +- Support for Linkind dimmer as GPIO ``Option A6`` [#14004](https://github.com/arendst/Tasmota/issues/14004) +- DDP schemes for light and WS2812 [#14017](https://github.com/arendst/Tasmota/issues/14017) +- Device Group Send full status item [#14045](https://github.com/arendst/Tasmota/issues/14045) +- Support for MAX7219 Dot Matrix displays [#14091](https://github.com/arendst/Tasmota/issues/14091) +- Experimental ADE7953 (Shelly EM) reset on restart [#14261](https://github.com/arendst/Tasmota/issues/14261) +- Solax X1 negative temperature support [#14278](https://github.com/arendst/Tasmota/issues/14278) +- Solax X1 modbus RTS support and offline status [#14305](https://github.com/arendst/Tasmota/issues/14305) +- Tasmota favicon to webbrowser tab [#14322](https://github.com/arendst/Tasmota/issues/14322) +- Support for BME688 with latest Bosch-Sensor-API library [#14513](https://github.com/arendst/Tasmota/issues/14513) +- Rule variable %color% [#14572](https://github.com/arendst/Tasmota/issues/14572) +- Support for MQ analog sensor for air quality by Francesco Adriani [#14581](https://github.com/arendst/Tasmota/issues/14581) +- ESP32 single binary firmware [#14239](https://github.com/arendst/Tasmota/issues/14239) +- ESP32 disable serial console when 3 (ESP32) or 2 (Other models) serial interfaces are requested [#14487](https://github.com/arendst/Tasmota/issues/14487) +- ESP32 support for TuyaMcu +- ESP32 Berry features +- ESP32 support for USE_PWM_DIMMER as GPIO ``Option E1`` ### Breaking Changed ### Changed +- ESP32 core library from v2.0.2 to v2.0.2.1 +- PubSubClient library from v2.8.12 to v2.8.13 +- TasmotaSerial library from v3.3.0 to v3.4.0 +- TasmotaModbus library from v1.2.0 to v3.4.0 +- ESP8266Audio library from v1.9.2 to v1.9.5 +- ESP8266SAM library from v1.0 to v1.0.1 +- BME68x-Sensor-API library from v3.5.9 to v4.4.7 +- From Semantic Versioning (SemVer) to Calendar Versioning (CalVer) +- Mitsubishi HVAC temperature resolution [#13936](https://github.com/arendst/Tasmota/issues/13936) +- Remove restriction of topic must differ from mqttclient [#14019](https://github.com/arendst/Tasmota/issues/14019) +- ESP32 Set stack size with ``#define SET_ESP32_STACK_SIZE``, added ``StackLowMark`` metrics +- ESP32 Berry stores compiled bytecode into IRAM, freeing space in heap [#14307](https://github.com/arendst/Tasmota/issues/14307) ### Fixed +- Intermittent exceptions and heap corruption due to PubSubClient library buffer overflow [#13700](https://github.com/arendst/Tasmota/issues/13700) +- EZOO2 sensor message format [#14000](https://github.com/arendst/Tasmota/issues/14000) +- DHT support negative temperatures on different hardware [#14173](https://github.com/arendst/Tasmota/issues/14173) +- Hardware serial parity and stop bits support [#14212](https://github.com/arendst/Tasmota/issues/14212) +- Edit file for SD card [#14229](https://github.com/arendst/Tasmota/issues/14229) +- Scripter memory corruption [#14268](https://github.com/arendst/Tasmota/issues/14268) +- ESP32 Webcam exception during flashwrites +- ESP32 LedPwmMode exception [#14073](https://github.com/arendst/Tasmota/issues/14073) +- ESP32 Compile error when I2S_Audio is enabled [#14095](https://github.com/arendst/Tasmota/issues/14095) +- ESP32 Provide proper OTA_URL for tasmota32solo1 [#14202](https://github.com/arendst/Tasmota/issues/14202) +- ESP32 OneWire-Stickbreaker (DS18x20) library support for ESP32C3 and ESP32S2 [#14338](https://github.com/arendst/Tasmota/issues/14338) ### Removed diff --git a/boards/esp32-cam.json b/boards/esp32-cam.json index fc3fc4f1f..4691051e4 100644 --- a/boards/esp32-cam.json +++ b/boards/esp32-cam.json @@ -4,7 +4,7 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -DHAS_PSRAM_FIX -mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-strategy=memw", + "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -DHAS_PSRAM_FIX -mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-strategy=memw -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_4M", "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dout", @@ -25,7 +25,7 @@ "arduino", "espidf" ], - "name": "AI Thinker ESP32-CAM, 4M Flash 4MB PSRAM, Tasmota 1856k Code/OTA, 320k SPIFFS", + "name": "AI Thinker ESP32-CAM, 4M Flash 4MB PSRAM, Tasmota 1856k Code/OTA, 320k FS", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, diff --git a/boards/esp32-m5core2.json b/boards/esp32-m5core2.json index 0170649fa..137f023a9 100644 --- a/boards/esp32-m5core2.json +++ b/boards/esp32-m5core2.json @@ -4,7 +4,7 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_M5STACK_Core2 -DBOARD_HAS_PSRAM", + "extra_flags": "-DARDUINO_M5STACK_Core2 -DBOARD_HAS_PSRAM -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_16M", "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dout", @@ -25,7 +25,7 @@ "arduino", "espidf" ], - "name": "M5Stack Core2 16M Flash, 4MB PSRAM, Tasmota 2944k Code/OTA, 10M SPIFFS", + "name": "M5Stack Core2 16M Flash, 4MB PSRAM, Tasmota 2944k Code/OTA, 10M FS", "upload": { "flash_size": "16MB", "maximum_ram_size": 327680, diff --git a/boards/esp32-odroid.json b/boards/esp32-odroid.json index 10bb8bf4d..119af3d9e 100644 --- a/boards/esp32-odroid.json +++ b/boards/esp32-odroid.json @@ -4,7 +4,7 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_ODROID_ESP32 -DBOARD_HAS_PSRAM -DHAS_PSRAM_FIX -mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-strategy=memw", + "extra_flags": "-DARDUINO_ODROID_ESP32 -DBOARD_HAS_PSRAM -DHAS_PSRAM_FIX -mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-strategy=memw -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_16M", "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dout", @@ -25,7 +25,7 @@ "arduino", "espidf" ], - "name": "ESP32 ODROID-GO 16M Flash, 4MB PSRAM, Tasmota 2944k Code/OTA, 10M SPIFFS", + "name": "ESP32 ODROID-GO 16M Flash, 4MB PSRAM, Tasmota 2944k Code/OTA, 10M FS", "upload": { "flash_size": "16MB", "maximum_ram_size": 327680, diff --git a/boards/esp32_16M.json b/boards/esp32_16M.json index 69abb9a09..9667b46ff 100644 --- a/boards/esp32_16M.json +++ b/boards/esp32_16M.json @@ -4,7 +4,7 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -DESP32_16M", + "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_16M", "f_cpu": "80000000L", "f_flash": "40000000L", "flash_mode": "dout", @@ -25,7 +25,7 @@ "arduino", "espidf" ], - "name": "Espressif Generic ESP32 16M Flash, Tasmota 2944k Code/OTA, 10M SPIFFS", + "name": "Espressif Generic ESP32 16M Flash, Tasmota 2944k Code/OTA, 10M FS", "upload": { "flash_size": "16MB", "maximum_ram_size": 327680, diff --git a/boards/esp32_4M.json b/boards/esp32_4M.json index f43be6848..ee7effe39 100644 --- a/boards/esp32_4M.json +++ b/boards/esp32_4M.json @@ -4,7 +4,7 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -DESP32_4M", + "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_4M", "f_cpu": "80000000L", "f_flash": "40000000L", "flash_mode": "dout", @@ -25,7 +25,7 @@ "arduino", "espidf" ], - "name": "Espressif Generic ESP32 4M Flash, Tasmota 1856k Code/OTA, 320k SPIFFS", + "name": "Espressif Generic ESP32 4M Flash, Tasmota 1856k Code/OTA, 320k FS", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, diff --git a/boards/esp32_8M.json b/boards/esp32_8M.json index adcd0caaa..b5dcfd676 100644 --- a/boards/esp32_8M.json +++ b/boards/esp32_8M.json @@ -4,7 +4,7 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -DESP32_8M", + "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_8M", "f_cpu": "80000000L", "f_flash": "40000000L", "flash_mode": "dout", @@ -25,7 +25,7 @@ "arduino", "espidf" ], - "name": "Espressif Generic ESP32 8M Flash, Tasmota 2944k Code/OTA, 2112k SPIFFS", + "name": "Espressif Generic ESP32 8M Flash, Tasmota 2944k Code/OTA, 2112k FS", "upload": { "flash_size": "8MB", "maximum_ram_size": 327680, diff --git a/boards/esp32_solo1_4M.json b/boards/esp32_solo1_4M.json index 64759d331..e5b86ade8 100644 --- a/boards/esp32_solo1_4M.json +++ b/boards/esp32_solo1_4M.json @@ -4,7 +4,7 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV -DESP32_4M", + "extra_flags": "-DARDUINO_ESP32_DEV -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_4M -DCORE32SOLO1", "f_cpu": "80000000L", "f_flash": "40000000L", "flash_mode": "dout", @@ -25,7 +25,7 @@ "arduino", "espidf" ], - "name": "Espressif Generic ESP32 4M Flash, Tasmota 1856k Code/OTA, 320k SPIFFS", + "name": "Espressif Generic ESP32 4M Flash, Tasmota 1856k Code/OTA, 320k FS", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, diff --git a/boards/esp32c3.json b/boards/esp32c3.json index cedcf1500..762172fc3 100644 --- a/boards/esp32c3.json +++ b/boards/esp32c3.json @@ -4,6 +4,7 @@ "ldscript": "esp32c3_out.ld" }, "core": "esp32", + "extra_flags": "-DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_4M -DESP32C3", "f_cpu": "160000000L", "f_flash": "80000000L", "flash_mode": "dout", @@ -21,7 +22,7 @@ "arduino", "espidf" ], - "name": "Espressif Generic ESP32-C3 4M Flash, Tasmota 1856k Code/OTA, 320k SPIFFS", + "name": "Espressif Generic ESP32-C3 4M Flash, Tasmota 1856k Code/OTA, 320k FS", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, diff --git a/boards/esp32s2.json b/boards/esp32s2.json index e18a2339c..e0736aa29 100644 --- a/boards/esp32s2.json +++ b/boards/esp32s2.json @@ -4,7 +4,7 @@ "ldscript": "esp32s2_out.ld" }, "core": "esp32", - "extra_flags": "-DBOARD_HAS_PSRAM", + "extra_flags": "-DBOARD_HAS_PSRAM -DESP32_4M -DESP32S2", "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dout", @@ -22,7 +22,7 @@ "espidf", "arduino" ], - "name": "Espressif Generic ESP32-S2 4M Flash, Tasmota 1856k Code/OTA, 320k SPIFFS", + "name": "Espressif Generic ESP32-S2 4M Flash, Tasmota 1856k Code/OTA, 320k FS", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, diff --git a/boards/esp8266_1M.json b/boards/esp8266_1M.json index bc5b1f49b..7cd01ec90 100644 --- a/boards/esp8266_1M.json +++ b/boards/esp8266_1M.json @@ -19,7 +19,7 @@ "esp8266-rtos-sdk", "esp8266-nonos-sdk" ], - "name": "Espressif Generic ESP8266 Tasmota 1M sketch NO SPIFFS", + "name": "Espressif Generic ESP8266 Tasmota 1M sketch NO FS", "upload": { "maximum_ram_size": 81920, "maximum_size": 995326, diff --git a/boards/esp8266_2M1M.json b/boards/esp8266_2M1M.json index e3a675373..afe54a343 100644 --- a/boards/esp8266_2M1M.json +++ b/boards/esp8266_2M1M.json @@ -19,7 +19,7 @@ "esp8266-rtos-sdk", "esp8266-nonos-sdk" ], - "name": "Espressif Generic ESP8266 Tasmota 1M sketch 1M SPIFFS", + "name": "Espressif Generic ESP8266 Tasmota 1M sketch 1M FS", "upload": { "maximum_ram_size": 81920, "maximum_size": 995326, diff --git a/boards/esp8266_2M256.json b/boards/esp8266_2M256.json index 734f62537..335b84ade 100644 --- a/boards/esp8266_2M256.json +++ b/boards/esp8266_2M256.json @@ -19,7 +19,7 @@ "esp8266-rtos-sdk", "esp8266-nonos-sdk" ], - "name": "Espressif Generic ESP8266 Tasmota 1M sketch 772k OTA 256k SPIFFS", + "name": "Espressif Generic ESP8266 Tasmota 1M sketch 772k OTA 256k FS", "upload": { "maximum_ram_size": 81920, "maximum_size": 995326, diff --git a/boards/esp8266_4M2M.json b/boards/esp8266_4M2M.json index 873c84f24..7b0e0c364 100644 --- a/boards/esp8266_4M2M.json +++ b/boards/esp8266_4M2M.json @@ -19,7 +19,7 @@ "esp8266-rtos-sdk", "esp8266-nonos-sdk" ], - "name": "Espressif Generic ESP8266 Tasmota 1M sketch 1M OTA 2M SPIFFS", + "name": "Espressif Generic ESP8266 Tasmota 1M sketch 1M OTA 2M FS", "upload": { "maximum_ram_size": 81920, "maximum_size": 995326, diff --git a/boards/esp8266_4M3M.json b/boards/esp8266_4M3M.json index c845d6e96..fec296cf0 100644 --- a/boards/esp8266_4M3M.json +++ b/boards/esp8266_4M3M.json @@ -19,7 +19,7 @@ "esp8266-rtos-sdk", "esp8266-nonos-sdk" ], - "name": "Espressif Generic ESP8266 Tasmota 1M sketch 3M SPIFFS", + "name": "Espressif Generic ESP8266 Tasmota 1M sketch 3M FS", "upload": { "maximum_ram_size": 81920, "maximum_size": 995326, diff --git a/boards/esp8266_zbbridge.json b/boards/esp8266_zbbridge.json index 975c1bc8c..dbc229004 100644 --- a/boards/esp8266_zbbridge.json +++ b/boards/esp8266_zbbridge.json @@ -4,7 +4,7 @@ "ldscript": "eagle.flash.2m256.ld" }, "core": "esp8266", - "extra_flags": "-DESP8266 -DARDUINO_ARCH_ESP8266 -DARDUINO_ESP8266_ESP01", + "extra_flags": "-DESP8266 -DARDUINO_ARCH_ESP8266 -DARDUINO_ESP8266_ESP01 -DESP8266_2M -DESP8266_2M256", "f_cpu": "160000000L", "f_flash": "40000000L", "flash_mode": "dout", @@ -19,7 +19,7 @@ "esp8266-rtos-sdk", "esp8266-nonos-sdk" ], - "name": "Sonoff ZbBridge Tasmota 1M sketch 772k OTA 256k SPIFFS", + "name": "Sonoff ZbBridge Tasmota 1M sketch 772k OTA 256k FS", "upload": { "maximum_ram_size": 81920, "maximum_size": 995326, diff --git a/lib/default/DHT-sensor-library/.gitignore b/lib/default/DHT-sensor-library/.gitignore new file mode 100644 index 000000000..542d266a9 --- /dev/null +++ b/lib/default/DHT-sensor-library/.gitignore @@ -0,0 +1,8 @@ +# osx +.DS_Store + +# doxygen +Doxyfile* +doxygen_sqlite3.db +html +*.tmp diff --git a/lib/default/DHT-sensor-library/CONTRIBUTING.md b/lib/default/DHT-sensor-library/CONTRIBUTING.md new file mode 100644 index 000000000..3227bf9cc --- /dev/null +++ b/lib/default/DHT-sensor-library/CONTRIBUTING.md @@ -0,0 +1,13 @@ +# Contribution Guidlines + +This library is the culmination of the expertise of many members of the open source community who have dedicated their time and hard work. The best way to ask for help or propose a new idea is to [create a new issue](https://github.com/adafruit/DHT-sensor-library/issues/new) while creating a Pull Request with your code changes allows you to share your own innovations with the rest of the community. + +The following are some guidelines to observe when creating issues or PRs: + +- Be friendly; it is important that we can all enjoy a safe space as we are all working on the same project and it is okay for people to have different ideas + +- [Use code blocks](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code); it helps us help you when we can read your code! On that note also refrain from pasting more than 30 lines of code in a post, instead [create a gist](https://gist.github.com/) if you need to share large snippets + +- Use reasonable titles; refrain from using overly long or capitalized titles as they are usually annoying and do little to encourage others to help :smile: + +- Be detailed; refrain from mentioning code problems without sharing your source code and always give information regarding your board and version of the library diff --git a/lib/default/DHT-sensor-library/DHT.cpp b/lib/default/DHT-sensor-library/DHT.cpp new file mode 100644 index 000000000..b36461224 --- /dev/null +++ b/lib/default/DHT-sensor-library/DHT.cpp @@ -0,0 +1,388 @@ +/*! + * @file DHT.cpp + * + * @mainpage DHT series of low cost temperature/humidity sensors. + * + * @section intro_sec Introduction + * + * This is a library for DHT series of low cost temperature/humidity sensors. + * + * You must have Adafruit Unified Sensor Library library installed to use this + * class. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit andopen-source hardware by purchasing products + * from Adafruit! + * + * @section author Author + * + * Written by Adafruit Industries. + * + * @section license License + * + * MIT license, all text above must be included in any redistribution + */ + +#include "DHT.h" + +#define MIN_INTERVAL 2000 /**< min interval value */ +#define TIMEOUT \ + UINT32_MAX /**< Used programmatically for timeout. \ + Not a timeout duration. Type: uint32_t. */ + +/*! + * @brief Instantiates a new DHT class + * @param pin + * pin number that sensor is connected + * @param type + * type of sensor + * @param count + * number of sensors + */ +DHT::DHT(uint8_t pin, uint8_t type, uint8_t count) { + (void)count; // Workaround to avoid compiler warning. + _pin = pin; + _type = type; +#ifdef __AVR + _bit = digitalPinToBitMask(pin); + _port = digitalPinToPort(pin); +#endif + _maxcycles = + microsecondsToClockCycles(1000); // 1 millisecond timeout for + // reading pulses from DHT sensor. + // Note that count is now ignored as the DHT reading algorithm adjusts itself + // based on the speed of the processor. +} + +/*! + * @brief Setup sensor pins and set pull timings + * @param usec + * Optionally pass pull-up time (in microseconds) before DHT reading + *starts. Default is 55 (see function declaration in DHT.h). + */ +void DHT::begin(uint8_t usec) { + // set up the pins! + pinMode(_pin, INPUT_PULLUP); + // Using this value makes sure that millis() - lastreadtime will be + // >= MIN_INTERVAL right away. Note that this assignment wraps around, + // but so will the subtraction. + _lastreadtime = millis() - MIN_INTERVAL; + DEBUG_PRINT("DHT max clock cycles: "); + DEBUG_PRINTLN(_maxcycles, DEC); + pullTime = usec; +} + +/*! + * @brief Read temperature + * @param S + * Scale. Boolean value: + * - true = Fahrenheit + * - false = Celcius + * @param force + * true if in force mode + * @return Temperature value in selected scale + */ +float DHT::readTemperature(bool S, bool force) { + float f = NAN; + + if (read(force)) { + switch (_type) { + case DHT11: + f = data[2]; + if (data[3] & 0x80) { + f = -1 - f; + } + f += (data[3] & 0x0f) * 0.1; + if (S) { + f = convertCtoF(f); + } + break; + case DHT12: + f = data[2]; + f += (data[3] & 0x0f) * 0.1; + if (data[2] & 0x80) { + f *= -1; + } + if (S) { + f = convertCtoF(f); + } + break; + case DHT22: + case DHT21: + f = ((word)(data[2] & 0x7F)) << 8 | data[3]; + f *= 0.1; + if (data[2] & 0x80) { + f *= -1; + } + if (S) { + f = convertCtoF(f); + } + break; + } + } + return f; +} + +/*! + * @brief Converts Celcius to Fahrenheit + * @param c + * value in Celcius + * @return float value in Fahrenheit + */ +float DHT::convertCtoF(float c) { return c * 1.8 + 32; } + +/*! + * @brief Converts Fahrenheit to Celcius + * @param f + * value in Fahrenheit + * @return float value in Celcius + */ +float DHT::convertFtoC(float f) { return (f - 32) * 0.55555; } + +/*! + * @brief Read Humidity + * @param force + * force read mode + * @return float value - humidity in percent + */ +float DHT::readHumidity(bool force) { + float f = NAN; + if (read(force)) { + switch (_type) { + case DHT11: + case DHT12: + f = data[0] + data[1] * 0.1; + break; + case DHT22: + case DHT21: + f = ((word)data[0]) << 8 | data[1]; + f *= 0.1; + break; + } + } + return f; +} + +/*! + * @brief Compute Heat Index + * Simplified version that reads temp and humidity from sensor + * @param isFahrenheit + * true if fahrenheit, false if celcius + *(default true) + * @return float heat index + */ +float DHT::computeHeatIndex(bool isFahrenheit) { + float hi = computeHeatIndex(readTemperature(isFahrenheit), readHumidity(), + isFahrenheit); + return hi; +} + +/*! + * @brief Compute Heat Index + * Using both Rothfusz and Steadman's equations + * (http://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml) + * @param temperature + * temperature in selected scale + * @param percentHumidity + * humidity in percent + * @param isFahrenheit + * true if fahrenheit, false if celcius + * @return float heat index + */ +float DHT::computeHeatIndex(float temperature, float percentHumidity, + bool isFahrenheit) { + float hi; + + if (!isFahrenheit) + temperature = convertCtoF(temperature); + + hi = 0.5 * (temperature + 61.0 + ((temperature - 68.0) * 1.2) + + (percentHumidity * 0.094)); + + if (hi > 79) { + hi = -42.379 + 2.04901523 * temperature + 10.14333127 * percentHumidity + + -0.22475541 * temperature * percentHumidity + + -0.00683783 * pow(temperature, 2) + + -0.05481717 * pow(percentHumidity, 2) + + 0.00122874 * pow(temperature, 2) * percentHumidity + + 0.00085282 * temperature * pow(percentHumidity, 2) + + -0.00000199 * pow(temperature, 2) * pow(percentHumidity, 2); + + if ((percentHumidity < 13) && (temperature >= 80.0) && + (temperature <= 112.0)) + hi -= ((13.0 - percentHumidity) * 0.25) * + sqrt((17.0 - abs(temperature - 95.0)) * 0.05882); + + else if ((percentHumidity > 85.0) && (temperature >= 80.0) && + (temperature <= 87.0)) + hi += ((percentHumidity - 85.0) * 0.1) * ((87.0 - temperature) * 0.2); + } + + return isFahrenheit ? hi : convertFtoC(hi); +} + +/*! + * @brief Read value from sensor or return last one from less than two + *seconds. + * @param force + * true if using force mode + * @return float value + */ +bool DHT::read(bool force) { + // Check if sensor was read less than two seconds ago and return early + // to use last reading. + uint32_t currenttime = millis(); + if (!force && ((currenttime - _lastreadtime) < MIN_INTERVAL)) { + return _lastresult; // return last correct measurement + } + _lastreadtime = currenttime; + + // Reset 40 bits of received data to zero. + data[0] = data[1] = data[2] = data[3] = data[4] = 0; + +#if defined(ESP8266) + yield(); // Handle WiFi / reset software watchdog +#endif + + // Send start signal. See DHT datasheet for full signal diagram: + // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf + + // Go into high impedence state to let pull-up raise data line level and + // start the reading process. + pinMode(_pin, INPUT_PULLUP); + delay(1); + + // First set data line low for a period according to sensor type + pinMode(_pin, OUTPUT); + digitalWrite(_pin, LOW); + switch (_type) { + case DHT22: + case DHT21: + delayMicroseconds(1100); // data sheet says "at least 1ms" + break; + case DHT11: + default: + delay(20); // data sheet says at least 18ms, 20ms just to be safe + break; + } + + uint32_t cycles[80]; + { + // End the start signal by setting data line high for 40 microseconds. + pinMode(_pin, INPUT_PULLUP); + + // Delay a moment to let sensor pull data line low. + delayMicroseconds(pullTime); + + // Now start reading the data line to get the value from the DHT sensor. + + // Turn off interrupts temporarily because the next sections + // are timing critical and we don't want any interruptions. + InterruptLock lock; + + // First expect a low signal for ~80 microseconds followed by a high signal + // for ~80 microseconds again. + if (expectPulse(LOW) == TIMEOUT) { + DEBUG_PRINTLN(F("DHT timeout waiting for start signal low pulse.")); + _lastresult = false; + return _lastresult; + } + if (expectPulse(HIGH) == TIMEOUT) { + DEBUG_PRINTLN(F("DHT timeout waiting for start signal high pulse.")); + _lastresult = false; + return _lastresult; + } + + // Now read the 40 bits sent by the sensor. Each bit is sent as a 50 + // microsecond low pulse followed by a variable length high pulse. If the + // high pulse is ~28 microseconds then it's a 0 and if it's ~70 microseconds + // then it's a 1. We measure the cycle count of the initial 50us low pulse + // and use that to compare to the cycle count of the high pulse to determine + // if the bit is a 0 (high state cycle count < low state cycle count), or a + // 1 (high state cycle count > low state cycle count). Note that for speed + // all the pulses are read into a array and then examined in a later step. + for (int i = 0; i < 80; i += 2) { + cycles[i] = expectPulse(LOW); + cycles[i + 1] = expectPulse(HIGH); + } + } // Timing critical code is now complete. + + // Inspect pulses and determine which ones are 0 (high state cycle count < low + // state cycle count), or 1 (high state cycle count > low state cycle count). + for (int i = 0; i < 40; ++i) { + uint32_t lowCycles = cycles[2 * i]; + uint32_t highCycles = cycles[2 * i + 1]; + if ((lowCycles == TIMEOUT) || (highCycles == TIMEOUT)) { + DEBUG_PRINTLN(F("DHT timeout waiting for pulse.")); + _lastresult = false; + return _lastresult; + } + data[i / 8] <<= 1; + // Now compare the low and high cycle times to see if the bit is a 0 or 1. + if (highCycles > lowCycles) { + // High cycles are greater than 50us low cycle count, must be a 1. + data[i / 8] |= 1; + } + // Else high cycles are less than (or equal to, a weird case) the 50us low + // cycle count so this must be a zero. Nothing needs to be changed in the + // stored data. + } + + DEBUG_PRINTLN(F("Received from DHT:")); + DEBUG_PRINT(data[0], HEX); + DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[1], HEX); + DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[2], HEX); + DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[3], HEX); + DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[4], HEX); + DEBUG_PRINT(F(" =? ")); + DEBUG_PRINTLN((data[0] + data[1] + data[2] + data[3]) & 0xFF, HEX); + + // Check we read 40 bits and that the checksum matches. + if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) { + _lastresult = true; + return _lastresult; + } else { + DEBUG_PRINTLN(F("DHT checksum failure!")); + _lastresult = false; + return _lastresult; + } +} + +// Expect the signal line to be at the specified level for a period of time and +// return a count of loop cycles spent at that level (this cycle count can be +// used to compare the relative time of two pulses). If more than a millisecond +// ellapses without the level changing then the call fails with a 0 response. +// This is adapted from Arduino's pulseInLong function (which is only available +// in the very latest IDE versions): +// https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_pulse.c +uint32_t DHT::expectPulse(bool level) { +#if (F_CPU > 16000000L) + uint32_t count = 0; +#else + uint16_t count = 0; // To work fast enough on slower AVR boards +#endif +// On AVR platforms use direct GPIO port access as it's much faster and better +// for catching pulses that are 10's of microseconds in length: +#ifdef __AVR + uint8_t portState = level ? _bit : 0; + while ((*portInputRegister(_port) & _bit) == portState) { + if (count++ >= _maxcycles) { + return TIMEOUT; // Exceeded timeout, fail. + } + } +// Otherwise fall back to using digitalRead (this seems to be necessary on +// ESP8266 right now, perhaps bugs in direct port access functions?). +#else + while (digitalRead(_pin) == level) { + if (count++ >= _maxcycles) { + return TIMEOUT; // Exceeded timeout, fail. + } + } +#endif + + return count; +} diff --git a/lib/default/DHT-sensor-library/DHT.h b/lib/default/DHT-sensor-library/DHT.h new file mode 100644 index 000000000..95570e1cf --- /dev/null +++ b/lib/default/DHT-sensor-library/DHT.h @@ -0,0 +1,109 @@ +/*! + * @file DHT.h + * + * This is a library for DHT series of low cost temperature/humidity sensors. + * + * You must have Adafruit Unified Sensor Library library installed to use this + * class. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit andopen-source hardware by purchasing products + * from Adafruit! + * + * Written by Adafruit Industries. + * + * MIT license, all text above must be included in any redistribution + */ + +#ifndef DHT_H +#define DHT_H + +#include "Arduino.h" + +/* Uncomment to enable printing out nice debug messages. */ +//#define DHT_DEBUG + +#define DEBUG_PRINTER \ + Serial /**< Define where debug output will be printed. \ + */ + +/* Setup debug printing macros. */ +#ifdef DHT_DEBUG +#define DEBUG_PRINT(...) \ + { DEBUG_PRINTER.print(__VA_ARGS__); } +#define DEBUG_PRINTLN(...) \ + { DEBUG_PRINTER.println(__VA_ARGS__); } +#else +#define DEBUG_PRINT(...) \ + {} /**< Debug Print Placeholder if Debug is disabled */ +#define DEBUG_PRINTLN(...) \ + {} /**< Debug Print Line Placeholder if Debug is disabled */ +#endif + +/* Define types of sensors. */ +static const uint8_t DHT11{11}; /**< DHT TYPE 11 */ +static const uint8_t DHT12{12}; /**< DHY TYPE 12 */ +static const uint8_t DHT21{21}; /**< DHT TYPE 21 */ +static const uint8_t DHT22{22}; /**< DHT TYPE 22 */ +static const uint8_t AM2301{21}; /**< AM2301 */ + +#if defined(TARGET_NAME) && (TARGET_NAME == ARDUINO_NANO33BLE) +#ifndef microsecondsToClockCycles +/*! + * As of 7 Sep 2020 the Arduino Nano 33 BLE boards do not have + * microsecondsToClockCycles defined. + */ +#define microsecondsToClockCycles(a) ((a) * (SystemCoreClock / 1000000L)) +#endif +#endif + +/*! + * @brief Class that stores state and functions for DHT + */ +class DHT { +public: + DHT(uint8_t pin, uint8_t type, uint8_t count = 6); + void begin(uint8_t usec = 55); + float readTemperature(bool S = false, bool force = false); + float convertCtoF(float); + float convertFtoC(float); + float computeHeatIndex(bool isFahrenheit = true); + float computeHeatIndex(float temperature, float percentHumidity, + bool isFahrenheit = true); + float readHumidity(bool force = false); + bool read(bool force = false); + +private: + uint8_t data[5]; + uint8_t _pin, _type; +#ifdef __AVR + // Use direct GPIO access on an 8-bit AVR so keep track of the port and + // bitmask for the digital pin connected to the DHT. Other platforms will use + // digitalRead. + uint8_t _bit, _port; +#endif + uint32_t _lastreadtime, _maxcycles; + bool _lastresult; + uint8_t pullTime; // Time (in usec) to pull up data line before reading + + uint32_t expectPulse(bool level); +}; + +/*! + * @brief Class that defines Interrupt Lock Avaiability + */ +class InterruptLock { +public: + InterruptLock() { +#if !defined(ARDUINO_ARCH_NRF52) + noInterrupts(); +#endif + } + ~InterruptLock() { +#if !defined(ARDUINO_ARCH_NRF52) + interrupts(); +#endif + } +}; + +#endif diff --git a/lib/default/DHT-sensor-library/README.md b/lib/default/DHT-sensor-library/README.md new file mode 100644 index 000000000..ba871876d --- /dev/null +++ b/lib/default/DHT-sensor-library/README.md @@ -0,0 +1,58 @@ +# DHT sensor library [![Build Status](https://github.com/adafruit/DHT-sensor-library/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/DHT-sensor-library/actions) + +## Description + +An Arduino library for the DHT series of low-cost temperature/humidity sensors. + +You can find DHT tutorials [here](https://learn.adafruit.com/dht). + +# Dependencies + * [Adafruit Unified Sensor Driver](https://github.com/adafruit/Adafruit_Sensor) + +# Contributing + +Contributions are welcome! Not only you’ll encourage the development of the library, but you’ll also learn how to best use the library and probably some C++ too + +Please read our [Code of Conduct](https://github.com/adafruit/DHT-sensor-library/blob/master/CODE_OF_CONDUCT.md>) +before contributing to help this project stay welcoming. + +## Documentation and doxygen +Documentation is produced by doxygen. Contributions should include documentation for any new code added. + +Some examples of how to use doxygen can be found in these guide pages: + +https://learn.adafruit.com/the-well-automated-arduino-library/doxygen + +https://learn.adafruit.com/the-well-automated-arduino-library/doxygen-tips + +Written by Adafruit Industries based on work by: + + * T. DiCola + * P. Y. Dragon + * L. Fried + * J. Hoffmann + * M. Kooijman + * J. M. Dana + * S. Conaway + * S. IJskes + * T. Forbes + * B. C + * T. J Myers + * L. Sørup + * per1234 + * O. Duffy + * matthiasdanner + * J. Lim + * G. Ambrozio + * chelmi + * adams13x13 + * Spacefish + * I. Scheller + * C. Miller + * 7eggert + + +MIT license, check license.txt for more information +All text above must be included in any redistribution + +To install, use the Arduino Library Manager and search for "DHT sensor library" and install the library. diff --git a/lib/default/DHT-sensor-library/code-of-conduct.md b/lib/default/DHT-sensor-library/code-of-conduct.md new file mode 100644 index 000000000..8ee6e4498 --- /dev/null +++ b/lib/default/DHT-sensor-library/code-of-conduct.md @@ -0,0 +1,127 @@ +# Adafruit Community Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and leaders pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level or type of +experience, education, socio-economic status, nationality, personal appearance, +race, religion, or sexual identity and orientation. + +## Our Standards + +We are committed to providing a friendly, safe and welcoming environment for +all. + +Examples of behavior that contributes to creating a positive environment +include: + +* Be kind and courteous to others +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Collaborating with other community members +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and sexual attention or advances +* The use of inappropriate images, including in a community member's avatar +* The use of inappropriate language, including in a community member's nickname +* Any spamming, flaming, baiting or other attention-stealing behavior +* Excessive or unwelcome helping; answering outside the scope of the question + asked +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate + +The goal of the standards and moderation guidelines outlined here is to build +and maintain a respectful community. We ask that you don’t just aim to be +"technically unimpeachable", but rather try to be your best self. + +We value many things beyond technical expertise, including collaboration and +supporting others within our community. Providing a positive experience for +other community members can have a much more significant impact than simply +providing the correct answer. + +## Our Responsibilities + +Project leaders are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project leaders have the right and responsibility to remove, edit, or +reject messages, comments, commits, code, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any community member for other behaviors that they deem +inappropriate, threatening, offensive, or harmful. + +## Moderation + +Instances of behaviors that violate the Adafruit Community Code of Conduct +may be reported by any member of the community. Community members are +encouraged to report these situations, including situations they witness +involving other community members. + +You may report in the following ways: + +In any situation, you may send an email to . + +On the Adafruit Discord, you may send an open message from any channel +to all Community Helpers by tagging @community helpers. You may also send an +open message from any channel, or a direct message to @kattni#1507, +@tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or +@Andon#8175. + +Email and direct message reports will be kept confidential. + +In situations on Discord where the issue is particularly egregious, possibly +illegal, requires immediate action, or violates the Discord terms of service, +you should also report the message directly to Discord. + +These are the steps for upholding our community’s standards of conduct. + +1. Any member of the community may report any situation that violates the +Adafruit Community Code of Conduct. All reports will be reviewed and +investigated. +2. If the behavior is an egregious violation, the community member who +committed the violation may be banned immediately, without warning. +3. Otherwise, moderators will first respond to such behavior with a warning. +4. Moderators follow a soft "three strikes" policy - the community member may +be given another chance, if they are receptive to the warning and change their +behavior. +5. If the community member is unreceptive or unreasonable when warned by a +moderator, or the warning goes unheeded, they may be banned for a first or +second offense. Repeated offenses will result in the community member being +banned. + +## Scope + +This Code of Conduct and the enforcement policies listed above apply to all +Adafruit Community venues. This includes but is not limited to any community +spaces (both public and private), the entire Adafruit Discord server, and +Adafruit GitHub repositories. Examples of Adafruit Community spaces include +but are not limited to meet-ups, audio chats on the Adafruit Discord, or +interaction at a conference. + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. As a community +member, you are representing our community, and are expected to behave +accordingly. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 1.4, available at +, +and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html). + +For other projects adopting the Adafruit Community Code of +Conduct, please contact the maintainers of those projects for enforcement. +If you wish to use this code of conduct for your own project, consider +explicitly mentioning your moderation policy or making a copy with your +own moderation policy so as to avoid confusion. diff --git a/lib/default/DHT-sensor-library/examples/DHT_Unified_Sensor/DHT_Unified_Sensor.ino b/lib/default/DHT-sensor-library/examples/DHT_Unified_Sensor/DHT_Unified_Sensor.ino new file mode 100644 index 000000000..0f70347ba --- /dev/null +++ b/lib/default/DHT-sensor-library/examples/DHT_Unified_Sensor/DHT_Unified_Sensor.ino @@ -0,0 +1,85 @@ +// DHT Temperature & Humidity Sensor +// Unified Sensor Library Example +// Written by Tony DiCola for Adafruit Industries +// Released under an MIT license. + +// REQUIRES the following Arduino libraries: +// - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library +// - Adafruit Unified Sensor Lib: https://github.com/adafruit/Adafruit_Sensor + +#include +#include +#include + +#define DHTPIN 2 // Digital pin connected to the DHT sensor +// Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 -- +// Pin 15 can work but DHT must be disconnected during program upload. + +// Uncomment the type of sensor in use: +//#define DHTTYPE DHT11 // DHT 11 +#define DHTTYPE DHT22 // DHT 22 (AM2302) +//#define DHTTYPE DHT21 // DHT 21 (AM2301) + +// See guide for details on sensor wiring and usage: +// https://learn.adafruit.com/dht/overview + +DHT_Unified dht(DHTPIN, DHTTYPE); + +uint32_t delayMS; + +void setup() { + Serial.begin(9600); + // Initialize device. + dht.begin(); + Serial.println(F("DHTxx Unified Sensor Example")); + // Print temperature sensor details. + sensor_t sensor; + dht.temperature().getSensor(&sensor); + Serial.println(F("------------------------------------")); + Serial.println(F("Temperature Sensor")); + Serial.print (F("Sensor Type: ")); Serial.println(sensor.name); + Serial.print (F("Driver Ver: ")); Serial.println(sensor.version); + Serial.print (F("Unique ID: ")); Serial.println(sensor.sensor_id); + Serial.print (F("Max Value: ")); Serial.print(sensor.max_value); Serial.println(F("°C")); + Serial.print (F("Min Value: ")); Serial.print(sensor.min_value); Serial.println(F("°C")); + Serial.print (F("Resolution: ")); Serial.print(sensor.resolution); Serial.println(F("°C")); + Serial.println(F("------------------------------------")); + // Print humidity sensor details. + dht.humidity().getSensor(&sensor); + Serial.println(F("Humidity Sensor")); + Serial.print (F("Sensor Type: ")); Serial.println(sensor.name); + Serial.print (F("Driver Ver: ")); Serial.println(sensor.version); + Serial.print (F("Unique ID: ")); Serial.println(sensor.sensor_id); + Serial.print (F("Max Value: ")); Serial.print(sensor.max_value); Serial.println(F("%")); + Serial.print (F("Min Value: ")); Serial.print(sensor.min_value); Serial.println(F("%")); + Serial.print (F("Resolution: ")); Serial.print(sensor.resolution); Serial.println(F("%")); + Serial.println(F("------------------------------------")); + // Set delay between sensor readings based on sensor details. + delayMS = sensor.min_delay / 1000; +} + +void loop() { + // Delay between measurements. + delay(delayMS); + // Get temperature event and print its value. + sensors_event_t event; + dht.temperature().getEvent(&event); + if (isnan(event.temperature)) { + Serial.println(F("Error reading temperature!")); + } + else { + Serial.print(F("Temperature: ")); + Serial.print(event.temperature); + Serial.println(F("°C")); + } + // Get humidity event and print its value. + dht.humidity().getEvent(&event); + if (isnan(event.relative_humidity)) { + Serial.println(F("Error reading humidity!")); + } + else { + Serial.print(F("Humidity: ")); + Serial.print(event.relative_humidity); + Serial.println(F("%")); + } +} diff --git a/lib/default/DHT-sensor-library/examples/DHTtester/DHTtester.ino b/lib/default/DHT-sensor-library/examples/DHTtester/DHTtester.ino new file mode 100644 index 000000000..d13507bfe --- /dev/null +++ b/lib/default/DHT-sensor-library/examples/DHTtester/DHTtester.ino @@ -0,0 +1,74 @@ +// Example testing sketch for various DHT humidity/temperature sensors +// Written by ladyada, public domain + +// REQUIRES the following Arduino libraries: +// - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library +// - Adafruit Unified Sensor Lib: https://github.com/adafruit/Adafruit_Sensor + +#include "DHT.h" + +#define DHTPIN 2 // Digital pin connected to the DHT sensor +// Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 -- +// Pin 15 can work but DHT must be disconnected during program upload. + +// Uncomment whatever type you're using! +//#define DHTTYPE DHT11 // DHT 11 +#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 +//#define DHTTYPE DHT21 // DHT 21 (AM2301) + +// Connect pin 1 (on the left) of the sensor to +5V +// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1 +// to 3.3V instead of 5V! +// Connect pin 2 of the sensor to whatever your DHTPIN is +// Connect pin 3 (on the right) of the sensor to GROUND (if your sensor has 3 pins) +// Connect pin 4 (on the right) of the sensor to GROUND and leave the pin 3 EMPTY (if your sensor has 4 pins) +// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor + +// Initialize DHT sensor. +// Note that older versions of this library took an optional third parameter to +// tweak the timings for faster processors. This parameter is no longer needed +// as the current DHT reading algorithm adjusts itself to work on faster procs. +DHT dht(DHTPIN, DHTTYPE); + +void setup() { + Serial.begin(9600); + Serial.println(F("DHTxx test!")); + + dht.begin(); +} + +void loop() { + // Wait a few seconds between measurements. + delay(2000); + + // Reading temperature or humidity takes about 250 milliseconds! + // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) + float h = dht.readHumidity(); + // Read temperature as Celsius (the default) + float t = dht.readTemperature(); + // Read temperature as Fahrenheit (isFahrenheit = true) + float f = dht.readTemperature(true); + + // Check if any reads failed and exit early (to try again). + if (isnan(h) || isnan(t) || isnan(f)) { + Serial.println(F("Failed to read from DHT sensor!")); + return; + } + + // Compute heat index in Fahrenheit (the default) + float hif = dht.computeHeatIndex(f, h); + // Compute heat index in Celsius (isFahreheit = false) + float hic = dht.computeHeatIndex(t, h, false); + + Serial.print(F("Humidity: ")); + Serial.print(h); + Serial.print(F("% Temperature: ")); + Serial.print(t); + Serial.print(F("°C ")); + Serial.print(f); + Serial.print(F("°F Heat index: ")); + Serial.print(hic); + Serial.print(F("°C ")); + Serial.print(hif); + Serial.println(F("°F")); +} diff --git a/lib/default/DHT-sensor-library/keywords.txt b/lib/default/DHT-sensor-library/keywords.txt new file mode 100644 index 000000000..3b0280fc4 --- /dev/null +++ b/lib/default/DHT-sensor-library/keywords.txt @@ -0,0 +1,22 @@ +########################################### +# Syntax Coloring Map For DHT-sensor-library +########################################### + +########################################### +# Datatypes (KEYWORD1) +########################################### + +DHT KEYWORD1 + +########################################### +# Methods and Functions (KEYWORD2) +########################################### + +begin KEYWORD2 +readTemperature KEYWORD2 +convertCtoF KEYWORD2 +convertFtoC KEYWORD2 +computeHeatIndex KEYWORD2 +readHumidity KEYWORD2 +read KEYWORD2 + diff --git a/lib/default/DHT-sensor-library/library.properties b/lib/default/DHT-sensor-library/library.properties new file mode 100644 index 000000000..5c24c5aa9 --- /dev/null +++ b/lib/default/DHT-sensor-library/library.properties @@ -0,0 +1,10 @@ +name=DHT sensor library +version=1.4.3 +author=Adafruit +maintainer=Adafruit +sentence=Arduino library for DHT11, DHT22, etc Temp & Humidity Sensors +paragraph=Arduino library for DHT11, DHT22, etc Temp & Humidity Sensors +category=Sensors +url=https://github.com/adafruit/DHT-sensor-library +architectures=* +depends=Adafruit Unified Sensor diff --git a/lib/default/DHT-sensor-library/license.txt b/lib/default/DHT-sensor-library/license.txt new file mode 100644 index 000000000..f06f843e4 --- /dev/null +++ b/lib/default/DHT-sensor-library/license.txt @@ -0,0 +1,20 @@ +Copyright (c) 2020 Adafruit Industries + + +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. diff --git a/lib/default/TasmotaLList/library.json b/lib/default/TasmotaLList/library.json index d49f03f71..d5c06d45c 100644 --- a/lib/default/TasmotaLList/library.json +++ b/lib/default/TasmotaLList/library.json @@ -4,8 +4,8 @@ "description": "Simple yet powerful linked-list", "license": "MIT", "homepage": "https://github.com/arendst/Tasmota", - "frameworks": "*", - "platforms": "*", + "frameworks": "arduino", + "platforms": "espressif32, espressif8266", "authors": { "name": "Stephan Hadinger", diff --git a/lib/default/TasmotaSerial-3.3.0/README.md b/lib/default/TasmotaSerial-3.4.0/README.md similarity index 100% rename from lib/default/TasmotaSerial-3.3.0/README.md rename to lib/default/TasmotaSerial-3.4.0/README.md diff --git a/lib/default/TasmotaSerial-3.3.0/examples/swsertest/swsertest.ino b/lib/default/TasmotaSerial-3.4.0/examples/swsertest/swsertest.ino similarity index 100% rename from lib/default/TasmotaSerial-3.3.0/examples/swsertest/swsertest.ino rename to lib/default/TasmotaSerial-3.4.0/examples/swsertest/swsertest.ino diff --git a/lib/default/TasmotaSerial-3.3.0/keywords.txt b/lib/default/TasmotaSerial-3.4.0/keywords.txt similarity index 100% rename from lib/default/TasmotaSerial-3.3.0/keywords.txt rename to lib/default/TasmotaSerial-3.4.0/keywords.txt diff --git a/lib/default/TasmotaSerial-3.3.0/library.json b/lib/default/TasmotaSerial-3.4.0/library.json similarity index 94% rename from lib/default/TasmotaSerial-3.3.0/library.json rename to lib/default/TasmotaSerial-3.4.0/library.json index f6d1aaaeb..e9e2294fb 100644 --- a/lib/default/TasmotaSerial-3.3.0/library.json +++ b/lib/default/TasmotaSerial-3.4.0/library.json @@ -1,6 +1,6 @@ { "name": "TasmotaSerial", - "version": "3.3.0", + "version": "3.4.0", "keywords": [ "serial", "io", "TasmotaSerial" ], diff --git a/lib/default/TasmotaSerial-3.3.0/library.properties b/lib/default/TasmotaSerial-3.4.0/library.properties similarity index 94% rename from lib/default/TasmotaSerial-3.3.0/library.properties rename to lib/default/TasmotaSerial-3.4.0/library.properties index 6b43764a6..d254a7355 100644 --- a/lib/default/TasmotaSerial-3.3.0/library.properties +++ b/lib/default/TasmotaSerial-3.4.0/library.properties @@ -1,5 +1,5 @@ name=TasmotaSerial -version=3.3.0 +version=3.4.0 author=Theo Arends maintainer=Theo Arends sentence=Implementation of software serial with hardware serial fallback for ESP8266 and ESP32. diff --git a/lib/default/TasmotaSerial-3.3.0/src/TasmotaSerial.cpp b/lib/default/TasmotaSerial-3.4.0/src/TasmotaSerial.cpp similarity index 91% rename from lib/default/TasmotaSerial-3.3.0/src/TasmotaSerial.cpp rename to lib/default/TasmotaSerial-3.4.0/src/TasmotaSerial.cpp index 07754719e..150d740b0 100644 --- a/lib/default/TasmotaSerial-3.3.0/src/TasmotaSerial.cpp +++ b/lib/default/TasmotaSerial-3.4.0/src/TasmotaSerial.cpp @@ -40,13 +40,7 @@ TasmotaSerial *tms_obj_list[16]; #include "driver/uart.h" -#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 -static int tasmota_serial_index = 2; // Allow UART2 and UART1 only -#elif CONFIG_IDF_TARGET_ESP32S2 // ESP32-S2 -static int tasmota_serial_index = 1; // Allow UART1 only -#elif CONFIG_IDF_TARGET_ESP32C3 // ESP32-C3 -static int tasmota_serial_index = 1; // Allow UART1 only -#endif +static int tasmota_serial_index = SOC_UART_NUM -1; // Available UART #endif // ESP32 @@ -90,7 +84,8 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fal } #endif // ESP8266 #ifdef ESP32 - if (transmit_pin > 33) { return; } // GPIO34 - GPIO39 are Input only + if ((receive_pin >= 0) && !GPIO_IS_VALID_GPIO(receive_pin)) { return; } + if ((transmit_pin >= 0) && !GPIO_IS_VALID_OUTPUT_GPIO(transmit_pin)) { return; } m_hardserial = true; #endif // ESP32 m_valid = true; @@ -111,7 +106,7 @@ TasmotaSerial::~TasmotaSerial(void) { #ifdef ESP32 TSerial->end(); - tasmota_serial_index++; + tasmota_serial_index++; // This only works if no more uarts are requested otherwise will need a global used_uart log #endif // ESP32 } @@ -121,21 +116,6 @@ bool TasmotaSerial::isValidGPIOpin(int pin) { bool TasmotaSerial::begin(uint32_t speed, uint32_t config) { if (!m_valid) { return false; } - if (config > 2) { - // Legacy support where software serial fakes two stop bits if either stop bits is 2 or parity is not None - m_stop_bits = ((config &0x30) >> 5) +1; - if ((1 == m_stop_bits) && (config &0x03)) { - m_stop_bits++; - } - } else { - m_stop_bits = ((config -1) &1) +1; -#ifdef ESP8266 - config = (2 == m_stop_bits) ? (uint32_t)SERIAL_8N2 : (uint32_t)SERIAL_8N1; -#endif // ESP8266 -#ifdef ESP32 - config = (2 == m_stop_bits) ? SERIAL_8N2 : SERIAL_8N1; -#endif // ESP32 - } if (m_hardserial) { #ifdef ESP8266 @@ -149,10 +129,17 @@ bool TasmotaSerial::begin(uint32_t speed, uint32_t config) { } #endif // ESP8266 #ifdef ESP32 - if (tasmota_serial_index > 0) { // We only support UART1 and UART2 and keep UART0 for debugging + if (tasmota_serial_index >= 0) { // We prefer UART1 and UART2 and keep UART0 for debugging m_uart = tasmota_serial_index; tasmota_serial_index--; - TSerial = new HardwareSerial(m_uart); + if (0 == m_uart) { + Serial.flush(); + Serial.end(); + delay(10); // Allow time to cleanup queues - if not used hangs ESP32 + TSerial = &Serial; + } else { + TSerial = new HardwareSerial(m_uart); + } if (serial_buffer_size > 256) { // RX Buffer can't be resized when Serial is already running (HardwareSerial.cpp) TSerial->setRxBufferSize(serial_buffer_size); } @@ -181,6 +168,18 @@ bool TasmotaSerial::begin(uint32_t speed, uint32_t config) { // Serial.printf("TSR: Using UART%d\n", m_uart); #endif // ESP32 } else { + // Software serial fakes two stop bits if either stop bits is 2 or parity is not None + // #define UART_NB_STOP_BIT_0 0B00000000 + // #define UART_NB_STOP_BIT_1 0B00010000 + // #define UART_NB_STOP_BIT_15 0B00100000 + // #define UART_NB_STOP_BIT_2 0B00110000 + m_stop_bits = ((config &0x30) >> 5) +1; + // #define UART_PARITY_NONE 0B00000000 + // #define UART_PARITY_EVEN 0B00000010 + // #define UART_PARITY_ODD 0B00000011 + if ((1 == m_stop_bits) && (config &0x03)) { + m_stop_bits++; + } // Use getCycleCount() loop to get as exact timing as possible m_bit_time = ESP.getCpuFreqMHz() * 1000000 / speed; m_bit_start_time = m_bit_time + m_bit_time/3 - (ESP.getCpuFreqMHz() > 120 ? 700 : 500); // pre-compute first wait @@ -195,7 +194,7 @@ bool TasmotaSerial::hardwareSerial(void) { return m_hardserial; #endif // ESP8266 #ifdef ESP32 - return false; // On ESP32 do not mess with Serial0 buffers + return (0 == m_uart); // We prefer UART1 and UART2 and keep UART0 for debugging #endif // ESP32 } diff --git a/lib/default/TasmotaSerial-3.3.0/src/TasmotaSerial.h b/lib/default/TasmotaSerial-3.4.0/src/TasmotaSerial.h similarity index 100% rename from lib/default/TasmotaSerial-3.3.0/src/TasmotaSerial.h rename to lib/default/TasmotaSerial-3.4.0/src/TasmotaSerial.h diff --git a/lib/default/pubsubclient-2.8.12/.gitignore b/lib/default/pubsubclient-2.8.13/.gitignore similarity index 100% rename from lib/default/pubsubclient-2.8.12/.gitignore rename to lib/default/pubsubclient-2.8.13/.gitignore diff --git a/lib/default/pubsubclient-2.8.12/.travis.yml b/lib/default/pubsubclient-2.8.13/.travis.yml similarity index 100% rename from lib/default/pubsubclient-2.8.12/.travis.yml rename to lib/default/pubsubclient-2.8.13/.travis.yml diff --git a/lib/default/pubsubclient-2.8.12/CHANGES.txt b/lib/default/pubsubclient-2.8.13/CHANGES.txt similarity index 100% rename from lib/default/pubsubclient-2.8.12/CHANGES.txt rename to lib/default/pubsubclient-2.8.13/CHANGES.txt diff --git a/lib/default/pubsubclient-2.8.12/LICENSE.txt b/lib/default/pubsubclient-2.8.13/LICENSE.txt similarity index 100% rename from lib/default/pubsubclient-2.8.12/LICENSE.txt rename to lib/default/pubsubclient-2.8.13/LICENSE.txt diff --git a/lib/default/pubsubclient-2.8.12/README.md b/lib/default/pubsubclient-2.8.13/README.md similarity index 100% rename from lib/default/pubsubclient-2.8.12/README.md rename to lib/default/pubsubclient-2.8.13/README.md diff --git a/lib/default/pubsubclient-2.8.12/examples/mqtt_auth/mqtt_auth.ino b/lib/default/pubsubclient-2.8.13/examples/mqtt_auth/mqtt_auth.ino similarity index 100% rename from lib/default/pubsubclient-2.8.12/examples/mqtt_auth/mqtt_auth.ino rename to lib/default/pubsubclient-2.8.13/examples/mqtt_auth/mqtt_auth.ino diff --git a/lib/default/pubsubclient-2.8.12/examples/mqtt_basic/mqtt_basic.ino b/lib/default/pubsubclient-2.8.13/examples/mqtt_basic/mqtt_basic.ino similarity index 100% rename from lib/default/pubsubclient-2.8.12/examples/mqtt_basic/mqtt_basic.ino rename to lib/default/pubsubclient-2.8.13/examples/mqtt_basic/mqtt_basic.ino diff --git a/lib/default/pubsubclient-2.8.12/examples/mqtt_esp8266/mqtt_esp8266.ino b/lib/default/pubsubclient-2.8.13/examples/mqtt_esp8266/mqtt_esp8266.ino similarity index 100% rename from lib/default/pubsubclient-2.8.12/examples/mqtt_esp8266/mqtt_esp8266.ino rename to lib/default/pubsubclient-2.8.13/examples/mqtt_esp8266/mqtt_esp8266.ino diff --git a/lib/default/pubsubclient-2.8.12/examples/mqtt_large_message/mqtt_large_message.ino b/lib/default/pubsubclient-2.8.13/examples/mqtt_large_message/mqtt_large_message.ino similarity index 100% rename from lib/default/pubsubclient-2.8.12/examples/mqtt_large_message/mqtt_large_message.ino rename to lib/default/pubsubclient-2.8.13/examples/mqtt_large_message/mqtt_large_message.ino diff --git a/lib/default/pubsubclient-2.8.12/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino b/lib/default/pubsubclient-2.8.13/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino similarity index 100% rename from lib/default/pubsubclient-2.8.12/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino rename to lib/default/pubsubclient-2.8.13/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino diff --git a/lib/default/pubsubclient-2.8.12/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino b/lib/default/pubsubclient-2.8.13/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino similarity index 100% rename from lib/default/pubsubclient-2.8.12/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino rename to lib/default/pubsubclient-2.8.13/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino diff --git a/lib/default/pubsubclient-2.8.12/examples/mqtt_stream/mqtt_stream.ino b/lib/default/pubsubclient-2.8.13/examples/mqtt_stream/mqtt_stream.ino similarity index 100% rename from lib/default/pubsubclient-2.8.12/examples/mqtt_stream/mqtt_stream.ino rename to lib/default/pubsubclient-2.8.13/examples/mqtt_stream/mqtt_stream.ino diff --git a/lib/default/pubsubclient-2.8.12/keywords.txt b/lib/default/pubsubclient-2.8.13/keywords.txt similarity index 100% rename from lib/default/pubsubclient-2.8.12/keywords.txt rename to lib/default/pubsubclient-2.8.13/keywords.txt diff --git a/lib/default/pubsubclient-2.8.12/library.json b/lib/default/pubsubclient-2.8.13/library.json similarity index 100% rename from lib/default/pubsubclient-2.8.12/library.json rename to lib/default/pubsubclient-2.8.13/library.json diff --git a/lib/default/pubsubclient-2.8.12/library.properties b/lib/default/pubsubclient-2.8.13/library.properties similarity index 100% rename from lib/default/pubsubclient-2.8.12/library.properties rename to lib/default/pubsubclient-2.8.13/library.properties diff --git a/lib/default/pubsubclient-2.8.12/src/PubSubClient.cpp b/lib/default/pubsubclient-2.8.13/src/PubSubClient.cpp similarity index 98% rename from lib/default/pubsubclient-2.8.12/src/PubSubClient.cpp rename to lib/default/pubsubclient-2.8.13/src/PubSubClient.cpp index acd0fab9b..c51879af0 100644 --- a/lib/default/pubsubclient-2.8.12/src/PubSubClient.cpp +++ b/lib/default/pubsubclient-2.8.13/src/PubSubClient.cpp @@ -439,6 +439,17 @@ boolean PubSubClient::loop() { if (type == MQTTPUBLISH) { if (callback) { uint16_t tl = (this->buffer[llen+1]<<8)+this->buffer[llen+2]; /* topic length in bytes */ + +// Start Tasmota patch +// Observed heap corruption in some cases since v10.0.0 +// Also see https://github.com/knolleary/pubsubclient/pull/843 + if (llen+3+tl>this->bufferSize) { + _state = MQTT_DISCONNECTED; + _client->stop(); + return false; + } +// End Tasmota patch + memmove(this->buffer+llen+2,this->buffer+llen+3,tl); /* move topic inside buffer 1 byte to front */ this->buffer[llen+2+tl] = 0; /* end the topic as a 'C' string with \x00 */ char *topic = (char*) this->buffer+llen+2; diff --git a/lib/default/pubsubclient-2.8.12/src/PubSubClient.h b/lib/default/pubsubclient-2.8.13/src/PubSubClient.h similarity index 100% rename from lib/default/pubsubclient-2.8.12/src/PubSubClient.h rename to lib/default/pubsubclient-2.8.13/src/PubSubClient.h diff --git a/lib/default/pubsubclient-2.8.12/tests/.gitignore b/lib/default/pubsubclient-2.8.13/tests/.gitignore similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/.gitignore rename to lib/default/pubsubclient-2.8.13/tests/.gitignore diff --git a/lib/default/pubsubclient-2.8.12/tests/Makefile b/lib/default/pubsubclient-2.8.13/tests/Makefile similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/Makefile rename to lib/default/pubsubclient-2.8.13/tests/Makefile diff --git a/lib/default/pubsubclient-2.8.12/tests/README.md b/lib/default/pubsubclient-2.8.13/tests/README.md similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/README.md rename to lib/default/pubsubclient-2.8.13/tests/README.md diff --git a/lib/default/pubsubclient-2.8.12/tests/src/connect_spec.cpp b/lib/default/pubsubclient-2.8.13/tests/src/connect_spec.cpp similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/connect_spec.cpp rename to lib/default/pubsubclient-2.8.13/tests/src/connect_spec.cpp diff --git a/lib/default/pubsubclient-2.8.12/tests/src/keepalive_spec.cpp b/lib/default/pubsubclient-2.8.13/tests/src/keepalive_spec.cpp similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/keepalive_spec.cpp rename to lib/default/pubsubclient-2.8.13/tests/src/keepalive_spec.cpp diff --git a/lib/default/pubsubclient-2.8.12/tests/src/lib/Arduino.h b/lib/default/pubsubclient-2.8.13/tests/src/lib/Arduino.h similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/lib/Arduino.h rename to lib/default/pubsubclient-2.8.13/tests/src/lib/Arduino.h diff --git a/lib/default/pubsubclient-2.8.12/tests/src/lib/BDDTest.cpp b/lib/default/pubsubclient-2.8.13/tests/src/lib/BDDTest.cpp similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/lib/BDDTest.cpp rename to lib/default/pubsubclient-2.8.13/tests/src/lib/BDDTest.cpp diff --git a/lib/default/pubsubclient-2.8.12/tests/src/lib/BDDTest.h b/lib/default/pubsubclient-2.8.13/tests/src/lib/BDDTest.h similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/lib/BDDTest.h rename to lib/default/pubsubclient-2.8.13/tests/src/lib/BDDTest.h diff --git a/lib/default/pubsubclient-2.8.12/tests/src/lib/Buffer.cpp b/lib/default/pubsubclient-2.8.13/tests/src/lib/Buffer.cpp similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/lib/Buffer.cpp rename to lib/default/pubsubclient-2.8.13/tests/src/lib/Buffer.cpp diff --git a/lib/default/pubsubclient-2.8.12/tests/src/lib/Buffer.h b/lib/default/pubsubclient-2.8.13/tests/src/lib/Buffer.h similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/lib/Buffer.h rename to lib/default/pubsubclient-2.8.13/tests/src/lib/Buffer.h diff --git a/lib/default/pubsubclient-2.8.12/tests/src/lib/Client.h b/lib/default/pubsubclient-2.8.13/tests/src/lib/Client.h similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/lib/Client.h rename to lib/default/pubsubclient-2.8.13/tests/src/lib/Client.h diff --git a/lib/default/pubsubclient-2.8.12/tests/src/lib/IPAddress.cpp b/lib/default/pubsubclient-2.8.13/tests/src/lib/IPAddress.cpp similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/lib/IPAddress.cpp rename to lib/default/pubsubclient-2.8.13/tests/src/lib/IPAddress.cpp diff --git a/lib/default/pubsubclient-2.8.12/tests/src/lib/IPAddress.h b/lib/default/pubsubclient-2.8.13/tests/src/lib/IPAddress.h similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/lib/IPAddress.h rename to lib/default/pubsubclient-2.8.13/tests/src/lib/IPAddress.h diff --git a/lib/default/pubsubclient-2.8.12/tests/src/lib/Print.h b/lib/default/pubsubclient-2.8.13/tests/src/lib/Print.h similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/lib/Print.h rename to lib/default/pubsubclient-2.8.13/tests/src/lib/Print.h diff --git a/lib/default/pubsubclient-2.8.12/tests/src/lib/ShimClient.cpp b/lib/default/pubsubclient-2.8.13/tests/src/lib/ShimClient.cpp similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/lib/ShimClient.cpp rename to lib/default/pubsubclient-2.8.13/tests/src/lib/ShimClient.cpp diff --git a/lib/default/pubsubclient-2.8.12/tests/src/lib/ShimClient.h b/lib/default/pubsubclient-2.8.13/tests/src/lib/ShimClient.h similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/lib/ShimClient.h rename to lib/default/pubsubclient-2.8.13/tests/src/lib/ShimClient.h diff --git a/lib/default/pubsubclient-2.8.12/tests/src/lib/Stream.cpp b/lib/default/pubsubclient-2.8.13/tests/src/lib/Stream.cpp similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/lib/Stream.cpp rename to lib/default/pubsubclient-2.8.13/tests/src/lib/Stream.cpp diff --git a/lib/default/pubsubclient-2.8.12/tests/src/lib/Stream.h b/lib/default/pubsubclient-2.8.13/tests/src/lib/Stream.h similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/lib/Stream.h rename to lib/default/pubsubclient-2.8.13/tests/src/lib/Stream.h diff --git a/lib/default/pubsubclient-2.8.12/tests/src/lib/trace.h b/lib/default/pubsubclient-2.8.13/tests/src/lib/trace.h similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/lib/trace.h rename to lib/default/pubsubclient-2.8.13/tests/src/lib/trace.h diff --git a/lib/default/pubsubclient-2.8.12/tests/src/publish_spec.cpp b/lib/default/pubsubclient-2.8.13/tests/src/publish_spec.cpp similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/publish_spec.cpp rename to lib/default/pubsubclient-2.8.13/tests/src/publish_spec.cpp diff --git a/lib/default/pubsubclient-2.8.12/tests/src/receive_spec.cpp b/lib/default/pubsubclient-2.8.13/tests/src/receive_spec.cpp similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/receive_spec.cpp rename to lib/default/pubsubclient-2.8.13/tests/src/receive_spec.cpp diff --git a/lib/default/pubsubclient-2.8.12/tests/src/subscribe_spec.cpp b/lib/default/pubsubclient-2.8.13/tests/src/subscribe_spec.cpp similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/src/subscribe_spec.cpp rename to lib/default/pubsubclient-2.8.13/tests/src/subscribe_spec.cpp diff --git a/lib/default/pubsubclient-2.8.12/tests/testcases/__init__.py b/lib/default/pubsubclient-2.8.13/tests/testcases/__init__.py similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/testcases/__init__.py rename to lib/default/pubsubclient-2.8.13/tests/testcases/__init__.py diff --git a/lib/default/pubsubclient-2.8.12/tests/testcases/mqtt_basic.py b/lib/default/pubsubclient-2.8.13/tests/testcases/mqtt_basic.py similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/testcases/mqtt_basic.py rename to lib/default/pubsubclient-2.8.13/tests/testcases/mqtt_basic.py diff --git a/lib/default/pubsubclient-2.8.12/tests/testcases/mqtt_publish_in_callback.py b/lib/default/pubsubclient-2.8.13/tests/testcases/mqtt_publish_in_callback.py similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/testcases/mqtt_publish_in_callback.py rename to lib/default/pubsubclient-2.8.13/tests/testcases/mqtt_publish_in_callback.py diff --git a/lib/default/pubsubclient-2.8.12/tests/testcases/settings.py b/lib/default/pubsubclient-2.8.13/tests/testcases/settings.py similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/testcases/settings.py rename to lib/default/pubsubclient-2.8.13/tests/testcases/settings.py diff --git a/lib/default/pubsubclient-2.8.12/tests/testsuite.py b/lib/default/pubsubclient-2.8.13/tests/testsuite.py similarity index 100% rename from lib/default/pubsubclient-2.8.12/tests/testsuite.py rename to lib/default/pubsubclient-2.8.13/tests/testsuite.py diff --git a/lib/lib_audio/ESP8266Audio/.github/workflows/pr-or-master-push.yml b/lib/lib_audio/ESP8266Audio/.github/workflows/pr-or-master-push.yml index 88d6fca71..fcbd0952e 100644 --- a/lib/lib_audio/ESP8266Audio/.github/workflows/pr-or-master-push.yml +++ b/lib/lib_audio/ESP8266Audio/.github/workflows/pr-or-master-push.yml @@ -86,3 +86,27 @@ jobs: valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./wav valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./midi + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: arduino/arduino-lint-action@v1 + with: + library-manager: 'update' + +# Validate orthography + code-spell: + name: Check spelling + runs-on: ubuntu-latest + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - name: Run codespell + uses: codespell-project/actions-codespell@master + with: + skip: ./src/libmad,./src/libhelix-aac,./src/libopus + ignore_words_list: ESP8266,esp8266,esp,dout,DOUT,ser,ans,inout,numer,hist diff --git a/lib/lib_audio/ESP8266Audio/README.md b/lib/lib_audio/ESP8266Audio/README.md index f243db52a..0b3ab8d5a 100644 --- a/lib/lib_audio/ESP8266Audio/README.md +++ b/lib/lib_audio/ESP8266Audio/README.md @@ -31,7 +31,9 @@ JohannesMTC has built a similar project especially for model trains: https://git A neat MQTT-driven ESP8266 light-and-sound device (alarm? toy? who can say!) was built by @CosmicMac, available at https://github.com/CosmicMac/ESParkle -A very interesting "linear clock" with a stepper motor, NTP time keeping, and configurable recorded chimes with schematics, 3D printer plans, and source code, is now available http://home.kpn.nl/bderogee1980/projects/linear_clock/linear_clock.html +A very interesting "linear clock" with a stepper motor, NTP time keeping, and configurable recorded chimes with schematics, 3D printer plans, and source code, is now available https://janderogee.com/projects/linear_clock/linear_clock.htm + +Source and instructions for a gorgeous wooden MP3-playing clock, FM radio and a walkie-talkie using the ESP8266 and AVR microcontrollers is available https://github.com/zduka/mp3-player ## Prerequisites First, make sure you are running the 2.6.3/later or GIT head version of the Arduino libraries for ESP8266, or the latest ESP32 SDK from Espressif. @@ -100,7 +102,7 @@ AudioFileSourcePROGMEM: Reads a file from a PROGMEM array. Under UNIX you can AudioFileSourceHTTPStream: Simple implementation of a streaming HTTP reader for ShoutCast-type MP3 streaming. Not yet resilient, and at 44.1khz 128bit stutters due to CPU limitations, but it works more or less. ## AudioFileSourceBuffer - Double buffering, useful for HTTP streams -AudioFileSourceBuffer is an input source that simpy adds an additional RAM buffer of the output of any other AudioFileSource. This is particularly useful for web streaming where you need to have 1-2 packets in memory to ensure hiccup-free playback. +AudioFileSourceBuffer is an input source that simply adds an additional RAM buffer of the output of any other AudioFileSource. This is particularly useful for web streaming where you need to have 1-2 packets in memory to ensure hiccup-free playback. Create your standard input file source, create the buffer with the original source as its input, and pass this buffer object to the generator. ```cpp @@ -158,7 +160,15 @@ AudioOutputSPIFFSWAV: Writes a binary WAV format with headers to a SPIFFS files AudioOutputNull: Just dumps samples to /dev/null. Used for speed testing as it doesn't artificially limit the AudioGenerator output speed since there are no buffers to fill/drain. ## I2S DACs -I've used both the Adafruit [I2S +3W amp DAC](https://www.adafruit.com/product/3006) and a generic PCM5102 based DAC with success. The biggest problems I've seen from users involve pinouts from the ESP8266 for GPIO and hooking up all necessary pins on the DAC board. +I've used both the Adafruit [I2S +3W amp DAC](https://www.adafruit.com/product/3006) and a generic PCM5102 based DAC with success. The biggest problems I've seen from users involve pinouts from the ESP8266 for GPIO and hooking up all necessary pins on the DAC board. The essential pins are: + +I2S pin | Common label* | ESP8266 pin +--------|---------------|------------- +LRC | D4 | GPIO2 +BCLK | D8 | GPIO15 +DIN | RX | GPIO3 + +\* The "common label" column applies to common NodeMCU and D1 Mini development boards. Unfortunately some manufacturers use different mappings so the labels listed here might not apply to your particular model. ### Adafruit I2S DAC This is quite simple and only needs the GND, VIN, LRC, BCLK< and DIN pins to be wired. Be sure to use +5V on the VIN to get the loudest sound. See the [Adafruit example page](https://learn.adafruit.com/adafruit-max98357-i2s-class-d-mono-amp) for more info. diff --git a/lib/lib_audio/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino b/lib/lib_audio/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino index 3c127883b..50b0ade33 100644 --- a/lib/lib_audio/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino +++ b/lib/lib_audio/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino @@ -8,7 +8,7 @@ // Espressif Audio Development Framework at: // https://docs.espressif.com/projects/esp-adf/en/latest/design-guide/audio-samples.html // -// On ESP8266 you might need to reencode FLAC files with max '-2' compression level +// On ESP8266 you might need to re-encode FLAC files with max '-2' compression level // (i.e. 1152 maximum block size) or you will run out of memory. FLAC files will be // slightly bigger but you don't loose audio quality with reencoding (lossles codec). diff --git a/lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino b/lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino index dcfa8f983..da9f685c3 100644 --- a/lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino +++ b/lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino @@ -25,6 +25,7 @@ void setup() WiFi.mode(WIFI_OFF); Serial.begin(115200); + SPIFFS.begin(); Serial.println("Starting up...\n"); audioLogger = &Serial; diff --git a/lib/lib_audio/ESP8266Audio/examples/PlayWAVFromFunction/PlayWAVFromFunction.ino b/lib/lib_audio/ESP8266Audio/examples/PlayWAVFromFunction/PlayWAVFromFunction.ino index fe0cc896d..9af90e0dc 100644 --- a/lib/lib_audio/ESP8266Audio/examples/PlayWAVFromFunction/PlayWAVFromFunction.ino +++ b/lib/lib_audio/ESP8266Audio/examples/PlayWAVFromFunction/PlayWAVFromFunction.ino @@ -44,7 +44,7 @@ void setup() { // param : float (current time [sec] of the song) // return : float (the amplitude of sound which varies from -1.f to +1.f) // - // sound function can be registerd only one or the same number with channels + // sound function can be registered only one or the same number with channels // if the channels > 1 && the number of function == 1, // same function are used to generate the sound in every channel // diff --git a/lib/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTPToSPDIF/StreamMP3FromHTTPToSPDIF.ino b/lib/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTPToSPDIF/StreamMP3FromHTTPToSPDIF.ino new file mode 100644 index 000000000..ef5429083 --- /dev/null +++ b/lib/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTPToSPDIF/StreamMP3FromHTTPToSPDIF.ino @@ -0,0 +1,142 @@ +#include + +#ifdef ESP32 + #include +#else + #include +#endif +#include "AudioFileSourceICYStream.h" +#include "AudioFileSourceBuffer.h" +#include "AudioGeneratorMP3.h" +//#include "AudioOutputI2SNoDAC.h" +#include "AudioOutputSPDIF.h" + +// +// Stream MP3 from HTTP to SPDIF +// + +// To run, set your ESP8266 build to 160MHz, update the SSID info, and upload. + +// Note: +// If using ESP8266 NodeMCU connect LED to RX pin and GND pin + +// Enter your WiFi setup here: +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char* ssid = STASSID; +const char* password = STAPSK; + +// Examples URLs +//const char *URL="http://kvbstreams.dyndns.org:8000/wkvi-am"; + +// Italian Rock Radio +const char *URL="http://streamingv2.shoutcast.com/radiofreccia"; + +// Stream URL of Logitech Media Server, aka LMS, Version: 8.2.0 (August 2021) +// const char *URL="http://192.168.1.121:9000/stream.mp3"; + +AudioGeneratorMP3 *mp3; +AudioFileSourceICYStream *file; +AudioFileSourceBuffer *buff; + +// Output device is SPDIF +AudioOutputSPDIF *out; + + +// Called when a metadata event occurs (i.e. an ID3 tag, an ICY block, etc. +void MDCallback(void *cbData, const char *type, bool isUnicode, const char *string) +{ + const char *ptr = reinterpret_cast(cbData); + (void) isUnicode; // Punt this ball for now + // Note that the type and string may be in PROGMEM, so copy them to RAM for printf + char s1[32], s2[64]; + strncpy_P(s1, type, sizeof(s1)); + s1[sizeof(s1)-1]=0; + strncpy_P(s2, string, sizeof(s2)); + s2[sizeof(s2)-1]=0; + Serial.printf("METADATA(%s) '%s' = '%s'\n", ptr, s1, s2); + Serial.flush(); +} + +// Called when there's a warning or error (like a buffer underflow or decode hiccup) +void StatusCallback(void *cbData, int code, const char *string) +{ + const char *ptr = reinterpret_cast(cbData); + // Note that the string may be in PROGMEM, so copy it to RAM for printf + char s1[64]; + strncpy_P(s1, string, sizeof(s1)); + s1[sizeof(s1)-1]=0; + Serial.printf("STATUS(%s) '%d' = '%s'\n", ptr, code, s1); + Serial.flush(); +} + + +void setup() +{ + Serial.begin(115200); + delay(1000); + Serial.println("Connecting to WiFi"); + + WiFi.disconnect(); + WiFi.softAPdisconnect(true); + WiFi.mode(WIFI_STA); + + WiFi.begin(ssid, password); + + // Try forever + while (WiFi.status() != WL_CONNECTED) { + Serial.println("...Connecting to WiFi"); + delay(1000); + } + Serial.println("Connected"); + + audioLogger = &Serial; + file = new AudioFileSourceICYStream(URL); + + // Commented out for performance issues with high rate MP3 stream + //file->RegisterMetadataCB(MDCallback, (void*)"ICY"); + + buff = new AudioFileSourceBuffer(file, 4096); // Doubled form default 2048 + + // Commented out for performance issues with high rate MP3 stream + //buff->RegisterStatusCB(StatusCallback, (void*)"buffer"); + + // Set SPDIF output + out = new AudioOutputSPDIF(); + mp3 = new AudioGeneratorMP3(); + + // Commented out for performance issues with high rate MP3 stream + //mp3->RegisterStatusCB(StatusCallback, (void*)"mp3"); + + mp3->begin(buff, out); +} + + +void loop() +{ + // Commented out + //static int lastms = 0; + + if (mp3->isRunning()) { + /* Commented out + if (millis()-lastms > 1000) { + lastms = millis(); + Serial.printf("Running for %d ms...\n", lastms); + Serial.flush(); + } + */ + if (!mp3->loop()) { + mp3->stop(); + } + } else { + Serial.printf("MP3 done\n"); + + // Restart ESP when streaming is done or errored + delay(10000); + + ESP.restart(); + } +} diff --git a/lib/lib_audio/ESP8266Audio/library.json b/lib/lib_audio/ESP8266Audio/library.json index 139291880..ddbb6d634 100644 --- a/lib/lib_audio/ESP8266Audio/library.json +++ b/lib/lib_audio/ESP8266Audio/library.json @@ -14,7 +14,7 @@ "type": "git", "url": "https://github.com/earlephilhower/ESP8266Audio" }, - "version": "1.9.2", + "version": "1.9.5", "homepage": "https://github.com/earlephilhower/ESP8266Audio", "frameworks": "Arduino", "examples": [ diff --git a/lib/lib_audio/ESP8266Audio/library.properties b/lib/lib_audio/ESP8266Audio/library.properties index 111915c1c..85a99c0e3 100644 --- a/lib/lib_audio/ESP8266Audio/library.properties +++ b/lib/lib_audio/ESP8266Audio/library.properties @@ -1,5 +1,5 @@ name=ESP8266Audio -version=1.9.2 +version=1.9.5 author=Earle F. Philhower, III maintainer=Earle F. Philhower, III sentence=Audio file and I2S sound playing routines for ESP8266, ESP32, and Raspberry Pi Pico RP2040 diff --git a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.cpp index 9e86eff21..885defa4e 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.cpp @@ -1,6 +1,6 @@ /* AudioFileSourceFunction - Audio ouptut generator which can generate WAV file data from function + Audio output generator which can generate WAV file data from function Copyright (C) 2021 Hideaki Tai diff --git a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.h index 6c41229ae..94b88d6fb 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.h +++ b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.h @@ -1,6 +1,6 @@ /* AudioFileSourceFunction - Audio ouptut generator which can generate WAV file data from function + Audio output generator which can generate WAV file data from function Copyright (C) 2021 Hideaki Tai diff --git a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.cpp index 63c84f328..25e641705 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.cpp @@ -20,7 +20,9 @@ #if defined(ESP32) || defined(ESP8266) -#define _GNU_SOURCE +#ifndef _GNU_SOURCE + #define _GNU_SOURCE +#endif #include "AudioFileSourceICYStream.h" #include @@ -47,6 +49,7 @@ bool AudioFileSourceICYStream::open(const char *url) http.addHeader("Icy-MetaData", "1"); http.collectHeaders( hdr, 4 ); http.setReuse(true); + http.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS); int code = http.GET(); if (code != HTTP_CODE_OK) { http.end(); diff --git a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceLittleFS.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceLittleFS.h index 27d94bb8b..b57b89fa3 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceLittleFS.h +++ b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceLittleFS.h @@ -21,8 +21,6 @@ #ifndef _AUDIOFILESOURCESPIFFS_H #define _AUDIOFILESOURCESPIFFS_H -#ifndef ESP32 // No LittleFS there, yet - #include #include @@ -39,5 +37,3 @@ class AudioFileSourceLittleFS : public AudioFileSourceFS #endif -#endif - diff --git a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp index 2c9eb3b96..475afa4d0 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp @@ -105,7 +105,7 @@ uint32_t AudioFileSourceSPIRAMBuffer::read(void *data, uint32_t len) } // Read up to the entire buffer from RAM - uint32_t toReadFromBuffer = std::min(len, writePtr - readPtr); + uint32_t toReadFromBuffer = std::min(len, (uint32_t)(writePtr - readPtr)); uint8_t *ptr = reinterpret_cast(data); if (toReadFromBuffer > 0) { #ifdef FAKERAM diff --git a/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.cpp b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.cpp index e3be2b2d0..5f1c5f3a3 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.cpp @@ -1,6 +1,6 @@ /* AudioGeneratorMIDI - Audio output generator that plays MIDI files using a SF2 SoundFont + Audio output generator that plays MIDI files using an SF2 SoundFont Copyright (C) 2017 Earle F. Philhower, III @@ -172,7 +172,7 @@ unsigned int AudioGeneratorMIDI::buffer_int32 (int offset) { unsigned long AudioGeneratorMIDI::get_varlen (int *ptr) { /* Get a 1-4 byte variable-length value and adjust the pointer past it. - These are a succession of 7-bit values with a MSB bit of zero marking the end */ + These are a succession of 7-bit values with an MSB bit of zero marking the end */ unsigned long val; int i, byte; @@ -331,7 +331,7 @@ note_off: } -// Open file, parse headers, get ready tio process MIDI +// Open file, parse headers, get ready to process MIDI void AudioGeneratorMIDI::PrepareMIDI(AudioFileSource *src) { MakeStreamFromAFS(src, &afsMIDI); @@ -364,7 +364,7 @@ void AudioGeneratorMIDI::PrepareMIDI(AudioFileSource *src) int AudioGeneratorMIDI::PlayMIDI() { /* Continue processing all tracks, in an order based on the simulated time. - This is not unlike multiway merging used for tape sorting algoritms in the 50's! */ + This is not unlike multiway merging used for tape sorting algorithms in the 50's! */ do { /* while there are still track notes to process */ static struct track_status *trk; diff --git a/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.cpp b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.cpp index f42154f85..b47b28396 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.cpp @@ -124,7 +124,7 @@ bool AudioGeneratorMOD::begin(AudioFileSource *source, AudioOutput *out) UpdateAmiga(); for (int i = 0; i < CHANNELS; i++) { - FatBuffer.channels[i] = reinterpret_cast(malloc(fatBufferSize)); + FatBuffer.channels[i] = reinterpret_cast(calloc(fatBufferSize, 1)); if (!FatBuffer.channels[i]) { stop(); return false; @@ -565,7 +565,7 @@ bool AudioGeneratorMOD::ProcessRow() Mixer.channelFrequency[channel] = Player.amiga / Player.lastAmigaPeriod[channel]; if (note != NONOTE) - Mixer.channelSampleOffset[channel] = sampleOffset << DIVIDER; + Mixer.channelSampleOffset[channel] = sampleOffset << FIXED_DIVIDER; if (sampleNumber) Mixer.channelSampleNumber[channel] = Player.lastSampleNumber[channel]; @@ -757,12 +757,12 @@ void AudioGeneratorMOD::GetSample(int16_t sample[2]) if (!Mixer.channelVolume[channel]) continue; samplePointer = Mixer.sampleBegin[Mixer.channelSampleNumber[channel]] + - (Mixer.channelSampleOffset[channel] >> DIVIDER); + (Mixer.channelSampleOffset[channel] >> FIXED_DIVIDER); if (Mixer.sampleLoopLength[Mixer.channelSampleNumber[channel]]) { if (samplePointer >= Mixer.sampleLoopEnd[Mixer.channelSampleNumber[channel]]) { - Mixer.channelSampleOffset[channel] -= Mixer.sampleLoopLength[Mixer.channelSampleNumber[channel]] << DIVIDER; + Mixer.channelSampleOffset[channel] -= Mixer.sampleLoopLength[Mixer.channelSampleNumber[channel]] << FIXED_DIVIDER; samplePointer -= Mixer.sampleLoopLength[Mixer.channelSampleNumber[channel]]; } @@ -801,7 +801,7 @@ void AudioGeneratorMOD::GetSample(int16_t sample[2]) out = current; // Integer linear interpolation - out += (next - current) * (Mixer.channelSampleOffset[channel] & ((1 << DIVIDER) - 1)) >> DIVIDER; + out += (next - current) * (Mixer.channelSampleOffset[channel] & ((1 << FIXED_DIVIDER) - 1)) >> FIXED_DIVIDER; // Upscale to BITDEPTH out <<= BITDEPTH - 8; diff --git a/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.h b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.h index 87fac18e9..060037750 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.h +++ b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.h @@ -56,14 +56,14 @@ class AudioGeneratorMOD : public AudioGenerator enum {BITDEPTH = 15}; int sampleRate; int fatBufferSize; //(6*1024) // File system buffers per-CHANNEL (i.e. total mem required is 4 * FATBUFFERSIZE) - enum {DIVIDER = 10}; // Fixed-point mantissa used for integer arithmetic + enum {FIXED_DIVIDER = 10}; // Fixed-point mantissa used for integer arithmetic int stereoSeparation; //STEREOSEPARATION = 32; // 0 (max) to 64 (mono) bool usePAL; // Hz = 7093789 / (amigaPeriod * 2) for PAL // Hz = 7159091 / (amigaPeriod * 2) for NTSC int AMIGA; - void UpdateAmiga() { AMIGA = ((usePAL?7159091:7093789) / 2 / sampleRate << DIVIDER); } + void UpdateAmiga() { AMIGA = ((usePAL?7159091:7093789) / 2 / sampleRate << FIXED_DIVIDER); } enum {ROWS = 64, SAMPLES = 31, CHANNELS = 4, NONOTE = 0xFFFF, NONOTE8 = 0xff }; diff --git a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp index 5e524894d..0eb3c0da7 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp @@ -1,7 +1,7 @@ /* AudioOutputI2S Base class for I2S interface port - + Copyright (C) 2017 Earle F. Philhower, III This program is free software: you can redistribute it and/or modify @@ -21,12 +21,10 @@ #include #ifdef ESP32 #include "driver/i2s.h" -#elif defined(ARDUINO_ARCH_RP2040) || defined(ESP8266) - #ifdef ARDUINO_ESP8266_MAJOR //this define was added in ESP8266 Arduino Core version v3.0.1 - #include "core_esp8266_i2s.h" //for Arduino core >= 3.0.1 - #else - #include "i2s.h" //for Arduino core <= 3.0.0 - #endif +#elif defined(ARDUINO_ARCH_RP2040) || ARDUINO_ESP8266_MAJOR >= 3 + #include +#elif ARDUINO_ESP8266_MAJOR < 3 + #include #endif #include "AudioOutputI2S.h" @@ -44,6 +42,7 @@ AudioOutputI2S::AudioOutputI2S(int port, int output_mode, int dma_buf_count, int //set defaults mono = false; + lsb_justified = false; bps = 16; channels = 2; hertz = 44100; @@ -150,6 +149,12 @@ bool AudioOutputI2S::SetOutputModeMono(bool mono) return true; } +bool AudioOutputI2S::SetLsbJustified(bool lsbJustified) +{ + this->lsb_justified = lsbJustified; + return true; +} + bool AudioOutputI2S::begin(bool txDAC) { #ifdef ESP32 @@ -170,17 +175,41 @@ bool AudioOutputI2S::begin(bool txDAC) i2s_mode_t mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX); if (output_mode == INTERNAL_DAC) { +#if CONFIG_IDF_TARGET_ESP32 mode = (i2s_mode_t)(mode | I2S_MODE_DAC_BUILT_IN); +#else + return false; +#endif } else if (output_mode == INTERNAL_PDM) { +#if CONFIG_IDF_TARGET_ESP32 mode = (i2s_mode_t)(mode | I2S_MODE_PDM); +#else + return false; +#endif } - i2s_comm_format_t comm_fmt = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB); + i2s_comm_format_t comm_fmt; if (output_mode == INTERNAL_DAC) { - comm_fmt = (i2s_comm_format_t)I2S_COMM_FORMAT_I2S_MSB; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) + comm_fmt = (i2s_comm_format_t) I2S_COMM_FORMAT_STAND_MSB; +#else + comm_fmt = (i2s_comm_format_t) I2S_COMM_FORMAT_I2S_MSB; +#endif + } + else if (lsb_justified) + { + comm_fmt = (i2s_comm_format_t) (I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_LSB); + } + else + { +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) + comm_fmt = (i2s_comm_format_t) (I2S_COMM_FORMAT_STAND_I2S); +#else + comm_fmt = (i2s_comm_format_t) (I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB); +#endif } i2s_config_t i2s_config_dac = { @@ -191,7 +220,7 @@ bool AudioOutputI2S::begin(bool txDAC) .communication_format = comm_fmt, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // lowest interrupt priority .dma_buf_count = dma_buf_count, - .dma_buf_len = 64, + .dma_buf_len = 128, .use_apll = use_apll // Use audio PLL }; audioLogger->printf("+%d %p\n", portNo, &i2s_config_dac); @@ -201,8 +230,12 @@ bool AudioOutputI2S::begin(bool txDAC) } if (output_mode == INTERNAL_DAC || output_mode == INTERNAL_PDM) { +#if CONFIG_IDF_TARGET_ESP32 i2s_set_pin((i2s_port_t)portNo, NULL); i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); +#else + return false; +#endif } else { @@ -273,11 +306,12 @@ bool AudioOutputI2S::ConsumeSample(int16_t sample[2]) { s32 = ((Amplify(ms[RIGHTCHANNEL])) << 16) | (Amplify(ms[LEFTCHANNEL]) & 0xffff); } -// Deprecated. Use i2s_write +//"i2s_write_bytes" has been removed in the ESP32 Arduino 2.0.0, use "i2s_write" instead. // return i2s_write_bytes((i2s_port_t)portNo, (const char *)&s32, sizeof(uint32_t), 0); - size_t bytes_written; - i2s_write((i2s_port_t)portNo, (const char*)&s32, sizeof(uint32_t), &bytes_written, 0); - return bytes_written; + + size_t i2s_bytes_written; + i2s_write((i2s_port_t)portNo, (const char*)&s32, sizeof(uint32_t), &i2s_bytes_written, 0); + return i2s_bytes_written; #elif defined(ESP8266) uint32_t s32 = ((Amplify(ms[RIGHTCHANNEL])) << 16) | (Amplify(ms[LEFTCHANNEL]) & 0xffff); return i2s_write_sample_nb(s32); // If we can't store it, return false. OTW true @@ -290,7 +324,7 @@ void AudioOutputI2S::flush() { #ifdef ESP32 // makes sure that all stored DMA samples are consumed / played - int buffersize = 64 * this->dma_buf_count; + int buffersize = 128 * this->dma_buf_count; int16_t samples[2] = {0x0, 0x0}; for (int i = 0; i < buffersize; i++) { diff --git a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.h b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.h index 90370dc27..b3f621d28 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.h +++ b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.h @@ -44,6 +44,7 @@ class AudioOutputI2S : public AudioOutput bool begin(bool txDAC); bool SetOutputModeMono(bool mono); // Force mono output no matter the input + bool SetLsbJustified(bool lsbJustified); // Allow supporting non-I2S chips, e.g. PT8211 protected: bool SetPinout(); @@ -51,6 +52,7 @@ class AudioOutputI2S : public AudioOutput uint8_t portNo; int output_mode; bool mono; + int lsb_justified; bool i2sOn; int dma_buf_count; int use_apll; diff --git a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp index 116d9ac74..976d73c77 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp @@ -1,7 +1,7 @@ /* AudioOutputI2SNoDAC Audio player using SW delta-sigma to generate "analog" on I2S data - + Copyright (C) 2017 Earle F. Philhower, III This program is free software: you can redistribute it and/or modify @@ -21,12 +21,10 @@ #include #ifdef ESP32 #include "driver/i2s.h" -#elif defined(ARDUINO_ARCH_RP2040) || defined(ESP8266) - #ifdef ARDUINO_ESP8266_MAJOR //this define was added in ESP8266 Arduino Core version v3.0.1 - #include "core_esp8266_i2s.h" //for Arduino core >= 3.0.1 - #else - #include "i2s.h" //for Arduino core <= 3.0.0 - #endif +#elif defined(ARDUINO_ARCH_RP2040) || ARDUINO_ESP8266_MAJOR >= 3 + #include +#elif ARDUINO_ESP8266_MAJOR < 3 + #include #endif #include "AudioOutputI2SNoDAC.h" @@ -70,7 +68,7 @@ void AudioOutputI2SNoDAC::DeltaSigma(int16_t sample[2], uint32_t dsBuff[8]) for (int j = 0; j < oversample32; j++) { uint32_t bits = 0; // The bits we convert the sample into, MSB to go on the wire first - + for (int i = 32; i > 0; i--) { bits = bits << 1; if (cumErr < 0) { @@ -99,12 +97,14 @@ bool AudioOutputI2SNoDAC::ConsumeSample(int16_t sample[2]) // Either send complete pulse stream or nothing #ifdef ESP32 -// Deprecated. Use i2s_write +//"i2s_write_bytes" has been removed in the ESP32 Arduino 2.0.0, use "i2s_write" instead. // if (!i2s_write_bytes((i2s_port_t)portNo, (const char *)dsBuff, sizeof(uint32_t) * (oversample/32), 0)) - size_t bytes_written; - i2s_write((i2s_port_t)portNo, (const char *)dsBuff, sizeof(uint32_t) * (oversample/32), &bytes_written, 0); - if (!bytes_written) + + size_t i2s_bytes_written; + i2s_write((i2s_port_t)portNo, (const char *)dsBuff, sizeof(uint32_t) * (oversample/32), &i2s_bytes_written, 0); + if (!i2s_bytes_written){ return false; + } #elif defined(ESP8266) if (!i2s_write_sample_nb(dsBuff[0])) return false; // No room at the inn // At this point we've sent in first of possibly 8 32-bits, need to send diff --git a/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.cpp index 53483d4ac..6e1cf1978 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.cpp @@ -3,7 +3,7 @@ S/PDIF output via I2S - Needs transciever from CMOS level to either optical or coaxial interface + Needs transceiver from CMOS level to either optical or coaxial interface See: https://www.epanorama.net/documents/audio/spdif.html Original idea and sources: @@ -94,7 +94,11 @@ AudioOutputSPDIF::AudioOutputSPDIF(int dout_pin, int port, int dma_buf_count) .sample_rate = 88200, // 2 x sampling_rate .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, // 32bit words .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // Right than left - .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB), +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) + .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_I2S), +#else + .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB), +#endif .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // lowest interrupt priority .dma_buf_count = dma_buf_count, .dma_buf_len = DMA_BUF_SIZE_DEFAULT, // bigger buffers, reduces interrupts @@ -265,7 +269,7 @@ bool AudioOutputSPDIF::ConsumeSample(int16_t sample[2]) #if defined(ESP32) // Assume DMA buffers are multiples of 16 bytes. Either we write all bytes or none. - uint32_t bytes_written; + size_t bytes_written; esp_err_t ret = i2s_write((i2s_port_t)portNo, (const char*)&buf, 8 * channels, &bytes_written, 0); // If we didn't write all bytes, return false early and do not increment frame_num if ((ret != ESP_OK) || (bytes_written != (8 * channels))) return false; diff --git a/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.h b/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.h index 5da160b3d..7cb194dbc 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.h +++ b/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.h @@ -3,7 +3,7 @@ S/PDIF output via I2S - Needs transciever from CMOS level to either optical or coaxial interface + Needs transceiver from CMOS level to either optical or coaxial interface See: https://www.epanorama.net/documents/audio/spdif.html Original idea and sources: diff --git a/lib/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.cpp index 33bbd34f8..f9032bb12 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.cpp @@ -54,6 +54,11 @@ bool AudioOutputSTDIO::begin() bool AudioOutputSTDIO::ConsumeSample(int16_t sample[2]) { + static int avail = 100; + if (!(--avail)) { + avail = 100; + return false; + } for (int i=0; i. */ -#ifdef ESP32 +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #include "AudioOutputULP.h" #include diff --git a/lib/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp b/lib/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp index 3d08efaf0..c2d2280c0 100644 --- a/lib/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp +++ b/lib/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp @@ -3,7 +3,7 @@ ESP8266Audio I2S Minimal driver Most of this code is taken and reworked from ESP8266 Arduino core, - which itsef is reworked from Espessif's I2S examples. + which itself is reworked from Espessif's I2S examples. Original code is licensed under LGPL 2.1 or above Reasons for rewrite: @@ -196,7 +196,7 @@ void SinglePinI2SDriver::setDividers(uint8_t div1, uint8_t div2) // Ensure dividers fit in bit fields div1 &= I2SBDM; div2 &= I2SCDM; - // trans master(active low), recv master(active_low), !bits mod(==16 bits/chanel), clear clock dividers + // trans master(active low), recv master(active_low), !bits mod(==16 bits/channel), clear clock dividers I2SC &= ~(I2STSM | I2SRSM | (I2SBMM << I2SBM) | (I2SBDM << I2SBD) | (I2SCDM << I2SCD)); // I2SRF = Send/recv right channel first // I2SMR = MSB recv/xmit first @@ -249,7 +249,7 @@ void SinglePinI2SDriver::startI2S() I2SFC |= I2SDE; // Enable DMA // I2STXCMM, I2SRXCMM=0 => Dual channel mode, RX/TX CHAN_MOD=0 I2SCC &= ~((I2STXCMM << I2STXCM) | (I2SRXCMM << I2SRXCM)); - // Set dividers to something resonable + // Set dividers to something reasonable currentRate = 0; setRate(44100); // Start I2S peripheral @@ -280,4 +280,4 @@ int SinglePinI2SDriver::getUnderflowCount() // Global instance SinglePinI2SDriver I2SDriver; -#endif // defined(ESP8266) \ No newline at end of file +#endif // defined(ESP8266) diff --git a/lib/lib_audio/ESP8266Audio/src/libflac/config.h b/lib/lib_audio/ESP8266Audio/src/libflac/config.h index cf6c07dfe..b0aebe44d 100644 --- a/lib/lib_audio/ESP8266Audio/src/libflac/config.h +++ b/lib/lib_audio/ESP8266Audio/src/libflac/config.h @@ -3,7 +3,9 @@ #ifdef DEBUG #undef NDEBUG #else - #define NDEBUG + #ifndef NDEBUG + #define NDEBUG + #endif #endif /* config.h. Generated from config.h.in by configure. */ diff --git a/lib/lib_audio/ESP8266Audio/src/libflac/stream_decoder.c b/lib/lib_audio/ESP8266Audio/src/libflac/stream_decoder.c index ec172fe8d..20ae399f5 100644 --- a/lib/lib_audio/ESP8266Audio/src/libflac/stream_decoder.c +++ b/lib/lib_audio/ESP8266Audio/src/libflac/stream_decoder.c @@ -2199,14 +2199,14 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder) * Three kinds of things can go wrong when reading the frame header: * 1) We may have sync'ed incorrectly and not landed on a frame header. * If we don't find a sync code, it can end up looking like we read - * a valid but unparseable header, until getting to the frame header + * a valid but unparsable header, until getting to the frame header * CRC. Even then we could get a false positive on the CRC. - * 2) We may have sync'ed correctly but on an unparseable frame (from a + * 2) We may have sync'ed correctly but on an unparsable frame (from a * future encoder). - * 3) We may be on a damaged frame which appears valid but unparseable. + * 3) We may be on a damaged frame which appears valid but unparsable. * * For all these reasons, we try and read a complete frame header as - * long as it seems valid, even if unparseable, up until the frame + * long as it seems valid, even if unparsable, up until the frame * header CRC. */ @@ -2839,7 +2839,7 @@ FLAC__bool read_callback_(FLAC__byte buffer[], size_t *bytes, void *client_data) * FLAC__STREAM_DECODER_UNPARSEABLE_STREAM and increment its * unparseable_frame_count. But there is a remote possibility * that it is properly synced at such a "future-codec frame", - * so to make sure, we wait to see many "unparseable" errors in + * so to make sure, we wait to see many "unparsable" errors in * a row before bailing out. */ if(decoder->private_->is_seeking && decoder->private_->unparseable_frame_count > 20) { @@ -3146,7 +3146,7 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s return false; } /* Now we need to get a frame. First we need to reset our - * unparseable_frame_count; if we get too many unparseable + * unparseable_frame_count; if we get too many unparsable * frames in a row, the read callback will return * FLAC__STREAM_DECODER_READ_STATUS_ABORT, causing * FLAC__stream_decoder_process_single() to return false. diff --git a/lib/lib_audio/ESP8266Audio/src/libhelix-aac/assembly.h b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/assembly.h index 595a8fc97..0c17f0c44 100644 --- a/lib/lib_audio/ESP8266Audio/src/libhelix-aac/assembly.h +++ b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/assembly.h @@ -558,7 +558,7 @@ static __inline int CLZ(int x) typedef union _U64 { Word64 w64; struct { -#ifdef __XTENSA__ +#if defined(__XTENSA__) || defined (__riscv) unsigned int lo32; signed int hi32; #else diff --git a/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/RPSL.txt b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/RPSL.txt index d040a4520..94b44586d 100644 --- a/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/RPSL.txt +++ b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/RPSL.txt @@ -201,7 +201,7 @@ and 3, above. 4.2 Compatible Source Licenses. Software modules that have been independently developed without any use of Covered Code and which contain no portion of the Covered Code, Modifications or other Derivative Works, but are used or combined -in any way wtih the Covered Code or any Derivative Work to form a larger +in any way with the Covered Code or any Derivative Work to form a larger Derivative Work, are exempt from the conditions described in Section 4.1 but only to the extent that: the software module, including any software that is linked to, integrated with, or part of the same applications as, the software diff --git a/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/assembly.h b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/assembly.h index b9e46c529..5ad0f30b8 100644 --- a/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/assembly.h +++ b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/assembly.h @@ -40,7 +40,7 @@ * * assembly.h - assembly language functions and prototypes for supported platforms * - * - inline rountines with access to 64-bit multiply results + * - inline routines with access to 64-bit multiply results * - x86 (_WIN32) and ARM (ARM_ADS, _WIN32_WCE) versions included * - some inline functions are mix of asm and C for speed * - some functions are in native asm files, so only the prototype is given here @@ -241,7 +241,7 @@ static __inline int MULSHIFT32(int x, int y) static __inline int FASTABS(int x) { - int t=0; /*Really is not necessary to initialiaze only to avoid warning*/ + int t=0; /*Really is not necessary to initialize only to avoid warning*/ __asm { eor t, x, x, asr #31 diff --git a/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/scalfact.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/scalfact.c index 4937e4530..d274b3615 100644 --- a/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/scalfact.c +++ b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/scalfact.c @@ -74,7 +74,7 @@ static const char SFLenTab[16][2] = { * Return: none * * Notes: set order of short blocks to s[band][window] instead of s[window][band] - * so that we index through consectutive memory locations when unpacking + * so that we index through consecutive memory locations when unpacking * (make sure dequantizer follows same convention) * Illegal Intensity Position = 7 (always) for MPEG1 scale factors **************************************************************************************/ diff --git a/lib/lib_audio/ESP8266Audio/src/libogg/README.md b/lib/lib_audio/ESP8266Audio/src/libogg/README.md index 63545e288..c3be01460 100644 --- a/lib/lib_audio/ESP8266Audio/src/libogg/README.md +++ b/lib/lib_audio/ESP8266Audio/src/libogg/README.md @@ -7,7 +7,7 @@ Ogg project codecs use the Ogg bitstream format to arrange the raw, compressed bitstream into a more robust, useful form. For example, the Ogg bitstream makes seeking, time stamping and error recovery -possible, as well as mixing several sepearate, concurrent media +possible, as well as mixing several separate, concurrent media streams into a single physical bitstream. ## What's here ## @@ -18,7 +18,7 @@ use with Ogg bitstreams. Directory: -- `src` The source for libogg, a BSD-license inplementation of the public domain Ogg bitstream format +- `src` The source for libogg, a BSD-license implementation of the public domain Ogg bitstream format - `include` Library API headers diff --git a/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/README.ESP8266 b/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/README.ESP8266 index e88104dfc..1009f36f6 100644 --- a/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/README.ESP8266 +++ b/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/README.ESP8266 @@ -28,7 +28,7 @@ Even with the caching, it was found that SPIFFS, while having great functionality, was horrbly slow. So I wrote a new "faster" ROM filesystem called, surprisingly, FastROMFilesystem. https://github.com/earlephilhower/ESP8266FastROMFS -If you are getting choppy playback, try this new filesytem or using a SD +If you are getting choppy playback, try this new filesystem or using a SD card (not tested by myself, but it'd be hard top be slower than SPIFFS). Simply going from SPIFFS to FastROMFilesystem took my testing of FURELISE.MID and 1MGM.SF2 from 0.5x realtime to 2.5x (i.e. from unusable diff --git a/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/tsf.h b/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/tsf.h index e786d1662..45d7b97a5 100644 --- a/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/tsf.h +++ b/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/tsf.h @@ -104,7 +104,7 @@ TSFDEF tsf* tsf_load(struct tsf_stream* stream); // Free the memory related to this tsf instance TSFDEF void tsf_close(tsf* f); -// Stop all playing notes immediatly and reset all channel parameters +// Stop all playing notes immediately and reset all channel parameters TSFDEF void tsf_reset(tsf* f); // Returns the preset index from a bank and preset number, or -1 if it does not exist in the loaded SoundFont @@ -202,7 +202,7 @@ TSFDEF void tsf_channel_set_tuning(tsf* f, int channel, float tuning); TSFDEF void tsf_channel_note_on(tsf* f, int channel, int key, float vel); TSFDEF void tsf_channel_note_off(tsf* f, int channel, int key); TSFDEF void tsf_channel_note_off_all(tsf* f, int channel); //end with sustain and release -TSFDEF void tsf_channel_sounds_off_all(tsf* f, int channel); //end immediatly +TSFDEF void tsf_channel_sounds_off_all(tsf* f, int channel); //end immediately // Apply a MIDI control change to the channel (not all controllers are supported!) TSFDEF void tsf_channel_midi_control(tsf* f, int channel, int controller, int control_value); diff --git a/lib/lib_audio/ESP8266Audio/src/opusfile/opusfile.h b/lib/lib_audio/ESP8266Audio/src/opusfile/opusfile.h index 7a6457240..11cc07a16 100644 --- a/lib/lib_audio/ESP8266Audio/src/opusfile/opusfile.h +++ b/lib/lib_audio/ESP8266Audio/src/opusfile/opusfile.h @@ -729,7 +729,7 @@ struct OpusServerInfo{ /**The software used by the origin server (Server). This is NULL if there was no Server header.*/ char *server; - /**The media type of the entity sent to the recepient (Content-Type). + /**The media type of the entity sent to the recipient (Content-Type). This is NULL if there was no Content-Type header.*/ char *content_type; @@ -1436,7 +1436,7 @@ void op_free(OggOpusFile *_of); Some of these functions may be used successfully on the partially open streams returned by op_test_callbacks() or one of the associated convenience functions. - Their documention will indicate so explicitly.*/ + Their documentation will indicate so explicitly.*/ /*@{*/ /**Returns whether or not the stream being read is seekable. diff --git a/lib/lib_audio/ESP8266Audio/tests/common.sh b/lib/lib_audio/ESP8266Audio/tests/common.sh index cabad512f..25c05cd66 100755 --- a/lib/lib_audio/ESP8266Audio/tests/common.sh +++ b/lib/lib_audio/ESP8266Audio/tests/common.sh @@ -58,7 +58,7 @@ function build_sketches() local sketchdirname=$(basename $sketchdir) local sketchname=$(basename $sketch) if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then - echo "Skipping $sketch, beacause it is not the main sketch file"; + echo "Skipping $sketch, because it is not the main sketch file"; continue fi; if [[ -f "$sketchdir/.test.skip" ]]; then diff --git a/lib/lib_audio/ESP8266Audio/tests/host/Makefile b/lib/lib_audio/ESP8266Audio/tests/host/Makefile index 25156dbcd..15eee60e6 100644 --- a/lib/lib_audio/ESP8266Audio/tests/host/Makefile +++ b/lib/lib_audio/ESP8266Audio/tests/host/Makefile @@ -83,7 +83,7 @@ CPPOPTS=-g -Wunused-parameter -Wall -std=c++11 -m32 -Wstack-usage=300 -include A .phony: all -all: mp3 aac wav midi opus flac +all: mp3 aac wav midi opus flac mod mp3: FORCE rm -f *.o @@ -106,6 +106,12 @@ flac: FORCE rm -f *.o echo valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all ./flac +mod: FORCE + rm -f *.o + g++ $(CPPOPTS) -o mod mod.cpp Serial.cpp ../../src/AudioFileSourcePROGMEM.cpp ../../src/AudioOutputSTDIO.cpp ../../src/AudioGeneratorMOD.cpp ../../src/AudioLogger.cpp -I ../../src/ -I. + rm -f *.o + echo valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all ./mod + wav: FORCE rm -f *.o g++ $(CPPOPTS) -o wav wav.cpp Serial.cpp ../../src/AudioFileSourceSTDIO.cpp ../../src/AudioOutputSTDIO.cpp ../../src/AudioGeneratorWAV.cpp ../../src/AudioLogger.cpp -I ../../src/ -I. @@ -128,6 +134,6 @@ opus: FORCE echo valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all ./opus clean: - rm -f mp3 aac wav midi opus flac *.o + rm -f mp3 aac wav midi opus flac mod *.o FORCE: diff --git a/lib/lib_audio/ESP8266Audio/tests/host/mod.cpp b/lib/lib_audio/ESP8266Audio/tests/host/mod.cpp new file mode 100644 index 000000000..18da2ce35 --- /dev/null +++ b/lib/lib_audio/ESP8266Audio/tests/host/mod.cpp @@ -0,0 +1,26 @@ +#include +#include "AudioFileSourcePROGMEM.h" +#include "AudioOutputSTDIO.h" +#include "AudioGeneratorMOD.h" + +#include "../../examples/PlayMODFromPROGMEMToDAC/enigma.h" + +int main(int argc, char **argv) +{ + (void) argc; + (void) argv; + + AudioFileSourcePROGMEM *file = new AudioFileSourcePROGMEM(enigma_mod, sizeof(enigma_mod)); + AudioOutputSTDIO *out = new AudioOutputSTDIO(); + out->SetFilename("mod.wav"); + AudioGeneratorMOD *mod = new AudioGeneratorMOD(); + + mod->begin(file, out); + // The MOD plays forever, so only run for ~30 seconds worth + for (int i=0; i<10000; i++) mod->loop(); + mod->stop(); + + delete out; + delete mod; + delete file; +} diff --git a/lib/lib_audio/ESP8266AudioAttention.md b/lib/lib_audio/ESP8266AudioAttention.md deleted file mode 100644 index 7077d8211..000000000 --- a/lib/lib_audio/ESP8266AudioAttention.md +++ /dev/null @@ -1,82 +0,0 @@ -The current library needs two fixes solving the deprecated ``i2s_write_bytes`` function. - -In file AudioOutputI2S.cpp: - -bool AudioOutputI2S::ConsumeSample(int16_t sample[2]) -{ - - //return if we haven't called ::begin yet - if (!i2sOn) - return false; - - int16_t ms[2]; - - ms[0] = sample[0]; - ms[1] = sample[1]; - MakeSampleStereo16( ms ); - - if (this->mono) { - // Average the two samples and overwrite - int32_t ttl = ms[LEFTCHANNEL] + ms[RIGHTCHANNEL]; - ms[LEFTCHANNEL] = ms[RIGHTCHANNEL] = (ttl>>1) & 0xffff; - } - #ifdef ESP32 - uint32_t s32; - if (output_mode == INTERNAL_DAC) - { - int16_t l = Amplify(ms[LEFTCHANNEL]) + 0x8000; - int16_t r = Amplify(ms[RIGHTCHANNEL]) + 0x8000; - s32 = (r << 16) | (l & 0xffff); - } - else - { - s32 = ((Amplify(ms[RIGHTCHANNEL])) << 16) | (Amplify(ms[LEFTCHANNEL]) & 0xffff); - } -// Deprecated. Use i2s_write -// return i2s_write_bytes((i2s_port_t)portNo, (const char *)&s32, sizeof(uint32_t), 0); - size_t bytes_written; - i2s_write((i2s_port_t)portNo, (const char*)&s32, sizeof(uint32_t), &bytes_written, 0); - return bytes_written; - #elif defined(ESP8266) - uint32_t s32 = ((Amplify(ms[RIGHTCHANNEL])) << 16) | (Amplify(ms[LEFTCHANNEL]) & 0xffff); - return i2s_write_sample_nb(s32); // If we can't store it, return false. OTW true - #elif defined(ARDUINO_ARCH_RP2040) - return !!I2S.write((void*)ms, 4); - #endif -} - -In file AudioOutputI2SNoDac.cpp: - -bool AudioOutputI2SNoDAC::ConsumeSample(int16_t sample[2]) -{ - int16_t ms[2]; - ms[0] = sample[0]; - ms[1] = sample[1]; - MakeSampleStereo16( ms ); - - // Make delta-sigma filled buffer - uint32_t dsBuff[8]; - DeltaSigma(ms, dsBuff); - - // Either send complete pulse stream or nothing -#ifdef ESP32 -// Deprecated. Use i2s_write -// if (!i2s_write_bytes((i2s_port_t)portNo, (const char *)dsBuff, sizeof(uint32_t) * (oversample/32), 0)) - size_t bytes_written; - i2s_write((i2s_port_t)portNo, (const char *)dsBuff, sizeof(uint32_t) * (oversample/32), &bytes_written, 0); - if (!bytes_written) - return false; -#elif defined(ESP8266) - if (!i2s_write_sample_nb(dsBuff[0])) return false; // No room at the inn - // At this point we've sent in first of possibly 8 32-bits, need to send - // remaining ones even if they block. - for (int i = 32; i < oversample; i+=32) - i2s_write_sample( dsBuff[i / 32]); -#elif defined(ARDUINO_ARCH_RP2040) - int16_t *p = (int16_t *) dsBuff; - for (int i = 0; i < oversample / 16; i++) { - I2S.write(*(p++)); - } -#endif - return true; -} diff --git a/lib/lib_audio/ESP8266SAM/README.md b/lib/lib_audio/ESP8266SAM/README.md index 6fb215564..694086db2 100644 --- a/lib/lib_audio/ESP8266SAM/README.md +++ b/lib/lib_audio/ESP8266SAM/README.md @@ -23,6 +23,10 @@ Output is fixed at 22050Hz due to some hardcoded delays to help match C64 intern The voice is formant generated and can be modified by setting things such as speed, pitch, mouth and throat configuration, and even sending in phonetic codes instead of English text. See @s-macke's repository for more information. +## Cool uses of SAM +Jan Derogee has used ESP8266SAM to build a complete VIC-20 compatible speech synthesis cartridge that works with BASIC applications. It also has a great background on early speech synthesis and a neat construction and demo video. Check it out at https://janderogee.com/projects/SerialSpeechSynthesisSAM/SerialSpeechSynthesisSAM.htm + + ## License While the ESP8266 wrapper is my own, the SAM software is a reverse-engineered version of a software published more than 34 years ago by "Don't ask Software". diff --git a/lib/lib_audio/ESP8266SAM/examples/SpeakNoDac/SpeakNoDac.ino b/lib/lib_audio/ESP8266SAM/examples/SpeakNoDac/SpeakNoDac.ino new file mode 100644 index 000000000..6951fe855 --- /dev/null +++ b/lib/lib_audio/ESP8266SAM/examples/SpeakNoDac/SpeakNoDac.ino @@ -0,0 +1,20 @@ +#include +#include +#include "AudioOutputI2SNoDAC.h" + +AudioOutputI2SNoDAC *out = NULL; + +void setup() +{ + out = new AudioOutputI2SNoDAC(); + out->begin(); +} + +void loop() +{ + ESP8266SAM *sam = new ESP8266SAM; + sam->Say(out, "Can you hear me now?"); + delay(500); + sam->Say(out, "I can't hear you!"); + delete sam; +} diff --git a/lib/lib_audio/ESP8266SAM/examples/remoteSAM/remoteSAM.ino b/lib/lib_audio/ESP8266SAM/examples/remoteSAM/remoteSAM.ino new file mode 100644 index 000000000..d6a82991e --- /dev/null +++ b/lib/lib_audio/ESP8266SAM/examples/remoteSAM/remoteSAM.ino @@ -0,0 +1,129 @@ +// In a webbrowser go to http://sam.local/say/{message} to make it speak +// ex: http://sam.local/say/hello world + +#include + +#if !defined(ESP8266) +#error This example is only for the ESP8266 +#endif + +#include +#include "AudioOutputI2SNoDAC.h" + +#include +#include +#include //Library for SSDP (Show ESP in Network on Windows) +#include //Library for WebServer +#include +#include + +AudioOutputI2SNoDAC *out = NULL; + +ESP8266WebServer server(80); //Web Server on port 80 +WiFiManager wifiManager; +const char* NAME = "SAM"; + +void setup() +{ + Serial.begin(115200); + out = new AudioOutputI2SNoDAC(); + out->begin(); + + wifiManager.autoConnect(NAME); + + MDNS.begin(NAME); + MDNS.addService("http", "tcp", 80); + NBNS.begin(NAME); + + server.on(UriBraces("/say/{}"), []() { + String message_encoded = server.pathArg(0); + String message_decoded = urldecode(message_encoded); + const char* message = message_decoded.c_str(); + + Serial.println(message_encoded); + Serial.println(message_decoded); + Serial.println(message); + + ESP8266SAM *sam = new ESP8266SAM; + sam->Say(out, message); + delete sam; + server.send(200, "text/plain", "OK"); + }); + + server.on("/description.xml", HTTP_GET, []() { + SSDP.schema(server.client()); + }); + server.begin(); + ssdp(); +} + +void ssdp() { + //Simple Service Discovery Protocol : Display ESP in Windows Network Tab + SSDP.setSchemaURL("description.xml"); + SSDP.setHTTPPort(80); + SSDP.setName(NAME); + SSDP.setDeviceType("upnp: rootdevice"); + SSDP.setSerialNumber("000000000001"); + SSDP.setURL("/say/connected"); + SSDP.setModelName("ESP8266SAM"); + SSDP.setModelNumber("0000000000001"); + SSDP.setModelURL("https://github.com/earlephilhower/ESP8266SAM"); + SSDP.setManufacturer("earlephilhower"); + SSDP.setManufacturerURL("https://github.com/earlephilhower/"); + SSDP.begin(); +} + +void loop() { + server.handleClient(); +} + +char* string2char(String command) { + if (command.length() != 0) { + char *p = const_cast(command.c_str()); + return p; + } else { + return ""; + } +} + +unsigned char h2int(char c) { + if (c >= '0' && c <= '9') { + return ((unsigned char)c - '0'); + } + if (c >= 'a' && c <= 'f') { + return ((unsigned char)c - 'a' + 10); + } + if (c >= 'A' && c <= 'F') { + return ((unsigned char)c - 'A' + 10); + } + return (0); +} + +String urldecode(String str) +{ + + String encodedString = ""; + char c; + char code0; + char code1; + for (int i = 0; i < str.length(); i++) { + c = str.charAt(i); + if (c == '+') { + encodedString += ' '; + } else if (c == '%') { + i++; + code0 = str.charAt(i); + i++; + code1 = str.charAt(i); + c = (h2int(code0) << 4) | h2int(code1); + encodedString += c; + } else { + + encodedString += c; + } + + yield(); + } + + return encodedString; +} diff --git a/lib/lib_audio/ESP8266SAM/library.json b/lib/lib_audio/ESP8266SAM/library.json index af66aee97..d03ac694c 100644 --- a/lib/lib_audio/ESP8266SAM/library.json +++ b/lib/lib_audio/ESP8266SAM/library.json @@ -1,7 +1,7 @@ { "name": "ESP8266SAM", - "description": "Speech synthesizer SAM ported to ESP8266/ESP32", - "keywords": "ESP8266, ESP32, Speecn Synthesis, SAM", + "description": "Speech synthesizer SAM ported to ESP8266/ESP32/RP2040", + "keywords": "ESP8266, ESP32, RP2040, Speecn Synthesis, SAM", "authors": [ { "name": "Earle F. Philhower, III", @@ -14,10 +14,9 @@ "type": "git", "url": "https://github.com/earlephilhower/ESP8266SAM" }, - "version": "1.0", + "version": "1.0.1", "homepage": "https://github.com/earlephilhower/ESP8266SAM", "frameworks": "Arduino", - "platforms": ["espressif8266", "espressif32"], "examples": [ "examples/*/*.ino" ] diff --git a/lib/lib_audio/ESP8266SAM/library.properties b/lib/lib_audio/ESP8266SAM/library.properties index ed295ef12..f4624783c 100644 --- a/lib/lib_audio/ESP8266SAM/library.properties +++ b/lib/lib_audio/ESP8266SAM/library.properties @@ -1,9 +1,9 @@ name=ESP8266SAM -version=1.0 +version=1.0.1 author=Earle F. Philhower, III maintainer=Earle F. Philhower, III -sentence=Speech synthesis on the ESP8266 and ESP32 -paragraph=Speech synthesis program SAM ported to ESP8266/ESP32 and ESP8266Audio +sentence=Speech synthesis on the ESP8266, ESP32, and RP2040 +paragraph=Speech synthesis program SAM ported to ESP8266/ESP32/RP2040 and ESP8266Audio category=Signal Input/Output url=https://github.com/earlephilhower/ESP8266SAM -architectures=esp8266,esp32 +architectures=esp8266,esp32,rp2040 diff --git a/lib/lib_audio/ESP8266SAM/src/ESP8266SAM.h b/lib/lib_audio/ESP8266SAM/src/ESP8266SAM.h index d947c72f0..526f41b91 100644 --- a/lib/lib_audio/ESP8266SAM/src/ESP8266SAM.h +++ b/lib/lib_audio/ESP8266SAM/src/ESP8266SAM.h @@ -1,7 +1,7 @@ /* ESP8266SAM Port of SAM to the ESP8266 - + Copyright (C) 2017 Earle F. Philhower, III This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -34,7 +34,7 @@ public: speed = 0; output = NULL; }; - + ~ESP8266SAM() { } @@ -70,3 +70,4 @@ private: }; #endif + diff --git a/lib/lib_audio/ESP8266SAM/src/ReciterTabs.h b/lib/lib_audio/ESP8266SAM/src/ReciterTabs.h index c89636e4d..3f152cc6a 100644 --- a/lib/lib_audio/ESP8266SAM/src/ReciterTabs.h +++ b/lib/lib_audio/ESP8266SAM/src/ReciterTabs.h @@ -2,8 +2,8 @@ #define RECITERTABS_H #include -#include "samdebug.h" -#if sam_debug +#include "esp8266sam_debug.h" +#if DEBUG_ESP8266SAM_LIB #define PROGMEM #endif diff --git a/lib/lib_audio/ESP8266SAM/src/RenderTabs.h b/lib/lib_audio/ESP8266SAM/src/RenderTabs.h index a98e93bc7..c492fb9c5 100644 --- a/lib/lib_audio/ESP8266SAM/src/RenderTabs.h +++ b/lib/lib_audio/ESP8266SAM/src/RenderTabs.h @@ -2,8 +2,8 @@ #define RENDERTABS_H #include -#include "samdebug.h" -#if sam_debug +#include "esp8266sam_debug.h" +#if DEBUG_ESP8266SAM_LIB #define PROGMEM #endif @@ -196,7 +196,7 @@ const unsigned char ampl3data[] PROGMEM = //tab42240 -const signed char sinus[256] PROGMEM = {0,3,6,9,12,16,19,22,25,28,31,34,37,40,43,46,49,51,54,57,60,63,65,68,71,73,76,78,81,83,85,88,90,92,94,96,98,100,102,104,106,107,109,111,112,113,115,116,117,118,120,121,122,122,123,124,125,125,126,126,126,127,127,127,127,127,127,127,126,126,126,125,125,124,123,122,122,121,120,118,117,116,115,113,112,111,109,107,106,104,102,100,98,96,94,92,90,88,85,83,81,78,76,73,71,68,65,63,60,57,54,51,49,46,43,40,37,34,31,28,25,22,19,16,12,9,6,3,0,-3,-6,-9,-12,-16,-19,-22,-25,-28,-31,-34,-37,-40,-43,-46,-49,-51,-54,-57,-60,-63,-65,-68,-71,-73,-76,-78,-81,-83,-85,-88,-90,-92,-94,-96,-98,-100,-102,-104,-106,-107,-109,-111,-112,-113,-115,-116,-117,-118,-120,-121,-122,-122,-123,-124,-125,-125,-126,-126,-126,-127,-127,-127,-127,-127,-127,-127,-126,-126,-126,-125,-125,-124,-123,-122,-122,-121,-120,-118,-117,-116,-115,-113,-112,-111,-109,-107,-106,-104,-102,-100,-98,-96,-94,-92,-90,-88,-85,-83,-81,-78,-76,-73,-71,-68,-65,-63,-60,-57,-54,-51,-49,-46,-43,-40,-37,-34,-31,-28,-25,-22,-19,-16,-12,-9,-6,-3}; +const signed char sinus[256] PROGMEM = {0,3,6,9,12,16,19,22,25,28,31,34,37,40,43,46,49,51,54,57,60,63,65,68,71,73,76,78,81,83,85,88,90,92,94,96,98,100,102,104,106,107,109,111,112,113,115,116,117,118,120,121,122,122,123,124,125,125,126,126,126,127,127,127,127,127,127,127,126,126,126,125,125,124,123,122,122,121,120,118,117,116,115,113,112,111,109,107,106,104,102,100,98,96,94,92,90,88,85,83,81,78,76,73,71,68,65,63,60,57,54,51,49,46,43,40,37,34,31,28,25,22,19,16,12,9,6,3,0,-3,-6,-9,-12,-16,-19,-22,-25,-28,-31,-34,-37,-40,-43,-46,-49,-51,-54,-57,-60,-63,-65,-68,-71,-73,-76,-78,-81,-83,-85,-88,-90,-92,-94,-96,-98,-100,-102,-104,-106,-107,-109,-111,-112,-113,-115,-116,-117,-118,-120,-121,-122,-122,-123,-124,-125,-125,-126,-126,-126,-127,-127,-127,-127,-127,-127,-127,-126,-126,-126,-125,-125,-124,-123,-122,-122,-121,-120,-118,-117,-116,-115,-113,-112,-111,-109,-107,-106,-104,-102,-100,-98,-96,-94,-92,-90,-88,-85,-83,-81,-78,-76,-73,-71,-68,-65,-63,-60,-57,-54,-51,-49,-46,-43,-40,-37,-34,-31,-28,-25,-22,-19,-16,-12,-9,-6,-3}; //tab42496 const unsigned char rectangle[] PROGMEM = diff --git a/lib/lib_audio/ESP8266SAM/src/SamTabs.h b/lib/lib_audio/ESP8266SAM/src/SamTabs.h index 4574746e7..933f95b0e 100644 --- a/lib/lib_audio/ESP8266SAM/src/SamTabs.h +++ b/lib/lib_audio/ESP8266SAM/src/SamTabs.h @@ -2,8 +2,8 @@ #define SAMTABS_H #include -#include "samdebug.h" -#if sam_debug +#include "esp8266sam_debug.h" +#if DEBUG_ESP8266SAM_LIB #define PROGMEM #endif diff --git a/lib/lib_audio/ESP8266SAM/src/samdebug.c b/lib/lib_audio/ESP8266SAM/src/esp8266sam_debug.c similarity index 100% rename from lib/lib_audio/ESP8266SAM/src/samdebug.c rename to lib/lib_audio/ESP8266SAM/src/esp8266sam_debug.c diff --git a/lib/lib_audio/ESP8266SAM/src/samdebug.h b/lib/lib_audio/ESP8266SAM/src/esp8266sam_debug.h similarity index 79% rename from lib/lib_audio/ESP8266SAM/src/samdebug.h rename to lib/lib_audio/ESP8266SAM/src/esp8266sam_debug.h index 5f862a0e6..de2a2f840 100644 --- a/lib/lib_audio/ESP8266SAM/src/samdebug.h +++ b/lib/lib_audio/ESP8266SAM/src/esp8266sam_debug.h @@ -1,5 +1,5 @@ -#ifndef DEBUG_H -#define DEBUG_H +#ifndef ESP8266SAM_DEBUG_H +#define ESP8266SAM_DEBUG_H void PrintPhonemes(unsigned char *phonemeindex, unsigned char *phonemeLength, unsigned char *stress); void PrintOutput( @@ -14,6 +14,6 @@ void PrintOutput( void PrintRule(int offset); -#define sam_debug 0 +#define DEBUG_ESP8266SAM_LIB 0 #endif diff --git a/lib/lib_audio/ESP8266SAM/src/reciter.c b/lib/lib_audio/ESP8266SAM/src/reciter.c index 3845609c3..f949ca579 100644 --- a/lib/lib_audio/ESP8266SAM/src/reciter.c +++ b/lib/lib_audio/ESP8266SAM/src/reciter.c @@ -2,7 +2,7 @@ #include #include "reciter.h" #include "ReciterTabs.h" -#include "samdebug.h" +#include "esp8266sam_debug.h" #include "SamData.h" unsigned char A, X, Y; @@ -527,7 +527,7 @@ pos37455: Y = mem64; mem61 = mem60; - if (sam_debug) + if (DEBUG_ESP8266SAM_LIB) PrintRule(mem62); pos37461: diff --git a/lib/lib_audio/ESP8266SAM/src/render.c b/lib/lib_audio/ESP8266SAM/src/render.c index f73c848a4..4cbabb190 100644 --- a/lib/lib_audio/ESP8266SAM/src/render.c +++ b/lib/lib_audio/ESP8266SAM/src/render.c @@ -5,8 +5,7 @@ #include "render.h" #include "RenderTabs.h" -#include "samdebug.h" -//extern int debug; +#include "esp8266sam_debug.h" #include #include "SamData.h" @@ -445,7 +444,7 @@ do mem44++; } while(mem44 != 0); yield(); -if (sam_debug) +if (DEBUG_ESP8266SAM_LIB) { PrintOutput(sampledConsonantFlag, frequency1, frequency2, frequency3, amplitude1, amplitude2, amplitude3, pitches); } @@ -786,7 +785,7 @@ if (sam_debug) X = A; mem38 = A - (A>>2); // 3/4*A ??? yield(); -if (sam_debug) +if (DEBUG_ESP8266SAM_LIB) { PrintOutput(sampledConsonantFlag, frequency1, frequency2, frequency3, amplitude1, amplitude2, amplitude3, pitches); } diff --git a/lib/lib_audio/ESP8266SAM/src/sam.c b/lib/lib_audio/ESP8266SAM/src/sam.c index 5dba52fda..c20d8dd2a 100644 --- a/lib/lib_audio/ESP8266SAM/src/sam.c +++ b/lib/lib_audio/ESP8266SAM/src/sam.c @@ -2,7 +2,7 @@ #include // strlen() //#include #include // define NULL -#include "samdebug.h" +#include "esp8266sam_debug.h" #include "sam.h" #include "render.h" #include "SamTabs.h" @@ -15,8 +15,6 @@ static unsigned char mouth = 128; static unsigned char throat = 128; int singmode = 0; -//extern int debug; - unsigned char mem39; unsigned char mem44; unsigned char mem47; @@ -146,7 +144,7 @@ int SAMMain( void (*cb)(void *, unsigned char), void *cbd ) phonemeindex[255] = 32; //to prevent buffer overflow if (!Parser1()) return 0; - if (sam_debug) + if (DEBUG_ESP8266SAM_LIB) PrintPhonemes(phonemeindex, phonemeLength, stress); Parser2(); CopyStress(); @@ -168,7 +166,7 @@ int SAMMain( void (*cb)(void *, unsigned char), void *cbd ) InsertBreath(); //mem[40158] = 255; - if (sam_debug) + if (DEBUG_ESP8266SAM_LIB) { PrintPhonemes(phonemeindex, phonemeLength, stress); } @@ -645,7 +643,7 @@ void Code41240() //void Code41397() void Parser2() { - if (sam_debug) printf("Parser2\n"); + if (DEBUG_ESP8266SAM_LIB) printf("Parser2\n"); unsigned char pos = 0; //mem66; unsigned char mem58 = 0; @@ -659,7 +657,7 @@ void Parser2() A = phonemeindex[pos]; // DEBUG: Print phoneme and index - if (sam_debug && A != 255) printf("%d: %c%c\n", X, signInputTable1[A], signInputTable2[A]); + if (DEBUG_ESP8266SAM_LIB && A != 255) printf("%d: %c%c\n", X, signInputTable1[A], signInputTable2[A]); // Is phoneme pause? if (A == 0) @@ -695,8 +693,8 @@ void Parser2() //pos41443: // Insert at WX or YX following, copying the stress - if (sam_debug) if (A==20) printf("RULE: insert WX following diphtong NOT ending in IY sound\n"); - if (sam_debug) if (A==21) printf("RULE: insert YX following diphtong ending in IY sound\n"); + if (DEBUG_ESP8266SAM_LIB) if (A==20) printf("RULE: insert WX following diphtong NOT ending in IY sound\n"); + if (DEBUG_ESP8266SAM_LIB) if (A==21) printf("RULE: insert YX following diphtong ending in IY sound\n"); Insert(pos+1, A, mem59, mem58); X = pos; // Jump to ??? @@ -716,7 +714,7 @@ pos41457: if (A != 78) goto pos41487; // 'UL' A = 24; // 'L' //change 'UL' to 'AX L' - if (sam_debug) printf("RULE: UL -> AX L\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: UL -> AX L\n"); pos41466: // Get current phoneme stress @@ -740,7 +738,7 @@ pos41487: if (A != 79) goto pos41495; // 'UM' // Jump up to branch - replaces current phoneme with AX and continues A = 27; // 'M' //change 'UM' to 'AX M' - if (sam_debug) printf("RULE: UM -> AX M\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: UM -> AX M\n"); goto pos41466; pos41495: @@ -754,7 +752,7 @@ pos41495: // Jump up to branch - replaces current phoneme with AX and continues A = 28; // 'N' //change UN to 'AX N' - if (sam_debug) printf("RULE: UN -> AX N\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: UN -> AX N\n"); goto pos41466; pos41503: @@ -802,7 +800,7 @@ pos41503: if (A != 0) { // Insert a glottal stop and move forward - if (sam_debug) printf("RULE: Insert glottal stop between two stressed vowels with space between them\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: Insert glottal stop between two stressed vowels with space between them\n"); // 31 = 'Q' Insert(X, 31, mem59, 0); pos++; @@ -831,7 +829,7 @@ pos41503: if (A == 69) // 'T' { // Change T to CH - if (sam_debug) printf("RULE: T R -> CH R\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: T R -> CH R\n"); phonemeindex[pos-1] = 42; goto pos41779; } @@ -846,7 +844,7 @@ pos41503: { // Change D to J phonemeindex[pos-1] = 44; - if (sam_debug) printf("RULE: D R -> J R\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: D R -> J R\n"); goto pos41788; } @@ -857,7 +855,7 @@ pos41503: // If vowel flag is set change R to RX A = flags[A] & 128; - if (sam_debug) printf("RULE: R -> RX\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: R -> RX\n"); if (A != 0) phonemeindex[pos] = 18; // 'RX' // continue to next phoneme @@ -876,7 +874,7 @@ pos41611: // If prior phoneme does not have VOWEL flag set, move to next phoneme if ((flags[phonemeindex[pos-1]] & 128) == 0) {pos++; continue;} // Prior phoneme has VOWEL flag set, so change L to LX and move to next phoneme - if (sam_debug) printf("RULE: L -> LX\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: L -> LX\n"); phonemeindex[X] = 19; // 'LX' pos++; continue; @@ -895,7 +893,7 @@ pos41611: // If prior phoneme is not G, move to next phoneme if (phonemeindex[pos-1] != 60) {pos++; continue;} // Replace S with Z and move on - if (sam_debug) printf("RULE: G S -> G Z\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: G S -> G Z\n"); phonemeindex[pos] = 38; // 'Z' pos++; continue; @@ -916,7 +914,7 @@ pos41611: { // VOWELS AND DIPHTONGS ENDING WITH IY SOUND flag set? A = flags[Y] & 32; - if (sam_debug) if (A==0) printf("RULE: K -> KX \n"); + if (DEBUG_ESP8266SAM_LIB) if (A==0) printf("RULE: K -> KX \n"); // Replace with KX if (A == 0) phonemeindex[pos] = 75; // 'KX' } @@ -943,7 +941,7 @@ pos41611: // If diphtong ending with YX, move continue processing next phoneme if ((flags[index] & 32) != 0) {pos++; continue;} // replace G with GX and continue processing next phoneme - if (sam_debug) printf("RULE: G -> GX \n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: G -> GX \n"); phonemeindex[pos] = 63; // 'GX' pos++; continue; @@ -968,7 +966,7 @@ pos41611: goto pos41812; } // Replace with softer version - if (sam_debug) printf("RULE: S* %c%c -> S* %c%c\n", signInputTable1[Y], signInputTable2[Y],signInputTable1[Y-12], signInputTable2[Y-12]); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: S* %c%c -> S* %c%c\n", signInputTable1[Y], signInputTable2[Y],signInputTable1[Y-12], signInputTable2[Y-12]); phonemeindex[pos] = Y-12; pos++; continue; @@ -991,7 +989,7 @@ pos41749: A = flags2[Y] & 4; // If not set, continue processing next phoneme if (A == 0) {pos++; continue;} - if (sam_debug) printf("RULE: UW -> UX\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: UW -> UX\n"); phonemeindex[X] = 16; pos++; continue; @@ -1005,7 +1003,7 @@ pos41779: if (A == 42) // 'CH' { // pos41783: - if (sam_debug) printf("CH -> CH CH+1\n"); + if (DEBUG_ESP8266SAM_LIB) printf("CH -> CH CH+1\n"); Insert(X+1, A+1, mem59, stress[X]); pos++; continue; @@ -1020,7 +1018,7 @@ pos41788: if (A == 44) // 'J' { - if (sam_debug) printf("J -> J J+1\n"); + if (DEBUG_ESP8266SAM_LIB) printf("J -> J J+1\n"); Insert(X+1, A+1, mem59, stress[X]); pos++; continue; @@ -1060,7 +1058,7 @@ pos41812: if (stress[X] != 0) {pos++; continue;} //pos41856: // Set phonemes to DX - if (sam_debug) printf("RULE: Soften T or D following vowel or ER and preceding a pause -> DX\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: Soften T or D following vowel or ER and preceding a pause -> DX\n"); phonemeindex[pos] = 30; // 'DX' } else { @@ -1070,7 +1068,7 @@ pos41812: else // Is next phoneme a vowel or ER? A = flags[A] & 128; - if (sam_debug) if (A != 0) printf("RULE: Soften T or D following vowel or ER and preceding a pause -> DX\n"); + if (DEBUG_ESP8266SAM_LIB) if (A != 0) printf("RULE: Soften T or D following vowel or ER and preceding a pause -> DX\n"); if (A != 0) phonemeindex[pos] = 30; // 'DX' } @@ -1160,14 +1158,14 @@ pos48644: // change phoneme length to (length * 1.5) + 1 A = (A >> 1) + A + 1; -if (sam_debug) printf("RULE: Lengthen or between and by 1.5\n"); -if (sam_debug) printf("PRE\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("RULE: Lengthen or between and by 1.5\n"); +if (DEBUG_ESP8266SAM_LIB) printf("PRE\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); phonemeLength[X] = A; -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); } // keep moving forward @@ -1221,15 +1219,15 @@ if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonem // RULE: RX | LX -if (sam_debug) printf("RULE: - decrease length by 1\n"); -if (sam_debug) printf("PRE\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable1[phonemeindex[loopIndex]], signInputTable2[phonemeindex[loopIndex]], phonemeLength[loopIndex]); +if (DEBUG_ESP8266SAM_LIB) printf("RULE: - decrease length by 1\n"); +if (DEBUG_ESP8266SAM_LIB) printf("PRE\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable1[phonemeindex[loopIndex]], signInputTable2[phonemeindex[loopIndex]], phonemeLength[loopIndex]); // decrease length of vowel by 1 frame phonemeLength[loopIndex]--; -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable1[phonemeindex[loopIndex]], signInputTable2[phonemeindex[loopIndex]], phonemeLength[loopIndex]); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable1[phonemeindex[loopIndex]], signInputTable2[phonemeindex[loopIndex]], phonemeLength[loopIndex]); } // move ahead @@ -1267,16 +1265,16 @@ if (sam_debug) printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable // move back X--; -if (sam_debug) printf("RULE: - decrease vowel by 1/8th\n"); -if (sam_debug) printf("PRE\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("RULE: - decrease vowel by 1/8th\n"); +if (DEBUG_ESP8266SAM_LIB) printf("PRE\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); // decrease length by 1/8th mem56 = phonemeLength[X] >> 3; phonemeLength[X] -= mem56; -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); // move ahead loopIndex++; @@ -1286,16 +1284,16 @@ if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonem // RULE: // -if (sam_debug) printf("RULE: - increase vowel by 1/2 + 1\n"); -if (sam_debug) printf("PRE\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); +if (DEBUG_ESP8266SAM_LIB) printf("RULE: - increase vowel by 1/2 + 1\n"); +if (DEBUG_ESP8266SAM_LIB) printf("PRE\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); // decrease length A = phonemeLength[X-1]; phonemeLength[X-1] = (A >> 2) + A + 1; // 5/4*A + 1 -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); // move ahead loopIndex++; @@ -1335,10 +1333,10 @@ if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phon // B*, D*, G*, GX, P*, T*, K*, KX { -if (sam_debug) printf("RULE: - set nasal = 5, consonant = 6\n"); -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); +if (DEBUG_ESP8266SAM_LIB) printf("RULE: - set nasal = 5, consonant = 6\n"); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); // set stop consonant length to 6 phonemeLength[X] = 6; @@ -1346,9 +1344,9 @@ if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phon // set nasal length to 5 phonemeLength[X-1] = 5; -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); } // move to next phoneme @@ -1388,10 +1386,10 @@ if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phon } // RULE: {optional silence} -if (sam_debug) printf("RULE: {optional silence} - shorten both to 1/2 + 1\n"); -if (sam_debug) printf("PRE\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); +if (DEBUG_ESP8266SAM_LIB) printf("RULE: {optional silence} - shorten both to 1/2 + 1\n"); +if (DEBUG_ESP8266SAM_LIB) printf("PRE\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); // X gets overwritten, so hold prior X value for debug statement int debugX = X; // shorten the prior phoneme length to (length/2 + 1) @@ -1401,9 +1399,9 @@ int debugX = X; // also shorten this phoneme length to (length/2 +1) phonemeLength[loopIndex] = (phonemeLength[loopIndex] >> 1) + 1; -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", debugX, signInputTable1[phonemeindex[debugX]], signInputTable2[phonemeindex[debugX]], phonemeLength[debugX]); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", debugX-1, signInputTable1[phonemeindex[debugX-1]], signInputTable2[phonemeindex[debugX-1]], phonemeLength[debugX-1]); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", debugX, signInputTable1[phonemeindex[debugX]], signInputTable2[phonemeindex[debugX]], phonemeLength[debugX]); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", debugX-1, signInputTable1[phonemeindex[debugX-1]], signInputTable2[phonemeindex[debugX-1]], phonemeLength[debugX-1]); // move ahead @@ -1429,15 +1427,15 @@ if (sam_debug) printf("phoneme %d (%c%c) length %d\n", debugX-1, signInputTable1 if((flags[index] & 2) != 0) // Rule: -if (sam_debug) printf("RULE: - decrease by 2\n"); -if (sam_debug) printf("PRE\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("RULE: - decrease by 2\n"); +if (DEBUG_ESP8266SAM_LIB) printf("PRE\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); // decrease the phoneme length by 2 frames (20 ms) phonemeLength[X] -= 2; -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); } // move to next phoneme diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README.md index 90fd8d4c8..f392c5529 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README.md @@ -10,8 +10,8 @@ This library enables you to **send _and_ receive** infra-red signals on an [ESP8266](https://github.com/esp8266/Arduino) or an [ESP32](https://github.com/espressif/arduino-esp32) using the [Arduino framework](https://www.arduino.cc/) using common 940nm IR LEDs and common IR receiver modules. e.g. TSOP{17,22,24,36,38,44,48}* demodulators etc. -## v2.8.0 Now Available -Version 2.8.0 of the library is now [available](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes. +## v2.8.1 Now Available +Version 2.8.1 of the library is now [available](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes. #### Upgrading from pre-v2.0 Usage of the library has been slightly changed in v2.0. You will need to change your usage to work with v2.0 and beyond. You can read more about the changes required on our [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_de.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_de.md index 4dbd835c4..884628149 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_de.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_de.md @@ -11,8 +11,8 @@ Diese Programmbibliothek ermöglicht das **Senden _und_ Empfangen** von Infrarotsignalen mit [ESP8266](https://github.com/esp8266/Arduino)- und [ESP32](https://github.com/espressif/arduino-esp32)-Mikrocontrollern mithilfe des [Arduino-Frameworks](https://www.arduino.cc/) und handelsüblichen 940nm Infrarot-LEDs undIR-Empfängermodulen, wie zum Beispiel TSOP{17,22,24,36,38,44,48}*-Demodulatoren. -## v2.8.0 jetzt verfügbar -Version 2.8.0 der Bibliothek ist nun [verfügbar](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Die [Versionshinweise](ReleaseNotes.md) enthalten alle wichtigen Neuerungen. +## v2.8.1 jetzt verfügbar +Version 2.8.1 der Bibliothek ist nun [verfügbar](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Die [Versionshinweise](ReleaseNotes.md) enthalten alle wichtigen Neuerungen. #### Hinweis für Nutzer von Versionen vor v2.0 Die Benutzung der Bibliothek hat sich mit Version 2.0 leicht geändert. Einige Anpassungen im aufrufenden Code werden nötig sein, um mit Version ab 2.0 korrekt zu funktionieren. Mehr zu den Anpassungen finden sich auf unserer [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0)-Seite. diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_fr.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_fr.md index d7033c093..3f1a93048 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_fr.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_fr.md @@ -10,8 +10,8 @@ Cette librairie vous permetra de **recevoir et d'envoyer des signaux** infrarouge sur le protocole [ESP8266](https://github.com/esp8266/Arduino) ou sur le protocole [ESP32](https://github.com/espressif/arduino-esp32) en utilisant le [Arduino framework](https://www.arduino.cc/) qui utilise la norme 940nm IR LEDs et le module basique de reception d'onde IR. Exemple : TSOP{17,22,24,36,38,44,48}* modules etc. -## v2.8.0 disponible -Version 2.8.0 de la libraire est maintenant [disponible](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Vous pouvez voir le [Release Notes](ReleaseNotes.md) pour tous les changements importants. +## v2.8.1 disponible +Version 2.8.1 de la libraire est maintenant [disponible](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Vous pouvez voir le [Release Notes](ReleaseNotes.md) pour tous les changements importants. #### mise à jour depuis pre-v2.0 L'utilisation de la librairie à un peu changer depuis la version in v2.0. Si vous voulez l'utiliser vous devrez changer votre utilisation aussi. Vous pouvez vous renseigner sur les précondition d'utilisation ici : [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/ReleaseNotes.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/ReleaseNotes.md index 0f41b562d..9c8d7df98 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/ReleaseNotes.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/ReleaseNotes.md @@ -1,5 +1,29 @@ # Release Notes +## _v2.8.1 (20220101)_ + +**[Bug Fixes]** +- Arduino ESP32 Core v2.0.2+ crashes due to our timer hack. (#1715 #1713) +- SONY: Fix old Sony CD-Player Remote (12 Bit) (#1714) + +**[Features]** +- Add tool to convert protocol & code to raw timing info. (#1708 #1707 #1703) +- Add basic support for COOLIX48 protocol. (#1697 #1694) +- MITSUBISHI_AC: Added support for i-SAVE mode. (#1666) +- TOSHIBA_AC: Add Filter setting support. aka. Pure. (#1693 #1692) +- Airton: Add detailed A/C support. (#1688 #1670) + +**[Misc]** +- Add a structured library version number. (#1717) +- Workflows Split UnitTests (#1712) +- Reduce time for workflow/Build (#1709) +- Fix some compiler & linter warnings (#1699 #1700) +- Fujitsu: Update supported A/C models (#1690 #1689 #1702 #1701) +- Remove extra `const` qualifier for char pointer (#1704) +- TCL: Update supported devices. (#1698) +- ESP32-C3: Work around for some C3 specific compiler issues. (#1696 #1695) + + ## _v2.8.0 (20211119)_ **[Bug Fixes]** diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SupportedProtocols.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SupportedProtocols.md index cf960a0eb..0b6fb06c1 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SupportedProtocols.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SupportedProtocols.md @@ -1,11 +1,11 @@ + Last generated: Fri 31 Dec 2021 21:49:00 +0000 ---> # IR Protocols supported by this library | Protocol | Brand | Model | A/C Model | Detailed A/C Support | | --- | --- | --- | --- | --- | -| [Airton](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Airton.cpp) | **Airton** | RD1A1 remote
SMVH09B-2A2A3NH ref. 409730 A/C | | - | +| [Airton](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Airton.cpp) | **[Airton](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Airton.h)** | RD1A1 remote
SMVH09B-2A2A3NH ref. 409730 A/C | | Yes | | [Airwell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Airwell.cpp) | **[Airwell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Airwell.h)** | DLS 21 DCI R410 AW A/C
RC04 remote
RC08W remote | | Yes | | [Aiwa](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Aiwa.cpp) | **Aiwa** | RC-T501 RCU | | - | | [Amcor](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Amcor.cpp) | **[Amcor](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Amcor.h)** | ADR-853H A/C
TAC-444 remote
TAC-495 remote | | Yes | @@ -15,6 +15,7 @@ | [Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.cpp) | **[Carrier/Surrey](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.h)** | 42QG5A55970 remote
53NGK009/012 Inverter
619EGX0090E0 A/C
619EGX0120E0 A/C
619EGX0180E0 A/C
619EGX0220E0 A/C | | Yes | | [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Airwell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | RC08B remote | | Yes | | [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Beko](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | BINR 070/071 split-type A/C
RG57K7(B)/BGEF Remote | | Yes | +| [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Bosch](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | B1ZAI2441W/B1ZAO2441W A/C
RG36B4/BGE remote | | Yes | | [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Kastron](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | RG57A7/BGEF Inverter remote | | Yes | | [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Kaysun](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | Casual CF A/C | | Yes | | [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | MS12FU-10HRDN1-QRD0GW(B) A/C
MSABAU-07HRFN1-QRD0GW A/C (circa 2016)
RG52D/BGE Remote | | Yes | @@ -35,7 +36,7 @@ | [EliteScreens](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_EliteScreens.cpp) | **Elite Screens** | CineTension2 / CineTension3 series
Home2 / Home3 series
Spectrum series
VMAX Plus4 series
VMAX2 / VMAX2 Plus series
ZSP-IR-B / ZSP-IR-W remote | | - | | [EliteScreens](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_EliteScreens.cpp) | **Lumene Screens** | Embassy | | - | | [Epson](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Epson.cpp) | **Epson** | EN-TW9100W Projector
EX3220 Projector
EX5220 Projector
EX5230 Projector
EX6220 Projector
EX7220 Projector
VS230 Projector
VS330 Projector | | - | -| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AGTV14LAC A/C (ARRAH2E)
AR-DB1 remote (ARDB1)
AR-DL10 remote (ARDB1)
AR-RAC1E remote (ARRAH2E)
AR-RAE1E remote (ARRAH2E)
AR-RAH1U remote (ARREB1E)
AR-RAH2E remote (ARRAH2E)
AR-REB1E remote (ARREB1E)
AR-REW4E remote (ARREW4E)
AR-RY4 remote (ARRY4)
AST9RSGCW A/C (ARDB1)
ASTB09LBC A/C (ARRY4)
ASU12RLF A/C (ARREB1E)
ASU30C1 A/C (ARDB1)
ASYG09KETA-B A/C (ARREW4E)
ASYG30LFCA A/C (ARRAH2E)
ASYG7LMCA A/C (ARREB1E) | ARDB1
ARJW2
ARRAH2E
ARREB1E
ARREW4E
ARRY4 | Yes | +| [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AGTV14LAC A/C (ARRAH2E)
AR-DB1 remote (ARDB1)
AR-DL10 remote (ARDB1)
AR-RAC1E remote (ARRAH2E)
AR-RAE1E remote (ARRAH2E)
AR-RAH1U remote (ARREB1E)
AR-RAH2E remote (ARRAH2E)
AR-REB1E remote (ARREB1E)
AR-REB4E remote (ARREB1E)
AR-REW1E remote (ARREW4E)
AR-REW4E remote (ARREW4E)
AR-RY4 remote (ARRY4)
AST9RSGCW A/C (ARDB1)
ASTB09LBC A/C (ARRY4)
ASTG09K A/C (ARREW4E)
ASTG18K A/C (ARREW4E)
ASU12RLF A/C (ARREB1E)
ASU30C1 A/C (ARDB1)
ASYG09KETA-B A/C (ARREW4E)
ASYG30LFCA A/C (ARRAH2E)
ASYG7LMCA A/C (ARREB1E) | ARDB1
ARJW2
ARRAH2E
ARREB1E
ARREW4E
ARRY4 | Yes | | [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu General](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AOHG09LLC A/C (ARRAH2E)
AR-JW2 remote (ARJW2)
AR-RCE1E remote (ARRAH2E)
ASHG09LLCA A/C (ARRAH2E) | ARDB1
ARJW2
ARRAH2E
ARREB1E
ARREW4E
ARRY4 | Yes | | [GICable](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GICable.cpp) | **G.I. Cable** | XRC-200 remote | | - | | [GlobalCache](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GlobalCache.cpp) | **Global Cache** | Control Tower IR DB | | - | @@ -79,7 +80,7 @@ | [Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.cpp) | **[Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.h)** | VLU series A/C | KKG29AC1
KKG9AC1 | Yes | | [Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.cpp) | **[Tronitechnik](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.h)** | KKG29A-C1 remote
Reykir 9000 A/C | KKG29AC1
KKG9AC1 | Yes | | [Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.cpp) | **[Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.h)** | HC3000 Projector (MITSUBISHI2)
KM14A 0179213 remote
MS-GK24VA A/C
TV (MITSUBISHI) | | Yes | -| [Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.cpp) | **[Mitsubishi Electric](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.h)** | 001CP T7WE10714 remote (MITSUBISHI136)
KPOA remote (MITSUBISHI112)
MLZ-RX5017AS A/C (MITSUBISHI_AC)
MSH-A24WV A/C (MITSUBISHI112)
MSZ-GV2519 A/C (MITSUBISHI_AC)
MSZ-SF25VE3 A/C (MITSUBISHI_AC)
MSZ-ZW4017S A/C (MITSUBISHI_AC)
MUH-A24WV A/C (MITSUBISHI112)
PEAD-RP71JAA Ducted A/C (MITSUBISHI136)
RH151/M21ED6426 remote (MITSUBISHI_AC)
SG153/M21EDF426 remote (MITSUBISHI_AC)
SG15D remote (MITSUBISHI_AC) | | Yes | +| [Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.cpp) | **[Mitsubishi Electric](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.h)** | 001CP T7WE10714 remote (MITSUBISHI136)
KPOA remote (MITSUBISHI112)
MLZ-RX5017AS A/C (MITSUBISHI_AC)
MSH-A24WV A/C (MITSUBISHI112)
MSZ-FHnnVE A/C (MITSUBISHI_AC)
MSZ-GV2519 A/C (MITSUBISHI_AC)
MSZ-SF25VE3 A/C (MITSUBISHI_AC)
MSZ-ZW4017S A/C (MITSUBISHI_AC)
MUH-A24WV A/C (MITSUBISHI112)
PEAD-RP71JAA Ducted A/C (MITSUBISHI136)
RH151/M21ED6426 remote (MITSUBISHI_AC)
SG153/M21EDF426 remote (MITSUBISHI_AC)
SG15D remote (MITSUBISHI_AC) | | Yes | | [MitsubishiHeavy](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_MitsubishiHeavy.cpp) | **[Mitsubishi Heavy Industries](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_MitsubishiHeavy.h)** | RKX502A001C remote (88 bit)
RLA502A700B remote (152 bit)
SRKxxZJ-S A/C (88 bit)
SRKxxZM-S A/C (152 bit)
SRKxxZMXA-S A/C (152 bit) | | Yes | | [Multibrackets](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Multibrackets.cpp) | **Multibrackets** | Motorized Swing mount large - 4500 | | - | | [NEC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.cpp) | **[Aloka](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_NEC.h)** | SleepyLights LED Lamp | | - | @@ -107,6 +108,7 @@ | [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **SilverCrest** | SSVS 85 A1 Fan | | - | | [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **Symphony** | Air Cooler 3Di | | - | | [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **Westinghouse** | 78095 Remote
Ceiling fan | | - | +| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Daewoo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | DSB-F0934ELH-V A/C
GYKQ-52E remote | GZ055BE1
TAC09CHSD | Yes | | [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Leberg](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | LBS-TOR07 A/C (TAC09CHSD) | GZ055BE1
TAC09CHSD | Yes | | [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[TCL](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | TAC-09CHSD/XA31I A/C (TAC09CHSD) | GZ055BE1
TAC09CHSD | Yes | | [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Teknopoint](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | Allegro SSA-09H A/C (GZ055BE1)
GZ-055B-E1 remote (GZ055BE1) | GZ055BE1
TAC09CHSD | Yes | @@ -114,7 +116,7 @@ | [Teco](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teco.cpp) | **[Alaska](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teco.h)** | SAC9010QC A/C
SAC9010QC remote | | Yes | | [Teknopoint](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teknopoint.cpp) | **Teknopoint** | Allegro SSA-09H A/C
GZ-055B-E1 remote | | - | | [Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.cpp) | **[Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.h)** | 42NQV025M2 / 38NYV025M2 A/C
42NQV035M2 / 38NYV035M2 A/C
42NQV050M2 / 38NYV050M2 A/C
42NQV060M2 / 38NYV060M2 A/C | | Yes | -| [Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.cpp) | **[Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.h)** | Akita EVO II
RAS 18SKP-ES
RAS-2558V A/C
RAS-B13N3KV2
RAS-B13N3KVP-E
WC-L03SE
WH-TA04NE
WH-UB03NJ remote | | Yes | +| [Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.cpp) | **[Toshiba](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Toshiba.h)** | Akita EVO II
RAS 18SKP-ES
RAS-2558V A/C
RAS-25SKVP2-ND A/C
RAS-B13N3KV2
RAS-B13N3KVP-E
WC-L03SE
WH-TA01JE remote
WH-TA04NE
WH-UB03NJ remote | | Yes | | [Transcold](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Transcold.cpp) | **[Transcold](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Transcold.h)** | M1-F-NO-6 A/C | | Yes | | [Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.cpp) | **[Duux](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.h)** | Blizzard Smart 10K / DXMA04 A/C (TROTEC) | | Yes | | [Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.cpp) | **[Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Trotec.h)** | PAC 3200 A/C (TROTEC)
PAC 3550 Pro A/C (TROTEC_3550) | | Yes | @@ -149,6 +151,7 @@ - CARRIER_AC40 - CARRIER_AC64 - COOLIX +- COOLIX48 - CORONA_AC - DAIKIN - DAIKIN128 diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRMQTTServer/IRMQTTServer.ino b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRMQTTServer/IRMQTTServer.ino index 180c4214c..c2e427166 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRMQTTServer/IRMQTTServer.ino +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRMQTTServer/IRMQTTServer.ino @@ -1249,7 +1249,7 @@ void handleInfo(void) { "Built: " __DATE__ " " __TIME__ "
" "Period Offset: ") + String(offset) + F("us
" - "IR Lib Version: " _IRREMOTEESP8266_VERSION_ "
" + "IR Lib Version: " _IRREMOTEESP8266_VERSION_STR "
" #if defined(ESP8266) "ESP8266 Core Version: ") + ESP.getCoreVersion() + F("
" "Free Sketch Space: ") + String(maxSketchSpace() >> 10) + F("k
" diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV2/IRrecvDumpV2.ino b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV2/IRrecvDumpV2.ino index ae7e21dab..70dbdba42 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV2/IRrecvDumpV2.ino +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV2/IRrecvDumpV2.ino @@ -154,7 +154,7 @@ void loop() { if (results.overflow) Serial.printf(D_WARN_BUFFERFULL "\n", kCaptureBufferSize); // Display the library version the message was captured with. - Serial.println(D_STR_LIBRARY " : v" _IRREMOTEESP8266_VERSION_ "\n"); + Serial.println(D_STR_LIBRARY " : v" _IRREMOTEESP8266_VERSION_STR "\n"); // Display the tolerance percentage if it has been change from the default. if (kTolerancePercentage != kTolerance) Serial.printf(D_STR_TOLERANCE " : %d%%\n", kTolerancePercentage); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV3/IRrecvDumpV3.ino b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV3/IRrecvDumpV3.ino index fc2037368..0948ae5e9 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV3/IRrecvDumpV3.ino +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV3/IRrecvDumpV3.ino @@ -163,7 +163,7 @@ void loop() { if (results.overflow) Serial.printf(D_WARN_BUFFERFULL "\n", kCaptureBufferSize); // Display the library version the message was captured with. - Serial.println(D_STR_LIBRARY " : v" _IRREMOTEESP8266_VERSION_ "\n"); + Serial.println(D_STR_LIBRARY " : v" _IRREMOTEESP8266_VERSION_STR "\n"); // Display the tolerance percentage if it has been change from the default. if (kTolerancePercentage != kTolerance) Serial.printf(D_STR_TOLERANCE " : %d%%\n", kTolerancePercentage); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/keywords.txt b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/keywords.txt index 592b5d99b..8e0379173 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/keywords.txt +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/keywords.txt @@ -20,6 +20,8 @@ # Datatypes & Classes (KEYWORD1) ####################################### +CoronaSection KEYWORD1 +IRAirtonAc KEYWORD1 IRAirwellAc KEYWORD1 IRAmcorAc KEYWORD1 IRArgoAC KEYWORD1 @@ -147,6 +149,7 @@ addTempFloatToString KEYWORD2 addTempToString KEYWORD2 addToggleToString KEYWORD2 adjustRepeat KEYWORD2 +airton KEYWORD2 airwell KEYWORD2 amcor KEYWORD2 argo KEYWORD2 @@ -174,6 +177,7 @@ checkSum KEYWORD2 checkZjsSig KEYWORD2 checkZmsSig KEYWORD2 checksum KEYWORD2 +cleanState KEYWORD2 clearOnTimerFlag KEYWORD2 clearPowerSpecial KEYWORD2 clearSensorTemp KEYWORD2 @@ -211,6 +215,7 @@ decodeCOOLIX KEYWORD2 decodeCarrierAC KEYWORD2 decodeCarrierAC40 KEYWORD2 decodeCarrierAC64 KEYWORD2 +decodeCoolix48 KEYWORD2 decodeCoronaAc KEYWORD2 decodeDISH KEYWORD2 decodeDaikin KEYWORD2 @@ -339,6 +344,7 @@ fujitsu KEYWORD2 get10CHeat KEYWORD2 get3D KEYWORD2 get8CHeat KEYWORD2 +getAbsenseDetect KEYWORD2 getBeep KEYWORD2 getBit KEYWORD2 getBoost KEYWORD2 @@ -356,9 +362,11 @@ getCorrectedRawLength KEYWORD2 getCurrTime KEYWORD2 getCurrentDay KEYWORD2 getCurrentTime KEYWORD2 +getDirectIndirect KEYWORD2 getDisplay KEYWORD2 getDisplayTempSource KEYWORD2 getDryGrade KEYWORD2 +getEcocool KEYWORD2 getEcono KEYWORD2 getEconoToggle KEYWORD2 getEnableSensorTemp KEYWORD2 @@ -377,6 +385,8 @@ getHold KEYWORD2 getHumid KEYWORD2 getHumidity KEYWORD2 getIFeel KEYWORD2 +getISave10C KEYWORD2 +getISee KEYWORD2 getId KEYWORD2 getInternalStateLength KEYWORD2 getIon KEYWORD2 @@ -388,6 +398,7 @@ getLock KEYWORD2 getMax KEYWORD2 getMode KEYWORD2 getMold KEYWORD2 +getNaturalFlow KEYWORD2 getNight KEYWORD2 getOffSleepTimer KEYWORD2 getOffTime KEYWORD2 @@ -423,7 +434,9 @@ getSleepTimerEnabled KEYWORD2 getSpecial KEYWORD2 getSpeed KEYWORD2 getStartClock KEYWORD2 +getState KEYWORD2 getStateLength KEYWORD2 +getStatePrev KEYWORD2 getStopClock KEYWORD2 getSupercool KEYWORD2 getSwing KEYWORD2 @@ -474,6 +487,7 @@ haier KEYWORD2 haier176 KEYWORD2 haierYrwo2 KEYWORD2 handleSpecialState KEYWORD2 +handleToggles KEYWORD2 hasACState KEYWORD2 hasInvertedStates KEYWORD2 hasStateChanged KEYWORD2 @@ -571,6 +585,7 @@ sendCOOLIX KEYWORD2 sendCarrierAC KEYWORD2 sendCarrierAC40 KEYWORD2 sendCarrierAC64 KEYWORD2 +sendCoolix48 KEYWORD2 sendCoronaAc KEYWORD2 sendDISH KEYWORD2 sendDaikin KEYWORD2 @@ -679,6 +694,7 @@ serialPrintUint64 KEYWORD2 set10CHeat KEYWORD2 set3D KEYWORD2 set8CHeat KEYWORD2 +setAbsenseDetect KEYWORD2 setAuto KEYWORD2 setBeep KEYWORD2 setBit KEYWORD2 @@ -696,9 +712,11 @@ setCommand KEYWORD2 setCurrTime KEYWORD2 setCurrentDay KEYWORD2 setCurrentTime KEYWORD2 +setDirectIndirect KEYWORD2 setDisplay KEYWORD2 setDisplayTempSource KEYWORD2 setDryGrade KEYWORD2 +setEcocool KEYWORD2 setEcono KEYWORD2 setEconoToggle KEYWORD2 setEnableSensorTemp KEYWORD2 @@ -717,6 +735,8 @@ setHold KEYWORD2 setHumid KEYWORD2 setHumidity KEYWORD2 setIFeel KEYWORD2 +setISave10C KEYWORD2 +setISee KEYWORD2 setId KEYWORD2 setInvertedStates KEYWORD2 setIon KEYWORD2 @@ -729,6 +749,7 @@ setMax KEYWORD2 setMode KEYWORD2 setModel KEYWORD2 setMold KEYWORD2 +setNaturalFlow KEYWORD2 setNight KEYWORD2 setOffTime KEYWORD2 setOffTimeEnabled KEYWORD2 @@ -819,6 +840,7 @@ technibel KEYWORD2 teco KEYWORD2 ticksHigh KEYWORD2 ticksLow KEYWORD2 +toCommon KEYWORD2 toString KEYWORD2 toggleArrisRelease KEYWORD2 toggleRC5 KEYWORD2 @@ -896,6 +918,7 @@ CARRIER_AC40 LITERAL1 CARRIER_AC64 LITERAL1 CARRIER_AC_BITS LITERAL1 COOLIX LITERAL1 +COOLIX48 LITERAL1 COOLIX_BITS LITERAL1 CORONA_AC LITERAL1 DAIKIN LITERAL1 @@ -930,6 +953,7 @@ DECODE_CARRIER_AC LITERAL1 DECODE_CARRIER_AC40 LITERAL1 DECODE_CARRIER_AC64 LITERAL1 DECODE_COOLIX LITERAL1 +DECODE_COOLIX48 LITERAL1 DECODE_CORONA_AC LITERAL1 DECODE_DAIKIN LITERAL1 DECODE_DAIKIN128 LITERAL1 @@ -1284,6 +1308,7 @@ SEND_CARRIER_AC LITERAL1 SEND_CARRIER_AC40 LITERAL1 SEND_CARRIER_AC64 LITERAL1 SEND_COOLIX LITERAL1 +SEND_COOLIX48 LITERAL1 SEND_CORONA_AC LITERAL1 SEND_DAIKIN LITERAL1 SEND_DAIKIN128 LITERAL1 @@ -1443,13 +1468,27 @@ k8CHeatStr LITERAL1 kA705Str LITERAL1 kA903Str LITERAL1 kA907Str LITERAL1 +kAbsenseDetectStr LITERAL1 kAirFlowStr LITERAL1 +kAirtonAuto LITERAL1 kAirtonBitMark LITERAL1 kAirtonBits LITERAL1 +kAirtonCool LITERAL1 kAirtonDefaultRepeat LITERAL1 +kAirtonDry LITERAL1 +kAirtonFan LITERAL1 +kAirtonFanAuto LITERAL1 +kAirtonFanHigh LITERAL1 +kAirtonFanLow LITERAL1 +kAirtonFanMax LITERAL1 +kAirtonFanMed LITERAL1 +kAirtonFanMin LITERAL1 kAirtonFreq LITERAL1 kAirtonHdrMark LITERAL1 kAirtonHdrSpace LITERAL1 +kAirtonHeat LITERAL1 +kAirtonMaxTemp LITERAL1 +kAirtonMinTemp LITERAL1 kAirtonOneSpace LITERAL1 kAirtonZeroSpace LITERAL1 kAirwellAuto LITERAL1 @@ -1645,6 +1684,8 @@ kCommandStr LITERAL1 kCool LITERAL1 kCoolStr LITERAL1 kCoolingStr LITERAL1 +kCoolix48Bits LITERAL1 +kCoolix48ExtraTolerance LITERAL1 kCoolixAuto LITERAL1 kCoolixBitMark LITERAL1 kCoolixBitMarkTicks LITERAL1 @@ -1997,6 +2038,8 @@ kDenonZeroSpaceTicks LITERAL1 kDg11j104Str LITERAL1 kDg11j13aStr LITERAL1 kDg11j191Str LITERAL1 +kDirectIndirectModeStr LITERAL1 +kDirectStr LITERAL1 kDishBitMark LITERAL1 kDishBitMarkTicks LITERAL1 kDishBits LITERAL1 @@ -2478,6 +2521,7 @@ kHourStr LITERAL1 kHoursStr LITERAL1 kHumidStr LITERAL1 kIFeelStr LITERAL1 +kISeeStr LITERAL1 kIdStr LITERAL1 kIdleState LITERAL1 kInaxBitMark LITERAL1 @@ -2489,6 +2533,7 @@ kInaxMinRepeat LITERAL1 kInaxOneSpace LITERAL1 kInaxTick LITERAL1 kInaxZeroSpace LITERAL1 +kIndirectStr LITERAL1 kInsideStr LITERAL1 kIonStr LITERAL1 kJkeStr LITERAL1 @@ -2894,6 +2939,8 @@ kMitsubishiACStateLength LITERAL1 kMitsubishiAcAuto LITERAL1 kMitsubishiAcBitMark LITERAL1 kMitsubishiAcCool LITERAL1 +kMitsubishiAcDirect LITERAL1 +kMitsubishiAcDirectOff LITERAL1 kMitsubishiAcDry LITERAL1 kMitsubishiAcExtraTolerance LITERAL1 kMitsubishiAcFan LITERAL1 @@ -2905,6 +2952,7 @@ kMitsubishiAcFanSilent LITERAL1 kMitsubishiAcHdrMark LITERAL1 kMitsubishiAcHdrSpace LITERAL1 kMitsubishiAcHeat LITERAL1 +kMitsubishiAcIndirect LITERAL1 kMitsubishiAcMaxTemp LITERAL1 kMitsubishiAcMinTemp LITERAL1 kMitsubishiAcNoTimer LITERAL1 diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.json b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.json index 99160ec37..e1777f1c4 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.json +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.json @@ -1,6 +1,6 @@ { "name": "IRremoteESP8266", - "version": "2.8.0", + "version": "2.8.1", "keywords": "infrared, ir, remote, esp8266, esp32", "description": "Send and receive infrared signals with multiple protocols (ESP8266/ESP32)", "repository": diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.properties b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.properties index e7580dd2d..5ee1f5229 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.properties +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.properties @@ -1,5 +1,5 @@ name=IRremoteESP8266 -version=2.8.0 +version=2.8.1 author=David Conran, Sebastien Warin, Mark Szabo, Ken Shirriff maintainer=David Conran, Mark Szabo, Sebastien Warin, Roi Dayan, Massimiliano Pinto, Christian Nilsson sentence=Send and receive infrared signals with multiple protocols (ESP8266/ESP32) diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.cpp index 557e5593e..f9d9647d3 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.cpp @@ -16,6 +16,7 @@ #include "IRremoteESP8266.h" #include "IRtext.h" #include "IRutils.h" +#include "ir_Airton.h" #include "ir_Airwell.h" #include "ir_Amcor.h" #include "ir_Argo.h" @@ -56,7 +57,7 @@ #ifndef STRCASECMP #if defined(ESP8266) #define STRCASECMP(LHS, RHS) \ - strcasecmp_P(LHS, reinterpret_cast(RHS)) + strcasecmp_P(LHS, reinterpret_cast(RHS)) #else // ESP8266 #define STRCASECMP(LHS, RHS) strcasecmp(LHS, RHS) #endif // ESP8266 @@ -152,9 +153,12 @@ stdAc::state_t IRac::getStatePrev(void) { return _prev; } /// @return true if the protocol is supported by this class, otherwise false. bool IRac::isProtocolSupported(const decode_type_t protocol) { switch (protocol) { +#if SEND_AIRTON + case decode_type_t::AIRTON: +#endif // SEND_AIRTON #if SEND_AIRWELL case decode_type_t::AIRWELL: -#endif +#endif // SEND_AIRWELL #if SEND_AMCOR case decode_type_t::AMCOR: #endif @@ -326,6 +330,44 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) { } } +#if SEND_AIRTON +/// Send an Airton 56-bit A/C message with the supplied settings. +/// @param[in, out] ac A Ptr to an IRAirtonAc object to use. +/// @param[in] on The power setting. +/// @param[in] mode The operation mode setting. +/// @param[in] degrees The temperature setting in degrees. +/// @param[in] fan The speed setting for the fan. +/// @param[in] swingv The vertical swing setting. +/// @param[in] turbo Run the device in turbo/powerful mode. +/// @param[in] light Turn on the LED/Display mode. +/// @param[in] econo Run the device in economical mode. +/// @param[in] filter Turn on the (ion/pollen/health/etc) filter mode. +/// @param[in] sleep Nr. of minutes for sleep mode. +/// @note -1 is Off, >= 0 is on. +void IRac::airton(IRAirtonAc *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const bool turbo, + const bool light, const bool econo, const bool filter, + const int16_t sleep) { + ac->begin(); + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwingV(swingv != stdAc::swingv_t::kOff); + // No Quiet setting available. + ac->setLight(light); + ac->setHealth(filter); + ac->setTurbo(turbo); + ac->setEcono(econo); + // No Clean setting available. + // No Beep setting available. + ac->setSleep(sleep >= 0); // Convert to a boolean. + ac->send(); +} +#endif // SEND_AIRTON + #if SEND_AIRWELL /// Send an Airwell A/C message with the supplied settings. /// @param[in, out] ac A Ptr to an IRAirwellAc object to use. @@ -1530,6 +1572,7 @@ void IRac::mitsubishi(IRMitsubishiAC *ac, ac->setVane(ac->convertSwingV(swingv)); ac->setWideVane(ac->convertSwingH(swingh)); if (quiet) ac->setFan(kMitsubishiAcFanSilent); + ac->setISave10C(false); // No Turbo setting available. // No Light setting available. // No Filter setting available. @@ -2116,11 +2159,12 @@ void IRac::teco(IRTecoAc *ac, /// @param[in] swingv The vertical swing setting. /// @param[in] turbo Run the device in turbo/powerful mode. /// @param[in] econo Run the device in economical mode. +/// @param[in] filter Turn on the (Pure/ion/pollen/etc) filter mode. void IRac::toshiba(IRToshibaAC *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, - const bool turbo, const bool econo) { + const bool turbo, const bool econo, const bool filter) { ac->begin(); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); @@ -2133,7 +2177,7 @@ void IRac::toshiba(IRToshibaAC *ac, ac->setTurbo(turbo); ac->setEcono(econo); // No Light setting available. - // No Filter setting available. + ac->setFilter(filter); // No Clean setting available. // No Beep setting available. // No Sleep setting available. @@ -2603,6 +2647,16 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { #endif // (SEND_LG || SEND_SHARP_AC) // Per vendor settings & setup. switch (send.protocol) { +#if SEND_AIRTON + case AIRTON: + { + IRAirtonAc ac(_pin, _inverted, _modulation); + airton(&ac, send.power, send.mode, degC, send.fanspeed, + send.swingv, send.turbo, send.light, send.econo, send.filter, + send.sleep); + break; + } +#endif // SEND_AIRTON #if SEND_AIRWELL case AIRWELL: { @@ -3062,7 +3116,7 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { { IRToshibaAC ac(_pin, _inverted, _modulation); toshiba(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv, - send.turbo, send.econo); + send.turbo, send.econo, send.filter); break; } #endif // SEND_TOSHIBA_AC @@ -3507,6 +3561,13 @@ namespace IRAcUtils { /// An empty string if we can't. String resultAcToString(const decode_results * const result) { switch (result->decode_type) { +#if DECODE_AIRTON + case decode_type_t::AIRTON: { + IRAirtonAc ac(kGpioUnused); + ac.setRaw(result->value); // AIRTON uses value instead of state. + return ac.toString(); + } +#endif // DECODE_AIRTON #if DECODE_AIRWELL case decode_type_t::AIRWELL: { IRAirwellAc ac(kGpioUnused); @@ -3931,6 +3992,14 @@ namespace IRAcUtils { ) { if (decode == NULL || result == NULL) return false; // Safety check. switch (decode->decode_type) { +#if DECODE_AIRTON + case decode_type_t::AIRTON: { + IRAirtonAc ac(kGpioUnused); + ac.setRaw(decode->value); // Uses value instead of state. + *result = ac.toCommon(); + break; + } +#endif // DECODE_AIRTON #if DECODE_AIRWELL case decode_type_t::AIRWELL: { IRAirwellAc ac(kGpioUnused); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.h index afa4bcee0..9954eecb0 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.h @@ -7,6 +7,7 @@ #include #endif #include "IRremoteESP8266.h" +#include "ir_Airton.h" #include "ir_Airwell.h" #include "ir_Amcor.h" #include "ir_Argo.h" @@ -109,6 +110,14 @@ class IRac { bool _inverted; ///< IR LED is lit when GPIO is LOW (true) or HIGH (false)? bool _modulation; ///< Is frequency modulation to be used? stdAc::state_t _prev; ///< The state we expect the device to currently be in. +#if SEND_AIRTON + void airton(IRAirtonAc *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const bool turbo, + const bool light, const bool econo, const bool filter, + const int16_t sleep = -1); +#endif // SEND_AIRTON #if SEND_AIRWELL void airwell(IRAirwellAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, @@ -457,7 +466,7 @@ void electra(IRElectraAc *ac, void toshiba(IRToshibaAC *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, - const bool turbo, const bool econo); + const bool turbo, const bool econo, const bool filter); #endif // SEND_TOSHIBA_AC #if SEND_TROTEC void trotec(IRTrotecESP *ac, diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.cpp index 4970dcf0b..5b9d91b88 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.cpp @@ -13,7 +13,7 @@ extern "C" { } #endif // ESP8266 #include -#endif +#endif // UNIT_TEST #include #ifdef UNIT_TEST #include @@ -56,6 +56,20 @@ static ETSTimer timer; } // namespace _IRrecv #endif // ESP8266 #if defined(ESP32) +// We need a horrible timer hack for ESP32 Arduino framework < v2.0.0 +#if !defined(_ESP32_IRRECV_TIMER_HACK) +// Version check +#if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) +// No need for the hack if we are running version >= 2.0.0 +#define _ESP32_IRRECV_TIMER_HACK false +#else // Version check +// If no ESP_ARDUINO_VERSION_MAJOR is defined, or less than 2, then we are +// using an old ESP32 core, so we need the hack. +#define _ESP32_IRRECV_TIMER_HACK true +#endif // Version check +#endif // !defined(_ESP32_IRRECV_TIMER_HACK) + +#if _ESP32_IRRECV_TIMER_HACK // Required structs/types from: // https://github.com/espressif/arduino-esp32/blob/6b0114366baf986c155e8173ab7c22bc0c5fcedc/cores/esp32/esp32-hal-timer.c#L28-L58 // These are needed to be able to directly manipulate the timer registers from @@ -117,7 +131,7 @@ typedef struct hw_timer_s { uint8_t timer; portMUX_TYPE lock; } hw_timer_t; -// End of Horrible Hack. +#endif // _ESP32_IRRECV_TIMER_HACK / End of Horrible Hack. namespace _IRrecv { static hw_timer_t * timer = NULL; @@ -211,6 +225,7 @@ static void USE_IRAM_ATTR gpio_intr() { #if defined(ESP32) // Reset the timeout. // +#if _ESP32_IRRECV_TIMER_HACK // The following three lines of code are the equiv of: // `timerWrite(timer, 0);` // We can't call that routine safely from inside an ISR as that procedure @@ -226,6 +241,10 @@ static void USE_IRAM_ATTR gpio_intr() { // @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1350 // @see https://github.com/espressif/arduino-esp32/blob/6b0114366baf986c155e8173ab7c22bc0c5fcedc/cores/esp32/esp32-hal-timer.c#L176-L178 timer->dev->config.alarm_en = 1; +#else // _ESP32_IRRECV_TIMER_HACK + timerWrite(timer, 0); + timerAlarmEnable(timer); +#endif // _ESP32_IRRECV_TIMER_HACK #endif // ESP32 } #endif // UNIT_TEST @@ -337,7 +356,9 @@ void IRrecv::enableIRIn(const bool pullup) { // Set the timer so it only fires once, and set it's trigger in uSeconds. timerAlarmWrite(timer, MS_TO_USEC(params.timeout), ONCE); // Note: Interrupt needs to be attached before it can be enabled or disabled. - timerAttachInterrupt(timer, &read_timeout, true); + // Note: EDGE (true) is not supported, use LEVEL (false). Ref: #1713 + // See: https://github.com/espressif/arduino-esp32/blob/caef4006af491130136b219c1205bdcf8f08bf2b/cores/esp32/esp32-hal-timer.c#L224-L227 + timerAttachInterrupt(timer, &read_timeout, false); #endif // ESP32 // Initialise state machine variables @@ -695,9 +716,9 @@ bool IRrecv::decode(decode_results *results, irparams_t *save, if (decodeSharp(results, offset)) return true; #endif #if DECODE_COOLIX - DPRINTLN("Attempting Coolix decode"); + DPRINTLN("Attempting Coolix 24-bit decode"); if (decodeCOOLIX(results, offset)) return true; -#endif +#endif // DECODE_COOLIX #if DECODE_NIKAI DPRINTLN("Attempting Nikai decode"); if (decodeNikai(results, offset)) return true; @@ -1047,6 +1068,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save, DPRINTLN("Attempting Airton decode"); if (decodeAirton(results, offset)) return true; #endif // DECODE_AIRTON +#if DECODE_COOLIX48 + DPRINTLN("Attempting Coolix 48-bit decode"); + if (decodeCoolix48(results, offset)) return true; +#endif // DECODE_COOLIX48 // Typically new protocols are added above this line. } #if DECODE_HASH @@ -1079,7 +1104,7 @@ uint32_t IRrecv::ticksLow(const uint32_t usecs, const uint8_t tolerance, // max() used to ensure the result can't drop below 0 before the cast. return ((uint32_t)std::max( (int32_t)(usecs * (1.0 - _validTolerance(tolerance) / 100.0) - delta), - 0)); + (int32_t)0)); } /// Calculate the upper bound of the nr. of ticks. @@ -1162,7 +1187,8 @@ bool IRrecv::matchAtLeast(uint32_t measured, uint32_t desired, // We really should never get a value of 0, except as the last value // in the buffer. If that is the case, then assume infinity and return true. if (measured == 0) return true; - return measured >= ticksLow(std::min(desired, MS_TO_USEC(params.timeout)), + return measured >= ticksLow(std::min(desired, + (uint32_t)MS_TO_USEC(params.timeout)), tolerance, delta); } diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.h index f4932b5a6..75070172d 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.h @@ -419,7 +419,12 @@ class IRrecv { bool decodeCOOLIX(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kCoolixBits, const bool strict = true); -#endif +#endif // DECODE_COOLIX +#if DECODE_COOLIX48 + bool decodeCoolix48(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kCoolix48Bits, + const bool strict = true); +#endif // DECODE_COOLIX48 #if DECODE_DENON bool decodeDenon(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kDenonBits, diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRremoteESP8266.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRremoteESP8266.h index 09a3011ce..3cd19a81d 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRremoteESP8266.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRremoteESP8266.h @@ -52,8 +52,29 @@ #include #endif // UNIT_TEST -// Library Version -#define _IRREMOTEESP8266_VERSION_ "2.8.0" +// Library Version Information +// Major version number (X.x.x) +#define _IRREMOTEESP8266_VERSION_MAJOR 2 +// Minor version number (x.X.x) +#define _IRREMOTEESP8266_VERSION_MINOR 8 +// Patch version number (x.x.X) +#define _IRREMOTEESP8266_VERSION_PATCH 1 +// Macro to convert version info into an integer +#define _IRREMOTEESP8266_VERSION_VAL(major, minor, patch) \ + ((major << 16) | (minor << 8) | (patch)) +// Macro to convert literal into a string +#define MKSTR(x) #x +// Integer version +#define _IRREMOTEESP8266_VERSION _IRREMOTEESP8266_VERSION_VAL(\ + _IRREMOTEESP8266_VERSION_MAJOR, \ + _IRREMOTEESP8266_VERSION_MINOR, \ + _IRREMOTEESP8266_VERSION_PATCH) +// String version +#define _IRREMOTEESP8266_VERSION_STR MKSTR(_IRREMOTEESP8266_VERSION_MAJOR) "." \ + MKSTR(_IRREMOTEESP8266_VERSION_MINOR) "." \ + MKSTR(_IRREMOTEESP8266_VERSION_PATCH) +// String version (DEPRECATED) +#define _IRREMOTEESP8266_VERSION_ _IRREMOTEESP8266_VERSION_STR // Set the language & locale for the library. See the `locale` dir for options. #ifndef _IR_LOCALE_ @@ -314,6 +335,13 @@ #define SEND_COOLIX _IR_ENABLE_DEFAULT_ #endif // SEND_COOLIX +#ifndef DECODE_COOLIX48 +#define DECODE_COOLIX48 _IR_ENABLE_DEFAULT_ +#endif // DECODE_COOLIX48 +#ifndef SEND_COOLIX48 +#define SEND_COOLIX48 _IR_ENABLE_DEFAULT_ +#endif // SEND_COOLIX48 + #ifndef DECODE_GLOBALCACHE #define DECODE_GLOBALCACHE false // Not applicable. #endif // DECODE_GLOBALCACHE @@ -975,8 +1003,9 @@ enum decode_type_t { ARRIS, RHOSS, AIRTON, + COOLIX48, // 110 // Add new entries before this one, and update it to point to the last entry. - kLastDecodeType = AIRTON, + kLastDecodeType = COOLIX48, }; // Message lengths & required repeat values @@ -998,6 +1027,7 @@ const uint16_t kArgoBits = kArgoStateLength * 8; const uint16_t kArgoDefaultRepeat = kNoRepeat; const uint16_t kArrisBits = 32; const uint16_t kCoolixBits = 24; +const uint16_t kCoolix48Bits = kCoolixBits * 2; const uint16_t kCoolixDefaultRepeat = kSingleRepeat; const uint16_t kCarrierAcBits = 32; const uint16_t kCarrierAcMinRepeat = kNoRepeat; diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.cpp index e20b97045..e0a66e068 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.cpp @@ -560,6 +560,7 @@ uint16_t IRsend::minRepeats(const decode_type_t protocol) { case AIWA_RC_T501: case AMCOR: case COOLIX: + case COOLIX48: case ELITESCREENS: case GICABLE: case INAX: @@ -661,6 +662,7 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) { return kDoshishaBits; // 40 case SANYO_LC7461: return kSanyoLC7461Bits; // 42 + case COOLIX48: case GOODWEATHER: case KELON: case MIDEA: @@ -829,7 +831,12 @@ bool IRsend::send(const decode_type_t type, const uint64_t data, case COOLIX: sendCOOLIX(data, nbits, min_repeat); break; -#endif +#endif // SEND_COOLIX +#if SEND_COOLIX48 + case COOLIX48: + sendCoolix48(data, nbits, min_repeat); + break; +#endif // SEND_COOLIX48 #if SEND_DAIKIN64 case DAIKIN64: sendDaikin64(data, nbits, min_repeat); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.h index d55ce0238..3696eb40f 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.h @@ -42,78 +42,78 @@ const uint32_t kDefaultMessageGap = 100000; /// Enumerators and Structures for the Common A/C API. namespace stdAc { - /// Common A/C settings for A/C operating modes. - enum class opmode_t { - kOff = -1, - kAuto = 0, - kCool = 1, - kHeat = 2, - kDry = 3, - kFan = 4, - // Add new entries before this one, and update it to point to the last entry - kLastOpmodeEnum = kFan, - }; +/// Common A/C settings for A/C operating modes. +enum class opmode_t { + kOff = -1, + kAuto = 0, + kCool = 1, + kHeat = 2, + kDry = 3, + kFan = 4, + // Add new entries before this one, and update it to point to the last entry + kLastOpmodeEnum = kFan, +}; - /// Common A/C settings for Fan Speeds. - enum class fanspeed_t { - kAuto = 0, - kMin = 1, - kLow = 2, - kMedium = 3, - kHigh = 4, - kMax = 5, - // Add new entries before this one, and update it to point to the last entry - kLastFanspeedEnum = kMax, - }; +/// Common A/C settings for Fan Speeds. +enum class fanspeed_t { + kAuto = 0, + kMin = 1, + kLow = 2, + kMedium = 3, + kHigh = 4, + kMax = 5, + // Add new entries before this one, and update it to point to the last entry + kLastFanspeedEnum = kMax, +}; - /// Common A/C settings for Vertical Swing. - enum class swingv_t { - kOff = -1, - kAuto = 0, - kHighest = 1, - kHigh = 2, - kMiddle = 3, - kLow = 4, - kLowest = 5, - // Add new entries before this one, and update it to point to the last entry - kLastSwingvEnum = kLowest, - }; +/// Common A/C settings for Vertical Swing. +enum class swingv_t { + kOff = -1, + kAuto = 0, + kHighest = 1, + kHigh = 2, + kMiddle = 3, + kLow = 4, + kLowest = 5, + // Add new entries before this one, and update it to point to the last entry + kLastSwingvEnum = kLowest, +}; - /// Common A/C settings for Horizontal Swing. - enum class swingh_t { - kOff = -1, - kAuto = 0, // a.k.a. On. - kLeftMax = 1, - kLeft = 2, - kMiddle = 3, - kRight = 4, - kRightMax = 5, - kWide = 6, // a.k.a. left & right at the same time. - // Add new entries before this one, and update it to point to the last entry - kLastSwinghEnum = kWide, - }; +/// Common A/C settings for Horizontal Swing. +enum class swingh_t { + kOff = -1, + kAuto = 0, // a.k.a. On. + kLeftMax = 1, + kLeft = 2, + kMiddle = 3, + kRight = 4, + kRightMax = 5, + kWide = 6, // a.k.a. left & right at the same time. + // Add new entries before this one, and update it to point to the last entry + kLastSwinghEnum = kWide, +}; - /// Structure to hold a common A/C state. - typedef struct { - decode_type_t protocol; - int16_t model; - bool power; - stdAc::opmode_t mode; - float degrees; - bool celsius; - stdAc::fanspeed_t fanspeed; - stdAc::swingv_t swingv; - stdAc::swingh_t swingh; - bool quiet; - bool turbo; - bool econo; - bool light; - bool filter; - bool clean; - bool beep; - int16_t sleep; - int16_t clock; - } state_t; +/// Structure to hold a common A/C state. +struct state_t { + decode_type_t protocol; + int16_t model; + bool power; + stdAc::opmode_t mode; + float degrees; + bool celsius; + stdAc::fanspeed_t fanspeed; + stdAc::swingv_t swingv; + stdAc::swingh_t swingh; + bool quiet; + bool turbo; + bool econo; + bool light; + bool filter; + bool clean; + bool beep; + int16_t sleep; + int16_t clock; +}; }; // namespace stdAc /// Fujitsu A/C model numbers @@ -381,9 +381,13 @@ class IRsend { uint16_t repeat = kNoRepeat); #endif #if SEND_COOLIX - void sendCOOLIX(uint64_t data, uint16_t nbits = kCoolixBits, - uint16_t repeat = kCoolixDefaultRepeat); -#endif + void sendCOOLIX(const uint64_t data, const uint16_t nbits = kCoolixBits, + const uint16_t repeat = kCoolixDefaultRepeat); +#endif // SEND_COOLIX +#if SEND_COOLIX48 + void sendCoolix48(const uint64_t data, const uint16_t nbits = kCoolix48Bits, + const uint16_t repeat = kCoolixDefaultRepeat); +#endif // SEND_COOLIX48 #if SEND_WHYNTER void sendWhynter(const uint64_t data, const uint16_t nbits = kWhynterBits, const uint16_t repeat = kNoRepeat); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.cpp index a580bff9f..077e7b0e7 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.cpp @@ -81,6 +81,14 @@ IRTEXT_CONST_STRING(kHoldStr, D_STR_HOLD); ///< "Hold" IRTEXT_CONST_STRING(kButtonStr, D_STR_BUTTON); ///< "Button" IRTEXT_CONST_STRING(k8CHeatStr, D_STR_8C_HEAT); ///< "8C Heat" IRTEXT_CONST_STRING(k10CHeatStr, D_STR_10C_HEAT); ///< "10C Heat" +IRTEXT_CONST_STRING(kISeeStr, D_STR_ISEE); ///< "ISee" +IRTEXT_CONST_STRING(kAbsenseDetectStr, D_STR_ABSENSEDETECT); + ///< "AbsenseDetect" +IRTEXT_CONST_STRING(kDirectIndirectModeStr, D_STR_DIRECTINDIRECTMODE); + ///< "Direct/Indirect mode" +IRTEXT_CONST_STRING(kDirectStr, D_STR_DIRECT); ///< "Direct" +IRTEXT_CONST_STRING(kIndirectStr, D_STR_INDIRECT); ///< "Indirect" + IRTEXT_CONST_STRING(kNightStr, D_STR_NIGHT); ///< "Night" IRTEXT_CONST_STRING(kSilentStr, D_STR_SILENT); ///< "Silent" IRTEXT_CONST_STRING(kFilterStr, D_STR_FILTER); ///< "Filter" @@ -382,6 +390,7 @@ IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) { D_STR_ARRIS "\x0" D_STR_RHOSS "\x0" D_STR_AIRTON "\x0" + D_STR_COOLIX48 "\x0" ///< New protocol strings should be added just above this line. "\x0" ///< This string requires double null termination. }; diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.h index ee8ea5934..031f73879 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.h @@ -231,5 +231,11 @@ extern IRTEXT_CONST_PTR(kYbofbStr); extern IRTEXT_CONST_PTR(kYesStr); extern IRTEXT_CONST_PTR(kZoneFollowStr); extern IRTEXT_CONST_PTR(kAllProtocolNamesStr); +extern IRTEXT_CONST_PTR(kISeeStr); +extern IRTEXT_CONST_PTR(kEcocoolStr); +extern IRTEXT_CONST_PTR(kAbsenseDetectStr); +extern IRTEXT_CONST_PTR(kDirectIndirectModeStr); +extern IRTEXT_CONST_PTR(kDirectStr); +extern IRTEXT_CONST_PTR(kIndirectStr); #endif // IRTEXT_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.cpp index d3a83c507..e1f889966 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.cpp @@ -1049,6 +1049,21 @@ namespace irutils { return nibbleonly ? sum & 0xF : sum; } + /// Sum all the bytes together in an integer. + /// @param[in] data The integer to be summed. + /// @param[in] count The number of bytes to sum. Starts from LSB. Max of 8. + /// @param[in] init Starting value of the calculation to use. (Default is 0) + /// @param[in] byteonly true, the result is 8 bits. false, it's 16 bits. + /// @return The 8/16-bit calculated result of all the bytes and init value. + uint16_t sumBytes(const uint64_t data, const uint8_t count, + const uint8_t init, const bool byteonly) { + uint16_t sum = init; + uint64_t copy = data; + const uint8_t nrofbytes = (count < 8) ? count : (64 / 8); + for (uint8_t i = 0; i < nrofbytes; i++, copy >>= 8) sum += (copy & 0xFF); + return byteonly ? sum & 0xFF : sum; + } + /// Convert a byte of Binary Coded Decimal(BCD) into an Integer. /// @param[in] bcd The BCD value. /// @return A normal Integer value. diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.h index 61fe8b269..a5dcde043 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.h @@ -94,6 +94,8 @@ namespace irutils { const uint8_t init = 0); uint8_t sumNibbles(const uint64_t data, const uint8_t count = 16, const uint8_t init = 0, const bool nibbleonly = true); + uint16_t sumBytes(const uint64_t data, const uint8_t count = 8, + const uint8_t init = 0, const bool byteonly = true); uint8_t bcdToUint8(const uint8_t bcd); uint8_t uint8ToBcd(const uint8_t integer); bool getBit(const uint64_t data, const uint8_t position, diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Airton.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Airton.cpp index 507894f37..83ad95ef7 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Airton.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Airton.cpp @@ -3,12 +3,11 @@ /// @brief Support for Airton protocol /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1670 -// Supports: -// Brand: Airton, Model: SMVH09B-2A2A3NH ref. 409730 A/C -// Brand: Airton, Model: RD1A1 remote - +#include "ir_Airton.h" +#include #include "IRrecv.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" const uint16_t kAirtonHdrMark = 6630; @@ -18,6 +17,12 @@ const uint16_t kAirtonOneSpace = 1260; const uint16_t kAirtonZeroSpace = 430; const uint16_t kAirtonFreq = 38000; // Hz. (Just a guess) +using irutils::addBoolToString; +using irutils::addModeToString; +using irutils::addFanToString; +using irutils::addTempToString; +using irutils::sumBytes; + #if SEND_AIRTON // Function should be safe up to 64 bits. /// Send a Airton formatted message. @@ -59,7 +64,8 @@ bool IRrecv::decodeAirton(decode_results *results, uint16_t offset, kAirtonBitMark, kAirtonZeroSpace, kAirtonBitMark, kDefaultMessageGap, true, kUseDefTol, kMarkExcess, false)) return false; - + // Compliance + if (strict && !IRAirtonAc::validChecksum(results->value)) return false; // Success results->decode_type = decode_type_t::AIRTON; results->bits = nbits; @@ -68,3 +74,289 @@ bool IRrecv::decodeAirton(decode_results *results, uint16_t offset, return true; } #endif // DECODE_AIRTON + +/// Class constructor +/// @param[in] pin GPIO to be used when sending. +/// @param[in] inverted Is the output signal to be inverted? +/// @param[in] use_modulation Is frequency modulation to be used? +IRAirtonAc::IRAirtonAc(const uint16_t pin, const bool inverted, + const bool use_modulation) + : _irsend(pin, inverted, use_modulation) { stateReset(); } + +/// Set up hardware to be able to send a message. +void IRAirtonAc::begin(void) { _irsend.begin(); } + +#if SEND_AIRTON +/// Send the current internal state as an IR message. +/// @param[in] repeat Nr. of times the message will be repeated. +void IRAirtonAc::send(const uint16_t repeat) { + _irsend.sendAirton(getRaw(), kAirtonBits, repeat); +} +#endif // SEND_AIRTON + +/// Calculate the checksum for the supplied state. +/// @param[in] state The source state to generate the checksum from. +/// @return The checksum value. +uint8_t IRAirtonAc::calcChecksum(const uint64_t state) { + return (uint8_t)(0x7F - sumBytes(state, 6)) ^ 0x2C; +} + +/// Verify the checksum is valid for a given state. +/// @param[in] state The value to verify the checksum of. +/// @return A boolean indicating if it's checksum is valid. +bool IRAirtonAc::validChecksum(const uint64_t state) { + AirtonProtocol p; + p.raw = state; + return p.Sum == IRAirtonAc::calcChecksum(state); +} + +/// Update the checksum value for the internal state. +void IRAirtonAc::checksum(void) { _.Sum = IRAirtonAc::calcChecksum(_.raw); } + +/// Reset the internals of the object to a known good state. +void IRAirtonAc::stateReset(void) { setRaw(0x11D3); } + +/// Get the raw state of the object, suitable to be sent with the appropriate +/// IRsend object method. +/// @return A copy to the internal state. +uint64_t IRAirtonAc::getRaw(void) { + checksum(); // Ensure correct bit array before returning + return _.raw; +} + +/// Set the raw state of the object. +/// @param[in] state The raw state from the native IR message. +void IRAirtonAc::setRaw(const uint64_t state) { _.raw = state; } + + +/// Set the internal state to have the power on. +void IRAirtonAc::on(void) { setPower(true); } + +/// Set the internal state to have the power off. +void IRAirtonAc::off(void) { setPower(false); } + +/// Set the internal state to have the desired power. +/// @param[in] on The desired power state. +void IRAirtonAc::setPower(const bool on) { + _.Power = on; + setMode(getMode()); // Re-do the mode incase we need to do something special. +} + +/// Get the power setting from the internal state. +/// @return A boolean indicating the power setting. +bool IRAirtonAc::getPower(void) const { return _.Power; } + +/// Get the current operation mode setting. +/// @return The current operation mode. +uint8_t IRAirtonAc::getMode(void) const { return _.Mode; } + +/// Set the desired operation mode. +/// @param[in] mode The desired operation mode. +void IRAirtonAc::setMode(const uint8_t mode) { + // Changing the mode always removes the sleep setting. + if (mode != _.Mode) setSleep(false); + // Set the actual mode. + _.Mode = (mode > kAirtonHeat) ? kAirtonAuto : mode; + // Handle special settings for each mode. + switch (_.Mode) { + case kAirtonAuto: + setTemp(25); // Auto has a fixed temp. + _.NotAutoOn = !getPower(); + break; + case kAirtonHeat: + // When powered on and in Heat mode, set a special bit. + _.HeatOn = getPower(); + // FALL-THRU + default: + _.NotAutoOn = true; + } + // Reset the economy setting if we need to. + setEcono(getEcono()); +} + +/// Convert a stdAc::opmode_t enum into its native mode. +/// @param[in] mode The enum to be converted. +/// @return The native equivalent of the enum. +uint8_t IRAirtonAc::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: return kAirtonCool; + case stdAc::opmode_t::kHeat: return kAirtonHeat; + case stdAc::opmode_t::kDry: return kAirtonDry; + case stdAc::opmode_t::kFan: return kAirtonFan; + default: return kAirtonAuto; + } +} + +/// Convert a native mode into its stdAc equivalent. +/// @param[in] mode The native setting to be converted. +/// @return The stdAc equivalent of the native setting. +stdAc::opmode_t IRAirtonAc::toCommonMode(const uint8_t mode) { + switch (mode) { + case kAirtonCool: return stdAc::opmode_t::kCool; + case kAirtonHeat: return stdAc::opmode_t::kHeat; + case kAirtonDry: return stdAc::opmode_t::kDry; + case kAirtonFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; + } +} + +/// Set the temperature. +/// @param[in] degrees The temperature in degrees celsius. +void IRAirtonAc::setTemp(const uint8_t degrees) { + uint8_t temp = std::max(kAirtonMinTemp, degrees); + temp = std::min(kAirtonMaxTemp, temp); + if (_.Mode == kAirtonAuto) temp = kAirtonMaxTemp; // Auto has a fixed temp. + _.Temp = temp - kAirtonMinTemp; +} + +/// Get the current temperature setting. +/// @return Get current setting for temp. in degrees celsius. +uint8_t IRAirtonAc::getTemp(void) const { return _.Temp + kAirtonMinTemp; } + + +/// Set the speed of the fan. +/// @param[in] speed The desired setting. +void IRAirtonAc::setFan(const uint8_t speed) { + _.Fan = (speed > kAirtonFanMax) ? kAirtonFanAuto : speed; +} + +/// Get the current fan speed setting. +/// @return The current fan speed. +uint8_t IRAirtonAc::getFan(void) const { return _.Fan; } + +/// Convert a stdAc::fanspeed_t enum into it's native speed. +/// @param[in] speed The enum to be converted. +/// @return The native equivalent of the enum. +uint8_t IRAirtonAc::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: return kAirtonFanMin; + case stdAc::fanspeed_t::kLow: return kAirtonFanLow; + case stdAc::fanspeed_t::kMedium: return kAirtonFanMed; + case stdAc::fanspeed_t::kHigh: return kAirtonFanHigh; + case stdAc::fanspeed_t::kMax: return kAirtonFanMax; + default: return kAirtonFanAuto; + } +} + +/// Convert a native fan speed into its stdAc equivalent. +/// @param[in] speed The native setting to be converted. +/// @return The stdAc equivalent of the native setting. +stdAc::fanspeed_t IRAirtonAc::toCommonFanSpeed(const uint8_t speed) { + switch (speed) { + case kAirtonFanMax: return stdAc::fanspeed_t::kMax; + case kAirtonFanHigh: return stdAc::fanspeed_t::kHigh; + case kAirtonFanMed: return stdAc::fanspeed_t::kMedium; + case kAirtonFanLow: return stdAc::fanspeed_t::kLow; + case kAirtonFanMin: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; + } +} + +/// Set the Vertical Swing setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRAirtonAc::setSwingV(const bool on) { _.SwingV = on; } + +/// Get the Vertical Swing setting of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRAirtonAc::getSwingV(void) const { return _.SwingV; } + +/// Set the Light/LED/Display setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRAirtonAc::setLight(const bool on) { _.Light = on; } + +/// Get the Light/LED/Display setting of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRAirtonAc::getLight(void) const { return _.Light; } + +/// Set the Economy setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +/// @note Only available in Cool mode. +void IRAirtonAc::setEcono(const bool on) { + _.Econo = on && (getMode() == kAirtonCool); +} + +/// Get the Economy setting of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRAirtonAc::getEcono(void) const { return _.Econo; } + +/// Set the Turbo setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRAirtonAc::setTurbo(const bool on) { + _.Turbo = on; + // Pressing the turbo button sets the fan to max as well. + if (on) setFan(kAirtonFanMax); +} + +/// Get the Turbo setting of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRAirtonAc::getTurbo(void) const { return _.Turbo; } + +/// Set the Sleep setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +/// @note Sleep not available in fan or auto mode. +void IRAirtonAc::setSleep(const bool on) { + switch (getMode()) { + case kAirtonAuto: + case kAirtonFan: _.Sleep = false; break; + default: _.Sleep = on; + } +} + +/// Get the Sleep setting of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRAirtonAc::getSleep(void) const { return _.Sleep; } + +/// Set the Health/Filter setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRAirtonAc::setHealth(const bool on) { _.Health = on; } + +/// Get the Health/Filter setting of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRAirtonAc::getHealth(void) const { return _.Health; } + +/// Convert the current internal state into its stdAc::state_t equivalent. +/// @return The stdAc equivalent of the native settings. +stdAc::state_t IRAirtonAc::toCommon(void) const { + stdAc::state_t result; + result.protocol = decode_type_t::AIRTON; + result.power = getPower(); + result.mode = toCommonMode(getMode()); + result.celsius = true; + result.degrees = getTemp(); + result.fanspeed = toCommonFanSpeed(getFan()); + result.swingv = getSwingV() ? stdAc::swingv_t::kAuto : stdAc::swingv_t::kOff; + result.econo = getEcono(); + result.turbo = getTurbo(); + result.filter = getHealth(); + result.light = getLight(); + result.sleep = getSleep() ? 0 : -1; + // Not supported. + result.model = -1; + result.swingh = stdAc::swingh_t::kOff; + result.quiet = false; + result.clean = false; + result.beep = false; + result.clock = -1; + return result; +} + +/// Convert the current internal state into a human readable string. +/// @return A human readable string. +String IRAirtonAc::toString(void) const { + String result = ""; + result.reserve(135); // Reserve some heap for the string to reduce fragging. + result += addBoolToString(getPower(), kPowerStr, false); + result += addModeToString(_.Mode, kAirtonAuto, kAirtonCool, + kAirtonHeat, kAirtonDry, kAirtonFan); + result += addFanToString(_.Fan, kAirtonFanHigh, kAirtonFanLow, + kAirtonFanAuto, kAirtonFanMin, kAirtonFanMed, + kAirtonFanMax); + result += addTempToString(getTemp()); + result += addBoolToString(getSwingV(), kSwingVStr); + result += addBoolToString(getEcono(), kEconoStr); + result += addBoolToString(getTurbo(), kTurboStr); + result += addBoolToString(getLight(), kLightStr); + result += addBoolToString(getHealth(), kHealthStr); + result += addBoolToString(getSleep(), kSleepStr); + return result; +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Airton.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Airton.h new file mode 100644 index 000000000..9b5e89f3f --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Airton.h @@ -0,0 +1,134 @@ +// Copyright 2021 David Conran (crankyoldgit) +/// @file +/// @brief Support for Airton protocol +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1670 + +// Supports: +// Brand: Airton, Model: SMVH09B-2A2A3NH ref. 409730 A/C +// Brand: Airton, Model: RD1A1 remote + +#ifndef IR_AIRTON_H_ +#define IR_AIRTON_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif + +/// Native representation of a Airton 56 A/C message. +/// @see https://docs.google.com/spreadsheets/d/1Kpq7WCkh85heLnTQGlwUfCR6eeu_vfBHvhii8wtP4LU/edit?usp=sharing +union AirtonProtocol{ + uint64_t raw; ///< The state in code form. + struct { // Common + // Byte 1 & 0 (LSB) + uint16_t Header :16; // Header. (0x11D3) + // Byte 2 + uint8_t Mode :3; // Operating Mode + uint8_t Power :1; // Power Control + uint8_t Fan :3; + uint8_t Turbo :1; + // Byte 3 + uint8_t Temp :4; // Degrees Celsius (+16 offset) + uint8_t :4; // Unknown / Unused. + // Byte 4 + uint8_t SwingV :1; + uint8_t :7; // Unknown / Unused. + // Byte 5 + uint8_t Econo :1; + uint8_t Sleep :1; + uint8_t NotAutoOn :1; + uint8_t :1; // Unknown / Unused. + uint8_t HeatOn :1; + uint8_t :1; // Unknown / Unused. + uint8_t Health :1; + uint8_t Light :1; + // Byte 6 + uint8_t Sum :8; // Sepecial checksum value + }; +}; + +// Constants +const uint8_t kAirtonAuto = 0b000; // 0 +const uint8_t kAirtonCool = 0b001; // 1 +const uint8_t kAirtonDry = 0b010; // 2 +const uint8_t kAirtonFan = 0b011; // 3 +const uint8_t kAirtonHeat = 0b100; // 4 + +const uint8_t kAirtonFanAuto = 0b000; // 0 +const uint8_t kAirtonFanMin = 0b001; // 1 +const uint8_t kAirtonFanLow = 0b010; // 2 +const uint8_t kAirtonFanMed = 0b011; // 3 +const uint8_t kAirtonFanHigh = 0b100; // 4 +const uint8_t kAirtonFanMax = 0b101; // 5 + +const uint8_t kAirtonMinTemp = 16; // 16C +const uint8_t kAirtonMaxTemp = 25; // 25C + + +/// Class for handling detailed Airton 56-bit A/C messages. +class IRAirtonAc { + public: + explicit IRAirtonAc(const uint16_t pin, const bool inverted = false, + const bool use_modulation = true); + void stateReset(void); +#if SEND_AIRTON + void send(const uint16_t repeat = kAirtonDefaultRepeat); + /// Run the calibration to calculate uSec timing offsets for this platform. + /// @return The uSec timing offset needed per modulation of the IR Led. + /// @note This will produce a 65ms IR signal pulse at 38kHz. + /// Only ever needs to be run once per object instantiation, if at all. + int8_t calibrate(void) { return _irsend.calibrate(); } +#endif // SEND_AIRTON + void begin(void); + void on(void); + void off(void); + void setPower(const bool on); + bool getPower(void) const; + void setTemp(const uint8_t degrees); + uint8_t getTemp(void) const; + void setFan(const uint8_t speed); + uint8_t getFan(void) const; + void setMode(const uint8_t mode); + uint8_t getMode(void) const; + uint64_t getRaw(void); + void setRaw(const uint64_t data); + void setLight(const bool on); + bool getLight(void) const; + void setEcono(const bool on); + bool getEcono(void) const; + void setTurbo(const bool on); + bool getTurbo(void) const; + void setHealth(const bool on); + bool getHealth(void) const; + void setSleep(const bool on); + bool getSleep(void) const; + void setSwingV(const bool on); + bool getSwingV(void) const; + static bool validChecksum(const uint64_t data); + static uint8_t calcChecksum(const uint64_t data); + static uint8_t convertMode(const stdAc::opmode_t mode); + static uint8_t convertFan(const stdAc::fanspeed_t speed); + static uint8_t convertSwingV(const stdAc::swingv_t position); + static stdAc::opmode_t toCommonMode(const uint8_t mode); + static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed); + stdAc::state_t toCommon(void) const; + String toString(void) const; +#ifndef UNIT_TEST + + private: + IRsend _irsend; ///< Instance of the IR send class +#else // UNIT_TEST + /// @cond IGNORE + IRsendTest _irsend; ///< Instance of the testing IR send class + /// @endcond +#endif // UNIT_TEST + AirtonProtocol _; + void checksum(void); +}; +#endif // IR_AIRTON_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.cpp index f5cacf0e7..7b5b140f0 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.cpp @@ -21,17 +21,18 @@ // pulse parameters in usec const uint16_t kCoolixTick = 276; // Approximately 10.5 cycles at 38kHz const uint16_t kCoolixBitMarkTicks = 2; -const uint16_t kCoolixBitMark = kCoolixBitMarkTicks * kCoolixTick; +const uint16_t kCoolixBitMark = kCoolixBitMarkTicks * kCoolixTick; // 552us const uint16_t kCoolixOneSpaceTicks = 6; -const uint16_t kCoolixOneSpace = kCoolixOneSpaceTicks * kCoolixTick; +const uint16_t kCoolixOneSpace = kCoolixOneSpaceTicks * kCoolixTick; // 1656us const uint16_t kCoolixZeroSpaceTicks = 2; -const uint16_t kCoolixZeroSpace = kCoolixZeroSpaceTicks * kCoolixTick; +const uint16_t kCoolixZeroSpace = kCoolixZeroSpaceTicks * kCoolixTick; // 552us const uint16_t kCoolixHdrMarkTicks = 17; -const uint16_t kCoolixHdrMark = kCoolixHdrMarkTicks * kCoolixTick; +const uint16_t kCoolixHdrMark = kCoolixHdrMarkTicks * kCoolixTick; // 4692us const uint16_t kCoolixHdrSpaceTicks = 16; -const uint16_t kCoolixHdrSpace = kCoolixHdrSpaceTicks * kCoolixTick; +const uint16_t kCoolixHdrSpace = kCoolixHdrSpaceTicks * kCoolixTick; // 4416us const uint16_t kCoolixMinGapTicks = kCoolixHdrMarkTicks + kCoolixZeroSpaceTicks; -const uint16_t kCoolixMinGap = kCoolixMinGapTicks * kCoolixTick; +const uint16_t kCoolixMinGap = kCoolixMinGapTicks * kCoolixTick; // 5244us +const uint8_t kCoolix48ExtraTolerance = 5; // Percent using irutils::addBoolToString; using irutils::addIntToString; @@ -40,7 +41,7 @@ using irutils::addModeToString; using irutils::addTempToString; #if SEND_COOLIX -/// Send a Coolix message +/// Send a Coolix 24-bit message /// Status: STABLE / Confirmed Working. /// @param[in] data The message to be sent. /// @param[in] nbits The number of bits of message to be sent. @@ -620,7 +621,7 @@ String IRCoolixAC::toString(void) const { } #if DECODE_COOLIX -/// Decode the supplied Coolix A/C message. +/// Decode the supplied Coolix 24-bit A/C message. /// Status: STABLE / Known Working. /// @param[in,out] results Ptr to the data to decode & where to store the decode /// result. @@ -699,3 +700,58 @@ bool IRrecv::decodeCOOLIX(decode_results *results, uint16_t offset, return true; } #endif // DECODE_COOLIX + +#if SEND_COOLIX48 +/// Send a Coolix 48-bit message. +/// Status: ALPHA / Untested. +/// @param[in] data The message to be sent. +/// @param[in] nbits The number of bits of message to be sent. +/// @param[in] repeat The number of times the command is to be repeated. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1694 +/// @note This is effectively the same as `sendCOOLIX()` except requiring the +/// bit flipping be done prior to the call. +void IRsend::sendCoolix48(const uint64_t data, const uint16_t nbits, + const uint16_t repeat) { + // Header + Data + Footer + sendGeneric(kCoolixHdrMark, kCoolixHdrSpace, + kCoolixBitMark, kCoolixOneSpace, + kCoolixBitMark, kCoolixZeroSpace, + kCoolixBitMark, kCoolixMinGap, + data, nbits, 38000, true, repeat, 33); +} +#endif // SEND_COOLIX48 + +#if DECODE_COOLIX +/// Decode the supplied Coolix 48-bit A/C message. +/// Status: BETA / Probably Working. +/// @param[in,out] results Ptr to the data to decode & where to store the decode +/// result. +/// @param[in] offset The starting index to use when attempting to decode the +/// raw data. Typically/Defaults to kStartOffset. +/// @param[in] nbits The number of data bits to expect. +/// @param[in] strict Flag indicating if we should perform strict matching. +/// @return A boolean. True if it can decode it, false if it can't. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1694 +bool IRrecv::decodeCoolix48(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (strict && nbits != kCoolix48Bits) + return false; // Not strictly a COOLIX48 message. + + // Header + Data + Footer + if (!matchGeneric(results->rawbuf + offset, &(results->value), + results->rawlen - offset, nbits, + kCoolixHdrMark, kCoolixHdrSpace, + kCoolixBitMark, kCoolixOneSpace, + kCoolixBitMark, kCoolixZeroSpace, + kCoolixBitMark, kCoolixMinGap, + true, _tolerance + kCoolix48ExtraTolerance, 0, true)) + return false; + + // Success + results->decode_type = COOLIX48; + results->bits = nbits; + results->address = 0; + results->command = 0; + return true; +} +#endif // DECODE_COOLIX48 diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.h index 42a2528d7..2155b54b0 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.h @@ -6,6 +6,8 @@ /// @note Kudos: /// Hamper: For the breakdown and mapping of the bit values. /// fraschizzato: For additional ZoneFollow & SwingVStep analysis. +/// @note Timers seem to use the `COOLIX48` protocol. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1694 // Supports: // Brand: Beko, Model: RG57K7(B)/BGEF Remote @@ -21,6 +23,8 @@ // Brand: Toshiba, Model: RAS-M13YKV-E A/C // Brand: Toshiba, Model: RAS-4M27YAV-E A/C // Brand: Toshiba, Model: WH-E1YE remote +// Brand: Bosch, Model: RG36B4/BGE remote +// Brand: Bosch, Model: B1ZAI2441W/B1ZAO2441W A/C #ifndef IR_COOLIX_H_ #define IR_COOLIX_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Fujitsu.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Fujitsu.h index 994b6f4a3..70c0a4cf0 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Fujitsu.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Fujitsu.h @@ -33,6 +33,10 @@ // Brand: Fujitsu, Model: ASU12RLF A/C (ARREB1E) // Brand: Fujitsu, Model: AR-REW4E remote (ARREW4E) // Brand: Fujitsu, Model: ASYG09KETA-B A/C (ARREW4E) +// Brand: Fujitsu, Model: AR-REB4E remote (ARREB1E) +// Brand: Fujitsu, Model: ASTG09K A/C (ARREW4E) +// Brand: Fujitsu, Model: ASTG18K A/C (ARREW4E) +// Brand: Fujitsu, Model: AR-REW1E remote (ARREW4E) #ifndef IR_FUJITSU_H_ #define IR_FUJITSU_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mitsubishi.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mitsubishi.cpp index 160a882bf..1e826a72d 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mitsubishi.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mitsubishi.cpp @@ -399,6 +399,8 @@ void IRMitsubishiAC::setTemp(const float degrees) { // Do we have a half degree celsius? _.HalfDegree = nrHalfDegrees & 1; _.Temp = static_cast(nrHalfDegrees / 2 - kMitsubishiAcMinTemp); + // If temp is modified, iSave10C cannot be ON (because temp is then > 10C) + setISave10C(false); } /// Get the current temperature setting. @@ -452,8 +454,104 @@ void IRMitsubishiAC::setMode(const uint8_t mode) { return; } _.Mode = mode; + // iSave10C can only be on in Heat mode. + if (mode != kMitsubishiAcHeat) { + setISave10C(false); + } } +/// Set the iSave10C (i-SAVE) mode of the A/C. +/// @param[in] state true, the setting is on. false, the setting is off. +/// @note Normal minimum temp is 16C; i-SAVE mode works as gate to enable AC +/// to use 10C as setting. However, when Remote control shows 10C, it still +/// emits 16C on the "Temp" bits, and instead it uses other bits to indicate +/// a target temp of 10C. +/// Slightly strange, but I guess it's to keep compatibility to systems +/// without i-SAVE. +/// i-SAVE only has this 10C functionality when the AC is already in Heat mode. +/// In all other modes, minimum temp is 16C. +/// I have found no other difference between normal Heat mode and i-SAVE +/// other than the ability to go to 10C. +/// In this implementation, i-SAVE mode is ONLY used to enable the AC +/// temperature setting to 10C. Therefore "Temp" is set to 16 disregarding +/// what the remote shows, and mode is set to Heat. +void IRMitsubishiAC::setISave10C(const bool state) { + if (state) setMode(kMitsubishiAcHeat); + if (state) setTemp(kMitsubishiAcMinTemp); + _.iSave10C = state; +} + +/// Get the iSave10C (i-SAVE) mode of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRMitsubishiAC::getISave10C(void) const { + return _.iSave10C; +} + +/// Set the requested iSee mode. +/// @param[in] state requested iSee mode. +void IRMitsubishiAC::setISee(const bool state) { + _.ISee = state; +} + +/// Get the iSee mode of the A/C. +/// @return The iSee mode setting. +bool IRMitsubishiAC::getISee(void) const { + return _.ISee; +} + +/// Set the requested Ecocool mode. +/// @param[in] state requested Ecocool mode. +void IRMitsubishiAC::setEcocool(const bool state) { + _.Ecocool = state; +} + +/// Get the Ecocool mode of the A/C. +/// @return The Ecocool mode setting. +bool IRMitsubishiAC::getEcocool(void) const { + return _.Ecocool; +} + +/// Set the requested Absense Detect mode. +/// @param[in] state requested Absense Detect mode. +void IRMitsubishiAC::setAbsenseDetect(const bool state) { + _.AbsenseDetect = state; +} + +/// Get the Absense Detect mode of the A/C. +/// @return The Absense Detect mode setting. +bool IRMitsubishiAC::getAbsenseDetect(void) const { + return _.AbsenseDetect; +} + +/// Set the requested Direct/Indirect mode. Only works if I-See mode is ON. +/// @param[in] mode requested Direct/Indirect mode. +void IRMitsubishiAC::setDirectIndirect(const uint8_t mode) { + if (_.ISee) { + _.DirectIndirect = std::min(mode, kMitsubishiAcDirect); // bounds check + } else { + _.DirectIndirect = 0; + } +} + +/// Get the Direct/Indirect mode of the A/C. +/// @return The native mode setting. +uint8_t IRMitsubishiAC::getDirectIndirect(void) const { + return _.DirectIndirect; +} + +/// Set the requested Natural Flow mode. +/// @param[in] state requested Natural Flow mode. +void IRMitsubishiAC::setNaturalFlow(const bool state) { + _.NaturalFlow = state; +} + +/// Get the Natural Flow mode of the A/C. +/// @return The Natural Flow mode setting. +bool IRMitsubishiAC::getNaturalFlow(void) const { + return _.NaturalFlow; +} + + /// Set the requested vane (Vertical Swing) operation mode of the a/c unit. /// @note On some models, this represents the Right vertical vane. /// @param[in] position The position/mode to set the vane to. @@ -463,12 +561,6 @@ void IRMitsubishiAC::setVane(const uint8_t position) { _.Vane = pos; } -/// Set the requested wide-vane (Horizontal Swing) operation mode of the a/c. -/// @param[in] position The position/mode to set the wide vane to. -void IRMitsubishiAC::setWideVane(const uint8_t position) { - _.WideVane = std::min(position, kMitsubishiAcWideVaneAuto); -} - /// Get the Vane (Vertical Swing) mode of the A/C. /// @note On some models, this represents the Right vertical vane. /// @return The native position/mode setting. @@ -476,12 +568,6 @@ uint8_t IRMitsubishiAC::getVane(void) const { return _.Vane; } -/// Get the Wide Vane (Horizontal Swing) mode of the A/C. -/// @return The native position/mode setting. -uint8_t IRMitsubishiAC::getWideVane(void) const { - return _.WideVane; -} - /// Set the requested Left Vane (Vertical Swing) operation mode of the a/c unit. /// @param[in] position The position/mode to set the vane to. void IRMitsubishiAC::setVaneLeft(const uint8_t position) { @@ -492,6 +578,18 @@ void IRMitsubishiAC::setVaneLeft(const uint8_t position) { /// @return The native position/mode setting. uint8_t IRMitsubishiAC::getVaneLeft(void) const { return _.VaneLeft; } +/// Set the requested wide-vane (Horizontal Swing) operation mode of the a/c. +/// @param[in] position The position/mode to set the wide vane to. +void IRMitsubishiAC::setWideVane(const uint8_t position) { + _.WideVane = std::min(position, kMitsubishiAcWideVaneAuto); +} + +/// Get the Wide Vane (Horizontal Swing) mode of the A/C. +/// @return The native position/mode setting. +uint8_t IRMitsubishiAC::getWideVane(void) const { + return _.WideVane; +} + /// Get the clock time of the A/C unit. /// @return Nr. of 10 minute increments past midnight. /// @note 1 = 1/6 hour (10 minutes). e.g. 4pm = 48. @@ -777,6 +875,12 @@ String IRMitsubishiAC::toString(void) const { result += ')'; } result += addBoolToString(_.WeeklyTimer, kWeeklyTimerStr); + result += addBoolToString(_.iSave10C, k10CHeatStr); + result += addBoolToString(_.ISee, kISeeStr); + result += addBoolToString(_.Ecocool, kEconoStr); + result += addBoolToString(_.AbsenseDetect, kAbsenseDetectStr); + result += addIntToString(_.DirectIndirect, kDirectIndirectModeStr); + result += addBoolToString(_.NaturalFlow, kFreshStr); return result; } diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mitsubishi.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mitsubishi.h index 1f3a42184..55afcdce6 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mitsubishi.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mitsubishi.h @@ -34,6 +34,7 @@ // Brand: Mitsubishi Electric, Model: MSZ-SF25VE3 A/C (MITSUBISHI_AC) // Brand: Mitsubishi Electric, Model: SG15D remote (MITSUBISHI_AC) // Brand: Mitsubishi Electric, Model: MSZ-ZW4017S A/C (MITSUBISHI_AC) +// Brand: Mitsubishi Electric, Model: MSZ-FHnnVE A/C (MITSUBISHI_AC) #ifndef IR_MITSUBISHI_H_ #define IR_MITSUBISHI_H_ @@ -62,7 +63,8 @@ union Mitsubishi144Protocol{ // Byte 6 uint8_t :3; uint8_t Mode :3; - uint8_t :2; + uint8_t ISee : 1; + uint8_t :1; // Byte 7 uint8_t Temp :4; uint8_t HalfDegree :1; @@ -72,7 +74,7 @@ union Mitsubishi144Protocol{ uint8_t WideVane:4; // SwingH // Byte 9 uint8_t Fan :3; - uint8_t Vane :3; // SwingV + uint8_t Vane :3; // SwingV or VaneRight uint8_t VaneBit :1; uint8_t FanAuto :1; // Byte 10 @@ -86,13 +88,21 @@ union Mitsubishi144Protocol{ uint8_t WeeklyTimer :1; uint8_t :4; // Byte 14 - uint8_t :8; + uint8_t :5; + uint8_t Ecocool :1; + uint8_t :2; // Byte 15 - uint8_t :8; + uint8_t DirectIndirect:2; + uint8_t AbsenseDetect :1; + uint8_t :2; + uint8_t iSave10C :1; // i-SAVE:mode=Heat & iSave=on AND 10C on remote + uint8_t :2; // Byte 16 - uint8_t :3; - uint8_t VaneLeft :3; // SwingV(Left) - uint8_t :2; + uint8_t :1; + uint8_t NaturalFlow :1; + uint8_t :1; + uint8_t VaneLeft :3; // SwingV(Left) + uint8_t :2; // Byte 17 uint8_t Sum :8; }; @@ -126,6 +136,9 @@ const uint8_t kMitsubishiAcWideVaneRight = 0b0100; // 4 const uint8_t kMitsubishiAcWideVaneRightMax = 0b0101; // 5 const uint8_t kMitsubishiAcWideVaneWide = 0b0110; // 6 const uint8_t kMitsubishiAcWideVaneAuto = 0b1000; // 8 +const uint8_t kMitsubishiAcDirectOff = 0b00; // Vanes move when AC wants to. +const uint8_t kMitsubishiAcIndirect = 0b01; +const uint8_t kMitsubishiAcDirect = 0b11; const uint8_t kMitsubishiAcNoTimer = 0; const uint8_t kMitsubishiAcStartTimer = 5; const uint8_t kMitsubishiAcStopTimer = 3; @@ -274,12 +287,24 @@ class IRMitsubishiAC { uint8_t getFan(void) const; void setMode(const uint8_t mode); uint8_t getMode(void) const; - void setVane(const uint8_t position); - void setWideVane(const uint8_t position); + void setISave10C(const bool state); + bool getISave10C(void) const; + void setISee(const bool state); + bool getISee(void) const; + void setDirectIndirect(const uint8_t position); + uint8_t getDirectIndirect(void) const; + void setEcocool(const bool state); + bool getEcocool(void) const; + void setAbsenseDetect(const bool state); + bool getAbsenseDetect(void) const; + void setNaturalFlow(const bool state); + bool getNaturalFlow(void) const; + void setVane(const uint8_t position); // controls RIGHT vane on some models uint8_t getVane(void) const; - uint8_t getWideVane(void) const; void setVaneLeft(const uint8_t position); uint8_t getVaneLeft(void) const; + void setWideVane(const uint8_t position); + uint8_t getWideVane(void) const; uint8_t* getRaw(void); void setRaw(const uint8_t* data); uint8_t getClock(void) const; diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sony.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sony.cpp index 0dbbec3c8..5746ee9b1 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sony.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sony.cpp @@ -120,7 +120,7 @@ uint32_t IRsend::encodeSony(const uint16_t nbits, const uint16_t command, /// bits long. bool IRrecv::decodeSony(decode_results *results, uint16_t offset, const uint16_t nbits, const bool strict) { - if (results->rawlen <= 2 * nbits + kHeader - 1 + offset) + if (results->rawlen < 2 * nbits + kHeader - 1 + offset) return false; // Message is smaller than we expected. // Compliance diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.h index e1696c42a..c7ae038d0 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.h @@ -8,6 +8,8 @@ // Brand: TCL, Model: TAC-09CHSD/XA31I A/C (TAC09CHSD) // Brand: Teknopoint, Model: Allegro SSA-09H A/C (GZ055BE1) // Brand: Teknopoint, Model: GZ-055B-E1 remote (GZ055BE1) +// Brand: Daewoo, Model: DSB-F0934ELH-V A/C +// Brand: Daewoo, Model: GYKQ-52E remote #ifndef IR_TCL_H_ #define IR_TCL_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Toshiba.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Toshiba.cpp index 0e3ac8ba2..7333493ef 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Toshiba.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Toshiba.cpp @@ -216,9 +216,7 @@ void IRToshibaAC::setTemp(const uint8_t degrees) { /// Get the current temperature setting. /// @return The current setting for temp. in degrees celsius. -uint8_t IRToshibaAC::getTemp(void) const { - return _.Temp + kToshibaAcMinTemp; -} +uint8_t IRToshibaAC::getTemp(void) const { return _.Temp + kToshibaAcMinTemp; } /// Set the speed of the fan. /// @param[in] speed The desired setting (0 is Auto, 1-5 is the speed, 5 is Max) @@ -339,6 +337,19 @@ void IRToshibaAC::setEcono(const bool on) { } } +/// Get the filter (Pure/Ion Filter) setting of the A/C. +/// @return true, if the current setting is on. Otherwise, false. +bool IRToshibaAC::getFilter(void) const { + return (getStateLength() >= kToshibaACStateLength) ? _.Filter : false; +} + +/// Set the filter (Pure/Ion Filter) setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRToshibaAC::setFilter(const bool on) { + _.Filter = on; + if (on) setStateLength(std::min(kToshibaACStateLength, getStateLength())); +} + /// Convert a stdAc::opmode_t enum into its native mode. /// @param[in] mode The enum to be converted. /// @return The native equivalent of the enum. @@ -421,6 +432,7 @@ stdAc::state_t IRToshibaAC::toCommon(const stdAc::state_t *prev) const { result.fanspeed = toCommonFanSpeed(getFan()); result.turbo = getTurbo(); result.econo = getEcono(); + result.filter = getFilter(); } switch (getSwing()) { case kToshibaAcSwingOn: @@ -436,7 +448,6 @@ stdAc::state_t IRToshibaAC::toCommon(const stdAc::state_t *prev) const { } // Not supported. result.light = false; - result.filter = false; result.swingh = stdAc::swingh_t::kOff; result.quiet = false; result.clean = false; @@ -450,7 +461,7 @@ stdAc::state_t IRToshibaAC::toCommon(const stdAc::state_t *prev) const { /// @return A human readable string. String IRToshibaAC::toString(void) const { String result = ""; - result.reserve(80); + result.reserve(95); result += addTempToString(getTemp(), true, false); switch (getStateLength()) { case kToshibaACStateLengthShort: @@ -477,6 +488,7 @@ String IRToshibaAC::toString(void) const { kToshibaAcFanMed); result += addBoolToString(getTurbo(), kTurboStr); result += addBoolToString(getEcono(), kEconoStr); + result += addBoolToString(getFilter(), kFilterStr); } return result; } diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Toshiba.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Toshiba.h index 3ebf5e693..1314cf54d 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Toshiba.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Toshiba.h @@ -8,6 +8,7 @@ /// @see https://docs.google.com/spreadsheets/d/1yidE2fvaO9kpCHfKafIdH31q4uaskYR1OwwrkyOxbp0/edit?usp=drivesdk /// @see https://www.toshiba-carrier.co.jp/global/about/index.htm /// @see http://www.toshiba-carrier.co.th/AboutUs/Pages/CompanyProfile.aspx +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1692 // Supports: // Brand: Toshiba, Model: RAS-B13N3KV2 @@ -18,6 +19,8 @@ // Brand: Toshiba, Model: WC-L03SE // Brand: Toshiba, Model: WH-UB03NJ remote // Brand: Toshiba, Model: RAS-2558V A/C +// Brand: Toshiba, Model: WH-TA01JE remote +// Brand: Toshiba, Model: RAS-25SKVP2-ND A/C // Brand: Carrier, Model: 42NQV060M2 / 38NYV060M2 A/C // Brand: Carrier, Model: 42NQV050M2 / 38NYV050M2 A/C // Brand: Carrier, Model: 42NQV035M2 / 38NYV035M2 A/C @@ -50,28 +53,31 @@ union ToshibaProtocol{ ///< 1 (56 bit message) ///< 3 (72 bit message) ///< 4 (80 bit message) - uint8_t Length :8; + uint8_t Length :8; // Byte[3] - The bit-inverted value of the "length" byte. - uint8_t :8; + uint8_t :8; // Byte[4] - uint8_t :3; - uint8_t LongMsg :1; - uint8_t :1; - uint8_t ShortMsg:1; - uint8_t :2; + uint8_t :3; + uint8_t LongMsg :1; + uint8_t :1; + uint8_t ShortMsg :1; + uint8_t :2; // Byte[5] - uint8_t Swing :3; - uint8_t :1; - uint8_t Temp :4; + uint8_t Swing :3; + uint8_t :1; + uint8_t Temp :4; // Byte[6] - uint8_t Mode :3; - uint8_t :2; - uint8_t Fan :3; + uint8_t Mode :3; + uint8_t :2; + uint8_t Fan :3; // Byte[7] - uint8_t :8; + uint8_t :4; + uint8_t Filter :1; + uint8_t :3; + // Byte[8] // (Checksum for 72 bit messages, Eco/Turbo for long 80 bit messages) - uint8_t EcoTurbo :8; + uint8_t EcoTurbo :8; }; }; @@ -144,6 +150,8 @@ class IRToshibaAC { bool getTurbo(void) const; void setEcono(const bool on); bool getEcono(void) const; + void setFilter(const bool on); + bool getFilter(void) const; void setMode(const uint8_t mode); uint8_t getMode(const bool raw = false) const; void setRaw(const uint8_t newState[], diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/defaults.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/defaults.h index 0fcc04791..d8142e20e 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/defaults.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/defaults.h @@ -120,6 +120,9 @@ #ifndef D_STR_IFEEL #define D_STR_IFEEL "IFeel" #endif // D_STR_IFEEL +#ifndef D_STR_ISEE +#define D_STR_ISEE "ISee" +#endif // D_STR_ISEE #ifndef D_STR_HUMID #define D_STR_HUMID "Humid" #endif // D_STR_HUMID @@ -207,6 +210,19 @@ #ifndef D_STR_SENSOR #define D_STR_SENSOR "Sensor" #endif // D_STR_SENSOR +#ifndef D_STR_ABSENSEDETECT +#define D_STR_ABSENSEDETECT "Absense detect" +#endif // D_STR_ABSENSEDETECT +#ifndef D_STR_DIRECT +#define D_STR_DIRECT "Direct" +#endif // D_STR_DIRECT +#ifndef D_STR_INDIRECT +#define D_STR_INDIRECT "Indirect" +#endif // D_STR_INDIRECT +#ifndef D_STR_DIRECTINDIRECTMODE +#define D_STR_DIRECTINDIRECTMODE D_STR_DIRECT " / " \ +D_STR_INDIRECT " " D_STR_MODE +#endif // D_STR_DIRECTINDIRECTMODE #ifndef D_STR_DISPLAY #define D_STR_DISPLAY "Display" #endif // D_STR_DISPLAY @@ -702,6 +718,9 @@ #ifndef D_STR_COOLIX #define D_STR_COOLIX "COOLIX" #endif // D_STR_COOLIX +#ifndef D_STR_COOLIX48 +#define D_STR_COOLIX48 D_STR_COOLIX "48" +#endif // D_STR_COOLIX48 #ifndef D_STR_CORONA_AC #define D_STR_CORONA_AC "CORONA_AC" #endif // D_STR_CORONA_AC diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/IRac_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/IRac_test.cpp index d43cfcd9d..2988e4b4b 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/IRac_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/IRac_test.cpp @@ -1,6 +1,7 @@ // Copyright 2019-2021 David Conran #include +#include "ir_Airton.h" #include "ir_Airwell.h" #include "ir_Amcor.h" #include "ir_Argo.h" @@ -44,6 +45,36 @@ // Tests for IRac class. +TEST(TestIRac, Airton) { + IRAirtonAc ac(kGpioUnused); + IRac irac(kGpioUnused); + IRrecv capture(kGpioUnused); + const char expected[] = + "Power: On, Mode: 1 (Cool), Fan: 5 (Maximum), Temp: 18C, " + "Swing(V): On, Econo: On, Turbo: On, Light: On, Health: On, Sleep: On"; + + ac.begin(); + irac.airton(&ac, + true, // Power + stdAc::opmode_t::kCool, // Mode + 18, // Celsius + stdAc::fanspeed_t::kMax, // Fan speed + stdAc::swingv_t::kAuto, // Vertical Swing + true, // Turbo + true, // Light/Display/LED + true, // Econo (Eco) + true, // Filter (Health) + 9 * 60 + 12); // Sleep (09:12) + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(AIRTON, ac._irsend.capture.decode_type); + ASSERT_EQ(kAirtonBits, ac._irsend.capture.bits); + ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture)); + stdAc::state_t r, p; + ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p)); +} + TEST(TestIRac, Airwell) { IRAirwellAc ac(kGpioUnused); IRac irac(kGpioUnused); @@ -1418,7 +1449,9 @@ TEST(TestIRac, Mitsubishi) { "Power: On, Mode: 3 (Cool), Temp: 20C, Fan: 2 (Medium), " "Swing(V): 0 (Auto), Swing(H): 3 (Middle), " "Clock: 14:30, On Timer: 00:00, Off Timer: 00:00, Timer: -, " - "Weekly Timer: Off"; + "Weekly Timer: Off" + ", 10C Heat: Off, ISee: Off, Econo: Off, Absense detect: Off, " + "Direct / Indirect Mode: 0, Fresh: Off"; ac.begin(); irac.mitsubishi(&ac, @@ -1958,7 +1991,7 @@ TEST(TestIRac, Toshiba) { IRrecv capture(kGpioUnused); char expected[] = "Temp: 29C, Power: On, Mode: 2 (Dry), Fan: 2 (UNKNOWN), " - "Turbo: Off, Econo: On"; + "Turbo: Off, Econo: On, Filter: Off"; ac.begin(); irac.toshiba(&ac, @@ -1968,7 +2001,8 @@ TEST(TestIRac, Toshiba) { stdAc::fanspeed_t::kLow, // Fan speed stdAc::swingv_t::kOff, // Vertical Swing false, // Turbo - true); // Econo + true, // Econo + false); // Filter ASSERT_EQ(expected, ac.toString()); ASSERT_EQ(kToshibaACStateLengthLong, ac.getStateLength()); ac._irsend.makeDecodeResult(); @@ -2873,7 +2907,7 @@ TEST(TestIRac, Issue1250) { // Now send the state so we can actually decode/capture what we sent. char expected_on[] = "Temp: 19C, Power: On, Mode: 4 (Fan), Fan: 0 (Auto), " - "Turbo: Off, Econo: Off"; + "Turbo: Off, Econo: Off, Filter: Off"; ac._irsend.reset(); irac.toshiba(&ac, irac.next.power, // Power @@ -2882,7 +2916,8 @@ TEST(TestIRac, Issue1250) { irac.next.fanspeed, // Fan speed irac.next.swingv, // Vertical Swing irac.next.turbo, // Turbo - irac.next.econo); // Econo + irac.next.econo, // Econo + irac.next.filter); // Filter ASSERT_EQ(expected_on, ac.toString()); ASSERT_EQ(kToshibaACStateLength, ac.getStateLength()); ac._irsend.makeDecodeResult(); @@ -2898,7 +2933,8 @@ TEST(TestIRac, Issue1250) { irac.sendAc(); // Now send the state so we can actually decode/capture what we sent. char expected_off[] = - "Temp: 19C, Power: Off, Fan: 0 (Auto), Turbo: Off, Econo: Off"; + "Temp: 19C, Power: Off, Fan: 0 (Auto), Turbo: Off, Econo: Off, " + "Filter: Off"; ac._irsend.reset(); irac.toshiba(&ac, irac.next.power, // Power @@ -2907,7 +2943,8 @@ TEST(TestIRac, Issue1250) { irac.next.fanspeed, // Fan speed irac.next.swingv, // Vertical Swing irac.next.turbo, // Turbo - irac.next.econo); // Econo + irac.next.econo, // Econo + irac.next.filter); // Filter ASSERT_EQ(expected_off, ac.toString()); ASSERT_EQ(kToshibaACStateLength, ac.getStateLength()); ac._irsend.makeDecodeResult(); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Airton_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Airton_test.cpp index e4e66ee13..2f2bb0bac 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Airton_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Airton_test.cpp @@ -1,5 +1,6 @@ // Copyright 2021 crankyoldgit +#include "ir_Airton.h" #include "IRac.h" #include "IRrecv.h" #include "IRrecv_test.h" @@ -34,6 +35,13 @@ TEST(TestDecodeAirton, RealExample) { EXPECT_EQ(0x5E1400090C11D3, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_EQ( + "Power: On, Mode: 4 (Heat), Fan: 0 (Auto), Temp: 25C, " + "Swing(V): Off, Econo: Off, Turbo: Off, Light: Off, " + "Health: Off, Sleep: Off", + IRAcUtils::resultAcToString(&irsend.capture)); + stdAc::state_t r, p; + ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p)); } TEST(TestDecodeAirton, SyntheticExample) { @@ -56,7 +64,265 @@ TEST(TestUtils, Housekeeping) { ASSERT_EQ("AIRTON", typeToString(decode_type_t::AIRTON)); ASSERT_EQ(decode_type_t::AIRTON, strToDecodeType("AIRTON")); ASSERT_FALSE(hasACState(decode_type_t::AIRTON)); - ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::AIRTON)); + ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::AIRTON)); ASSERT_EQ(kAirtonBits, IRsend::defaultBits(decode_type_t::AIRTON)); ASSERT_EQ(kAirtonDefaultRepeat, IRsend::minRepeats(decode_type_t::AIRTON)); } + +// Tests for IRAirtonAc class. + +TEST(TestIRAirtonAcClass, Power) { + IRAirtonAc ac(kGpioUnused); + ac.begin(); + + ac.on(); + EXPECT_TRUE(ac.getPower()); + + ac.off(); + EXPECT_FALSE(ac.getPower()); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); +} + +TEST(TestIRAirtonAcClass, Checksums) { + ASSERT_TRUE(IRAirtonAc::validChecksum(0x5E1400090C11D3)); + ASSERT_EQ(0x5E, IRAirtonAc::calcChecksum(0x5E1400090C11D3)); + ASSERT_FALSE(IRAirtonAc::validChecksum(0x551400090C11D3)); + ASSERT_TRUE(IRAirtonAc::validChecksum(0x2F8801060911D3)); + ASSERT_TRUE(IRAirtonAc::validChecksum(0xDB8800021A11D3)); +} + +TEST(TestIRAirtonAcClass, Temperature) { + IRAirtonAc ac(kGpioUnused); + ac.begin(); + ac.setMode(kAirtonCool); // Cool mode allows the entire temp range. + ac.setTemp(0); + EXPECT_EQ(kAirtonMinTemp, ac.getTemp()); + + ac.setTemp(255); + EXPECT_EQ(kAirtonMaxTemp, ac.getTemp()); + + ac.setTemp(kAirtonMinTemp); + EXPECT_EQ(kAirtonMinTemp, ac.getTemp()); + + ac.setTemp(kAirtonMaxTemp); + EXPECT_EQ(kAirtonMaxTemp, ac.getTemp()); + + ac.setTemp(kAirtonMinTemp - 1); + EXPECT_EQ(kAirtonMinTemp, ac.getTemp()); + + ac.setTemp(kAirtonMaxTemp + 1); + EXPECT_EQ(kAirtonMaxTemp, ac.getTemp()); + + ac.setTemp(17); + EXPECT_EQ(17, ac.getTemp()); + + ac.setTemp(21); + EXPECT_EQ(21, ac.getTemp()); + + ac.setTemp(20); + EXPECT_EQ(20, ac.getTemp()); +} + +TEST(TestIRAirtonAcClass, OperatingMode) { + IRAirtonAc ac(kGpioUnused); + ac.begin(); + + ac.setMode(kAirtonCool); + EXPECT_EQ(kAirtonCool, ac.getMode()); + ac.setMode(kAirtonDry); + EXPECT_EQ(kAirtonDry, ac.getMode()); + ac.setMode(kAirtonFan); + EXPECT_EQ(kAirtonFan, ac.getMode()); + EXPECT_NE(kAirtonMaxTemp, ac.getTemp()); + ac.setMode(kAirtonAuto); + EXPECT_EQ(kAirtonAuto, ac.getMode()); + EXPECT_EQ(kAirtonMaxTemp, ac.getTemp()); + ac.setMode(kAirtonHeat); + EXPECT_EQ(kAirtonHeat, ac.getMode()); + + ac.setMode(kAirtonHeat + 1); + EXPECT_EQ(kAirtonAuto, ac.getMode()); + ac.setMode(255); + EXPECT_EQ(kAirtonAuto, ac.getMode()); +} + +TEST(TestIRAirtonAcClass, FanSpeed) { + IRAirtonAc ac(kGpioUnused); + ac.begin(); + ac.setMode(kAirtonCool); // All fan speeds available in this mode. + + ac.setFan(0); + EXPECT_EQ(kAirtonFanAuto, ac.getFan()); + + ac.setFan(255); + EXPECT_EQ(kAirtonFanAuto, ac.getFan()); + + ac.setFan(kAirtonFanHigh); + EXPECT_EQ(kAirtonFanHigh, ac.getFan()); + + ac.setFan(kAirtonFanLow); + EXPECT_EQ(kAirtonFanLow, ac.getFan()); + + ac.setFan(kAirtonFanMax); + EXPECT_EQ(kAirtonFanMax, ac.getFan()); + + ac.setFan(kAirtonFanMin); + EXPECT_EQ(kAirtonFanMin, ac.getFan()); + + ac.setFan(kAirtonFanMed); + EXPECT_EQ(kAirtonFanMed, ac.getFan()); + + ac.setFan(kAirtonFanMax + 1); + EXPECT_EQ(kAirtonFanAuto, ac.getFan()); +} + +TEST(TestIRAirtonAcClass, SwingV) { + IRAirtonAc ac(kGpioUnused); + ac.begin(); + + ac.setSwingV(false); + EXPECT_FALSE(ac.getSwingV()); + ac.setSwingV(true); + EXPECT_TRUE(ac.getSwingV()); + ac.setSwingV(false); + EXPECT_FALSE(ac.getSwingV()); + + // Known swingv on state + ac.setRaw(0xBC0401050111D3); + EXPECT_TRUE(ac.getSwingV()); +} + +TEST(TestIRAirtonAcClass, Light) { + IRAirtonAc ac(kGpioUnused); + ac.begin(); + + ac.setLight(false); + EXPECT_FALSE(ac.getLight()); + ac.setLight(true); + EXPECT_TRUE(ac.getLight()); + ac.setLight(false); + EXPECT_FALSE(ac.getLight()); + + // Known light on state + ac.setRaw(0x298801040911D3); + EXPECT_TRUE(ac.getLight()); +} + +TEST(TestIRAirtonAcClass, ConstructKnownExamples) { + IRAirtonAc ac(kGpioUnused); + ac.begin(); + ac.stateReset(); + ac.on(); + ac.setMode(kAirtonHeat); + ac.setFan(kAirtonFanAuto); + ac.setTemp(25); + ac.setSwingV(false); + ac.setLight(false); + ac.setTurbo(false); + ac.setSleep(false); + ac.setEcono(false); + ac.setHealth(false); + EXPECT_EQ( + "Power: On, Mode: 4 (Heat), Fan: 0 (Auto), Temp: 25C, " + "Swing(V): Off, Econo: Off, Turbo: Off, Light: Off, " + "Health: Off, Sleep: Off", + ac.toString()); + EXPECT_EQ(0x5E1400090C11D3, ac.getRaw()); +} + +TEST(TestIRAirtonAcClass, Turbo) { + IRAirtonAc ac(kGpioUnused); + ac.begin(); + + ac.setTurbo(false); + EXPECT_FALSE(ac.getTurbo()); + EXPECT_NE(kAirtonFanMax, ac.getFan()); + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); + EXPECT_EQ(kAirtonFanMax, ac.getFan()); + ac.setTurbo(false); + EXPECT_FALSE(ac.getTurbo()); + + // Known Turbo on state + ac.setRaw(0x92040000D911D3); + EXPECT_TRUE(ac.getTurbo()); +} + +TEST(TestIRAirtonAcClass, Sleep) { + IRAirtonAc ac(kGpioUnused); + ac.begin(); + + ac.setMode(kAirtonCool); // Sleep is available in Cool mode. + ac.setSleep(false); + EXPECT_FALSE(ac.getSleep()); + ac.setSleep(true); + EXPECT_TRUE(ac.getSleep()); + ac.setSleep(false); + EXPECT_FALSE(ac.getSleep()); + + ac.setSleep(true); + // Sleep is available in Heat mode, but changing modes resets it. + ac.setMode(kAirtonHeat); + EXPECT_FALSE(ac.getSleep()); + ac.setSleep(true); + EXPECT_TRUE(ac.getSleep()); + + ac.setMode(kAirtonAuto); // Sleep is NOT available in Auto mode. + EXPECT_FALSE(ac.getSleep()); + ac.setSleep(true); + EXPECT_FALSE(ac.getSleep()); + + ac.setMode(kAirtonFan); // Sleep is NOT available in Fan mode. + EXPECT_FALSE(ac.getSleep()); + ac.setSleep(true); + EXPECT_FALSE(ac.getSleep()); + + // Known Sleep on state + ac.setRaw(0xA00600000911D3); + EXPECT_TRUE(ac.getSleep()); + EXPECT_NE(kAirtonAuto, ac.getMode()); + EXPECT_NE(kAirtonFan, ac.getMode()); +} + +TEST(TestIRAirtonAcClass, Health) { + IRAirtonAc ac(kGpioUnused); + ac.begin(); + + ac.setHealth(false); + EXPECT_FALSE(ac.getHealth()); + ac.setHealth(true); + EXPECT_TRUE(ac.getHealth()); + ac.setHealth(false); + EXPECT_FALSE(ac.getHealth()); + + // Known Health on state + ac.setRaw(0xE5C900000911D3); + EXPECT_TRUE(ac.getHealth()); +} + +TEST(TestIRAirtonAcClass, Econo) { + IRAirtonAc ac(kGpioUnused); + ac.begin(); + ac.setMode(kAirtonCool); // Econo is only available in Cool. + ac.setEcono(false); + EXPECT_FALSE(ac.getEcono()); + ac.setEcono(true); + EXPECT_TRUE(ac.getEcono()); + ac.setEcono(false); + EXPECT_FALSE(ac.getEcono()); + + ac.setEcono(true); + ac.setMode(kAirtonHeat); // Econo is only available in Cool, not Heat! + EXPECT_FALSE(ac.getEcono()); + ac.setEcono(true); + EXPECT_FALSE(ac.getEcono()); + + // Known Econo on state + ac.setRaw(0xE5C900000911D3); + EXPECT_TRUE(ac.getEcono()); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Coolix_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Coolix_test.cpp index 46c554882..62e0d6b0e 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Coolix_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Coolix_test.cpp @@ -6,6 +6,25 @@ #include "IRsend_test.h" #include "gtest/gtest.h" + +TEST(TestUtils, Housekeeping) { + // COOLIX + ASSERT_EQ("COOLIX", typeToString(decode_type_t::COOLIX)); + ASSERT_EQ(decode_type_t::COOLIX, strToDecodeType("COOLIX")); + ASSERT_FALSE(hasACState(decode_type_t::COOLIX)); + ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::COOLIX)); + ASSERT_EQ(kCoolixBits, IRsend::defaultBits(decode_type_t::COOLIX)); + ASSERT_EQ(kSingleRepeat, IRsend::minRepeats(decode_type_t::COOLIX)); + + // COOLIX48 + ASSERT_EQ("COOLIX48", typeToString(decode_type_t::COOLIX48)); + ASSERT_EQ(decode_type_t::COOLIX48, strToDecodeType("COOLIX48")); + ASSERT_FALSE(hasACState(decode_type_t::COOLIX48)); + ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::COOLIX48)); + ASSERT_EQ(kCoolix48Bits, IRsend::defaultBits(decode_type_t::COOLIX48)); + ASSERT_EQ(kSingleRepeat, IRsend::minRepeats(decode_type_t::COOLIX48)); +} + // Tests for sendCOOLIX(). // Test sending typical data only. @@ -941,3 +960,76 @@ TEST(TestCoolixACClass, VerifyZoneFollowFan) { "Zone Follow: On, Sensor Temp: 19C", ac.toString()); } + +TEST(TestDecodeCoolix48, RealExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + + // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1694#issue-1068786691 + // Off Timer: 1 hour + const uint16_t rawData[199] = { + 4342, 4454, 486, 1724, 436, 658, 438, 1748, 464, 1718, 462, 634, 440, 656, + 462, 1696, 488, 634, 462, 634, 436, 1722, 516, 608, 462, 660, 436, 1694, + 488, 1720, 440, 630, 488, 1700, 488, 1704, 458, 660, 462, 1698, 490, 632, + 462, 634, 436, 684, 436, 1700, 464, 1748, 462, 634, 462, 1720, 436, 658, + 462, 1700, 488, 1692, 512, 1696, 438, 684, 410, 686, 434, 688, 408, 1696, + 488, 1694, 464, 682, 414, 1748, 436, 1722, 488, 632, 438, 686, 408, 662, + 462, 1696, 488, 1722, 462, 1696, 462, 1746, 436, 1798, 386, 1694, 490, + 1720, 516, 5234, 4370, 4446, 490, 1690, 492, 658, 434, 1726, 436, 1746, + 464, 604, 488, 658, 412, 1718, 490, 636, 460, 660, 438, 1698, 460, 662, + 458, 632, 436, 1718, 490, 1720, 488, 608, 436, 1754, 462, 1726, 438, 682, + 414, 1748, 464, 632, 460, 660, 410, 658, 438, 1748, 464, 1694, 464, 660, + 436, 1720, 488, 634, 460, 1726, 462, 1724, 462, 1692, 490, 606, 462, 714, + 384, 660, 460, 1722, 460, 1722, 490, 606, 464, 1718, 490, 1670, 486, 634, + 462, 662, 410, 660, 460, 1722, 464, 1718, 460, 1696, 464, 1720, 462, 1720, + 462, 1722, 486, 1700, 462}; // UNKNOWN 1F691B97 + + irsend.begin(); + irsend.reset(); + + irsend.sendRaw(rawData, 199, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(COOLIX48, irsend.capture.decode_type); + EXPECT_EQ(kCoolix48Bits, irsend.capture.bits); + EXPECT_EQ(0xB24DA35C6C7F, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +TEST(TestDecodeCoolix48, SyntheticSelfDecode) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + irsend.reset(); + irsend.sendCoolix48(0xB24DA35C6C7F); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(COOLIX48, irsend.capture.decode_type); + EXPECT_EQ(kCoolix48Bits, irsend.capture.bits); + EXPECT_EQ(0xB24DA35C6C7F, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + EXPECT_EQ( + "f38000d33" + "m4692s4416" // Message. + "m552s1656m552s552m552s1656m552s1656m552s552m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s552m552s1656m552s1656m552s552m552s1656" + "m552s1656m552s552m552s1656m552s552m552s552m552s552m552s1656m552s1656" + "m552s552m552s1656m552s552m552s1656m552s1656m552s1656m552s552m552s552" + "m552s552m552s1656m552s1656m552s552m552s1656m552s1656m552s552m552s552" + "m552s552m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s5244" + "m4692s4416" // Repeat + "m552s1656m552s552m552s1656m552s1656m552s552m552s552m552s1656m552s552" + "m552s552m552s1656m552s552m552s552m552s1656m552s1656m552s552m552s1656" + "m552s1656m552s552m552s1656m552s552m552s552m552s552m552s1656m552s1656" + "m552s552m552s1656m552s552m552s1656m552s1656m552s1656m552s552m552s552" + "m552s552m552s1656m552s1656m552s552m552s1656m552s1656m552s552m552s552" + "m552s552m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656" + "m552s5244", + irsend.outputStr()); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Mitsubishi_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Mitsubishi_test.cpp index 28cc04d8e..815d4f996 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Mitsubishi_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Mitsubishi_test.cpp @@ -913,7 +913,9 @@ TEST(TestMitsubishiACClass, HumanReadable) { "Power: On, Mode: 1 (Heat), Temp: 22C, Fan: 6 (Quiet), " "Swing(V): 0 (Auto), Swing(H): 3 (Middle), " "Clock: 17:10, On Timer: 00:00, Off Timer: 00:00, Timer: -, " - "Weekly Timer: Off", + "Weekly Timer: Off" + ", 10C Heat: Off, ISee: Off, Econo: Off, Absense detect: Off, " + "Direct / Indirect Mode: 0, Fresh: Off", ac.toString()); ac.setTemp(21.5); ac.setWeeklyTimerEnabled(true); @@ -921,7 +923,9 @@ TEST(TestMitsubishiACClass, HumanReadable) { "Power: On, Mode: 1 (Heat), Temp: 21.5C, Fan: 6 (Quiet), " "Swing(V): 0 (Auto), Swing(H): 3 (Middle), " "Clock: 17:10, On Timer: 00:00, Off Timer: 00:00, Timer: -, " - "Weekly Timer: On", + "Weekly Timer: On" + ", 10C Heat: Off, ISee: Off, Econo: Off, Absense detect: Off, " + "Direct / Indirect Mode: 0, Fresh: Off", ac.toString()); } @@ -1434,7 +1438,9 @@ TEST(TestDecodeMitsubishiAC, Issue891) { "Power: Off, Mode: 3 (Cool), Temp: 24C, Fan: 0 (Auto), " "Swing(V): 0 (Auto), Swing(H): 3 (Middle), " "Clock: 00:00, On Timer: 00:00, Off Timer: 00:00, Timer: -, " - "Weekly Timer: Off", + "Weekly Timer: Off" + ", 10C Heat: Off, ISee: Off, Econo: Off, Absense detect: Off, " + "Direct / Indirect Mode: 0, Fresh: Off", ac.toString()); } diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Toshiba_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Toshiba_test.cpp index 1785b3895..4a63780d5 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Toshiba_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Toshiba_test.cpp @@ -312,20 +312,21 @@ TEST(TestToshibaACClass, HumanReadableOutput) { ac.setRaw(initial_state); EXPECT_EQ("Temp: 17C, Power: On, Mode: 0 (Auto), Fan: 0 (Auto), " - "Turbo: Off, Econo: Off", + "Turbo: Off, Econo: Off, Filter: Off", ac.toString()); ac.setRaw(modified_state); EXPECT_EQ("Temp: 17C, Power: On, Mode: 1 (Cool), Fan: 5 (High), " - "Turbo: Off, Econo: Off", + "Turbo: Off, Econo: Off, Filter: Off", ac.toString()); ac.setTemp(25); ac.setFan(3); ac.setMode(kToshibaAcDry); EXPECT_EQ("Temp: 25C, Power: On, Mode: 2 (Dry), Fan: 3 (Medium), " - "Turbo: Off, Econo: Off", + "Turbo: Off, Econo: Off, Filter: Off", ac.toString()); ac.off(); - EXPECT_EQ("Temp: 25C, Power: Off, Fan: 3 (Medium), Turbo: Off, Econo: Off", + EXPECT_EQ("Temp: 25C, Power: Off, Fan: 3 (Medium), Turbo: Off, Econo: Off, " + "Filter: Off", ac.toString()); } @@ -379,7 +380,7 @@ TEST(TestDecodeToshibaAC, SyntheticExample) { EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( "Temp: 17C, Power: On, Mode: 0 (Auto), Fan: 0 (Auto), Turbo: Off, " - "Econo: Off", + "Econo: Off, Filter: Off", IRAcUtils::resultAcToString(&irsend.capture)); stdAc::state_t r, p; ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p)); @@ -555,6 +556,7 @@ TEST(TestToshibaACClass, toCommon) { ac.setMode(kToshibaAcCool); ac.setTemp(20); ac.setFan(kToshibaAcFanMax); + ac.setFilter(true); // Now test it. ASSERT_EQ(decode_type_t::TOSHIBA_AC, ac.toCommon().protocol); ASSERT_EQ(-1, ac.toCommon().model); @@ -563,13 +565,13 @@ TEST(TestToshibaACClass, toCommon) { ASSERT_EQ(20, ac.toCommon().degrees); ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode); ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed); + ASSERT_TRUE(ac.toCommon().filter); // Unsupported. ASSERT_EQ(stdAc::swingv_t::kOff, ac.toCommon().swingv); ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh); ASSERT_FALSE(ac.toCommon().turbo); ASSERT_FALSE(ac.toCommon().econo); ASSERT_FALSE(ac.toCommon().light); - ASSERT_FALSE(ac.toCommon().filter); ASSERT_FALSE(ac.toCommon().clean); ASSERT_FALSE(ac.toCommon().beep); ASSERT_FALSE(ac.toCommon().quiet); @@ -626,7 +628,7 @@ TEST(TestDecodeToshibaAC, RealLongExample) { EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( "Temp: 22C, Power: On, Mode: 0 (Auto), Fan: 0 (Auto), Turbo: On, " - "Econo: Off", + "Econo: Off, Filter: Off", IRAcUtils::resultAcToString(&irsend.capture)); } @@ -731,7 +733,7 @@ TEST(TestToshibaACClass, ConstructLongState) { ac.setEcono(true); EXPECT_EQ( "Temp: 29C, Power: On, Mode: 2 (Dry), Fan: 2 (UNKNOWN), " - "Turbo: Off, Econo: On", + "Turbo: Off, Econo: On, Filter: Off", ac.toString()); EXPECT_EQ(kToshibaACStateLengthLong, ac.getStateLength()); const uint8_t expectedState[kToshibaACStateLengthLong] = { @@ -781,7 +783,8 @@ TEST(TestDecodeToshibaAC, RealExample_WHUB03NJ) { EXPECT_EQ(kToshibaACBits, irsend.capture.bits); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "Temp: 20C, Power: Off, Fan: 0 (Auto), Turbo: Off, Econo: Off", + "Temp: 20C, Power: Off, Fan: 0 (Auto), Turbo: Off, Econo: Off, " + "Filter: Off", IRAcUtils::resultAcToString(&irsend.capture)); } @@ -828,3 +831,34 @@ TEST(TestToshibaACClass, SwingCodes) { "Temp: 17C, Swing(V): 4 (Toggle)", ac.toString()); } + +// For https://github.com/crankyoldgit/IRremoteESP8266/issues/1692 +TEST(TestToshibaACClass, Filter) { + IRToshibaAC ac(kGpioUnused); + ac.begin(); + EXPECT_FALSE(ac.getFilter()); + + ac.setFilter(true); + EXPECT_TRUE(ac.getFilter()); + + + ac.setFilter(false); + EXPECT_FALSE(ac.getFilter()); + + ac.setFilter(true); + EXPECT_TRUE(ac.getFilter()); + + const uint8_t pure_off[kToshibaACStateLength] = { + 0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x40, 0x03, 0x00, 0x42}; + ac.setRaw(pure_off); + EXPECT_FALSE(ac.getFilter()); + + const uint8_t pure_on[kToshibaACStateLength] = { + 0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x40, 0x03, 0x10, 0x52}; + ac.setRaw(pure_on); + EXPECT_TRUE(ac.getFilter()); + + // Convert a known filter/pure on state to a known off filter/pure state. + ac.setFilter(false); + EXPECT_STATE_EQ(pure_off, ac.getRaw(), ac.getStateLength() * 8); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/Makefile b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/Makefile index 15f192efd..bf65a996d 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/Makefile +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/Makefile @@ -27,7 +27,9 @@ CPPFLAGS += -DUNIT_TEST -D_IR_LOCALE_=en-AU # Flags passed to the C++ compiler. CXXFLAGS += -g -Wall -Wextra -pthread -std=gnu++11 -all : gc_decode mode2_decode +objects = $(patsubst %.cpp,%,$(wildcard *.cpp)) + +all : $(objects) run_tests : all failed=""; \ @@ -35,6 +37,10 @@ run_tests : all echo "RUNNING: $${py_unittest}"; \ python3 ./$${py_unittest} || failed="$${failed} $${py_unittest}"; \ done; \ + for shell_unittest in *_test.sh; do \ + echo "RUNNING: $${shell_unittest}"; \ + bash ./$${shell_unittest} || failed="$${failed} $${shell_unittest}"; \ + done; \ if [ -n "$${failed}" ]; then \ echo "FAIL: :-( :-( Unit test(s)$${failed} failed! :-( :-("; exit 1; \ else \ @@ -46,7 +52,7 @@ run-% : all python3 ./$*.py; clean : - rm -f *.o *.pyc gc_decode mode2_decode + rm -f *.o *.pyc $(objects) # Keep all intermediate files. @@ -80,7 +86,7 @@ IRrecv.o : $(USER_DIR)/IRrecv.cpp $(USER_DIR)/IRrecv.h $(USER_DIR)/IRremoteESP82 # new specific targets goes above this line -%_decode : $(COMMON_OBJ) %_decode.o +$(objects) : %: $(COMMON_OBJ) %.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ ir_%.o : $(USER_DIR)/ir_%.h $(USER_DIR)/ir_%.cpp $(COMMON_DEPS) $(GTEST_HEADERS) diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/code_to_raw.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/code_to_raw.cpp new file mode 100644 index 000000000..7358f16da --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/code_to_raw.cpp @@ -0,0 +1,148 @@ +// Quick and dirty tool to convert a protocol's (hex) codes to raw timings. +// Copyright 2021 David Conran + +#include +#include +#include +#include +#include +#include "IRac.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "IRutils.h" + + +void usage_error(char *name) { + std::cerr << "Usage: " << name + << " --protocol PROTOCOL_NAME" + << " --code " + << " [--bits 1-" << kStateSizeMax * 8 << "]" + << " [--timinginfo]" + << std::endl; +} + +int main(int argc, char *argv[]) { + int argv_offset = 1; + int repeats = 0; + uint64_t code = 0; + uint8_t state[kStateSizeMax] = {0}; // All array elements are set to 0. + decode_type_t input_type = decode_type_t::UNKNOWN; + bool timinginfo = false; + + // Check the invocation/calling usage. + if (argc < 5 || argc > 8) { + usage_error(argv[0]); + return 1; + } + + if (strncmp("--protocol", argv[argv_offset], 11) == 0) { + argv_offset++; + input_type = strToDecodeType(argv[argv_offset]); + switch (input_type) { + // Unsupported types + case decode_type_t::UNUSED: + case decode_type_t::UNKNOWN: + case decode_type_t::GLOBALCACHE: + case decode_type_t::PRONTO: + case decode_type_t::RAW: + std::cerr << "The protocol specified is not supported by this program." + << std::endl; + return 1; + default: + break; + } + argv_offset++; + } + + uint16_t nbits = IRsend::defaultBits(input_type); + uint16_t stateSize = nbits / 8; + if (strncmp("--code", argv[argv_offset], 7) == 0) { + argv_offset++; + String hexstr = String(argv[argv_offset]); + uint64_t strOffset = 0; + if (hexstr.rfind("0x", 0) || hexstr.rfind("0X", 0)) strOffset = 2; + + // Calculate how many hexadecimal characters there are. + uint64_t hexstrlength = hexstr.length() - strOffset; + + // Ptr to the least significant byte of the resulting state for this + // protocol. + uint8_t *statePtr = &state[stateSize - 1]; + + // Convert the string into a state array of the correct length. + for (uint16_t i = 0; i < hexstrlength; i++) { + // Grab the next least sigificant hexadecimal digit from the string. + uint8_t c = tolower(hexstr[hexstrlength + strOffset - i - 1]); + if (isxdigit(c)) { + if (isdigit(c)) + c -= '0'; + else + c = c - 'a' + 10; + } else { + std::cerr << "Code " << argv[argv_offset] + << " contains non-hexidecimal characters." << std::endl; + return 3; + } + if (i % 2 == 1) { // Odd: Upper half of the byte. + *statePtr += (c << 4); + statePtr--; // Advance up to the next least significant byte of state. + } else { // Even: Lower half of the byte. + *statePtr = c; + } + } + if (!hasACState(input_type)) + code = std::stoull(argv[argv_offset], nullptr, 16); + argv_offset++; + } + + if (argc - argv_offset > 0 && strncmp("--bits", argv[argv_offset], 7) == 0) { + argv_offset++; + nbits = std::stoul(argv[argv_offset], nullptr, 10); + if (nbits == 0 && (nbits <= kStateSizeMax * 8)) { + std::cerr << "Nr. of bits " << argv[argv_offset] + << " is invalid." << std::endl; + return 1; + } + stateSize = nbits / 8; + argv_offset++; + } + + if (argc - argv_offset > 0 && + strncmp("--timinginfo", argv[argv_offset], 13) == 0) { + argv_offset++; + timinginfo = true; + } + + if (argc - argv_offset != 0) { + usage_error(argv[0]); + return 1; + } + + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + irsend.reset(); + + if (hasACState(input_type)) // Is it larger than 64 bits? + irsend.send(input_type, state, stateSize); + else + irsend.send(input_type, code, nbits, repeats); + + irsend.makeDecodeResult(); + irrecv.decode(&irsend.capture); + + std::cout << "Code type: " << irsend.capture.decode_type << " (" + << typeToString(irsend.capture.decode_type) << ")" << std::endl + << "Code bits: " << irsend.capture.bits << std::endl; + if (hasACState(irsend.capture.decode_type)) { + String description = IRAcUtils::resultAcToString(&irsend.capture); + if (description.length()) { + std::cout << "Description: " << description.c_str() << std::endl; + } + } + + std::cout << std::endl << resultToSourceCode(&irsend.capture) << std::endl; + if (timinginfo) std::cout << resultToTimingInfo(&irsend.capture); + + return 0; +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/code_to_raw_test.sh b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/code_to_raw_test.sh new file mode 100755 index 000000000..fd587f2ad --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/code_to_raw_test.sh @@ -0,0 +1,65 @@ +#! /bin/bash +CODE_TO_RAW=./code_to_raw +if [[ ! -x ${CODE_TO_RAW} ]]; then + echo "'raw_to_code' failed to compile and produce an executable." + exit 1 +fi + +function unittest_success() +{ + COMMAND=$1 + EXPECTED="$2" + echo -n "Testing: \"${COMMAND}\" ..." + OUTPUT="$(${COMMAND})" + STATUS=$? + FAILURE="" + if [[ ${STATUS} -ne 0 ]]; then + FAILURE="Non-Zero Exit status: ${STATUS}. " + fi + if [[ "${OUTPUT}" != "${EXPECTED}" ]]; then + FAILURE="${FAILURE} Unexpected Output: \"${OUTPUT}\" != \"${EXPECTED}\"" + fi + if [[ -z ${FAILURE} ]]; then + echo " ok!" + return 0 + else + echo + echo "FAILED: ${FAILURE}" + return 1 + fi +} + +read -r -d '' OUT << EOM +Code type: 4 (SONY) +Code bits: 12 + +uint16_t rawData[78] = {2400, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 600, 600, 600, 600, 600, 24600, 2400, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 600, 600, 600, 600, 600, 24600, 2400, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 600, 600, 600, 600, 600, 24600 }; // SONY F50 +uint32_t address = 0x1; +uint32_t command = 0x2F; +uint64_t data = 0xF50; +EOM + +unittest_success "${CODE_TO_RAW} --protocol Sony --code 0xf50 --bits 12" "${OUT}" + +read -r -d '' OUT << EOM +Code type: 7 (SAMSUNG) +Code bits: 32 + +uint16_t rawData[68] = {4480, 4480, 560, 1680, 560, 1680, 560, 1680, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 1680, 560, 1680, 560, 1680, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 1680, 560, 560, 560, 560, 560, 1680, 560, 1680, 560, 560, 560, 560, 560, 1680, 560, 560, 560, 1680, 560, 1680, 560, 560, 560, 560, 560, 1680, 560, 1680, 560, 560, 560, 47040 }; // SAMSUNG E0E09966 +uint32_t address = 0x7; +uint32_t command = 0x99; +uint64_t data = 0xE0E09966; +EOM + +unittest_success "${CODE_TO_RAW} --protocol SAMSUNG --code 0xE0E09966" "${OUT}" + +read -r -d '' OUT << xEOMx +Code type: 18 (KELVINATOR) +Code bits: 128 +Description: Power: On, Mode: 1 (Cool), Temp: 27C, Fan: 1 (Low), Turbo: Off, Quiet: Off, XFan: On, Ion: Off, Light: Off, Swing(H): Off, Swing(V): Off + +uint16_t rawData[280] = {9010, 4504, 680, 1530, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 19974, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 1530, 680, 39950, 9010, 4504, 680, 1530, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 1530, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 19974, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 1530, 680, 1530, 680, 39950 }; // KELVINATOR +uint8_t state[16] = {0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xF0}; +xEOMx + +unittest_success "${CODE_TO_RAW} --protocol KELVINATOR --code 0x190B8050000000E0190B8070000010F0" "${OUT}" diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/extract_lib_version.sh b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/extract_lib_version.sh new file mode 100755 index 000000000..8bea94334 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/extract_lib_version.sh @@ -0,0 +1,14 @@ +#!/bin/bash -e +# Copyright 2021 crankyoldgit +# Extract and constuct the string version of the IRremoteESP8266 Library Version +function getVerNum() +{ + echo $(egrep "^#define\s+_IRREMOTEESP8266_VERSION_$1\s+" \ + src/IRremoteESP8266.h | awk '{print $3;}') +} + +MAJOR=$(getVerNum "MAJOR") +MINOR=$(getVerNum "MINOR") +PATCH=$(getVerNum "PATCH") +LIB_VERSION="${MAJOR}.${MINOR}.${PATCH}" +echo $LIB_VERSION diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/mkkeywords b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/mkkeywords index e050e4964..34def1332 100755 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/mkkeywords +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/mkkeywords @@ -30,7 +30,8 @@ cat << EndOfTextEndOfTextEndOfText EndOfTextEndOfTextEndOfText -CLASSES=$(egrep -h "^ *((enum|class) |} [a-zA-Z0-9_]+_t;$)" src/*.h | +CLASSES=$(egrep -h \ + "^ *((enum|class|struct) [a-zA-Z0-9_]+|} [a-zA-Z0-9_]+_t;$)" src/*.h | sed 's/^ *//;s/enum class//;s/\;$//' | cut -d' ' -f2 | sort -u | grep -v "^__") for i in ${CLASSES}; do @@ -45,7 +46,7 @@ cat << EndOfTextEndOfTextEndOfText EndOfTextEndOfTextEndOfText CTYPES="u?int(8|16|32|64)?(_t)?|void|bool|char|float|long|double|String|static" -OURTYPES="match_result_t|state_t|decode_type_t" +OURTYPES="match_result_t|stdAc::state_t|decode_type_t" METHODS=$(egrep -h "^[ ]{0,2}(${CTYPES}|${OURTYPES})\*? [^ ]*\(" src/*.cpp | sed 's/^ //' | cut -d' ' -f2 | sed 's/^\([^:]*::\| *\* *\)//' | cut -d'(' -f1 | sort -u | grep -v RAM_ATTR) diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/scrape_supported_devices.py b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/scrape_supported_devices.py new file mode 100755 index 000000000..f40b3e959 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/scrape_supported_devices.py @@ -0,0 +1,426 @@ +#!/usr/bin/env python3 +"""Generate SupportedProtocols.md by scraping source code files""" +import pathlib +import argparse +import subprocess +from io import StringIO +import sys +import re +import time + +CODE_URL = "https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_" + +BRAND_MODEL = re.compile(r""" + Brand:\s{1,20} # "Brand:" label followd by between 1 and 20 whitespace chars. + \b(?P.{1,40})\b # The actual brand of the device, max 40 chars. + \s{0,10}, # Followed by at most 10 whitespace chars, then a comma. + \s{1,20} # The between 1 and 20 whitespace chars. + Model:\s{1,20} # "Model:" label followd by between 1 and 20 whitespace chars. + \b(?P.{1,80}) # The model info of the device, max 80 chars. + \s{0,5}$ # Followed by at most 5 whitespaces before the end of line. + """, re.VERBOSE) +ENUMS = re.compile(r"enum (\w{1,60}) {(.{1,5000}?)};", re.DOTALL) +ENUM_ENTRY = re.compile(r"^\s{1,80}(\w{1,80})", re.MULTILINE) +DECODED_PROTOCOLS = re.compile(r""" + .{0,80} # Ignore upto an 80 char line of whitespace/code etc. + # Now look for code that looks like we are assigning the Protocol type. + # There are two typical styles used: + (?:results->decode_type # The first style. + | # Or + typeguess) # The second style + \s{0,5}=\s{0,5} # The assignment operator and potential whitespace + (?:decode_type_t::)? # The protocol could have an optional type prefix. + (\w{1,40}); # Finally, the last word of code should be the Protocol. + """, re.VERBOSE) +AC_FN = re.compile(r"ir_(.{1,80})\.h") +AC_MODEL_ENUM_RE = re.compile(r"(.{1,40})_ac_remote_model_t") +IRSEND_FN_RE = re.compile(r"IRsend\.h") +ALL_FN = re.compile(r"ir_(.{1,80})\.(h|cpp)") + +EXCLUDED_PROTOCOLS = ["UNKNOWN", "UNUSED", "kLastDecodeType", "typeguess"] +EXCLUDED_ACS = ["Magiquest", "NEC"] + +def getgitcommittime(): + """Call git to get time of last commit + """ + try: + label = subprocess.check_output(\ + ["git", "show", "-s", "--format=%ct", "HEAD"]).strip() + return int(label) + except FileNotFoundError as err: + print("Git failed, which is ok, no git binary found?:", err) + return None + except subprocess.SubprocessError as err: + print("Git failed, which is ok, see output, maybe no git checkout?:", err) + return None + +def getmarkdownheader(): + """Get the generated header + """ + srctime = getgitcommittime() + # pylint: disable=C0209 + return """""".format( + time.strftime("%a %d %b %Y %H:%M:%S +0000", time.gmtime(srctime))) + # pylint: enable=C0209 + + + +def getallprotocols(): + """Return all protocls configured in IRremoteESP8266.h + """ + irremote = ARGS.directory / "IRremoteESP8266.h" + enums = getenums(irremote)["decode_type_t"] + if not enums: + errorexit("Error getting ENUMS from IRremoteESP8266.h") + return enums + + +def getdecodedprotocols(): + """All protocols that include decoding support""" + ret = set() + for path in ARGS.directory.iterdir(): + if path.suffix != ".cpp": + continue + matches = DECODED_PROTOCOLS.finditer(path.open(encoding="utf-8").read()) + for match in matches: + protocol = match.group(1) + if protocol not in EXCLUDED_PROTOCOLS: + ret.add(protocol) + return ret + + +def getallacs(): + """All supported A/C codes""" + ret = {} + for path in ARGS.directory.iterdir(): + match = AC_FN.match(path.name) + if match: + acprotocol = match.group(1) + rawmodels = getenums(path) + models = set() + for model in rawmodels: + model = model.upper() + model = model.replace(f"K{acprotocol.upper()}", "") + if model and model not in EXCLUDED_PROTOCOLS: + models.add(model) + if acprotocol in ret: + ret[acprotocol].update(models) + else: + ret[acprotocol] = models + # Parse IRsend.h's enums + match = IRSEND_FN_RE.match(path.name) + if match: + rawmodels = getenums(path) + for acprotocol, acmodels in rawmodels.items(): + models = set() + for model in acmodels: + model = model.upper() + model = model.replace(f"K{acprotocol.upper()}", "") + if model and model not in EXCLUDED_PROTOCOLS: + models.add(model) + if acprotocol in ret: + ret[acprotocol].update(models) + else: + ret[acprotocol] = models + return ret + +class FnSets(): + """Container for getalldevices""" + def __init__(self): + self.allcodes = {} + self.fnnomatch = set() + self.allhfileprotos = set() + self.fnhmatch = set() + self.fncppmatch = set() + + def add(self, supports, path): + """add the path to correct set based on supports""" + if path.suffix == ".h": + self.allhfileprotos.add(path.stem) + if supports: + if path.suffix == ".h": + self.fnhmatch.add(path.stem) + elif path.suffix == ".cpp": + self.fncppmatch.add(path.stem) + else: + self.fnnomatch.add(path.stem) + + def printwarnings(self): + """print warnings""" + # all protos with support in .cpp file, when there is a .h file + # meaning that the documentation should probably be moved to .h + # in the future, with doxygen, that might change + protosincppwithh = list(self.fncppmatch & self.allhfileprotos) + if protosincppwithh: + protosincppwithh.sort() + print("The following files has supports section in .cpp, expected in .h") + for path in protosincppwithh: + print(f"\t{path}") + + protosincppandh = list(self.fncppmatch & self.fnhmatch) + if protosincppandh: + protosincppandh.sort() + print("The following files has supports section in both .h and .cpp") + for path in protosincppandh: + print(f"\t{path}") + + nosupports = self.getnosupports() + if nosupports: + nosupports.sort() + print("The following files had no supports section:") + for path in nosupports: + print(f"\t{path}") + + return protosincppwithh or protosincppandh or nosupports + + def getnosupports(self): + """get protos without supports sections""" + return list(self.fnnomatch - self.fnhmatch - self.fncppmatch) + + +def getalldevices(): + """All devices and associated branding and model information (if available) + """ + sets = FnSets() + for path in ARGS.directory.iterdir(): + match = ALL_FN.match(path.name) + if not match: + continue + supports = extractsupports(path) + sets.add(supports, path) + protocol = match.group(1) + for brand, model in supports: + protocolbrand = (protocol, brand) + pbset = sets.allcodes.get(protocolbrand, []) + if model in pbset: + print(f"Model {model} is duplicated for {protocol}, {brand}") + sets.allcodes[protocolbrand] = pbset + [model] + + for fnprotocol in sets.getnosupports(): + sets.allcodes[(fnprotocol[3:], "Unknown")] = [] + return sets + + +def getenums(path): + """Returns the keys for the first enum type in path + """ + ret = {} + for enums in ENUMS.finditer(path.open(encoding="utf-8").read()): + if enums: + enum_name = AC_MODEL_ENUM_RE.search(enums.group(1)) + if enum_name: + enum_name = enum_name.group(1).capitalize() + else: + enum_name = enums.group(1) + ret[enum_name] = set() + for enum in ENUM_ENTRY.finditer(enums.group(2)): + enum = enum.group(1) + if enum in EXCLUDED_PROTOCOLS: + continue + ret[enum_name].add(enum) + return ret + + +ARGS = None + + +def initargs(): + """Init the command line arguments""" + global ARGS # pylint: disable=global-statement + parser = argparse.ArgumentParser() + parser.add_argument( + "-n", + "--noout", + help="generate no output data, combine with --alert to only check", + action="store_true", + ) + parser.add_argument( + "-s", + "--stdout", + help="output to stdout rather than SupportedProtocols.md", + action="store_true", + ) + parser.add_argument("-v", + "--verbose", + help="increase output verbosity", + action="store_true") + parser.add_argument( + "-a", + "--alert", + help="alert if a file does not have a supports section, " + "non zero exit code if issues where found", + action="store_true", + ) + parser.add_argument( + "directory", + nargs="?", + help="directory of the source git checkout", + default=None, + ) + ARGS = parser.parse_args() + if ARGS.directory is None: + src = pathlib.Path("../src") + if not src.is_dir(): + src = pathlib.Path("./src") + else: + src = pathlib.Path(ARGS.directory) / "src" + if not src.is_dir(): + errorexit(f"Directory not valid: {src!s}") + ARGS.directory = src + return ARGS + +def getmdfile(): + """Resolves SupportedProtocols.md path""" + foutpath = ARGS.directory / "../SupportedProtocols.md" + return foutpath.resolve() + +def errorexit(msg): + """Print an error and exit on critical error""" + sys.stderr.write(f"{msg}\n") + sys.exit(1) + +def extractsupports(path): + """Extract all of the Supports: sections and associated brands and models + """ + supports = [] + insupports = False + for line in path.open(encoding="utf-8"): + if not line.startswith("//"): + continue + line = line[2:].strip() + if line == "Supports:": + insupports = True + continue + if insupports: + match = BRAND_MODEL.match(line) + if match: + supports.append((match.group("brand"), match.group("model"))) + else: + insupports = False + continue + # search and inform about any legacy formated supports data + elif any(x in line for x in [ \ + "seems compatible with", + "be compatible with", + "it working with here"]): + print(f"\t{path.name} Legacy supports format found\n\t\t{line}") + return supports + + +def makeurl(txt, path): + """Make a Markup URL from given filename""" + return f"[{txt}]({CODE_URL + path})" + + +def outputprotocols(fout, protocols): + """For a given protocol set, sort and output the markdown""" + protocols = list(protocols) + protocols.sort() + for protocol in protocols: + fout.write(f"- {protocol}\n") + + +def generate(fout): + """Generate data to fout + return True on any issues (when alert is active)""" + decodedprotocols = getdecodedprotocols() + sendonly = getallprotocols() - decodedprotocols + allacs = getallacs() + + sets = getalldevices() + allcodes = sets.allcodes + allbrands = list(allcodes.keys()) + allbrands.sort() + + fout.write("\n# IR Protocols supported by this library\n\n") + fout.write( + "| Protocol | Brand | Model | A/C Model | Detailed A/C Support |\n") + fout.write("| --- | --- | --- | --- | --- |\n") + + for protocolbrand in allbrands: + protocol, brand = protocolbrand + codes = allcodes[protocolbrand] + codes.sort() + acmodels = [] + acsupport = "-" + if protocol in allacs: + acmodels = list(allacs[protocol]) + acmodels.sort() + brand = makeurl(brand, protocol + ".h") + if protocol not in EXCLUDED_ACS: + acsupport = "Yes" + # pylint: disable=C0209 + fout.write("| {} | **{}** | {} | {} | {} |\n".format( + makeurl(protocol, protocol + ".cpp"), + brand, + "
".join(codes).replace("|", "\\|"), + "
".join(acmodels), + acsupport, + )) + # pylint: enable=C0209 + + fout.write("\n\n## Send only protocols:\n\n") + outputprotocols(fout, sendonly) + + fout.write("\n\n## Send & decodable protocols:\n\n") + outputprotocols(fout, decodedprotocols) + + return ARGS.alert and sets.printwarnings() + +def generatenone(): + """No out write + return True on any issues""" + return generate(StringIO()) + +def generatestdout(): + """Standard out write + return True on any issues""" + fout = sys.stdout + fout.write(getmarkdownheader()) + return generate(fout) + +def generatefile(): + """File write, extra detection of changes in existing file + return True on any issues, but only if there is changes""" + # get file path + foutpath = getmdfile() + if ARGS.verbose: + print(f"Output path: {foutpath!s}") + # write data to temp memorystream + ftemp = StringIO() + ret = generate(ftemp) + # get old filedata, skipping header + with getmdfile().open("r", encoding="utf-8") as forg: + olddata = forg.readlines()[3:] + # get new data, skip first empty line + ftemp.seek(0) + newdata = ftemp.readlines()[1:] + # if new data is same as old we don't need to write anything + if newdata == olddata: + print("No changes, exit without write") + return False + # write output + with foutpath.open("w", encoding="utf-8") as fout: + fout.write(getmarkdownheader()) + fout.write(ftemp.getvalue()) + + return ret + +def main(): + """Default main function + return True on any issues""" + initargs() + if ARGS.verbose: + print(f"Looking for files in: {ARGS.directory.resolve()!s}") + if ARGS.noout: + return generatenone() + if ARGS.stdout: + return generatestdout() + # default file + return generatefile() + + +if __name__ == "__main__": + sys.exit(1 if main() else 0) diff --git a/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.cpp b/lib/lib_basic/OneWire-Stickbreaker/OneWire.cpp similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.cpp rename to lib/lib_basic/OneWire-Stickbreaker/OneWire.cpp diff --git a/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.h b/lib/lib_basic/OneWire-Stickbreaker/OneWire.h similarity index 95% rename from lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.h rename to lib/lib_basic/OneWire-Stickbreaker/OneWire.h index edb31d1eb..2747bea4e 100644 --- a/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.h +++ b/lib/lib_basic/OneWire-Stickbreaker/OneWire.h @@ -161,7 +161,7 @@ IO_REG_TYPE directRead(IO_REG_TYPE pin) #else // plain ESP32 if ( pin < 32 ) return (GPIO.in >> pin) & 0x1; - else if ( pin < 40 ) + else if ( pin < 46 ) return (GPIO.in1.val >> (pin - 32)) & 0x1; #endif @@ -176,7 +176,7 @@ void directWriteLow(IO_REG_TYPE pin) #else // plain ESP32 if ( pin < 32 ) GPIO.out_w1tc = ((uint32_t)1 << pin); - else if ( pin < 34 ) + else if ( pin < 46 ) GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32)); #endif } @@ -189,7 +189,7 @@ void directWriteHigh(IO_REG_TYPE pin) #else // plain ESP32 if ( pin < 32 ) GPIO.out_w1ts = ((uint32_t)1 << pin); - else if ( pin < 34 ) + else if ( pin < 46 ) GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32)); #endif } @@ -211,19 +211,15 @@ void directModeInput(IO_REG_TYPE pin) ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); } #elif ESP_IDF_VERSION_MAJOR > 3 // ESP32-S2 needs IDF 4.2 or later - int rtcio_num = rtc_io_number_get((gpio_num_t)pin); - - if (rtcio_num >= 0) { - uint32_t rtc_reg(rtc_io_desc[rtcio_num].reg); - - if ( rtc_reg ) // RTC pins PULL settings - { - ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtcio_num].mux); - ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtcio_num].pullup | rtc_io_desc[rtcio_num].pulldown); - } + int8_t rtc_io = esp32_gpioMux[pin].rtc; + uint32_t rtc_reg = (rtc_io != -1)?rtc_io_desc[rtc_io].reg:0; + if ( rtc_reg ) // RTC pins PULL settings + { + ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].mux); + ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].pullup | rtc_io_desc[rtc_io].pulldown); } #endif - + // Input if ( pin < 32 ) GPIO.enable_w1tc = ((uint32_t)1 << pin); else @@ -231,7 +227,7 @@ void directModeInput(IO_REG_TYPE pin) uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers? pinFunction |= FUN_IE; // input enable but required for output as well? - pinFunction |= ((uint32_t)2 << MCU_SEL_S); + pinFunction |= ((uint32_t)PIN_FUNC_GPIO << MCU_SEL_S); ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction; @@ -257,19 +253,15 @@ void directModeOutput(IO_REG_TYPE pin) ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); } #elif ESP_IDF_VERSION_MAJOR > 3 // ESP32-S2 needs IDF 4.2 or later - int rtcio_num = rtc_io_number_get((gpio_num_t)pin); - - if (rtcio_num >= 0) { - uint32_t rtc_reg(rtc_io_desc[rtcio_num].reg); - - if ( rtc_reg ) // RTC pins PULL settings - { - ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtcio_num].mux); - ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtcio_num].pullup | rtc_io_desc[rtcio_num].pulldown); - } + int8_t rtc_io = esp32_gpioMux[pin].rtc; + uint32_t rtc_reg = (rtc_io != -1)?rtc_io_desc[rtc_io].reg:0; + if ( rtc_reg ) // RTC pins PULL settings + { + ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].mux); + ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].pullup | rtc_io_desc[rtc_io].pulldown); } #endif - + // Output if ( pin < 32 ) GPIO.enable_w1ts = ((uint32_t)1 << pin); else // already validated to pins <= 33 @@ -277,7 +269,7 @@ void directModeOutput(IO_REG_TYPE pin) uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers? pinFunction |= FUN_IE; // input enable but required for output as well? - pinFunction |= ((uint32_t)2 << MCU_SEL_S); + pinFunction |= ((uint32_t)PIN_FUNC_GPIO << MCU_SEL_S); ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction; diff --git a/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/README.md b/lib/lib_basic/OneWire-Stickbreaker/README.md similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/README.md rename to lib/lib_basic/OneWire-Stickbreaker/README.md diff --git a/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS18x20_Temperature/DS18x20_Temperature.pde b/lib/lib_basic/OneWire-Stickbreaker/examples/DS18x20_Temperature/DS18x20_Temperature.pde similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS18x20_Temperature/DS18x20_Temperature.pde rename to lib/lib_basic/OneWire-Stickbreaker/examples/DS18x20_Temperature/DS18x20_Temperature.pde diff --git a/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS2408_Switch/DS2408_Switch.pde b/lib/lib_basic/OneWire-Stickbreaker/examples/DS2408_Switch/DS2408_Switch.pde similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS2408_Switch/DS2408_Switch.pde rename to lib/lib_basic/OneWire-Stickbreaker/examples/DS2408_Switch/DS2408_Switch.pde diff --git a/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS250x_PROM/DS250x_PROM.pde b/lib/lib_basic/OneWire-Stickbreaker/examples/DS250x_PROM/DS250x_PROM.pde similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS250x_PROM/DS250x_PROM.pde rename to lib/lib_basic/OneWire-Stickbreaker/examples/DS250x_PROM/DS250x_PROM.pde diff --git a/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/keywords.txt b/lib/lib_basic/OneWire-Stickbreaker/keywords.txt similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/keywords.txt rename to lib/lib_basic/OneWire-Stickbreaker/keywords.txt diff --git a/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/library.json b/lib/lib_basic/OneWire-Stickbreaker/library.json similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/library.json rename to lib/lib_basic/OneWire-Stickbreaker/library.json diff --git a/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/library.properties b/lib/lib_basic/OneWire-Stickbreaker/library.properties similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/library.properties rename to lib/lib_basic/OneWire-Stickbreaker/library.properties diff --git a/lib/lib_basic/TasmotaModbus-1.2.0/README.md b/lib/lib_basic/TasmotaModbus-3.4.0/README.md similarity index 100% rename from lib/lib_basic/TasmotaModbus-1.2.0/README.md rename to lib/lib_basic/TasmotaModbus-3.4.0/README.md diff --git a/lib/lib_basic/TasmotaModbus-1.2.0/examples/modbustest/modbustest.ino b/lib/lib_basic/TasmotaModbus-3.4.0/examples/modbustest/modbustest.ino similarity index 100% rename from lib/lib_basic/TasmotaModbus-1.2.0/examples/modbustest/modbustest.ino rename to lib/lib_basic/TasmotaModbus-3.4.0/examples/modbustest/modbustest.ino diff --git a/lib/lib_basic/TasmotaModbus-1.2.0/keywords.txt b/lib/lib_basic/TasmotaModbus-3.4.0/keywords.txt similarity index 100% rename from lib/lib_basic/TasmotaModbus-1.2.0/keywords.txt rename to lib/lib_basic/TasmotaModbus-3.4.0/keywords.txt diff --git a/lib/lib_basic/TasmotaModbus-1.2.0/library.json b/lib/lib_basic/TasmotaModbus-3.4.0/library.json similarity index 93% rename from lib/lib_basic/TasmotaModbus-1.2.0/library.json rename to lib/lib_basic/TasmotaModbus-3.4.0/library.json index 3c28959ea..9c93d13b5 100644 --- a/lib/lib_basic/TasmotaModbus-1.2.0/library.json +++ b/lib/lib_basic/TasmotaModbus-3.4.0/library.json @@ -1,6 +1,6 @@ { "name": "TasmotaModbus", - "version": "1.2.0", + "version": "3.4.0", "keywords": [ "serial", "io", "TasmotaModbus" ], diff --git a/lib/lib_basic/TasmotaModbus-1.2.0/library.properties b/lib/lib_basic/TasmotaModbus-3.4.0/library.properties similarity index 93% rename from lib/lib_basic/TasmotaModbus-1.2.0/library.properties rename to lib/lib_basic/TasmotaModbus-3.4.0/library.properties index 7ac182843..748962a53 100644 --- a/lib/lib_basic/TasmotaModbus-1.2.0/library.properties +++ b/lib/lib_basic/TasmotaModbus-3.4.0/library.properties @@ -1,5 +1,5 @@ name=TasmotaModbus -version=1.2.0 +version=3.4.0 author=Theo Arends maintainer=Theo Arends sentence=Basic modbus wrapper for TasmotaSerial for ESP8266. diff --git a/lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp b/lib/lib_basic/TasmotaModbus-3.4.0/src/TasmotaModbus.cpp similarity index 98% rename from lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp rename to lib/lib_basic/TasmotaModbus-3.4.0/src/TasmotaModbus.cpp index 8c2180505..bd9b7a06b 100644 --- a/lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp +++ b/lib/lib_basic/TasmotaModbus-3.4.0/src/TasmotaModbus.cpp @@ -42,11 +42,11 @@ uint16_t TasmotaModbus::CalculateCRC(uint8_t *frame, uint8_t num) return crc; } -int TasmotaModbus::Begin(long speed, int stop_bits) +int TasmotaModbus::Begin(long speed, uint32_t config) { int result = 0; - if (begin(speed, stop_bits)) { + if (begin(speed, config)) { result = 1; if (hardwareSerial()) { result = 2; } } diff --git a/lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.h b/lib/lib_basic/TasmotaModbus-3.4.0/src/TasmotaModbus.h similarity index 96% rename from lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.h rename to lib/lib_basic/TasmotaModbus-3.4.0/src/TasmotaModbus.h index d6c0c2883..78fc3d50b 100644 --- a/lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.h +++ b/lib/lib_basic/TasmotaModbus-3.4.0/src/TasmotaModbus.h @@ -30,7 +30,7 @@ class TasmotaModbus : public TasmotaSerial { TasmotaModbus(int receive_pin, int transmit_pin); virtual ~TasmotaModbus() {} - int Begin(long speed = TM_MODBUS_BAUDRATE, int stop_bits = 1); + int Begin(long speed = TM_MODBUS_BAUDRATE, uint32_t config = SERIAL_8N1); uint16_t CalculateCRC(uint8_t *frame, uint8_t num); diff --git a/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp index 5e88150cc..398dba0df 100644 --- a/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp +++ b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp @@ -1610,10 +1610,12 @@ void Adafruit_GFX_Button::drawButton(boolean inverted) { text = _fillcolor; } + #if defined USE_UFILESYS if (_label[0]=='/') { draw_picture(_label, _x1, _y1, _w, _h, outline, inverted); _gfx->drawRect(_x1, _y1, _w, _h, text); } else { + #endif uint8_t r = min(_w, _h) / 4; // Corner radius _gfx->fillRoundRect(_x1, _y1, _w, _h, r, fill); _gfx->drawRoundRect(_x1, _y1, _w, _h, r, outline); @@ -1622,7 +1624,9 @@ void Adafruit_GFX_Button::drawButton(boolean inverted) { _gfx->setTextColor(text); _gfx->setTextSize(_textsize_x, _textsize_y); _gfx->print(_label); + #if defined USE_UFILESYS } + #endif } /**************************************************************************/ diff --git a/lib/lib_display/LedControl/src/LedControl.cpp b/lib/lib_display/LedControl/src/LedControl.cpp index e43211fd8..e2230944c 100644 --- a/lib/lib_display/LedControl/src/LedControl.cpp +++ b/lib/lib_display/LedControl/src/LedControl.cpp @@ -208,4 +208,3 @@ void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data) digitalWrite(SPI_CS,HIGH); } - diff --git a/lib/lib_display/LedControl/src/LedControl.h b/lib/lib_display/LedControl/src/LedControl.h index f8180d07d..1cd3b13b4 100644 --- a/lib/lib_display/LedControl/src/LedControl.h +++ b/lib/lib_display/LedControl/src/LedControl.h @@ -187,4 +187,3 @@ class LedControl { #endif //LedControl.h - diff --git a/lib/lib_display/LedControl/src/LedMatrix.cpp b/lib/lib_display/LedControl/src/LedMatrix.cpp new file mode 100644 index 000000000..fb23fbc26 --- /dev/null +++ b/lib/lib_display/LedControl/src/LedMatrix.cpp @@ -0,0 +1,422 @@ +/* + * LedMatrix.h - Extends the Library LedControl for multiple 8x8 LED dot matrix maxDevices, based on MAX7219/MAX7221 + * Copyright (c) 2021 Michael Beuss + * + * 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: + * + * 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. + */ + +#include "LedMatrix.h" +#include "font_6x8_base.h" +//#include "font_6x8_UTF8_C2.h" // additional characters if needed +//#include "font_6x8_UTF8_C3.h" // additional characters (latin1) if needed +#include "../../../../tasmota/my_user_config.h" // to check compiler option USE_UTF8_LATIN1 +#ifdef USE_UTF8_LATIN1 + #include "font_6x8_UTF8_C2.h" // 256 bytes + #include "font_6x8_UTF8_C3.h" // 512 bytes +#endif + + +//the opcodes for the MAX7221 and MAX7219 +#define OP_NOOP 0 +#define OP_DIGIT0 1 +#define OP_DIGIT1 2 +#define OP_DIGIT2 3 +#define OP_DIGIT3 4 +#define OP_DIGIT4 5 +#define OP_DIGIT5 6 +#define OP_DIGIT6 7 +#define OP_DIGIT7 8 +#define OP_DECODEMODE 9 +#define OP_INTENSITY 10 +#define OP_SCANLIMIT 11 +#define OP_SHUTDOWN 12 +#define OP_DISPLAYTEST 15 + +LedMatrix::LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, unsigned int rows) +{ + if (colums * rows > MAX72XX_MAX_DEVICES) + { + // dimension exeeds maximum buffer size + if (colums >= MAX72XX_MAX_DEVICES) + { + colums = MAX72XX_MAX_DEVICES; + rows = 1; + } + else + { + rows = MAX72XX_MAX_DEVICES / colums; + } + } + + charWidth = font_char_width; // defined in header file of font + charHeight = font_char_height; // defined in header file of font + modulesPerRow = colums; + modulesPerCol = rows; + displayWidth = colums * 8; + displayHeight = rows * 8; + maxDevices = colums * rows; + moduleOrientation = ORIENTATION_UPSIDE_DOWN; // use setOrientation() to turn it + textBuf[0] = 0; + textWidth = 0; + textPosX = 0; + textPosY = 0; + appendTextBuf[0] = 0; + setScrollAppendText(" "); + powerIsOn = false; + + // initialize all connected MAX7219/MAX7221 devices + SPI_MOSI = dataPin; + SPI_CLK = clkPin; + SPI_CS = csPin; + pinMode(SPI_MOSI, OUTPUT); + pinMode(SPI_CLK, OUTPUT); + pinMode(SPI_CS, OUTPUT); + SPI_MOSI = dataPin; + + //spiTransfer_value(OP_DISPLAYTEST, 0); // display test + spiTransfer_value(OP_SCANLIMIT, 7); // scanlimit is set to max on startup + spiTransfer_value(OP_DECODEMODE, 0); // decode is done in source + clearDisplay(); + //spiTransfer_value(OP_SHUTDOWN, 0); //we go into shutdown-mode (LEDs off) on startup + setIntensity(7); // initialize with the half of the maximum intensity [0..15] + power(true); // power on; +} + +bool LedMatrix::drawText( const char *str, bool clearBefore) +{ + if(clearBefore) clearDisplay(); + strncpy(textBuf, str, TEXT_BUFFER_SIZE -1); + textPosX = 0; + textPosY = 0; + textLen = countChars(str); + textWidth = textLen * charWidth; + if(textWidth <= displayWidth) + { + // text fits into the display, place it into the center + textPosX = (displayWidth - textWidth) / 2; // center + } + else + { + // The text ist longer than the display width. Scrolling is needed. + // Add a space in front of text to have a distance to the pervious scroll text. + addSpace(); + } + drawTextAt(textBuf, textPosX, textPosY); + refresh(); // refresh display with the new drawed string content + return true; +} + +bool LedMatrix::drawTextAt( const char *str, const int x, const int y ) +{ + // draw character by character + int xPos = x; + const char* fontChar = nullptr; + for (unsigned int i = 0; (i= 0x20 && c < 0x80) // basic font + { + fontChar = font_20_7F[c-0x20]; + } + +#ifdef font_6x8_UTF8_C2_h + else if(c == 0xC2) // UTF special characters + { + i++; + c= str[i]; + if(c>= 0xA0 && c < 0xC0) + { + fontChar = font_UTF_C2_A0_BF[c - 0xA0]; + } + } +#endif // font_6x8_UTF8_C2_h + +#ifdef font_6x8_UTF8_C3_h + else if(c == 0xC3) // UTF latin1 + { + i++; + c= str[i]; + if(c>= 0x80 && c < 0xC0) + { + fontChar = font_UTF_C3_80_BF[c - 0x80]; + } + } +#endif // font_6x8_UTF8_C3_h + + else if(c>= 0xC0 && c <= 0xDF) + { + i += 1; // 2 byte UTF sequence + } + else if(c>= 0xE0 && c <= 0xEF) + { + i += 2; // 3 byte UTF sequence + } + else if(c>= 0xF0 && c <= 0xF7) + { + i += 3; // 4 byte UTF sequence + } + + drawCharAt(fontChar, xPos, y); + xPos += charWidth; + } + return true; +} + +int LedMatrix::countChars( const char* utfText) +{ + int len = 0; + for( int i = 0; (i 15) + return false; + + spiTransfer_value(OP_INTENSITY, intensity); + return true; +} + +bool LedMatrix::setOrientation(LedMatrix::ModuleOrientation orientation) +{ + if(moduleOrientation != orientation) + { + moduleOrientation = orientation; + refresh(); + } + return true; +} + +bool LedMatrix::setScrollAppendText(const char* append ) +{ + strncpy(appendTextBuf, append, TEXT_APPEND_BUFFER_SIZE -1); + return (strlen(append) < TEXT_APPEND_BUFFER_SIZE); +} + +bool LedMatrix::setPixel(const int x, const int y, bool on) +{ + if (x >= displayWidth || y >= displayHeight) + return false; + + int modul_col = x / 8; // x pos divided by 8 is the index of the modul to the right + int buffer_pos = modul_col + y * modulesPerRow; + byte buffer_byte = 0x80 >> (x % 8); + if (on) + { + buffer[buffer_pos] |= buffer_byte; // set bit + } + else + { + buffer[buffer_pos] &= ~buffer_byte; // reset bit + } + return true; +} + +void LedMatrix::refresh() +{ + int col = 0; + int pixelRow = 0; + int bufPos = 0; + int deviceRow = 0; + for(int ledRow = 7; ledRow >= 0; ledRow--) // refresh from buttom to top + { + for( int addr = 0; addr < maxDevices; addr++) + { + if(moduleOrientation == ORIENTATION_NORMAL || moduleOrientation == ORIENTATION_UPSIDE_DOWN) + { + col = addr % modulesPerRow; + pixelRow = (addr / modulesPerRow) * 8 + ledRow; + bufPos = pixelRow * modulesPerRow + col; + if(moduleOrientation == ORIENTATION_NORMAL) + { + // ORIENTATION_NORMAL + deviceDataBuff[addr] = revereBitorder(buffer[bufPos]); // mirror + deviceRow = 7 - ledRow; // upside down + } + else + { + // ORIENTATION_UPSIDE_DOWN + deviceDataBuff[maxDevices -1 - addr] = buffer[bufPos]; + deviceRow = ledRow; + } + } + else // ORIENTATION_TURN_RIGHT || ORIENTATION_TURN_LEFT + { + // not implemented yet + } + } + setRow_allDevices(deviceRow, deviceDataBuff); + } +} + +// private functions +/** + * @brief + * + * @param fontChar defines the pixelrows of a character. const char fontChar[charHeight] + * @param x + * @param y + */ +bool LedMatrix::drawCharAt( const char* fontChar, const int x, const int y) +{ + // ignore when the character position is not visible on the display + bool visible = ( + x > 0 - (int)charWidth && x < (int)displayWidth && + y > 0 - (int)charHeight && y < (int)displayHeight + ); + if (!visible) return false; + + // ignore the leading bits above charWidth of the font definition + static const byte charOffset = 8 - charWidth; + + for (byte charY = 0; charY < charHeight; charY++) + { + char pixelRow = (fontChar[charY]) << charOffset; // skip the first bits when the character width is smaller than 8 pixel + for (byte charX = 0; charX < charWidth; charX++) + { + bool pixel = (pixelRow & 0x80); // pixel=true when upper bit is set + setPixel(x + charX, y + charY, pixel); + pixelRow = pixelRow << 1; // next pixel + } + } + return true; +} + +byte LedMatrix::revereBitorder (byte b) +{ + static const byte lookup[16] = { + 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, + 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf + }; + return (lookup[b & 0b1111] << 4) | lookup[b >> 4]; +} + +void LedMatrix::addSpace() +{ + strncat(textBuf, appendTextBuf, TEXT_BUFFER_SIZE -1); + textPosX = strlen(appendTextBuf) * charWidth; // start scrolling with space + textLen = countChars(textBuf); + textWidth = countChars(textBuf) * charWidth; +} + +void LedMatrix::setRow_allDevices(int row, byte *data) +{ + if (row < 0 || row > 7) + return; + spiTransfer_array(row + 1, data); +} + +void LedMatrix::spiTransfer_array(byte opcode, const byte* data) { + // create an array with the data to shift out + for (int addr = 0; addr < maxDevices; addr++) + { + spidata[addr * 2 + 1] = opcode; + spidata[addr * 2] = data[addr]; + } + // enable the line + digitalWrite(SPI_CS, LOW); + // shift out the data + for (int i = maxDevices * 2 -1; i >= 0; i--) + { + shiftOut(SPI_MOSI, SPI_CLK, MSBFIRST, spidata[i]); + } + // latch the data onto the display + digitalWrite(SPI_CS, HIGH); +} + +void LedMatrix::spiTransfer_value(byte opcode, byte value) +{ + memset(deviceDataBuff, (byte)value, maxDevices); + spiTransfer_array(opcode, deviceDataBuff); +} + + + diff --git a/lib/lib_display/LedControl/src/LedMatrix.h b/lib/lib_display/LedControl/src/LedMatrix.h new file mode 100644 index 000000000..b77038ecc --- /dev/null +++ b/lib/lib_display/LedControl/src/LedMatrix.h @@ -0,0 +1,211 @@ +/* + * LedMatrix.h - Extends the Library LedControl for multiple 8x8 LED dot matrix devices, based on MAX7219/MAX7221 + * Copyright (c) 2021 Michael Beuss + * + * 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: + * + * 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 LedMatrix_h +#define LedMatrix_h + +#include + +#if (ARDUINO >= 100) +#include +#else +#include +#endif + +#ifndef MAX72XX_MAX_DEVICES +#define MAX72XX_MAX_DEVICES 32 // maximum number of devices based on MXA7219/MAX7221 +#endif + +#define MATRIX_BUFFER_SIZE MAX72XX_MAX_DEVICES * 8 // 8 bytes per modul. One byte represents 8 LEDs. +#define TEXT_BUFFER_SIZE 256 // maximum text length that can be scrolled +#define TEXT_APPEND_BUFFER_SIZE 16 // used for characters that are appended to the scroll text, before it repeats +#define SPI_BUFFER_SIZE MAX72XX_MAX_DEVICES * 2 // buffer size fort shifting commands to all devices (2 bytes each) + + +/** + * @brief LedMatrix controls multiple 8x8 LED dot matrx devices. + * All devices in rows and clolums together build a common display pixel matrix. + * + */ +class LedMatrix +{ + public: + enum ModuleOrientation // orientation of 8x8 LED dot matrix mdules (first module starts at top left) + { + ORIENTATION_NORMAL, // first pixel is on top left, no turn is necessary + ORIENTATION_TURN_RIGHT, // first pixel is on bottom left, for correction it has to turn 90° right + ORIENTATION_UPSIDE_DOWN, // first pixel is on bottom right, fpr correction it has to turn 180° + ORIENTATION_TURN_LEFT, // first pixel is on top right, for correction is has to turn 90° left. + }; + + public: + /** + * @brief Construct a new LED Matrix object + * + * @param colums of 8x8 LED dot matrix devices + * @param rows of 8x8 LED dot matrix devices + */ + LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, unsigned int rows); + + /** + * @brief Draws a string to the display. + * When the text fits into the display, it will be shown in the center. + * When the text is longer than than the display width, it can be scrolled per pixel with function scrollText(). + * + * @param str string to display + * @param clearBefore true (default) clears old display content before, false: do not clear display before + */ + bool drawText( const char *str, bool clearBefore = true ); + + /** + * @brief Dwaws a character string to a defined display position. The position (x,y) is used for the upper left pixel of the text. + * Existing content outside the drawing text area will not be cleared. But you can use clearDisplay() before. + * Use refresh() after all text parts are drawed. + * + * @param str string to display + * @param x horizantal pixel position to start with string (0 is most left) + * @param y vertical pixel position for the top position of the string (0 is top) + */ + bool drawTextAt( const char *str, const int x, const int y ); + + /** + * @brief Scroll the current text one pixel to the left. + * Repeat with from start when end of text reached. This function can be called every 50 ms to get a propper scroll speed. + * + */ + bool scrollText(); + + /** + * @brief switches the display on or off + * + * @param on true: on false: off + */ + + void power( bool on ); + + bool isPowerOn(); + + /** + * @brief cleares the display and text buffer + * + */ + bool clearDisplay(void); + + /** + * @brief Set the brightness of the display + * + * @param dim 0..15 (0: dark .. 15: light) + */ + bool setIntensity(byte dim); + + /** + * @brief Set the orientation of the 8x8 LED dot matrix module + * + * @param orientation + */ + bool setOrientation(LedMatrix::ModuleOrientation orientation); + + /** + * @brief Set ap pixel at a defined position. + * After all Pixels are set, call refresh() to send it to the display. + * + * @param x horizontal position from left + * @param y vertical position from top + * @param on true: on, false: off + */ + + /** + * @brief Adds a string before the scrolling text to set a distance. Usually some spaces are used. + * + * @param append text to append to the scrolling text before repeating. + */ + bool setScrollAppendText(const char* append ); + + bool setPixel( const int x, const int y, bool on=true); + /** + * @brief sends the changed content of the buffer to the display + * + */ + void refresh(); + + private: + + bool drawCharAt( const char* fontChar, int x, int y ); // Draws a character to a defined position + int countChars( const char* utfText); // count the characters of an UTF8 string. To be uesd instead of strlen(). + byte revereBitorder(byte b); // returnes the byte in the reverse bit order. + void addSpace(); // adds characters in front of the text to get a distance to the repeating scroll text + + // device contrl MAX7219/MAX7221 + /** + * @brief Set data for the same row of all devices + * + * @param row [0..8] + * @param value array of bytes, one for each device + */ + void setRow_allDevices(int row, byte* value); + + /* Send out a command with the same opcode to all devices */ + /** + * @brief sends opcode with specific data values to each device + * + * @param opcode + * @param data array of byte values (data[0] is the value for the first device) + */ + void spiTransfer_array(byte opcode, const byte* data); + + /** + * @brief sends opcode with same value to all devices + */ + void spiTransfer_value(byte opcode, byte value); + + + private: + int SPI_MOSI; // Data is shifted out of this pin + int SPI_CLK; // The clock is signaled on this pin + int SPI_CS; // This one is driven LOW for chip selectzion + + unsigned int modulesPerRow; + unsigned int modulesPerCol; + unsigned int displayWidth; // matrix width [pixel] + unsigned int displayHeight; // matrix height [pixel] + int maxDevices; // number of used 8x8 devices + uint8_t moduleOrientation; + byte buffer[MATRIX_BUFFER_SIZE]; + byte deviceDataBuff[MAX72XX_MAX_DEVICES]; + int charWidth; + int charHeight; + char textBuf[TEXT_BUFFER_SIZE]; + char appendTextBuf[TEXT_APPEND_BUFFER_SIZE]; + int textLen; // number of UTF8 characters + int textWidth; // width of text [pixel] + int textPosX; // horizontal pixel position of scrolling text + int textPosY; // vertical pixelposition of scrolling text; + byte spidata[SPI_BUFFER_SIZE]; // The array for shifting the data to the devices + bool powerIsOn; + +}; + +#endif //LedMatrix_h \ No newline at end of file diff --git a/lib/lib_display/LedControl/src/font_6x8_UTF8_C2.h b/lib/lib_display/LedControl/src/font_6x8_UTF8_C2.h new file mode 100644 index 000000000..72854b4da --- /dev/null +++ b/lib/lib_display/LedControl/src/font_6x8_UTF8_C2.h @@ -0,0 +1,340 @@ +// 6x8 ascii font +#ifndef font_6x8_UTF8_C2_h +#define font_6x8_UTF8_C2_h +/** + * additional characters to font_6x8_base.h + * 256 bytes + * + */ + +/* +UTF8 after 0xC2 + …0 …1 …2 …3 …4 …5 …6 …7 …8 …9 …A …B …C …D …E …F +A… NBSP¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ SHY ® ¯ +B… ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ +*/ +const char font_UTF_C2_A0_BF[0xC0-0xA0][8] = { + + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x80 NBSP + { + 0b00000100, + 0b00000000, + 0b00000100, + 0b00000100, + 0b00001110, + 0b00001110, + 0b00000100, + 0b00000000, + }, // 0x81 ¡ + { + 0b00000000, + 0b00000100, + 0b00001110, + 0b00010000, + 0b00010000, + 0b00001110, + 0b00000100, + 0b00000000, + }, // 0x82 ¢ + { + 0b00000110, + 0b00001001, + 0b00001000, + 0b00011110, + 0b00001000, + 0b00001001, + 0b00010111, + 0b00000000, + }, // 0x83 £ + { + 0b00010001, + 0b00001110, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00001110, + 0b00010001, + 0b00000000, + }, // 0x84 ¤ + { + 0b00010001, + 0b00001010, + 0b00000100, + 0b00011111, + 0b00000100, + 0b00011111, + 0b00000100, + 0b00000000, + }, // 0x85 ¥ + { + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000000, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000000, + }, // 0x86 ¦ + { + 0b00001110, + 0b00010001, + 0b00001100, + 0b00001010, + 0b00000110, + 0b00010001, + 0b00001110, + 0b00000000, + }, // 0x87 § + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00001010, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x88 ¨ + { + 0b00011110, + 0b00100001, + 0b00101101, + 0b00101001, + 0b00101101, + 0b00100001, + 0b00011110, + 0b00000000, + }, // 0x89 © + { + 0b00001110, + 0b00000001, + 0b00001111, + 0b00010001, + 0b00001111, + 0b00000000, + 0b00001111, + 0b00000000, + }, // 0x8A ª + { + 0b00000000, + 0b00000000, + 0b00001001, + 0b00010010, + 0b00001001, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x8B « + { + 0b00000000, + 0b00000000, + 0b00111111, + 0b00000001, + 0b00000001, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x8C ¬ + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000001, + 0b00000001, + 0b00000000, + 0b11111111, + 0b00000000, + }, // 0x8D SHY + { + 0b00011110, + 0b00100101, + 0b00101011, + 0b00101101, + 0b00101011, + 0b00100001, + 0b00011110, + 0b00000000, + }, // 0x8E ® + { + 0b00000000, + 0b00001110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x8F ¯ + { + 0b00001100, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x90 ° + { + 0b00000000, + 0b00000100, + 0b00001110, + 0b00000100, + 0b00000000, + 0b00001110, + 0b00000000, + 0b00000000, + }, // 0x91 ± + { + 0b00011000, + 0b00000100, + 0b00001000, + 0b00011100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x92 ² + { + 0b00011100, + 0b00001000, + 0b00001100, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x93 ³ + { + 0b00001100, + 0b00001100, + 0b00001000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x94 ´ + { + 0b00000000, + 0b00000000, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00011100, + 0b00010000, + 0b00010000, + }, // 0x95 µ + { + 0b00001111, + 0b00010101, + 0b00010101, + 0b00001101, + 0b00000101, + 0b00000101, + 0b00000101, + 0b00000000, + }, // 0x96 ¶ + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00001000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x97 · + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00001110, + 0b00000110, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x98 ¸ + { + 0b00001000, + 0b00011000, + 0b00001000, + 0b00001000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x99 ¹ + { + 0b00001100, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + 0b00011110, + 0b00000000, + }, // 0x9A º + { + 0b00000000, + 0b00000000, + 0b00010010, + 0b00001001, + 0b00010010, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x9B » + { + 0b00010000, + 0b00010010, + 0b00010100, + 0b00001011, + 0b00010101, + 0b00000111, + 0b00000001, + 0b00000000, + }, // 0x9C ¼ + { + 0b00010000, + 0b00010010, + 0b00010100, + 0b00001110, + 0b00010001, + 0b00000010, + 0b00000111, + 0b00000000, + }, // 0x9D ½ + { + 0b00110000, + 0b00011010, + 0b00110100, + 0b00001011, + 0b00010101, + 0b00000111, + 0b00000001, + 0b00000000, + }, // 0x9E ¾ + { + 0b00000100, + 0b00000000, + 0b00000100, + 0b00001100, + 0b00010000, + 0b00010001, + 0b00001110, + 0b00000000, + }, // 0x9F ¿ +}; + +#endif // font_6x8_UTF8_C2_h \ No newline at end of file diff --git a/lib/lib_display/LedControl/src/font_6x8_UTF8_C3.h b/lib/lib_display/LedControl/src/font_6x8_UTF8_C3.h new file mode 100644 index 000000000..aa32f434a --- /dev/null +++ b/lib/lib_display/LedControl/src/font_6x8_UTF8_C3.h @@ -0,0 +1,678 @@ +// 6x8 ascii font +#ifndef font_6x8_UTF8_C3_h +#define font_6x8_UTF8_C3_h +/** + * additional characters to font_6x8_base.h + * 512 bytes + * + */ + +/* +UTF8 after 0xC3 + …0 …1 …2 …3 …4 …5 …6 …7 …8 …9 …A …B …C …D …E …F +8… À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï +9… Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß +A… à á â ã ä å æ ç è é ê ë ì í î ï +B… ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ +*/ +const char font_UTF_C3_80_BF[0xC0-0x80][8] = { + + { + 0b00001100, + 0b00000000, + 0b00000100, + 0b00001010, + 0b00010001, + 0b00011111, + 0b00010001, + 0b00000000, + }, // 0x80 À + { + 0b00000110, + 0b00000000, + 0b00000100, + 0b00001010, + 0b00010001, + 0b00011111, + 0b00010001, + 0b00000000, + }, // 0x81 Á + { + 0b00001110, + 0b00000000, + 0b00000100, + 0b00001010, + 0b00010001, + 0b00011111, + 0b00010001, + 0b00000000, + }, // 0x82 Â + { + 0b00000101, + 0b00001010, + 0b00000100, + 0b00001010, + 0b00010001, + 0b00011111, + 0b00010001, + 0b00000000, + }, // 0x83 Ã + { + 0b00001010, + 0b00000000, + 0b00000100, + 0b00001010, + 0b00010001, + 0b00011111, + 0b00010001, + 0b00000000, + }, // 0x84 Ä + { + 0b00001110, + 0b00001010, + 0b00001110, + 0b00011011, + 0b00010001, + 0b00011111, + 0b00010001, + 0b00000000, + }, // 0x85 Å + { + 0b00000111, + 0b00001100, + 0b00010100, + 0b00010111, + 0b00011100, + 0b00010100, + 0b00010111, + 0b00000000, + }, // 0x86 Æ + { + 0b00001110, + 0b00010001, + 0b00010000, + 0b00010000, + 0b00010001, + 0b00001110, + 0b00000100, + 0b00001100, + }, // 0x87 Ç + { + 0b00001100, + 0b00000000, + 0b00011111, + 0b00010000, + 0b00011110, + 0b00010000, + 0b00011111, + 0b00000000, + }, // 0x88 È + + { + 0b00000011, + 0b00000000, + 0b00011111, + 0b00010000, + 0b00011110, + 0b00010000, + 0b00011111, + 0b00000000, + }, // 0x89 É + { + 0b00001110, + 0b00000000, + 0b00011111, + 0b00010000, + 0b00011110, + 0b00010000, + 0b00011111, + 0b00000000, + }, // 0x8A Ê + { + 0b00001010, + 0b00000000, + 0b00011111, + 0b00010000, + 0b00011110, + 0b00010000, + 0b00011111, + 0b00000000, + }, // 0x8B Ë + { + 0b00001100, + 0b00000000, + 0b00001110, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00001110, + 0b00000000, + }, // 0x8C Ì + { + 0b00000110, + 0b00000000, + 0b00001110, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00001110, + 0b00000000, + }, // 0x8D Í + { + 0b00001110, + 0b00000000, + 0b00001110, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00001110, + 0b00000000, + }, // 0x8E Î + { + 0b00001010, + 0b00000000, + 0b00001110, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00001110, + 0b00000000, + }, // 0x8F Ï + + { + 0b00001110, + 0b00001001, + 0b00001001, + 0b00011101, + 0b00001001, + 0b00001001, + 0b00001110, + 0b00000000, + }, // 0x90 Ð + { + 0b00001010, + 0b00010100, + 0b00000000, + 0b00010010, + 0b00011010, + 0b00010110, + 0b00010010, + 0b00000000, + }, // 0x91 Ñ + { + 0b00011000, + 0b00001100, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + }, // 0x92 Ò + { + 0b00000110, + 0b00001100, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + }, // 0x93 Ó + { + 0b00001110, + 0b00001100, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + }, // 0x94 Ô + { + 0b00001010, + 0b00010100, + 0b00001100, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + }, // 0x95 Õ + { + 0b00010010, + 0b00001100, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + }, // 0x96 Ö + { + 0b00000000, + 0b00010001, + 0b00001010, + 0b00000100, + 0b00001010, + 0b00010001, + 0b00000000, + 0b00000000, + }, // 0x97 × + { + 0b00001111, + 0b00010011, + 0b00010101, + 0b00010101, + 0b00010101, + 0b00011001, + 0b00011110, + 0b00000000, + }, // 0x98 Ø + + { + 0b00011000, + 0b00000000, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + }, // 0x99 Ù + { + 0b00000110, + 0b00000000, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + }, // 0x9A Ú + { + 0b00001110, + 0b00000000, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + }, // 0x9B Û + { + 0b00001010, + 0b00000000, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + }, // 0x9C Ü + { + 0b00000110, + 0b00000000, + 0b00010001, + 0b00001010, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000000, + }, // 0x9D Ý + { + 0b00011000, + 0b00010000, + 0b00011100, + 0b00010010, + 0b00010010, + 0b00011100, + 0b00010000, + 0b00011000, + }, // 0x9E Þ + { + 0b00000000, + 0b00011100, + 0b00010010, + 0b00011100, + 0b00010010, + 0b00010010, + 0b00011100, + 0b00010000, + }, // 0x9F ß + + { + 0b00001100, + 0b00000000, + 0b00001110, + 0b00000001, + 0b00001111, + 0b00010001, + 0b00001111, + 0b00000000, + }, // 0xA0 à + { + 0b00000110, + 0b00000000, + 0b00001110, + 0b00000001, + 0b00001111, + 0b00010001, + 0b00001111, + 0b00000000, + }, // 0xA1 á + { + 0b00001110, + 0b00000000, + 0b00001110, + 0b00000001, + 0b00001111, + 0b00010001, + 0b00001111, + 0b00000000, + }, // 0xA2 â + { + 0b00000101, + 0b00001010, + 0b00001110, + 0b00000001, + 0b00001111, + 0b00010001, + 0b00001111, + 0b00000000, + }, // 0xA3 ã + { + 0b00001010, + 0b00000000, + 0b00001110, + 0b00000001, + 0b00001111, + 0b00010001, + 0b00001111, + 0b00000000, + }, // 0xA4 ä + { + 0b00001110, + 0b00001010, + 0b00001110, + 0b00000001, + 0b00001111, + 0b00010001, + 0b00001111, + 0b00000000, + }, // 0xA5 å + { + 0b00000000, + 0b00000000, + 0b00011110, + 0b00000101, + 0b00011111, + 0b00010100, + 0b00001111, + 0b00000000, + }, // 0xA6 æ + { + 0b00000000, + 0b00001110, + 0b00010001, + 0b00010000, + 0b00010001, + 0b00001110, + 0b00000100, + 0b00001100, + }, // 0xA7 ç + { + 0b00001100, + 0b00000000, + 0b00001110, + 0b00010001, + 0b00011110, + 0b00010000, + 0b00001110, + 0b00000000, + }, // 0xA8 è + { + 0b00000011, + 0b00000000, + 0b00001110, + 0b00010001, + 0b00011110, + 0b00010000, + 0b00001110, + 0b00000000, + }, // 0xA9 é + { + 0b00001110, + 0b00000000, + 0b00001110, + 0b00010001, + 0b00011110, + 0b00010000, + 0b00001110, + 0b00000000, + }, // 0xAA ê + { + 0b00001010, + 0b00000000, + 0b00001110, + 0b00010001, + 0b00011110, + 0b00010000, + 0b00001110, + 0b00000000, + }, // 0xAB ë + { + 0b00001000, + 0b00000000, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000110, + 0b00000000, + }, // 0xAC ì + { + 0b00000110, + 0b00000000, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000110, + 0b00000000, + }, // 0xAD í + { + 0b00000110, + 0b00000000, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000110, + 0b00000000, + }, // 0xAE î + { + 0b00001010, + 0b00000000, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000110, + 0b00000000, + }, // 0xAF ï + + { + 0b00001100, + 0b00010000, + 0b00001000, + 0b00000100, + 0b00001110, + 0b00010010, + 0b00001100, + 0b00000000, + }, // 0xB0 ð + { + 0b00001010, + 0b00010100, + 0b00000000, + 0b00011100, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00000000, + }, // 0xB1 ñ + { + 0b00011000, + 0b00000000, + 0b00001100, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + }, // 0xB2 ò + { + 0b00000110, + 0b00000000, + 0b00001100, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + }, // 0xB3 ó + { + 0b00001110, + 0b00000000, + 0b00001100, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + }, // 0xB4 ô + { + 0b00001010, + 0b00010100, + 0b00000000, + 0b00001100, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + }, // 0xB5 õ + { + 0b00001010, + 0b00000000, + 0b00001100, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00000000, + }, // 0xB6 ö + { + 0b00000000, + 0b00000100, + 0b00000000, + 0b00011111, + 0b00000000, + 0b00000100, + 0b00000000, + 0b00000000, + }, // 0xB7 ÷ + { + 0b00000000, + 0b00000000, + 0b00000001, + 0b00001110, + 0b00010110, + 0b00011010, + 0b00011100, + 0b00100000, + }, // 0xB8 ø + { + 0b00011000, + 0b00000000, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00010110, + 0b00001010, + 0b00000000, + }, // 0xB9 ù + { + 0b00000110, + 0b00000000, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00010110, + 0b00001010, + 0b00000000, + }, // 0xBA ú + { + 0b00001110, + 0b00000000, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00010110, + 0b00001010, + 0b00000000, + }, // 0xBB û + { + 0b00010010, + 0b00000000, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00010110, + 0b00001010, + 0b00000000, + }, // 0xBC ü + { + 0b00000110, + 0b00000000, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001110, + 0b00000100, + 0b00011000, + }, // 0xBD ý + { + 0b00000000, + 0b00011000, + 0b00010000, + 0b00011100, + 0b00010010, + 0b00011100, + 0b00010000, + 0b00011000, + }, // 0xBE þ + { + 0b00001010, + 0b00000000, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001110, + 0b00000100, + 0b00011000, + }, // 0xBF ÿ +}; + +/* +ISO/IEC 8859-1 (latin1) + …0 …1 …2 …3 …4 …5 …6 …7 …8 …9 …A …B …C …D …E …F +A… NBSP ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ SHY ® ¯ +B… ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ +C… À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï +D… Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß +E… à á â ã ä å æ ç è é ê ë ì í î ï +F… ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ +*/ + +#endif // font_6x8_UTF8_C3_h \ No newline at end of file diff --git a/lib/lib_display/LedControl/src/font_6x8_base.h b/lib/lib_display/LedControl/src/font_6x8_base.h new file mode 100644 index 000000000..084b28c00 --- /dev/null +++ b/lib/lib_display/LedControl/src/font_6x8_base.h @@ -0,0 +1,986 @@ +// 6x8 ascii font +#ifndef font_6x8_base_h +#define font_6x8_base_h +/** + * Momory size of basic ascii font: 768 bytes + * + */ + +/* + …0 …1 …2 …3 …4 …5 …6 …7 …8 …9 …A …B …C …D …E …F +2… SP ! " # $ % & ' ( ) * + , - . / +3… 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +4… @ A B C D E F G H I J K L M N O +5… P Q R S T U V W X Y Z [ \ ] ^ _ +6… ` a b c d e f g h i j k l m n o +7… p q r s t u v w x y z { | } ~ +*/ + +const unsigned int font_char_width = 6; +const unsigned int font_char_height = 8; + +const char font_20_7F[0x80-0x20][8] = { + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x20 + { + 0b00000100, + 0b00001110, + 0b00001110, + 0b00000100, + 0b00000100, + 0b00000000, + 0b00000100, + 0b00000000, + }, // 0x21 ! + { + 0b00011011, + 0b00011011, + 0b00010010, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x22 " + { + 0b00000000, + 0b00001010, + 0b00011111, + 0b00001010, + 0b00001010, + 0b00011111, + 0b00001010, + 0b00000000, + }, // 0x23 # + { + 0b00001000, + 0b00001110, + 0b00010000, + 0b00001100, + 0b00000010, + 0b00011100, + 0b00000100, + 0b00000000, + }, // 0x24 $ + { + 0b00011001, + 0b00011001, + 0b00000010, + 0b00000100, + 0b00001000, + 0b00010011, + 0b00010011, + 0b00000000, + }, // 0x25 % + { + 0b00001000, + 0b00010100, + 0b00010100, + 0b00001000, + 0b00010101, + 0b00010010, + 0b00001101, + 0b00000000, + }, // 0x26 & + { + 0b00001100, + 0b00001100, + 0b00001000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x27 ' + { + 0b00000100, + 0b00001000, + 0b00001000, + 0b00001000, + 0b00001000, + 0b00001000, + 0b00000100, + 0b00000000, + }, // 0x28 ( + { + 0b00001000, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00001000, + 0b00000000, + }, // 0x29 ) + { + 0b00000000, + 0b00001010, + 0b00001110, + 0b00011111, + 0b00001110, + 0b00001010, + 0b00000000, + 0b00000000, + }, // 0x2A * + { + 0b00000000, + 0b00000100, + 0b00000100, + 0b00011111, + 0b00000100, + 0b00000100, + 0b00000000, + 0b00000000, + }, // 0x2B + + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00001000, + }, // 0x2C , + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x2D - + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00000000, + }, // 0x2E . + { + 0b00000000, + 0b00000001, + 0b00000010, + 0b00000100, + 0b00001000, + 0b00010000, + 0b00000000, + 0b00000000, + }, // 0x2F / + { + 0b00001110, + 0b00010001, + 0b00010011, + 0b00010101, + 0b00011001, + 0b00010001, + 0b00001110, + 0b00000000, + }, // 0x30 0 + { + 0b00000100, + 0b00001100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00001110, + 0b00000000, + }, // 0x31 1 + { + 0b00001110, + 0b00010001, + 0b00000001, + 0b00000110, + 0b00001000, + 0b00010000, + 0b00011111, + 0b00000000, + }, // 0x32 2 + { + 0b00001110, + 0b00010001, + 0b00000001, + 0b00001110, + 0b00000001, + 0b00010001, + 0b00001110, + 0b00000000, + }, // 0x33 3 + { + 0b00000010, + 0b00000110, + 0b00001010, + 0b00010010, + 0b00011111, + 0b00000010, + 0b00000010, + 0b00000000, + }, // 0x34 4 + { + 0b00011111, + 0b00010000, + 0b00010000, + 0b00011110, + 0b00000001, + 0b00010001, + 0b00001110, + 0b00000000, + }, // 0x35 5 + { + 0b00000110, + 0b00001000, + 0b00010000, + 0b00011110, + 0b00010001, + 0b00010001, + 0b00001110, + 0b00000000, + }, // 0x36 6 + { + 0b00011111, + 0b00000001, + 0b00000010, + 0b00000100, + 0b00001000, + 0b00001000, + 0b00001000, + 0b00000000, + }, // 0x37 7 + { + 0b00001110, + 0b00010001, + 0b00010001, + 0b00001110, + 0b00010001, + 0b00010001, + 0b00001110, + 0b00000000, + }, // 0x38 8 + { + 0b00001110, + 0b00010001, + 0b00010001, + 0b00001111, + 0b00000001, + 0b00000010, + 0b00001100, + 0b00000000, + }, // 0x39 9 + { + 0b00000000, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00000000, + }, // 0x3A : + { + 0b00000000, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00001000, + }, // 0x3B ; + { + 0b00000010, + 0b00000100, + 0b00001000, + 0b00010000, + 0b00001000, + 0b00000100, + 0b00000010, + 0b00000000, + }, // 0x3C < + { + 0b00000000, + 0b00000000, + 0b00011111, + 0b00000000, + 0b00000000, + 0b00011111, + 0b00000000, + 0b00000000, + }, // 0x3D = + { + 0b00001000, + 0b00000100, + 0b00000010, + 0b00000001, + 0b00000010, + 0b00000100, + 0b00001000, + 0b00000000, + }, // 0x3E > + { + 0b00001110, + 0b00010001, + 0b00000001, + 0b00000110, + 0b00000100, + 0b00000000, + 0b00000100, + 0b00000000, + }, // 0x3F ? + + { + 0b00001110, + 0b00010001, + 0b00010111, + 0b00010101, + 0b00010111, + 0b00010000, + 0b00001110, + 0b00000000, + }, // 0x40 @ + { + 0b00001110, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00011111, + 0b00010001, + 0b00010001, + 0b00000000, + }, // 0x41 A + { + 0b00011110, + 0b00010001, + 0b00010001, + 0b00011110, + 0b00010001, + 0b00010001, + 0b00011110, + 0b00000000, + }, // 0x42 B + { + 0b00001110, + 0b00010001, + 0b00010000, + 0b00010000, + 0b00010000, + 0b00010001, + 0b00001110, + 0b00000000, + }, // 0x43 C + { + 0b00011110, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00011110, + 0b00000000, + }, // 0x44 D + { + 0b00011111, + 0b00010000, + 0b00010000, + 0b00011110, + 0b00010000, + 0b00010000, + 0b00011111, + 0b00000000, + }, // 0x45 E + { + 0b00011111, + 0b00010000, + 0b00010000, + 0b00011110, + 0b00010000, + 0b00010000, + 0b00010000, + 0b00000000, + }, // 0x46 F + { + 0b00001110, + 0b00010001, + 0b00010000, + 0b00010111, + 0b00010001, + 0b00010001, + 0b00001111, + 0b00000000, + }, // 0x47 G + { + 0b00010001, + 0b00010001, + 0b00010001, + 0b00011111, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00000000, + }, // 0x48 H + { + 0b00001110, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00001110, + 0b00000000, + }, // 0x49 I + { + 0b00000001, + 0b00000001, + 0b00000001, + 0b00000001, + 0b00010001, + 0b00010001, + 0b00001110, + 0b00000000, + }, // 0x4A J + { + 0b00010001, + 0b00010010, + 0b00010100, + 0b00011000, + 0b00010100, + 0b00010010, + 0b00010001, + 0b00000000, + }, // 0x4B K + { + 0b00010000, + 0b00010000, + 0b00010000, + 0b00010000, + 0b00010000, + 0b00010000, + 0b00011111, + 0b00000000, + }, // 0x4C L + { + 0b00010001, + 0b00011011, + 0b00010101, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00000000, + }, // 0x4D M + { + 0b00010001, + 0b00011001, + 0b00010101, + 0b00010011, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00000000, + }, // 0x4E N + { + 0b00001110, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00001110, + 0b00000000, + }, // 0x4F O + { + 0b00011110, + 0b00010001, + 0b00010001, + 0b00011110, + 0b00010000, + 0b00010000, + 0b00010000, + 0b00000000, + }, // 0x50 P + { + 0b00001110, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00010101, + 0b00010010, + 0b00001101, + 0b00000000, + }, // 0x51 Q + { + 0b00011110, + 0b00010001, + 0b00010001, + 0b00011110, + 0b00010010, + 0b00010001, + 0b00010001, + 0b00000000, + }, // 0x52 R + { + 0b00001110, + 0b00010001, + 0b00010000, + 0b00001110, + 0b00000001, + 0b00010001, + 0b00001110, + 0b00000000, + }, // 0x53 S + { + 0b00011111, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000000, + }, // 0x54 T + { + 0b00010001, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00001110, + 0b00000000, + }, // 0x55 U + { + 0b00010001, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00001010, + 0b00000100, + 0b00000000, + }, // 0x56 V + { + 0b00010001, + 0b00010001, + 0b00010101, + 0b00010101, + 0b00010101, + 0b00010101, + 0b00001010, + 0b00000000, + }, // 0x57 W + { + 0b00010001, + 0b00010001, + 0b00001010, + 0b00000100, + 0b00001010, + 0b00010001, + 0b00010001, + 0b00000000, + }, // 0x58 X + { + 0b00010001, + 0b00010001, + 0b00010001, + 0b00001010, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000000, + }, // 0x59 Y + { + 0b00011110, + 0b00000010, + 0b00000100, + 0b00001000, + 0b00010000, + 0b00010000, + 0b00011110, + 0b00000000, + }, // 0x5A Z + { + 0b00001110, + 0b00001000, + 0b00001000, + 0b00001000, + 0b00001000, + 0b00001000, + 0b00001110, + 0b00000000, + }, // 0x5B [ + { + 0b00000000, + 0b00010000, + 0b00001000, + 0b00000100, + 0b00000010, + 0b00000001, + 0b00000000, + 0b00000000, + }, // 0x5C backslash + { + 0b00001110, + 0b00000010, + 0b00000010, + 0b00000010, + 0b00000010, + 0b00000010, + 0b00001110, + 0b00000000, + }, // 0x5D ] + { + 0b00000100, + 0b00001010, + 0b00010001, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x5E ^ + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111111, + }, // 0x5F _ + { + 0b00001100, + 0b00001100, + 0b00000100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x60 ` + { + 0b00000000, + 0b00000000, + 0b00001110, + 0b00000001, + 0b00001111, + 0b00010001, + 0b00001111, + 0b00000000, + }, // 0x61 a + { + 0b00010000, + 0b00010000, + 0b00011110, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00011110, + 0b00000000, + }, // 0x62 b + { + 0b00000000, + 0b00000000, + 0b00001110, + 0b00010001, + 0b00010000, + 0b00010001, + 0b00001110, + 0b00000000, + }, // 0x63 c + { + 0b00000001, + 0b00000001, + 0b00001111, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00001111, + 0b00000000, + }, // 0x64 d + { + 0b00000000, + 0b00000000, + 0b00001110, + 0b00010001, + 0b00011110, + 0b00010000, + 0b00001110, + 0b00000000, + }, // 0x65 e + { + 0b00000110, + 0b00001000, + 0b00001000, + 0b00011110, + 0b00001000, + 0b00001000, + 0b00001000, + 0b00000000, + }, // 0x66 f + { + 0b00000000, + 0b00000000, + 0b00001111, + 0b00010001, + 0b00010001, + 0b00001111, + 0b00000001, + 0b00001110, + }, // 0x67 g + { + 0b00010000, + 0b00010000, + 0b00011100, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00000000, + }, // 0x68 h + { + 0b00000100, + 0b00000000, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000110, + 0b00000000, + }, // 0x69 i + { + 0b00000010, + 0b00000000, + 0b00000110, + 0b00000010, + 0b00000010, + 0b00000010, + 0b00010010, + 0b00001100, + }, // 0x6A j + { + 0b00010000, + 0b00010000, + 0b00010010, + 0b00010100, + 0b00011000, + 0b00010100, + 0b00010010, + 0b00000000, + }, // 0x6B k + { + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000110, + 0b00000000, + }, // 0x6C l + { + 0b00000000, + 0b00000000, + 0b00011010, + 0b00010101, + 0b00010101, + 0b00010001, + 0b00010001, + 0b00000000, + }, // 0x6D m + { + 0b00000000, + 0b00000000, + 0b00011100, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00000000, + }, // 0x6E n + { + 0b00000000, + 0b00000000, + 0b00001110, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00001110, + 0b00000000, + }, // 0x6F o + { + 0b00000000, + 0b00000000, + 0b00011110, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00011110, + 0b00010000, + }, // 0x70 p + { + 0b00000000, + 0b00000000, + 0b00001111, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00001111, + 0b00000001, + }, // 0x71 q + { + 0b00000000, + 0b00000000, + 0b00010110, + 0b00001001, + 0b00001000, + 0b00001000, + 0b00011100, + 0b00000000, + }, // 0x72 r + { + 0b00000000, + 0b00000000, + 0b00001110, + 0b00010000, + 0b00001110, + 0b00000001, + 0b00001110, + 0b00000000, + }, // 0x73 s + { + 0b00000000, + 0b00001000, + 0b00011110, + 0b00001000, + 0b00001000, + 0b00001010, + 0b00000100, + 0b00000000, + }, // 0x74 t + { + 0b00000000, + 0b00000000, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00010110, + 0b00001010, + 0b00000000, + }, // 0x75 u + { + 0b00000000, + 0b00000000, + 0b00010001, + 0b00010001, + 0b00010001, + 0b00001010, + 0b00000100, + 0b00000000, + }, // 0x76 v + { + 0b00000000, + 0b00000000, + 0b00010001, + 0b00010001, + 0b00010101, + 0b00011111, + 0b00001010, + 0b00000000, + }, // 0x77 w + { + 0b00000000, + 0b00000000, + 0b00010010, + 0b00010010, + 0b00001100, + 0b00010010, + 0b00010010, + 0b00000000, + }, // 0x78 x + { + 0b00000000, + 0b00000000, + 0b00010010, + 0b00010010, + 0b00010010, + 0b00001110, + 0b00000100, + 0b00011000, + }, // 0x79 y + { + 0b00000000, + 0b00000000, + 0b00011110, + 0b00000010, + 0b00001100, + 0b00010000, + 0b00011110, + 0b00000000, + }, // 0x7A z + { + 0b00000110, + 0b00001000, + 0b00001000, + 0b00011000, + 0b00001000, + 0b00001000, + 0b00000110, + 0b00000000, + }, // 0x7B { + { + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000000, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000000, + }, // 0x7C | + { + 0b00001100, + 0b00000010, + 0b00000010, + 0b00000011, + 0b00000010, + 0b00000010, + 0b00001100, + 0b00000000, + }, // 0x7D } + { + 0b00001010, + 0b00010100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, // 0x7E ~ + { + 0b00000100, + 0b00001110, + 0b00011011, + 0b00010001, + 0b00010001, + 0b00011111, + 0b00000000, + 0b00000000, + }, // 0x7F ␡ +}; + +#endif // font_6x8_base_h \ No newline at end of file diff --git a/lib/lib_display/UDisplay/uDisplay.cpp b/lib/lib_display/UDisplay/uDisplay.cpp index 8414795e0..f6ac1a20b 100755 --- a/lib/lib_display/UDisplay/uDisplay.cpp +++ b/lib/lib_display/UDisplay/uDisplay.cpp @@ -20,7 +20,7 @@ #include #include "uDisplay.h" -#define UDSP_DEBUG +// #define UDSP_DEBUG const uint16_t udisp_colors[]={UDISP_BLACK,UDISP_WHITE,UDISP_RED,UDISP_GREEN,UDISP_BLUE,UDISP_CYAN,UDISP_MAGENTA,\ UDISP_YELLOW,UDISP_NAVY,UDISP_DARKGREEN,UDISP_DARKCYAN,UDISP_MAROON,UDISP_PURPLE,UDISP_OLIVE,\ diff --git a/lib/lib_display/arduino-tm1637/SevenSegmentTM1637.h b/lib/lib_display/arduino-tm1637/SevenSegmentTM1637.h index 95a06b113..eeaf7adc2 100644 --- a/lib/lib_display/arduino-tm1637/SevenSegmentTM1637.h +++ b/lib/lib_display/arduino-tm1637/SevenSegmentTM1637.h @@ -183,24 +183,24 @@ public: void setPrintDelay(uint16_t printDelay); // helpers ////////////////////////////////////////////////////////////////// - /* Encodes a character to sevensegment binairy + /* Encodes a character to sevensegment binary * @param [in] c a character to encode */ uint8_t encode(char c); - /* Encodes a single digit to sevensegment binairy + /* Encodes a single digit to sevensegment binary * @param [in] d a digit to encode */ uint8_t encode(int16_t d); - /* Encodes a null terminated c string (char array) to sevensegment binairy + /* Encodes a null terminated c string (char array) to sevensegment binary * @param [out] buffer holds the encodes char array @param [in] str the c string to encode @param [in] bufferSize the size/length of the buffer */ size_t encode(uint8_t* buffer, const char* str, size_t bufferSize); - /* Encodes a byte array to sevensegment binairy + /* Encodes a byte array to sevensegment binary * @param [out] buffer holds the encodes char array @param [in] byteArr the byte array to encode diff --git a/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp b/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp index 92492167a..9a805fb2b 100644 --- a/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp +++ b/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp @@ -77,7 +77,14 @@ void ESPKNXIP::send(address_t const &receiver, knx_command_type_t ct, uint8_t da DEBUG_PRINTLN(F("")); #endif +#ifdef ESP8266 udp.beginPacketMulticast(MULTICAST_IP, MULTICAST_PORT, WiFi.localIP()); +#else + if (0 == udp.beginMulticastPacket()) { + udp.beginMulticast(MULTICAST_IP, MULTICAST_PORT); + udp.beginMulticastPacket(); + } +#endif udp.write(buf, len); udp.endPacket(); delay(1); diff --git a/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-webserver.cpp b/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-webserver.cpp index bdbc013fd..be2745ab4 100644 --- a/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-webserver.cpp +++ b/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-webserver.cpp @@ -42,7 +42,7 @@ void ESPKNXIP::__handle_root() case FEEDBACK_TYPE_FLOAT: m += F(""); m += feedbacks[i].options.float_options.prefix; - m += String(*(float *)feedbacks[i].data, feedbacks[i].options.float_options.precision); + m += String(*(float *)feedbacks[i].data, (unsigned int)feedbacks[i].options.float_options.precision); m += feedbacks[i].options.float_options.suffix; m += F(""); break; diff --git a/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.cpp b/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.cpp index 35cbb2161..cc2bbf49a 100644 --- a/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.cpp +++ b/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.cpp @@ -95,7 +95,11 @@ void ESPKNXIP::__start() #endif server->begin(); } +#ifdef ESP8266 udp.beginMulticast(WiFi.localIP(), MULTICAST_IP, MULTICAST_PORT); +#else + udp.beginMulticast(MULTICAST_IP, MULTICAST_PORT); +#endif } void ESPKNXIP::save_to_eeprom() diff --git a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/LICENSE b/lib/lib_i2c/BME680_driver-bme680_v3.5.9/LICENSE deleted file mode 100644 index ab7a8c8b2..000000000 --- a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/LICENSE +++ /dev/null @@ -1,39 +0,0 @@ -Copyright (C) 2017 - 2018 Bosch Sensortec GmbH - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -Neither the name of the copyright holder nor the names of the -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER -OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE - -The information provided is believed to be accurate and reliable. -The copyright holder assumes no responsibility -for the consequences of use -of such information nor for any infringement of patents or -other rights of third parties which may result from its use. -No license is granted by implication or otherwise under any patent or -patent rights of the copyright holder. \ No newline at end of file diff --git a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/README.md b/lib/lib_i2c/BME680_driver-bme680_v3.5.9/README.md deleted file mode 100644 index 43abe55c8..000000000 --- a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/README.md +++ /dev/null @@ -1,282 +0,0 @@ -# BME680 sensor API - -## Introduction - -This package contains the Bosch Sensortec's BME680 gas sensor API - -The sensor driver package includes bme680.h, bme680.c and bme680_defs.h files - -## Version - -File | Version | Date ---------------|---------|------------- -bme680.c | 3.5.9 | 19 Jun 2018 -bme680.h | 3.5.9 | 19 Jun 2018 -bme680_defs.h | 3.5.9 | 19 Jun 2018 - -## Integration details - -* Integrate bme680.h, bme680_defs.h and bme680.c file in to your project. -* Include the bme680.h file in your code like below. - -``` c -#include "bme680.h" -``` - -## File information - -* bme680_defs.h : This header file has the constants, macros and datatype declarations. -* bme680.h : This header file contains the declarations of the sensor driver APIs. -* bme680.c : This source file contains the definitions of the sensor driver APIs. - -## Supported sensor interfaces - -* SPI 4-wire -* I2C - -## Usage guide - -### Initializing the sensor - -To initialize the sensor, you will first need to create a device structure. You -can do this by creating an instance of the structure bme680_dev. Then go on to -fill in the various parameters as shown below - -#### Example for SPI 4-Wire - -``` c - struct bme680_dev gas_sensor; - - /* You may assign a chip select identifier to be handled later */ - gas_sensor.dev_id = 0; - gas_sensor.intf = BME680_SPI_INTF; - gas_sensor.read = user_spi_read; - gas_sensor.write = user_spi_write; - gas_sensor.delay_ms = user_delay_ms; - /* amb_temp can be set to 25 prior to configuring the gas sensor - * or by performing a few temperature readings without operating the gas sensor. - */ - gas_sensor.amb_temp = 25; - - int8_t rslt = BME680_OK; - rslt = bme680_init(&gas_sensor); -``` - -#### Example for I2C - -``` c - struct bme680_dev gas_sensor; - - gas_sensor.dev_id = BME680_I2C_ADDR_PRIMARY; - gas_sensor.intf = BME680_I2C_INTF; - gas_sensor.read = user_i2c_read; - gas_sensor.write = user_i2c_write; - gas_sensor.delay_ms = user_delay_ms; - /* amb_temp can be set to 25 prior to configuring the gas sensor - * or by performing a few temperature readings without operating the gas sensor. - */ - gas_sensor.amb_temp = 25; - - - int8_t rslt = BME680_OK; - rslt = bme680_init(&gas_sensor); -``` - -Regarding compensation functions for temperature, pressure, humidity and gas we have two implementations. - - - Integer version - - floating point version - -By default, Integer version is used in the API - -If the user needs the floating point version, the user has to un-comment BME680_FLOAT_POINT_COMPENSATION macro -in bme680_defs.h file or to add it in the compiler flags. - -### Configuring the sensor - -#### Example for configuring the sensor in forced mode - -``` c - uint8_t set_required_settings; - - /* Set the temperature, pressure and humidity settings */ - gas_sensor.tph_sett.os_hum = BME680_OS_2X; - gas_sensor.tph_sett.os_pres = BME680_OS_4X; - gas_sensor.tph_sett.os_temp = BME680_OS_8X; - gas_sensor.tph_sett.filter = BME680_FILTER_SIZE_3; - - /* Set the remaining gas sensor settings and link the heating profile */ - gas_sensor.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS; - /* Create a ramp heat waveform in 3 steps */ - gas_sensor.gas_sett.heatr_temp = 320; /* degree Celsius */ - gas_sensor.gas_sett.heatr_dur = 150; /* milliseconds */ - - /* Select the power mode */ - /* Must be set before writing the sensor configuration */ - gas_sensor.power_mode = BME680_FORCED_MODE; - - /* Set the required sensor settings needed */ - set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL - | BME680_GAS_SENSOR_SEL; - - /* Set the desired sensor configuration */ - rslt = bme680_set_sensor_settings(set_required_settings,&gas_sensor); - - /* Set the power mode */ - rslt = bme680_set_sensor_mode(&gas_sensor); - - -``` - -### Reading sensor data - -#### Example for reading all sensor data - -``` c - /* Get the total measurement duration so as to sleep or wait till the - * measurement is complete */ - uint16_t meas_period; - bme680_get_profile_dur(&meas_period, &gas_sensor); - - struct bme680_field_data data; - - while(1) - { - user_delay_ms(meas_period); /* Delay till the measurement is ready */ - - rslt = bme680_get_sensor_data(&data, &gas_sensor); - - printf("T: %.2f degC, P: %.2f hPa, H %.2f %%rH ", data.temperature / 100.0f, - data.pressure / 100.0f, data.humidity / 1000.0f ); - /* Avoid using measurements from an unstable heating setup */ - if(data.status & BME680_GASM_VALID_MSK) - printf(", G: %d ohms", data.gas_resistance); - - printf("\r\n"); - - /* Trigger the next measurement if you would like to read data out continuously */ - if (gas_sensor.power_mode == BME680_FORCED_MODE) { - rslt = bme680_set_sensor_mode(&gas_sensor); - } - } -``` - -### Templates for function pointers - -``` c - -void user_delay_ms(uint32_t period) -{ - /* - * Return control or wait, - * for a period amount of milliseconds - */ -} - -int8_t user_spi_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) -{ - int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ - - /* - * The parameter dev_id can be used as a variable to select which Chip Select pin has - * to be set low to activate the relevant device on the SPI bus - */ - - /* - * Data on the bus should be like - * |----------------+---------------------+-------------| - * | MOSI | MISO | Chip Select | - * |----------------+---------------------|-------------| - * | (don't care) | (don't care) | HIGH | - * | (reg_addr) | (don't care) | LOW | - * | (don't care) | (reg_data[0]) | LOW | - * | (....) | (....) | LOW | - * | (don't care) | (reg_data[len - 1]) | LOW | - * | (don't care) | (don't care) | HIGH | - * |----------------+---------------------|-------------| - */ - - return rslt; -} - -int8_t user_spi_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) -{ - int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ - - /* - * The parameter dev_id can be used as a variable to select which Chip Select pin has - * to be set low to activate the relevant device on the SPI bus - */ - - /* - * Data on the bus should be like - * |---------------------+--------------+-------------| - * | MOSI | MISO | Chip Select | - * |---------------------+--------------|-------------| - * | (don't care) | (don't care) | HIGH | - * | (reg_addr) | (don't care) | LOW | - * | (reg_data[0]) | (don't care) | LOW | - * | (....) | (....) | LOW | - * | (reg_data[len - 1]) | (don't care) | LOW | - * | (don't care) | (don't care) | HIGH | - * |---------------------+--------------|-------------| - */ - - return rslt; -} - -int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) -{ - int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ - - /* - * The parameter dev_id can be used as a variable to store the I2C address of the device - */ - - /* - * Data on the bus should be like - * |------------+---------------------| - * | I2C action | Data | - * |------------+---------------------| - * | Start | - | - * | Write | (reg_addr) | - * | Stop | - | - * | Start | - | - * | Read | (reg_data[0]) | - * | Read | (....) | - * | Read | (reg_data[len - 1]) | - * | Stop | - | - * |------------+---------------------| - */ - - return rslt; -} - -int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) -{ - int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ - - /* - * The parameter dev_id can be used as a variable to store the I2C address of the device - */ - - /* - * Data on the bus should be like - * |------------+---------------------| - * | I2C action | Data | - * |------------+---------------------| - * | Start | - | - * | Write | (reg_addr) | - * | Write | (reg_data[0]) | - * | Write | (....) | - * | Write | (reg_data[len - 1]) | - * | Stop | - | - * |------------+---------------------| - */ - - return rslt; -} - -``` - -## Copyright (C) 2017 - 2018 Bosch Sensortec GmbH \ No newline at end of file diff --git a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.c b/lib/lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.c deleted file mode 100644 index c64e5f421..000000000 --- a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.c +++ /dev/null @@ -1,187 +0,0 @@ -/**\mainpage - * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of the copyright holder nor the names of the - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE - * - * The information provided is believed to be accurate and reliable. - * The copyright holder assumes no responsibility - * for the consequences of use - * of such information nor for any infringement of patents or - * other rights of third parties which may result from its use. - * No license is granted by implication or otherwise under any patent or - * patent rights of the copyright holder. - * - * File bme680_selftest.c - * @date 16 May 2018 - * @version 3.5.3 - * - */ - -/*! - * @addtogroup bme680_selftest - * @brief - * @{*/ - -#include "bme680_selftest.h" - -#define MIN_TEMPERATURE INT16_C(0) /* 0 degree Celsius */ -#define MAX_TEMPERATURE INT16_C(6000) /* 60 degree Celsius */ - -#define MIN_PRESSURE UINT32_C(90000) /* 900 hecto Pascals */ -#define MAX_PRESSURE UINT32_C(110000) /* 1100 hecto Pascals */ - -#define MIN_HUMIDITY UINT32_C(20000) /* 20% relative humidity */ -#define MAX_HUMIDITY UINT32_C(80000) /* 80% relative humidity*/ - -#define HEATR_DUR 2000 -#define N_MEAS 6 -#define LOW_TEMP 150 -#define HIGH_TEMP 350 - -/*! - * @brief Function to analyze the sensor data - * - * @param[in] data Array of measurement data - * @param[in] n_meas Number of measurements - * - * @return Error code - * @retval 0 Success - * @retval > 0 Warning - */ -static int8_t analyze_sensor_data(struct bme680_field_data *data, uint8_t n_meas); - -/*! - * @brief Self-test API for the BME680 - */ -int8_t bme680_self_test(struct bme680_dev *dev) -{ - int8_t rslt = BME680_OK; - struct bme680_field_data data[N_MEAS]; - - struct bme680_dev t_dev; - - /* Copy required parameters from reference bme680_dev struct */ - t_dev.dev_id = dev->dev_id; - t_dev.amb_temp = 25; - t_dev.read = dev->read; - t_dev.write = dev->write; - t_dev.intf = dev->intf; - t_dev.delay_ms = dev->delay_ms; - - rslt = bme680_init(&t_dev); - - if (rslt == BME680_OK) { - /* Select the power mode */ - /* Must be set before writing the sensor configuration */ - t_dev.power_mode = BME680_FORCED_MODE; - - uint16_t settings_sel; - - /* Set the temperature, pressure and humidity & filter settings */ - t_dev.tph_sett.os_hum = BME680_OS_1X; - t_dev.tph_sett.os_pres = BME680_OS_16X; - t_dev.tph_sett.os_temp = BME680_OS_2X; - - /* Set the remaining gas sensor settings and link the heating profile */ - t_dev.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS; - t_dev.gas_sett.heatr_dur = HEATR_DUR; - - settings_sel = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_GAS_SENSOR_SEL; - - uint16_t profile_dur = 0; - bme680_get_profile_dur(&profile_dur, &t_dev); - - uint8_t i = 0; - while ((rslt == BME680_OK) && (i < N_MEAS)) { - if (rslt == BME680_OK) { - - if (i % 2 == 0) - t_dev.gas_sett.heatr_temp = HIGH_TEMP; /* Higher temperature */ - else - t_dev.gas_sett.heatr_temp = LOW_TEMP; /* Lower temperature */ - - rslt = bme680_set_sensor_settings(settings_sel, &t_dev); - - if (rslt == BME680_OK) { - - rslt = bme680_set_sensor_mode(&t_dev); /* Trigger a measurement */ - - t_dev.delay_ms(profile_dur); /* Wait for the measurement to complete */ - - rslt = bme680_get_sensor_data(&data[i], &t_dev); - } - } - - i++; - } - - if (rslt == BME680_OK) - rslt = analyze_sensor_data(data, N_MEAS); - } - - return rslt; -} - -/*! - * @brief Function to analyze the sensor data - */ -static int8_t analyze_sensor_data(struct bme680_field_data *data, uint8_t n_meas) -{ - int8_t rslt = BME680_OK; - uint8_t self_test_failed = 0, i; - uint32_t cent_res = 0; - - if ((data[0].temperature < MIN_TEMPERATURE) || (data[0].temperature > MAX_TEMPERATURE)) - self_test_failed++; - - if ((data[0].pressure < MIN_PRESSURE) || (data[0].pressure > MAX_PRESSURE)) - self_test_failed++; - - if ((data[0].humidity < MIN_HUMIDITY) || (data[0].humidity > MAX_HUMIDITY)) - self_test_failed++; - - for (i = 0; i < n_meas; i++) /* Every gas measurement should be valid */ - if (!(data[i].status & BME680_GASM_VALID_MSK)) - self_test_failed++; - - if (n_meas >= 6) - cent_res = (data[3].gas_resistance + data[5].gas_resistance) / (2 * data[4].gas_resistance); - - if ((cent_res * 5) < 6) - self_test_failed++; - - if (self_test_failed) - rslt = BME680_W_SELF_TEST_FAILED; - - return rslt; -} - -/** @}*/ diff --git a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.h b/lib/lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.h deleted file mode 100644 index 7cc4e639f..000000000 --- a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.h +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of the copyright holder nor the names of the - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE - * - * The information provided is believed to be accurate and reliable. - * The copyright holder assumes no responsibility - * for the consequences of use - * of such information nor for any infringement of patents or - * other rights of third parties which may result from its use. - * No license is granted by implication or otherwise under any patent or - * patent rights of the copyright holder. - * - * @file bme680_selftest.h - * @date 16 May 2018 - * @version 3.5.3 - * @brief - * - */ - -/*! - * @addtogroup bme680_selftest - * @brief - * @{*/ - - -#ifndef BME680_SELFTEST_H_ -#define BME680_SELFTEST_H_ - -#include "bme680.h" - -/*! CPP guard */ -#ifdef __cplusplus -extern "C" -{ -#endif - -#define BME680_W_SELF_TEST_FAILED 3 - -/*! - * @brief Self-test API for the BME680 - * - * @param[in] Device structure containing relevant information on how - * to communicate with the sensor - * - * @return Error code - * @retval 0 Success - * @retval < 0 Error - * @retval > 0 Warning - */ -int8_t bme680_self_test(struct bme680_dev *dev); - -/*! CPP guard */ -#ifdef __cplusplus -} -#endif - -#endif /* BME680_SELFTEST_H_ */ - -/** @}*/ diff --git a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/bme680.c b/lib/lib_i2c/BME680_driver-bme680_v3.5.9/bme680.c deleted file mode 100644 index 6067725a9..000000000 --- a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/bme680.c +++ /dev/null @@ -1,1367 +0,0 @@ -/**\mainpage - * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of the copyright holder nor the names of the - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE - * - * The information provided is believed to be accurate and reliable. - * The copyright holder assumes no responsibility - * for the consequences of use - * of such information nor for any infringement of patents or - * other rights of third parties which may result from its use. - * No license is granted by implication or otherwise under any patent or - * patent rights of the copyright holder. - * - * File bme680.c - * @date 19 Jun 2018 - * @version 3.5.9 - * - */ - -/*! @file bme680.c - @brief Sensor driver for BME680 sensor */ -#include "bme680.h" - -/*! - * @brief This internal API is used to read the calibrated data from the sensor. - * - * This function is used to retrieve the calibration - * data from the image registers of the sensor. - * - * @note Registers 89h to A1h for calibration data 1 to 24 - * from bit 0 to 7 - * @note Registers E1h to F0h for calibration data 25 to 40 - * from bit 0 to 7 - * @param[in] dev :Structure instance of bme680_dev. - * - * @return Result of API execution status. - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error - */ -static int8_t get_calib_data(struct bme680_dev *dev); - -/*! - * @brief This internal API is used to set the gas configuration of the sensor. - * - * @param[in] dev :Structure instance of bme680_dev. - * - * @return Result of API execution status. - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error - */ -static int8_t set_gas_config(struct bme680_dev *dev); - -/*! - * @brief This internal API is used to get the gas configuration of the sensor. - * @note heatr_temp and heatr_dur values are currently register data - * and not the actual values set - * - * @param[in] dev :Structure instance of bme680_dev. - * - * @return Result of API execution status. - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error - */ -static int8_t get_gas_config(struct bme680_dev *dev); - -/*! - * @brief This internal API is used to calculate the Heat duration value. - * - * @param[in] dur :Value of the duration to be shared. - * - * @return uint8_t threshold duration after calculation. - */ -static uint8_t calc_heater_dur(uint16_t dur); - -#ifndef BME680_FLOAT_POINT_COMPENSATION - -/*! - * @brief This internal API is used to calculate the temperature value. - * - * @param[in] dev :Structure instance of bme680_dev. - * @param[in] temp_adc :Contains the temperature ADC value . - * - * @return uint32_t calculated temperature. - */ -static int16_t calc_temperature(uint32_t temp_adc, struct bme680_dev *dev); - -/*! - * @brief This internal API is used to calculate the pressure value. - * - * @param[in] dev :Structure instance of bme680_dev. - * @param[in] pres_adc :Contains the pressure ADC value . - * - * @return uint32_t calculated pressure. - */ -static uint32_t calc_pressure(uint32_t pres_adc, const struct bme680_dev *dev); - -/*! - * @brief This internal API is used to calculate the humidity value. - * - * @param[in] dev :Structure instance of bme680_dev. - * @param[in] hum_adc :Contains the humidity ADC value. - * - * @return uint32_t calculated humidity. - */ -static uint32_t calc_humidity(uint16_t hum_adc, const struct bme680_dev *dev); - -/*! - * @brief This internal API is used to calculate the Gas Resistance value. - * - * @param[in] dev :Structure instance of bme680_dev. - * @param[in] gas_res_adc :Contains the Gas Resistance ADC value. - * @param[in] gas_range :Contains the range of gas values. - * - * @return uint32_t calculated gas resistance. - */ -static uint32_t calc_gas_resistance(uint16_t gas_res_adc, uint8_t gas_range, const struct bme680_dev *dev); - -/*! - * @brief This internal API is used to calculate the Heat Resistance value. - * - * @param[in] dev : Structure instance of bme680_dev - * @param[in] temp : Contains the target temperature value. - * - * @return uint8_t calculated heater resistance. - */ -static uint8_t calc_heater_res(uint16_t temp, const struct bme680_dev *dev); - -#else -/*! - * @brief This internal API is used to calculate the - * temperature value value in float format - * - * @param[in] dev :Structure instance of bme680_dev. - * @param[in] temp_adc :Contains the temperature ADC value . - * - * @return Calculated temperature in float - */ -static float calc_temperature(uint32_t temp_adc, struct bme680_dev *dev); - -/*! - * @brief This internal API is used to calculate the - * pressure value value in float format - * - * @param[in] dev :Structure instance of bme680_dev. - * @param[in] pres_adc :Contains the pressure ADC value . - * - * @return Calculated pressure in float. - */ -static float calc_pressure(uint32_t pres_adc, const struct bme680_dev *dev); - -/*! - * @brief This internal API is used to calculate the - * humidity value value in float format - * - * @param[in] dev :Structure instance of bme680_dev. - * @param[in] hum_adc :Contains the humidity ADC value. - * - * @return Calculated humidity in float. - */ -static float calc_humidity(uint16_t hum_adc, const struct bme680_dev *dev); - -/*! - * @brief This internal API is used to calculate the - * gas resistance value value in float format - * - * @param[in] dev :Structure instance of bme680_dev. - * @param[in] gas_res_adc :Contains the Gas Resistance ADC value. - * @param[in] gas_range :Contains the range of gas values. - * - * @return Calculated gas resistance in float. - */ -static float calc_gas_resistance(uint16_t gas_res_adc, uint8_t gas_range, const struct bme680_dev *dev); - -/*! - * @brief This internal API is used to calculate the - * heater resistance value in float format - * - * @param[in] temp : Contains the target temperature value. - * @param[in] dev : Structure instance of bme680_dev. - * - * @return Calculated heater resistance in float. - */ -static float calc_heater_res(uint16_t temp, const struct bme680_dev *dev); - -#endif - -/*! - * @brief This internal API is used to calculate the field data of sensor. - * - * @param[out] data :Structure instance to hold the data - * @param[in] dev :Structure instance of bme680_dev. - * - * @return int8_t result of the field data from sensor. - */ -static int8_t read_field_data(struct bme680_field_data *data, struct bme680_dev *dev); - -/*! - * @brief This internal API is used to set the memory page - * based on register address. - * - * The value of memory page - * value | Description - * --------|-------------- - * 0 | BME680_PAGE0_SPI - * 1 | BME680_PAGE1_SPI - * - * @param[in] dev :Structure instance of bme680_dev. - * @param[in] reg_addr :Contains the register address array. - * - * @return Result of API execution status - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error - */ -static int8_t set_mem_page(uint8_t reg_addr, struct bme680_dev *dev); - -/*! - * @brief This internal API is used to get the memory page based - * on register address. - * - * The value of memory page - * value | Description - * --------|-------------- - * 0 | BME680_PAGE0_SPI - * 1 | BME680_PAGE1_SPI - * - * @param[in] dev :Structure instance of bme680_dev. - * - * @return Result of API execution status - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error - */ -static int8_t get_mem_page(struct bme680_dev *dev); - -/*! - * @brief This internal API is used to validate the device pointer for - * null conditions. - * - * @param[in] dev :Structure instance of bme680_dev. - * - * @return Result of API execution status - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error - */ -static int8_t null_ptr_check(const struct bme680_dev *dev); - -/*! - * @brief This internal API is used to check the boundary - * conditions. - * - * @param[in] value :pointer to the value. - * @param[in] min :minimum value. - * @param[in] max :maximum value. - * @param[in] dev :Structure instance of bme680_dev. - * - * @return Result of API execution status - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error - */ -static int8_t boundary_check(uint8_t *value, uint8_t min, uint8_t max, struct bme680_dev *dev); - -/****************** Global Function Definitions *******************************/ -/*! - *@brief This API is the entry point. - *It reads the chip-id and calibration data from the sensor. - */ -int8_t bme680_init(struct bme680_dev *dev) -{ - int8_t rslt; - - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - if (rslt == BME680_OK) { - /* Soft reset to restore it to default values*/ - rslt = bme680_soft_reset(dev); - if (rslt == BME680_OK) { - rslt = bme680_get_regs(BME680_CHIP_ID_ADDR, &dev->chip_id, 1, dev); - if (rslt == BME680_OK) { - if (dev->chip_id == BME680_CHIP_ID) { - /* Get the Calibration data */ - rslt = get_calib_data(dev); - } else { - rslt = BME680_E_DEV_NOT_FOUND; - } - } - } - } - - return rslt; -} - -/*! - * @brief This API reads the data from the given register address of the sensor. - */ -int8_t bme680_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct bme680_dev *dev) -{ - int8_t rslt; - - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - if (rslt == BME680_OK) { - if (dev->intf == BME680_SPI_INTF) { - /* Set the memory page */ - rslt = set_mem_page(reg_addr, dev); - if (rslt == BME680_OK) - reg_addr = reg_addr | BME680_SPI_RD_MSK; - } - dev->com_rslt = dev->read(dev->dev_id, reg_addr, reg_data, len); - if (dev->com_rslt != 0) - rslt = BME680_E_COM_FAIL; - } - - return rslt; -} - -/*! - * @brief This API writes the given data to the register address - * of the sensor. - */ -int8_t bme680_set_regs(const uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, struct bme680_dev *dev) -{ - int8_t rslt; - /* Length of the temporary buffer is 2*(length of register)*/ - uint8_t tmp_buff[BME680_TMP_BUFFER_LENGTH] = { 0 }; - uint16_t index; - - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - if (rslt == BME680_OK) { - if ((len > 0) && (len < BME680_TMP_BUFFER_LENGTH / 2)) { - /* Interleave the 2 arrays */ - for (index = 0; index < len; index++) { - if (dev->intf == BME680_SPI_INTF) { - /* Set the memory page */ - rslt = set_mem_page(reg_addr[index], dev); - tmp_buff[(2 * index)] = reg_addr[index] & BME680_SPI_WR_MSK; - } else { - tmp_buff[(2 * index)] = reg_addr[index]; - } - tmp_buff[(2 * index) + 1] = reg_data[index]; - } - /* Write the interleaved array */ - if (rslt == BME680_OK) { - dev->com_rslt = dev->write(dev->dev_id, tmp_buff[0], &tmp_buff[1], (2 * len) - 1); - if (dev->com_rslt != 0) - rslt = BME680_E_COM_FAIL; - } - } else { - rslt = BME680_E_INVALID_LENGTH; - } - } - - return rslt; -} - -/*! - * @brief This API performs the soft reset of the sensor. - */ -int8_t bme680_soft_reset(struct bme680_dev *dev) -{ - int8_t rslt; - uint8_t reg_addr = BME680_SOFT_RESET_ADDR; - /* 0xb6 is the soft reset command */ - uint8_t soft_rst_cmd = BME680_SOFT_RESET_CMD; - - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - if (rslt == BME680_OK) { - if (dev->intf == BME680_SPI_INTF) - rslt = get_mem_page(dev); - - /* Reset the device */ - if (rslt == BME680_OK) { - rslt = bme680_set_regs(®_addr, &soft_rst_cmd, 1, dev); - /* Wait for 5ms */ - dev->delay_ms(BME680_RESET_PERIOD); - - if (rslt == BME680_OK) { - /* After reset get the memory page */ - if (dev->intf == BME680_SPI_INTF) - rslt = get_mem_page(dev); - } - } - } - - return rslt; -} - -/*! - * @brief This API is used to set the oversampling, filter and T,P,H, gas selection - * settings in the sensor. - */ -int8_t bme680_set_sensor_settings(uint16_t desired_settings, struct bme680_dev *dev) -{ - int8_t rslt; - uint8_t reg_addr; - uint8_t data = 0; - uint8_t count = 0; - uint8_t reg_array[BME680_REG_BUFFER_LENGTH] = { 0 }; - uint8_t data_array[BME680_REG_BUFFER_LENGTH] = { 0 }; - uint8_t intended_power_mode = dev->power_mode; /* Save intended power mode */ - - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - if (rslt == BME680_OK) { - if (desired_settings & BME680_GAS_MEAS_SEL) - rslt = set_gas_config(dev); - - dev->power_mode = BME680_SLEEP_MODE; - if (rslt == BME680_OK) - rslt = bme680_set_sensor_mode(dev); - - /* Selecting the filter */ - if (desired_settings & BME680_FILTER_SEL) { - rslt = boundary_check(&dev->tph_sett.filter, BME680_FILTER_SIZE_0, BME680_FILTER_SIZE_127, dev); - reg_addr = BME680_CONF_ODR_FILT_ADDR; - - if (rslt == BME680_OK) - rslt = bme680_get_regs(reg_addr, &data, 1, dev); - - if (desired_settings & BME680_FILTER_SEL) - data = BME680_SET_BITS(data, BME680_FILTER, dev->tph_sett.filter); - - reg_array[count] = reg_addr; /* Append configuration */ - data_array[count] = data; - count++; - } - - /* Selecting heater control for the sensor */ - if (desired_settings & BME680_HCNTRL_SEL) { - rslt = boundary_check(&dev->gas_sett.heatr_ctrl, BME680_ENABLE_HEATER, - BME680_DISABLE_HEATER, dev); - reg_addr = BME680_CONF_HEAT_CTRL_ADDR; - - if (rslt == BME680_OK) - rslt = bme680_get_regs(reg_addr, &data, 1, dev); - data = BME680_SET_BITS_POS_0(data, BME680_HCTRL, dev->gas_sett.heatr_ctrl); - - reg_array[count] = reg_addr; /* Append configuration */ - data_array[count] = data; - count++; - } - - /* Selecting heater T,P oversampling for the sensor */ - if (desired_settings & (BME680_OST_SEL | BME680_OSP_SEL)) { - rslt = boundary_check(&dev->tph_sett.os_temp, BME680_OS_NONE, BME680_OS_16X, dev); - reg_addr = BME680_CONF_T_P_MODE_ADDR; - - if (rslt == BME680_OK) - rslt = bme680_get_regs(reg_addr, &data, 1, dev); - - if (desired_settings & BME680_OST_SEL) - data = BME680_SET_BITS(data, BME680_OST, dev->tph_sett.os_temp); - - if (desired_settings & BME680_OSP_SEL) - data = BME680_SET_BITS(data, BME680_OSP, dev->tph_sett.os_pres); - - reg_array[count] = reg_addr; - data_array[count] = data; - count++; - } - - /* Selecting humidity oversampling for the sensor */ - if (desired_settings & BME680_OSH_SEL) { - rslt = boundary_check(&dev->tph_sett.os_hum, BME680_OS_NONE, BME680_OS_16X, dev); - reg_addr = BME680_CONF_OS_H_ADDR; - - if (rslt == BME680_OK) - rslt = bme680_get_regs(reg_addr, &data, 1, dev); - data = BME680_SET_BITS_POS_0(data, BME680_OSH, dev->tph_sett.os_hum); - - reg_array[count] = reg_addr; /* Append configuration */ - data_array[count] = data; - count++; - } - - /* Selecting the runGas and NB conversion settings for the sensor */ - if (desired_settings & (BME680_RUN_GAS_SEL | BME680_NBCONV_SEL)) { - rslt = boundary_check(&dev->gas_sett.run_gas, BME680_RUN_GAS_DISABLE, - BME680_RUN_GAS_ENABLE, dev); - if (rslt == BME680_OK) { - /* Validate boundary conditions */ - rslt = boundary_check(&dev->gas_sett.nb_conv, BME680_NBCONV_MIN, - BME680_NBCONV_MAX, dev); - } - - reg_addr = BME680_CONF_ODR_RUN_GAS_NBC_ADDR; - - if (rslt == BME680_OK) - rslt = bme680_get_regs(reg_addr, &data, 1, dev); - - if (desired_settings & BME680_RUN_GAS_SEL) - data = BME680_SET_BITS(data, BME680_RUN_GAS, dev->gas_sett.run_gas); - - if (desired_settings & BME680_NBCONV_SEL) - data = BME680_SET_BITS_POS_0(data, BME680_NBCONV, dev->gas_sett.nb_conv); - - reg_array[count] = reg_addr; /* Append configuration */ - data_array[count] = data; - count++; - } - - if (rslt == BME680_OK) - rslt = bme680_set_regs(reg_array, data_array, count, dev); - - /* Restore previous intended power mode */ - dev->power_mode = intended_power_mode; - } - - return rslt; -} - -/*! - * @brief This API is used to get the oversampling, filter and T,P,H, gas selection - * settings in the sensor. - */ -int8_t bme680_get_sensor_settings(uint16_t desired_settings, struct bme680_dev *dev) -{ - int8_t rslt; - /* starting address of the register array for burst read*/ - uint8_t reg_addr = BME680_CONF_HEAT_CTRL_ADDR; - uint8_t data_array[BME680_REG_BUFFER_LENGTH] = { 0 }; - - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - if (rslt == BME680_OK) { - rslt = bme680_get_regs(reg_addr, data_array, BME680_REG_BUFFER_LENGTH, dev); - - if (rslt == BME680_OK) { - if (desired_settings & BME680_GAS_MEAS_SEL) - rslt = get_gas_config(dev); - - /* get the T,P,H ,Filter,ODR settings here */ - if (desired_settings & BME680_FILTER_SEL) - dev->tph_sett.filter = BME680_GET_BITS(data_array[BME680_REG_FILTER_INDEX], - BME680_FILTER); - - if (desired_settings & (BME680_OST_SEL | BME680_OSP_SEL)) { - dev->tph_sett.os_temp = BME680_GET_BITS(data_array[BME680_REG_TEMP_INDEX], BME680_OST); - dev->tph_sett.os_pres = BME680_GET_BITS(data_array[BME680_REG_PRES_INDEX], BME680_OSP); - } - - if (desired_settings & BME680_OSH_SEL) - dev->tph_sett.os_hum = BME680_GET_BITS_POS_0(data_array[BME680_REG_HUM_INDEX], - BME680_OSH); - - /* get the gas related settings */ - if (desired_settings & BME680_HCNTRL_SEL) - dev->gas_sett.heatr_ctrl = BME680_GET_BITS_POS_0(data_array[BME680_REG_HCTRL_INDEX], - BME680_HCTRL); - - if (desired_settings & (BME680_RUN_GAS_SEL | BME680_NBCONV_SEL)) { - dev->gas_sett.nb_conv = BME680_GET_BITS_POS_0(data_array[BME680_REG_NBCONV_INDEX], - BME680_NBCONV); - dev->gas_sett.run_gas = BME680_GET_BITS(data_array[BME680_REG_RUN_GAS_INDEX], - BME680_RUN_GAS); - } - } - } else { - rslt = BME680_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API is used to set the power mode of the sensor. - */ -int8_t bme680_set_sensor_mode(struct bme680_dev *dev) -{ - int8_t rslt; - uint8_t tmp_pow_mode; - uint8_t pow_mode = 0; - uint8_t reg_addr = BME680_CONF_T_P_MODE_ADDR; - - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - if (rslt == BME680_OK) { - /* Call repeatedly until in sleep */ - do { - rslt = bme680_get_regs(BME680_CONF_T_P_MODE_ADDR, &tmp_pow_mode, 1, dev); - if (rslt == BME680_OK) { - /* Put to sleep before changing mode */ - pow_mode = (tmp_pow_mode & BME680_MODE_MSK); - - if (pow_mode != BME680_SLEEP_MODE) { - tmp_pow_mode = tmp_pow_mode & (~BME680_MODE_MSK); /* Set to sleep */ - rslt = bme680_set_regs(®_addr, &tmp_pow_mode, 1, dev); - dev->delay_ms(BME680_POLL_PERIOD_MS); - } - } - } while (pow_mode != BME680_SLEEP_MODE); - - /* Already in sleep */ - if (dev->power_mode != BME680_SLEEP_MODE) { - tmp_pow_mode = (tmp_pow_mode & ~BME680_MODE_MSK) | (dev->power_mode & BME680_MODE_MSK); - if (rslt == BME680_OK) - rslt = bme680_set_regs(®_addr, &tmp_pow_mode, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API is used to get the power mode of the sensor. - */ -int8_t bme680_get_sensor_mode(struct bme680_dev *dev) -{ - int8_t rslt; - uint8_t mode; - - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - if (rslt == BME680_OK) { - rslt = bme680_get_regs(BME680_CONF_T_P_MODE_ADDR, &mode, 1, dev); - /* Masking the other register bit info*/ - dev->power_mode = mode & BME680_MODE_MSK; - } - - return rslt; -} - -/*! - * @brief This API is used to set the profile duration of the sensor. - */ -void bme680_set_profile_dur(uint16_t duration, struct bme680_dev *dev) -{ - uint32_t tph_dur; /* Calculate in us */ - uint32_t meas_cycles; - uint8_t os_to_meas_cycles[6] = {0, 1, 2, 4, 8, 16}; - - meas_cycles = os_to_meas_cycles[dev->tph_sett.os_temp]; - meas_cycles += os_to_meas_cycles[dev->tph_sett.os_pres]; - meas_cycles += os_to_meas_cycles[dev->tph_sett.os_hum]; - - /* TPH measurement duration */ - tph_dur = meas_cycles * UINT32_C(1963); - tph_dur += UINT32_C(477 * 4); /* TPH switching duration */ - tph_dur += UINT32_C(477 * 5); /* Gas measurement duration */ - tph_dur += UINT32_C(500); /* Get it to the closest whole number.*/ - tph_dur /= UINT32_C(1000); /* Convert to ms */ - - tph_dur += UINT32_C(1); /* Wake up duration of 1ms */ - /* The remaining time should be used for heating */ - dev->gas_sett.heatr_dur = duration - (uint16_t) tph_dur; -} - -/*! - * @brief This API is used to get the profile duration of the sensor. - */ -void bme680_get_profile_dur(uint16_t *duration, const struct bme680_dev *dev) -{ - uint32_t tph_dur; /* Calculate in us */ - uint32_t meas_cycles; - uint8_t os_to_meas_cycles[6] = {0, 1, 2, 4, 8, 16}; - - meas_cycles = os_to_meas_cycles[dev->tph_sett.os_temp]; - meas_cycles += os_to_meas_cycles[dev->tph_sett.os_pres]; - meas_cycles += os_to_meas_cycles[dev->tph_sett.os_hum]; - - /* TPH measurement duration */ - tph_dur = meas_cycles * UINT32_C(1963); - tph_dur += UINT32_C(477 * 4); /* TPH switching duration */ - tph_dur += UINT32_C(477 * 5); /* Gas measurement duration */ - tph_dur += UINT32_C(500); /* Get it to the closest whole number.*/ - tph_dur /= UINT32_C(1000); /* Convert to ms */ - - tph_dur += UINT32_C(1); /* Wake up duration of 1ms */ - - *duration = (uint16_t) tph_dur; - - /* Get the gas duration only when the run gas is enabled */ - if (dev->gas_sett.run_gas) { - /* The remaining time should be used for heating */ - *duration += dev->gas_sett.heatr_dur; - } -} - -/*! - * @brief This API reads the pressure, temperature and humidity and gas data - * from the sensor, compensates the data and store it in the bme680_data - * structure instance passed by the user. - */ -int8_t bme680_get_sensor_data(struct bme680_field_data *data, struct bme680_dev *dev) -{ - int8_t rslt; - - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - if (rslt == BME680_OK) { - /* Reading the sensor data in forced mode only */ - rslt = read_field_data(data, dev); - if (rslt == BME680_OK) { - if (data->status & BME680_NEW_DATA_MSK) - dev->new_fields = 1; - else - dev->new_fields = 0; - } - } - - return rslt; -} - -/*! - * @brief This internal API is used to read the calibrated data from the sensor. - */ -static int8_t get_calib_data(struct bme680_dev *dev) -{ - int8_t rslt; - uint8_t coeff_array[BME680_COEFF_SIZE] = { 0 }; - uint8_t temp_var = 0; /* Temporary variable */ - - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - if (rslt == BME680_OK) { - rslt = bme680_get_regs(BME680_COEFF_ADDR1, coeff_array, BME680_COEFF_ADDR1_LEN, dev); - /* Append the second half in the same array */ - if (rslt == BME680_OK) - rslt = bme680_get_regs(BME680_COEFF_ADDR2, &coeff_array[BME680_COEFF_ADDR1_LEN] - , BME680_COEFF_ADDR2_LEN, dev); - - /* Temperature related coefficients */ - dev->calib.par_t1 = (uint16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_T1_MSB_REG], - coeff_array[BME680_T1_LSB_REG])); - dev->calib.par_t2 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_T2_MSB_REG], - coeff_array[BME680_T2_LSB_REG])); - dev->calib.par_t3 = (int8_t) (coeff_array[BME680_T3_REG]); - - /* Pressure related coefficients */ - dev->calib.par_p1 = (uint16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P1_MSB_REG], - coeff_array[BME680_P1_LSB_REG])); - dev->calib.par_p2 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P2_MSB_REG], - coeff_array[BME680_P2_LSB_REG])); - dev->calib.par_p3 = (int8_t) coeff_array[BME680_P3_REG]; - dev->calib.par_p4 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P4_MSB_REG], - coeff_array[BME680_P4_LSB_REG])); - dev->calib.par_p5 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P5_MSB_REG], - coeff_array[BME680_P5_LSB_REG])); - dev->calib.par_p6 = (int8_t) (coeff_array[BME680_P6_REG]); - dev->calib.par_p7 = (int8_t) (coeff_array[BME680_P7_REG]); - dev->calib.par_p8 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P8_MSB_REG], - coeff_array[BME680_P8_LSB_REG])); - dev->calib.par_p9 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P9_MSB_REG], - coeff_array[BME680_P9_LSB_REG])); - dev->calib.par_p10 = (uint8_t) (coeff_array[BME680_P10_REG]); - - /* Humidity related coefficients */ - dev->calib.par_h1 = (uint16_t) (((uint16_t) coeff_array[BME680_H1_MSB_REG] << BME680_HUM_REG_SHIFT_VAL) - | (coeff_array[BME680_H1_LSB_REG] & BME680_BIT_H1_DATA_MSK)); - dev->calib.par_h2 = (uint16_t) (((uint16_t) coeff_array[BME680_H2_MSB_REG] << BME680_HUM_REG_SHIFT_VAL) - | ((coeff_array[BME680_H2_LSB_REG]) >> BME680_HUM_REG_SHIFT_VAL)); - dev->calib.par_h3 = (int8_t) coeff_array[BME680_H3_REG]; - dev->calib.par_h4 = (int8_t) coeff_array[BME680_H4_REG]; - dev->calib.par_h5 = (int8_t) coeff_array[BME680_H5_REG]; - dev->calib.par_h6 = (uint8_t) coeff_array[BME680_H6_REG]; - dev->calib.par_h7 = (int8_t) coeff_array[BME680_H7_REG]; - - /* Gas heater related coefficients */ - dev->calib.par_gh1 = (int8_t) coeff_array[BME680_GH1_REG]; - dev->calib.par_gh2 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_GH2_MSB_REG], - coeff_array[BME680_GH2_LSB_REG])); - dev->calib.par_gh3 = (int8_t) coeff_array[BME680_GH3_REG]; - - /* Other coefficients */ - if (rslt == BME680_OK) { - rslt = bme680_get_regs(BME680_ADDR_RES_HEAT_RANGE_ADDR, &temp_var, 1, dev); - - dev->calib.res_heat_range = ((temp_var & BME680_RHRANGE_MSK) / 16); - if (rslt == BME680_OK) { - rslt = bme680_get_regs(BME680_ADDR_RES_HEAT_VAL_ADDR, &temp_var, 1, dev); - - dev->calib.res_heat_val = (int8_t) temp_var; - if (rslt == BME680_OK) - rslt = bme680_get_regs(BME680_ADDR_RANGE_SW_ERR_ADDR, &temp_var, 1, dev); - } - } - dev->calib.range_sw_err = ((int8_t) temp_var & (int8_t) BME680_RSERROR_MSK) / 16; - } - - return rslt; -} - -/*! - * @brief This internal API is used to set the gas configuration of the sensor. - */ -static int8_t set_gas_config(struct bme680_dev *dev) -{ - int8_t rslt; - - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - if (rslt == BME680_OK) { - - uint8_t reg_addr[2] = {0}; - uint8_t reg_data[2] = {0}; - - if (dev->power_mode == BME680_FORCED_MODE) { - reg_addr[0] = BME680_RES_HEAT0_ADDR; - reg_data[0] = calc_heater_res(dev->gas_sett.heatr_temp, dev); - reg_addr[1] = BME680_GAS_WAIT0_ADDR; - reg_data[1] = calc_heater_dur(dev->gas_sett.heatr_dur); - dev->gas_sett.nb_conv = 0; - } else { - rslt = BME680_W_DEFINE_PWR_MODE; - } - if (rslt == BME680_OK) - rslt = bme680_set_regs(reg_addr, reg_data, 2, dev); - } - - return rslt; -} - -/*! - * @brief This internal API is used to get the gas configuration of the sensor. - * @note heatr_temp and heatr_dur values are currently register data - * and not the actual values set - */ -static int8_t get_gas_config(struct bme680_dev *dev) -{ - int8_t rslt; - /* starting address of the register array for burst read*/ - uint8_t reg_addr1 = BME680_ADDR_SENS_CONF_START; - uint8_t reg_addr2 = BME680_ADDR_GAS_CONF_START; - uint8_t reg_data = 0; - - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - if (rslt == BME680_OK) { - if (BME680_SPI_INTF == dev->intf) { - /* Memory page switch the SPI address*/ - rslt = set_mem_page(reg_addr1, dev); - } - - if (rslt == BME680_OK) { - rslt = bme680_get_regs(reg_addr1, ®_data, 1, dev); - if (rslt == BME680_OK) { - dev->gas_sett.heatr_temp = reg_data; - rslt = bme680_get_regs(reg_addr2, ®_data, 1, dev); - if (rslt == BME680_OK) { - /* Heating duration register value */ - dev->gas_sett.heatr_dur = reg_data; - } - } - } - } - - return rslt; -} - -#ifndef BME680_FLOAT_POINT_COMPENSATION - -/*! - * @brief This internal API is used to calculate the temperature value. - */ -static int16_t calc_temperature(uint32_t temp_adc, struct bme680_dev *dev) -{ - int64_t var1; - int64_t var2; - int64_t var3; - int16_t calc_temp; - - var1 = ((int32_t) temp_adc >> 3) - ((int32_t) dev->calib.par_t1 << 1); - var2 = (var1 * (int32_t) dev->calib.par_t2) >> 11; - var3 = ((var1 >> 1) * (var1 >> 1)) >> 12; - var3 = ((var3) * ((int32_t) dev->calib.par_t3 << 4)) >> 14; - dev->calib.t_fine = (int32_t) (var2 + var3); - calc_temp = (int16_t) (((dev->calib.t_fine * 5) + 128) >> 8); - - return calc_temp; -} - -/*! - * @brief This internal API is used to calculate the pressure value. - */ -static uint32_t calc_pressure(uint32_t pres_adc, const struct bme680_dev *dev) -{ - int32_t var1; - int32_t var2; - int32_t var3; - int32_t pressure_comp; - - var1 = (((int32_t)dev->calib.t_fine) >> 1) - 64000; - var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * - (int32_t)dev->calib.par_p6) >> 2; - var2 = var2 + ((var1 * (int32_t)dev->calib.par_p5) << 1); - var2 = (var2 >> 2) + ((int32_t)dev->calib.par_p4 << 16); - var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) * - ((int32_t)dev->calib.par_p3 << 5)) >> 3) + - (((int32_t)dev->calib.par_p2 * var1) >> 1); - var1 = var1 >> 18; - var1 = ((32768 + var1) * (int32_t)dev->calib.par_p1) >> 15; - pressure_comp = 1048576 - pres_adc; - pressure_comp = (int32_t)((pressure_comp - (var2 >> 12)) * ((uint32_t)3125)); - if (pressure_comp >= BME680_MAX_OVERFLOW_VAL) - pressure_comp = ((pressure_comp / var1) << 1); - else - pressure_comp = ((pressure_comp << 1) / var1); - var1 = ((int32_t)dev->calib.par_p9 * (int32_t)(((pressure_comp >> 3) * - (pressure_comp >> 3)) >> 13)) >> 12; - var2 = ((int32_t)(pressure_comp >> 2) * - (int32_t)dev->calib.par_p8) >> 13; - var3 = ((int32_t)(pressure_comp >> 8) * (int32_t)(pressure_comp >> 8) * - (int32_t)(pressure_comp >> 8) * - (int32_t)dev->calib.par_p10) >> 17; - - pressure_comp = (int32_t)(pressure_comp) + ((var1 + var2 + var3 + - ((int32_t)dev->calib.par_p7 << 7)) >> 4); - - return (uint32_t)pressure_comp; - -} - -/*! - * @brief This internal API is used to calculate the humidity value. - */ -static uint32_t calc_humidity(uint16_t hum_adc, const struct bme680_dev *dev) -{ - int32_t var1; - int32_t var2; - int32_t var3; - int32_t var4; - int32_t var5; - int32_t var6; - int32_t temp_scaled; - int32_t calc_hum; - - temp_scaled = (((int32_t) dev->calib.t_fine * 5) + 128) >> 8; - var1 = (int32_t) (hum_adc - ((int32_t) ((int32_t) dev->calib.par_h1 * 16))) - - (((temp_scaled * (int32_t) dev->calib.par_h3) / ((int32_t) 100)) >> 1); - var2 = ((int32_t) dev->calib.par_h2 - * (((temp_scaled * (int32_t) dev->calib.par_h4) / ((int32_t) 100)) - + (((temp_scaled * ((temp_scaled * (int32_t) dev->calib.par_h5) / ((int32_t) 100))) >> 6) - / ((int32_t) 100)) + (int32_t) (1 << 14))) >> 10; - var3 = var1 * var2; - var4 = (int32_t) dev->calib.par_h6 << 7; - var4 = ((var4) + ((temp_scaled * (int32_t) dev->calib.par_h7) / ((int32_t) 100))) >> 4; - var5 = ((var3 >> 14) * (var3 >> 14)) >> 10; - var6 = (var4 * var5) >> 1; - calc_hum = (((var3 + var6) >> 10) * ((int32_t) 1000)) >> 12; - - if (calc_hum > 100000) /* Cap at 100%rH */ - calc_hum = 100000; - else if (calc_hum < 0) - calc_hum = 0; - - return (uint32_t) calc_hum; -} - -/*! - * @brief This internal API is used to calculate the Gas Resistance value. - */ -static uint32_t calc_gas_resistance(uint16_t gas_res_adc, uint8_t gas_range, const struct bme680_dev *dev) -{ - int64_t var1; - uint64_t var2; - int64_t var3; - uint32_t calc_gas_res; - /**Look up table 1 for the possible gas range values */ - uint32_t lookupTable1[16] = { UINT32_C(2147483647), UINT32_C(2147483647), UINT32_C(2147483647), UINT32_C(2147483647), - UINT32_C(2147483647), UINT32_C(2126008810), UINT32_C(2147483647), UINT32_C(2130303777), - UINT32_C(2147483647), UINT32_C(2147483647), UINT32_C(2143188679), UINT32_C(2136746228), - UINT32_C(2147483647), UINT32_C(2126008810), UINT32_C(2147483647), UINT32_C(2147483647) }; - /**Look up table 2 for the possible gas range values */ - uint32_t lookupTable2[16] = { UINT32_C(4096000000), UINT32_C(2048000000), UINT32_C(1024000000), UINT32_C(512000000), - UINT32_C(255744255), UINT32_C(127110228), UINT32_C(64000000), UINT32_C(32258064), UINT32_C(16016016), - UINT32_C(8000000), UINT32_C(4000000), UINT32_C(2000000), UINT32_C(1000000), UINT32_C(500000), - UINT32_C(250000), UINT32_C(125000) }; - - var1 = (int64_t) ((1340 + (5 * (int64_t) dev->calib.range_sw_err)) * - ((int64_t) lookupTable1[gas_range])) >> 16; - var2 = (((int64_t) ((int64_t) gas_res_adc << 15) - (int64_t) (16777216)) + var1); - var3 = (((int64_t) lookupTable2[gas_range] * (int64_t) var1) >> 9); - calc_gas_res = (uint32_t) ((var3 + ((int64_t) var2 >> 1)) / (int64_t) var2); - - return calc_gas_res; -} - -/*! - * @brief This internal API is used to calculate the Heat Resistance value. - */ -static uint8_t calc_heater_res(uint16_t temp, const struct bme680_dev *dev) -{ - uint8_t heatr_res; - int32_t var1; - int32_t var2; - int32_t var3; - int32_t var4; - int32_t var5; - int32_t heatr_res_x100; - - if (temp > 400) /* Cap temperature */ - temp = 400; - - var1 = (((int32_t) dev->amb_temp * dev->calib.par_gh3) / 1000) * 256; - var2 = (dev->calib.par_gh1 + 784) * (((((dev->calib.par_gh2 + 154009) * temp * 5) / 100) + 3276800) / 10); - var3 = var1 + (var2 / 2); - var4 = (var3 / (dev->calib.res_heat_range + 4)); - var5 = (131 * dev->calib.res_heat_val) + 65536; - heatr_res_x100 = (int32_t) (((var4 / var5) - 250) * 34); - heatr_res = (uint8_t) ((heatr_res_x100 + 50) / 100); - - return heatr_res; -} - -#else - - -/*! - * @brief This internal API is used to calculate the - * temperature value in float format - */ -static float calc_temperature(uint32_t temp_adc, struct bme680_dev *dev) -{ - float var1 = 0; - float var2 = 0; - float calc_temp = 0; - - /* calculate var1 data */ - var1 = ((((float)temp_adc / 16384.0f) - ((float)dev->calib.par_t1 / 1024.0f)) - * ((float)dev->calib.par_t2)); - - /* calculate var2 data */ - var2 = (((((float)temp_adc / 131072.0f) - ((float)dev->calib.par_t1 / 8192.0f)) * - (((float)temp_adc / 131072.0f) - ((float)dev->calib.par_t1 / 8192.0f))) * - ((float)dev->calib.par_t3 * 16.0f)); - - /* t_fine value*/ - dev->calib.t_fine = (var1 + var2); - - /* compensated temperature data*/ - calc_temp = ((dev->calib.t_fine) / 5120.0f); - - return calc_temp; -} - -/*! - * @brief This internal API is used to calculate the - * pressure value in float format - */ -static float calc_pressure(uint32_t pres_adc, const struct bme680_dev *dev) -{ - float var1 = 0; - float var2 = 0; - float var3 = 0; - float calc_pres = 0; - - var1 = (((float)dev->calib.t_fine / 2.0f) - 64000.0f); - var2 = var1 * var1 * (((float)dev->calib.par_p6) / (131072.0f)); - var2 = var2 + (var1 * ((float)dev->calib.par_p5) * 2.0f); - var2 = (var2 / 4.0f) + (((float)dev->calib.par_p4) * 65536.0f); - var1 = (((((float)dev->calib.par_p3 * var1 * var1) / 16384.0f) - + ((float)dev->calib.par_p2 * var1)) / 524288.0f); - var1 = ((1.0f + (var1 / 32768.0f)) * ((float)dev->calib.par_p1)); - calc_pres = (1048576.0f - ((float)pres_adc)); - - /* Avoid exception caused by division by zero */ - if ((int)var1 != 0) { - calc_pres = (((calc_pres - (var2 / 4096.0f)) * 6250.0f) / var1); - var1 = (((float)dev->calib.par_p9) * calc_pres * calc_pres) / 2147483648.0f; - var2 = calc_pres * (((float)dev->calib.par_p8) / 32768.0f); - var3 = ((calc_pres / 256.0f) * (calc_pres / 256.0f) * (calc_pres / 256.0f) - * (dev->calib.par_p10 / 131072.0f)); - calc_pres = (calc_pres + (var1 + var2 + var3 + ((float)dev->calib.par_p7 * 128.0f)) / 16.0f); - } else { - calc_pres = 0; - } - - return calc_pres; -} - -/*! - * @brief This internal API is used to calculate the - * humidity value in float format - */ -static float calc_humidity(uint16_t hum_adc, const struct bme680_dev *dev) -{ - float calc_hum = 0; - float var1 = 0; - float var2 = 0; - float var3 = 0; - float var4 = 0; - float temp_comp; - - /* compensated temperature data*/ - temp_comp = ((dev->calib.t_fine) / 5120.0f); - - var1 = (float)((float)hum_adc) - (((float)dev->calib.par_h1 * 16.0f) + (((float)dev->calib.par_h3 / 2.0f) - * temp_comp)); - - var2 = var1 * ((float)(((float) dev->calib.par_h2 / 262144.0f) * (1.0f + (((float)dev->calib.par_h4 / 16384.0f) - * temp_comp) + (((float)dev->calib.par_h5 / 1048576.0f) * temp_comp * temp_comp)))); - - var3 = (float) dev->calib.par_h6 / 16384.0f; - - var4 = (float) dev->calib.par_h7 / 2097152.0f; - - calc_hum = var2 + ((var3 + (var4 * temp_comp)) * var2 * var2); - - if (calc_hum > 100.0f) - calc_hum = 100.0f; - else if (calc_hum < 0.0f) - calc_hum = 0.0f; - - return calc_hum; -} - -/*! - * @brief This internal API is used to calculate the - * gas resistance value in float format - */ -static float calc_gas_resistance(uint16_t gas_res_adc, uint8_t gas_range, const struct bme680_dev *dev) -{ - float calc_gas_res; - float var1 = 0; - float var2 = 0; - float var3 = 0; - - const float lookup_k1_range[16] = { - 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -0.8, - 0.0, 0.0, -0.2, -0.5, 0.0, -1.0, 0.0, 0.0}; - const float lookup_k2_range[16] = { - 0.0, 0.0, 0.0, 0.0, 0.1, 0.7, 0.0, -0.8, - -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; - - var1 = (1340.0f + (5.0f * dev->calib.range_sw_err)); - var2 = (var1) * (1.0f + lookup_k1_range[gas_range]/100.0f); - var3 = 1.0f + (lookup_k2_range[gas_range]/100.0f); - - calc_gas_res = 1.0f / (float)(var3 * (0.000000125f) * (float)(1 << gas_range) * (((((float)gas_res_adc) - - 512.0f)/var2) + 1.0f)); - - return calc_gas_res; -} - -/*! - * @brief This internal API is used to calculate the - * heater resistance value in float format - */ -static float calc_heater_res(uint16_t temp, const struct bme680_dev *dev) -{ - float var1 = 0; - float var2 = 0; - float var3 = 0; - float var4 = 0; - float var5 = 0; - float res_heat = 0; - - if (temp > 400) /* Cap temperature */ - temp = 400; - - var1 = (((float)dev->calib.par_gh1 / (16.0f)) + 49.0f); - var2 = ((((float)dev->calib.par_gh2 / (32768.0f)) * (0.0005f)) + 0.00235f); - var3 = ((float)dev->calib.par_gh3 / (1024.0f)); - var4 = (var1 * (1.0f + (var2 * (float)temp))); - var5 = (var4 + (var3 * (float)dev->amb_temp)); - res_heat = (uint8_t)(3.4f * ((var5 * (4 / (4 + (float)dev->calib.res_heat_range)) * - (1/(1 + ((float) dev->calib.res_heat_val * 0.002f)))) - 25)); - - return res_heat; -} - -#endif - -/*! - * @brief This internal API is used to calculate the Heat duration value. - */ -static uint8_t calc_heater_dur(uint16_t dur) -{ - uint8_t factor = 0; - uint8_t durval; - - if (dur >= 0xfc0) { - durval = 0xff; /* Max duration*/ - } else { - while (dur > 0x3F) { - dur = dur / 4; - factor += 1; - } - durval = (uint8_t) (dur + (factor * 64)); - } - - return durval; -} - -/*! - * @brief This internal API is used to calculate the field data of sensor. - */ -static int8_t read_field_data(struct bme680_field_data *data, struct bme680_dev *dev) -{ - int8_t rslt; - uint8_t buff[BME680_FIELD_LENGTH] = { 0 }; - uint8_t gas_range; - uint32_t adc_temp; - uint32_t adc_pres; - uint16_t adc_hum; - uint16_t adc_gas_res; - uint8_t tries = 10; - - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - do { - if (rslt == BME680_OK) { - rslt = bme680_get_regs(((uint8_t) (BME680_FIELD0_ADDR)), buff, (uint16_t) BME680_FIELD_LENGTH, - dev); - - data->status = buff[0] & BME680_NEW_DATA_MSK; - data->gas_index = buff[0] & BME680_GAS_INDEX_MSK; - data->meas_index = buff[1]; - - /* read the raw data from the sensor */ - adc_pres = (uint32_t) (((uint32_t) buff[2] * 4096) | ((uint32_t) buff[3] * 16) - | ((uint32_t) buff[4] / 16)); - adc_temp = (uint32_t) (((uint32_t) buff[5] * 4096) | ((uint32_t) buff[6] * 16) - | ((uint32_t) buff[7] / 16)); - adc_hum = (uint16_t) (((uint32_t) buff[8] * 256) | (uint32_t) buff[9]); - adc_gas_res = (uint16_t) ((uint32_t) buff[13] * 4 | (((uint32_t) buff[14]) / 64)); - gas_range = buff[14] & BME680_GAS_RANGE_MSK; - - data->status |= buff[14] & BME680_GASM_VALID_MSK; - data->status |= buff[14] & BME680_HEAT_STAB_MSK; - - if (data->status & BME680_NEW_DATA_MSK) { - data->temperature = calc_temperature(adc_temp, dev); - data->pressure = calc_pressure(adc_pres, dev); - data->humidity = calc_humidity(adc_hum, dev); - data->gas_resistance = calc_gas_resistance(adc_gas_res, gas_range, dev); - break; - } - /* Delay to poll the data */ - dev->delay_ms(BME680_POLL_PERIOD_MS); - } - tries--; - } while (tries); - - if (!tries) - rslt = BME680_W_NO_NEW_DATA; - - return rslt; -} - -/*! - * @brief This internal API is used to set the memory page based on register address. - */ -static int8_t set_mem_page(uint8_t reg_addr, struct bme680_dev *dev) -{ - int8_t rslt; - uint8_t reg; - uint8_t mem_page; - - /* Check for null pointers in the device structure*/ - rslt = null_ptr_check(dev); - if (rslt == BME680_OK) { - if (reg_addr > 0x7f) - mem_page = BME680_MEM_PAGE1; - else - mem_page = BME680_MEM_PAGE0; - - if (mem_page != dev->mem_page) { - dev->mem_page = mem_page; - - dev->com_rslt = dev->read(dev->dev_id, BME680_MEM_PAGE_ADDR | BME680_SPI_RD_MSK, ®, 1); - if (dev->com_rslt != 0) - rslt = BME680_E_COM_FAIL; - - if (rslt == BME680_OK) { - reg = reg & (~BME680_MEM_PAGE_MSK); - reg = reg | (dev->mem_page & BME680_MEM_PAGE_MSK); - - dev->com_rslt = dev->write(dev->dev_id, BME680_MEM_PAGE_ADDR & BME680_SPI_WR_MSK, - ®, 1); - if (dev->com_rslt != 0) - rslt = BME680_E_COM_FAIL; - } - } - } - - return rslt; -} - -/*! - * @brief This internal API is used to get the memory page based on register address. - */ -static int8_t get_mem_page(struct bme680_dev *dev) -{ - int8_t rslt; - uint8_t reg; - - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - if (rslt == BME680_OK) { - dev->com_rslt = dev->read(dev->dev_id, BME680_MEM_PAGE_ADDR | BME680_SPI_RD_MSK, ®, 1); - if (dev->com_rslt != 0) - rslt = BME680_E_COM_FAIL; - else - dev->mem_page = reg & BME680_MEM_PAGE_MSK; - } - - return rslt; -} - -/*! - * @brief This internal API is used to validate the boundary - * conditions. - */ -static int8_t boundary_check(uint8_t *value, uint8_t min, uint8_t max, struct bme680_dev *dev) -{ - int8_t rslt = BME680_OK; - - if (value != NULL) { - /* Check if value is below minimum value */ - if (*value < min) { - /* Auto correct the invalid value to minimum value */ - *value = min; - dev->info_msg |= BME680_I_MIN_CORRECTION; - } - /* Check if value is above maximum value */ - if (*value > max) { - /* Auto correct the invalid value to maximum value */ - *value = max; - dev->info_msg |= BME680_I_MAX_CORRECTION; - } - } else { - rslt = BME680_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This internal API is used to validate the device structure pointer for - * null conditions. - */ -static int8_t null_ptr_check(const struct bme680_dev *dev) -{ - int8_t rslt; - - if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL)) { - /* Device structure pointer is not valid */ - rslt = BME680_E_NULL_PTR; - } else { - /* Device structure is fine */ - rslt = BME680_OK; - } - - return rslt; -} diff --git a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/bme680.h b/lib/lib_i2c/BME680_driver-bme680_v3.5.9/bme680.h deleted file mode 100644 index 7c59be0f6..000000000 --- a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/bme680.h +++ /dev/null @@ -1,225 +0,0 @@ -/** - * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of the copyright holder nor the names of the - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE - * - * The information provided is believed to be accurate and reliable. - * The copyright holder assumes no responsibility - * for the consequences of use - * of such information nor for any infringement of patents or - * other rights of third parties which may result from its use. - * No license is granted by implication or otherwise under any patent or - * patent rights of the copyright holder. - * - * @file bme680.h - * @date 19 Jun 2018 - * @version 3.5.9 - * @brief - * - */ -/*! @file bme680.h - @brief Sensor driver for BME680 sensor */ -/*! - * @defgroup BME680 SENSOR API - * @{*/ -#ifndef BME680_H_ -#define BME680_H_ - -/*! CPP guard */ -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Header includes */ -#include "bme680_defs.h" - -/* function prototype declarations */ -/*! - * @brief This API is the entry point. - * It reads the chip-id and calibration data from the sensor. - * - * @param[in,out] dev : Structure instance of bme680_dev - * - * @return Result of API execution status - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error - */ -int8_t bme680_init(struct bme680_dev *dev); - -/*! - * @brief This API writes the given data to the register address - * of the sensor. - * - * @param[in] reg_addr : Register address from where the data to be written. - * @param[in] reg_data : Pointer to data buffer which is to be written - * in the sensor. - * @param[in] len : No of bytes of data to write.. - * @param[in] dev : Structure instance of bme680_dev. - * - * @return Result of API execution status - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error - */ -int8_t bme680_set_regs(const uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, struct bme680_dev *dev); - -/*! - * @brief This API reads the data from the given register address of the sensor. - * - * @param[in] reg_addr : Register address from where the data to be read - * @param[out] reg_data : Pointer to data buffer to store the read data. - * @param[in] len : No of bytes of data to be read. - * @param[in] dev : Structure instance of bme680_dev. - * - * @return Result of API execution status - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error - */ -int8_t bme680_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct bme680_dev *dev); - -/*! - * @brief This API performs the soft reset of the sensor. - * - * @param[in] dev : Structure instance of bme680_dev. - * - * @return Result of API execution status - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. - */ -int8_t bme680_soft_reset(struct bme680_dev *dev); - -/*! - * @brief This API is used to set the power mode of the sensor. - * - * @param[in] dev : Structure instance of bme680_dev - * @note : Pass the value to bme680_dev.power_mode structure variable. - * - * value | mode - * -------------|------------------ - * 0x00 | BME680_SLEEP_MODE - * 0x01 | BME680_FORCED_MODE - * - * * @return Result of API execution status - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error - */ -int8_t bme680_set_sensor_mode(struct bme680_dev *dev); - -/*! - * @brief This API is used to get the power mode of the sensor. - * - * @param[in] dev : Structure instance of bme680_dev - * @note : bme680_dev.power_mode structure variable hold the power mode. - * - * value | mode - * ---------|------------------ - * 0x00 | BME680_SLEEP_MODE - * 0x01 | BME680_FORCED_MODE - * - * @return Result of API execution status - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error - */ -int8_t bme680_get_sensor_mode(struct bme680_dev *dev); - -/*! - * @brief This API is used to set the profile duration of the sensor. - * - * @param[in] dev : Structure instance of bme680_dev. - * @param[in] duration : Duration of the measurement in ms. - * - * @return Nothing - */ -void bme680_set_profile_dur(uint16_t duration, struct bme680_dev *dev); - -/*! - * @brief This API is used to get the profile duration of the sensor. - * - * @param[in] dev : Structure instance of bme680_dev. - * @param[in] duration : Duration of the measurement in ms. - * - * @return Nothing - */ -void bme680_get_profile_dur(uint16_t *duration, const struct bme680_dev *dev); - -/*! - * @brief This API reads the pressure, temperature and humidity and gas data - * from the sensor, compensates the data and store it in the bme680_data - * structure instance passed by the user. - * - * @param[out] data: Structure instance to hold the data. - * @param[in] dev : Structure instance of bme680_dev. - * - * @return Result of API execution status - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error - */ -int8_t bme680_get_sensor_data(struct bme680_field_data *data, struct bme680_dev *dev); - -/*! - * @brief This API is used to set the oversampling, filter and T,P,H, gas selection - * settings in the sensor. - * - * @param[in] dev : Structure instance of bme680_dev. - * @param[in] desired_settings : Variable used to select the settings which - * are to be set in the sensor. - * - * Macros | Functionality - *---------------------------------|---------------------------------------------- - * BME680_OST_SEL | To set temperature oversampling. - * BME680_OSP_SEL | To set pressure oversampling. - * BME680_OSH_SEL | To set humidity oversampling. - * BME680_GAS_MEAS_SEL | To set gas measurement setting. - * BME680_FILTER_SEL | To set filter setting. - * BME680_HCNTRL_SEL | To set humidity control setting. - * BME680_RUN_GAS_SEL | To set run gas setting. - * BME680_NBCONV_SEL | To set NB conversion setting. - * BME680_GAS_SENSOR_SEL | To set all gas sensor related settings - * - * @note : Below are the macros to be used by the user for selecting the - * desired settings. User can do OR operation of these macros for configuring - * multiple settings. - * - * @return Result of API execution status - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. - */ -int8_t bme680_set_sensor_settings(uint16_t desired_settings, struct bme680_dev *dev); - -/*! - * @brief This API is used to get the oversampling, filter and T,P,H, gas selection - * settings in the sensor. - * - * @param[in] dev : Structure instance of bme680_dev. - * @param[in] desired_settings : Variable used to select the settings which - * are to be get from the sensor. - * - * @return Result of API execution status - * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. - */ -int8_t bme680_get_sensor_settings(uint16_t desired_settings, struct bme680_dev *dev); -#ifdef __cplusplus -} -#endif /* End of CPP guard */ -#endif /* BME680_H_ */ -/** @}*/ diff --git a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/bme680_defs.h b/lib/lib_i2c/BME680_driver-bme680_v3.5.9/bme680_defs.h deleted file mode 100644 index 495edfe00..000000000 --- a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/bme680_defs.h +++ /dev/null @@ -1,545 +0,0 @@ -/** - * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of the copyright holder nor the names of the - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE - * - * The information provided is believed to be accurate and reliable. - * The copyright holder assumes no responsibility - * for the consequences of use - * of such information nor for any infringement of patents or - * other rights of third parties which may result from its use. - * No license is granted by implication or otherwise under any patent or - * patent rights of the copyright holder. - * - * @file bme680_defs.h - * @date 19 Jun 2018 - * @version 3.5.9 - * @brief - * - */ - -/*! @file bme680_defs.h - @brief Sensor driver for BME680 sensor */ -/*! - * @defgroup BME680 SENSOR API - * @brief - * @{*/ -#ifndef BME680_DEFS_H_ -#define BME680_DEFS_H_ - -/********************************************************/ -/* header includes */ -#ifdef __KERNEL__ -#include -#include -#else -#include -#include -#endif - -/******************************************************************************/ -/*! @name Common macros */ -/******************************************************************************/ - -#if !defined(UINT8_C) && !defined(INT8_C) -#define INT8_C(x) S8_C(x) -#define UINT8_C(x) U8_C(x) -#endif - -#if !defined(UINT16_C) && !defined(INT16_C) -#define INT16_C(x) S16_C(x) -#define UINT16_C(x) U16_C(x) -#endif - -#if !defined(INT32_C) && !defined(UINT32_C) -#define INT32_C(x) S32_C(x) -#define UINT32_C(x) U32_C(x) -#endif - -#if !defined(INT64_C) && !defined(UINT64_C) -#define INT64_C(x) S64_C(x) -#define UINT64_C(x) U64_C(x) -#endif - -/**@}*/ - -/**\name C standard macros */ -#ifndef NULL -#ifdef __cplusplus -#define NULL 0 -#else -#define NULL ((void *) 0) -#endif -#endif - -/** BME680 configuration macros */ -/** Enable or un-comment the macro to provide floating point data output */ -#ifndef BME680_FLOAT_POINT_COMPENSATION -/* #define BME680_FLOAT_POINT_COMPENSATION */ -#endif - -/** BME680 General config */ -#define BME680_POLL_PERIOD_MS UINT8_C(10) - -/** BME680 I2C addresses */ -#define BME680_I2C_ADDR_PRIMARY UINT8_C(0x76) -#define BME680_I2C_ADDR_SECONDARY UINT8_C(0x77) - -/** BME680 unique chip identifier */ -#define BME680_CHIP_ID UINT8_C(0x61) - -/** BME680 coefficients related defines */ -#define BME680_COEFF_SIZE UINT8_C(41) -#define BME680_COEFF_ADDR1_LEN UINT8_C(25) -#define BME680_COEFF_ADDR2_LEN UINT8_C(16) - -/** BME680 field_x related defines */ -#define BME680_FIELD_LENGTH UINT8_C(15) -#define BME680_FIELD_ADDR_OFFSET UINT8_C(17) - -/** Soft reset command */ -#define BME680_SOFT_RESET_CMD UINT8_C(0xb6) - -/** Error code definitions */ -#define BME680_OK INT8_C(0) -/* Errors */ -#define BME680_E_NULL_PTR INT8_C(-1) -#define BME680_E_COM_FAIL INT8_C(-2) -#define BME680_E_DEV_NOT_FOUND INT8_C(-3) -#define BME680_E_INVALID_LENGTH INT8_C(-4) - -/* Warnings */ -#define BME680_W_DEFINE_PWR_MODE INT8_C(1) -#define BME680_W_NO_NEW_DATA INT8_C(2) - -/* Info's */ -#define BME680_I_MIN_CORRECTION UINT8_C(1) -#define BME680_I_MAX_CORRECTION UINT8_C(2) - -/** Register map */ -/** Other coefficient's address */ -#define BME680_ADDR_RES_HEAT_VAL_ADDR UINT8_C(0x00) -#define BME680_ADDR_RES_HEAT_RANGE_ADDR UINT8_C(0x02) -#define BME680_ADDR_RANGE_SW_ERR_ADDR UINT8_C(0x04) -#define BME680_ADDR_SENS_CONF_START UINT8_C(0x5A) -#define BME680_ADDR_GAS_CONF_START UINT8_C(0x64) - -/** Field settings */ -#define BME680_FIELD0_ADDR UINT8_C(0x1d) - -/** Heater settings */ -#define BME680_RES_HEAT0_ADDR UINT8_C(0x5a) -#define BME680_GAS_WAIT0_ADDR UINT8_C(0x64) - -/** Sensor configuration registers */ -#define BME680_CONF_HEAT_CTRL_ADDR UINT8_C(0x70) -#define BME680_CONF_ODR_RUN_GAS_NBC_ADDR UINT8_C(0x71) -#define BME680_CONF_OS_H_ADDR UINT8_C(0x72) -#define BME680_MEM_PAGE_ADDR UINT8_C(0xf3) -#define BME680_CONF_T_P_MODE_ADDR UINT8_C(0x74) -#define BME680_CONF_ODR_FILT_ADDR UINT8_C(0x75) - -/** Coefficient's address */ -#define BME680_COEFF_ADDR1 UINT8_C(0x89) -#define BME680_COEFF_ADDR2 UINT8_C(0xe1) - -/** Chip identifier */ -#define BME680_CHIP_ID_ADDR UINT8_C(0xd0) - -/** Soft reset register */ -#define BME680_SOFT_RESET_ADDR UINT8_C(0xe0) - -/** Heater control settings */ -#define BME680_ENABLE_HEATER UINT8_C(0x00) -#define BME680_DISABLE_HEATER UINT8_C(0x08) - -/** Gas measurement settings */ -#define BME680_DISABLE_GAS_MEAS UINT8_C(0x00) -#define BME680_ENABLE_GAS_MEAS UINT8_C(0x01) - -/** Over-sampling settings */ -#define BME680_OS_NONE UINT8_C(0) -#define BME680_OS_1X UINT8_C(1) -#define BME680_OS_2X UINT8_C(2) -#define BME680_OS_4X UINT8_C(3) -#define BME680_OS_8X UINT8_C(4) -#define BME680_OS_16X UINT8_C(5) - -/** IIR filter settings */ -#define BME680_FILTER_SIZE_0 UINT8_C(0) -#define BME680_FILTER_SIZE_1 UINT8_C(1) -#define BME680_FILTER_SIZE_3 UINT8_C(2) -#define BME680_FILTER_SIZE_7 UINT8_C(3) -#define BME680_FILTER_SIZE_15 UINT8_C(4) -#define BME680_FILTER_SIZE_31 UINT8_C(5) -#define BME680_FILTER_SIZE_63 UINT8_C(6) -#define BME680_FILTER_SIZE_127 UINT8_C(7) - -/** Power mode settings */ -#define BME680_SLEEP_MODE UINT8_C(0) -#define BME680_FORCED_MODE UINT8_C(1) - -/** Delay related macro declaration */ -#define BME680_RESET_PERIOD UINT32_C(10) - -/** SPI memory page settings */ -#define BME680_MEM_PAGE0 UINT8_C(0x10) -#define BME680_MEM_PAGE1 UINT8_C(0x00) - -/** Ambient humidity shift value for compensation */ -#define BME680_HUM_REG_SHIFT_VAL UINT8_C(4) - -/** Run gas enable and disable settings */ -#define BME680_RUN_GAS_DISABLE UINT8_C(0) -#define BME680_RUN_GAS_ENABLE UINT8_C(1) - -/** Buffer length macro declaration */ -#define BME680_TMP_BUFFER_LENGTH UINT8_C(40) -#define BME680_REG_BUFFER_LENGTH UINT8_C(6) -#define BME680_FIELD_DATA_LENGTH UINT8_C(3) -#define BME680_GAS_REG_BUF_LENGTH UINT8_C(20) - -/** Settings selector */ -#define BME680_OST_SEL UINT16_C(1) -#define BME680_OSP_SEL UINT16_C(2) -#define BME680_OSH_SEL UINT16_C(4) -#define BME680_GAS_MEAS_SEL UINT16_C(8) -#define BME680_FILTER_SEL UINT16_C(16) -#define BME680_HCNTRL_SEL UINT16_C(32) -#define BME680_RUN_GAS_SEL UINT16_C(64) -#define BME680_NBCONV_SEL UINT16_C(128) -#define BME680_GAS_SENSOR_SEL (BME680_GAS_MEAS_SEL | BME680_RUN_GAS_SEL | BME680_NBCONV_SEL) - -/** Number of conversion settings*/ -#define BME680_NBCONV_MIN UINT8_C(0) -#define BME680_NBCONV_MAX UINT8_C(10) - -/** Mask definitions */ -#define BME680_GAS_MEAS_MSK UINT8_C(0x30) -#define BME680_NBCONV_MSK UINT8_C(0X0F) -#define BME680_FILTER_MSK UINT8_C(0X1C) -#define BME680_OST_MSK UINT8_C(0XE0) -#define BME680_OSP_MSK UINT8_C(0X1C) -#define BME680_OSH_MSK UINT8_C(0X07) -#define BME680_HCTRL_MSK UINT8_C(0x08) -#define BME680_RUN_GAS_MSK UINT8_C(0x10) -#define BME680_MODE_MSK UINT8_C(0x03) -#define BME680_RHRANGE_MSK UINT8_C(0x30) -#define BME680_RSERROR_MSK UINT8_C(0xf0) -#define BME680_NEW_DATA_MSK UINT8_C(0x80) -#define BME680_GAS_INDEX_MSK UINT8_C(0x0f) -#define BME680_GAS_RANGE_MSK UINT8_C(0x0f) -#define BME680_GASM_VALID_MSK UINT8_C(0x20) -#define BME680_HEAT_STAB_MSK UINT8_C(0x10) -#define BME680_MEM_PAGE_MSK UINT8_C(0x10) -#define BME680_SPI_RD_MSK UINT8_C(0x80) -#define BME680_SPI_WR_MSK UINT8_C(0x7f) -#define BME680_BIT_H1_DATA_MSK UINT8_C(0x0F) - -/** Bit position definitions for sensor settings */ -#define BME680_GAS_MEAS_POS UINT8_C(4) -#define BME680_FILTER_POS UINT8_C(2) -#define BME680_OST_POS UINT8_C(5) -#define BME680_OSP_POS UINT8_C(2) -#define BME680_RUN_GAS_POS UINT8_C(4) - -/** Array Index to Field data mapping for Calibration Data*/ -#define BME680_T2_LSB_REG (1) -#define BME680_T2_MSB_REG (2) -#define BME680_T3_REG (3) -#define BME680_P1_LSB_REG (5) -#define BME680_P1_MSB_REG (6) -#define BME680_P2_LSB_REG (7) -#define BME680_P2_MSB_REG (8) -#define BME680_P3_REG (9) -#define BME680_P4_LSB_REG (11) -#define BME680_P4_MSB_REG (12) -#define BME680_P5_LSB_REG (13) -#define BME680_P5_MSB_REG (14) -#define BME680_P7_REG (15) -#define BME680_P6_REG (16) -#define BME680_P8_LSB_REG (19) -#define BME680_P8_MSB_REG (20) -#define BME680_P9_LSB_REG (21) -#define BME680_P9_MSB_REG (22) -#define BME680_P10_REG (23) -#define BME680_H2_MSB_REG (25) -#define BME680_H2_LSB_REG (26) -#define BME680_H1_LSB_REG (26) -#define BME680_H1_MSB_REG (27) -#define BME680_H3_REG (28) -#define BME680_H4_REG (29) -#define BME680_H5_REG (30) -#define BME680_H6_REG (31) -#define BME680_H7_REG (32) -#define BME680_T1_LSB_REG (33) -#define BME680_T1_MSB_REG (34) -#define BME680_GH2_LSB_REG (35) -#define BME680_GH2_MSB_REG (36) -#define BME680_GH1_REG (37) -#define BME680_GH3_REG (38) - -/** BME680 register buffer index settings*/ -#define BME680_REG_FILTER_INDEX UINT8_C(5) -#define BME680_REG_TEMP_INDEX UINT8_C(4) -#define BME680_REG_PRES_INDEX UINT8_C(4) -#define BME680_REG_HUM_INDEX UINT8_C(2) -#define BME680_REG_NBCONV_INDEX UINT8_C(1) -#define BME680_REG_RUN_GAS_INDEX UINT8_C(1) -#define BME680_REG_HCTRL_INDEX UINT8_C(0) - -/** BME680 pressure calculation macros */ -/*! This max value is used to provide precedence to multiplication or division - * in pressure compensation equation to achieve least loss of precision and - * avoiding overflows. - * i.e Comparing value, BME680_MAX_OVERFLOW_VAL = INT32_C(1 << 30) - */ -#define BME680_MAX_OVERFLOW_VAL INT32_C(0x40000000) - -/** Macro to combine two 8 bit data's to form a 16 bit data */ -#define BME680_CONCAT_BYTES(msb, lsb) (((uint16_t)msb << 8) | (uint16_t)lsb) - -/** Macro to SET and GET BITS of a register */ -#define BME680_SET_BITS(reg_data, bitname, data) \ - ((reg_data & ~(bitname##_MSK)) | \ - ((data << bitname##_POS) & bitname##_MSK)) -#define BME680_GET_BITS(reg_data, bitname) ((reg_data & (bitname##_MSK)) >> \ - (bitname##_POS)) - -/** Macro variant to handle the bitname position if it is zero */ -#define BME680_SET_BITS_POS_0(reg_data, bitname, data) \ - ((reg_data & ~(bitname##_MSK)) | \ - (data & bitname##_MSK)) -#define BME680_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK)) - -/** Type definitions */ -/*! - * Generic communication function pointer - * @param[in] dev_id: Place holder to store the id of the device structure - * Can be used to store the index of the Chip select or - * I2C address of the device. - * @param[in] reg_addr: Used to select the register the where data needs to - * be read from or written to. - * @param[in/out] reg_data: Data array to read/write - * @param[in] len: Length of the data array - */ -typedef int8_t (*bme680_com_fptr_t)(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len); - -/*! - * Delay function pointer - * @param[in] period: Time period in milliseconds - */ -typedef void (*bme680_delay_fptr_t)(uint32_t period); - -/*! - * @brief Interface selection Enumerations - */ -enum bme680_intf { - /*! SPI interface */ - BME680_SPI_INTF, - /*! I2C interface */ - BME680_I2C_INTF -}; - -/* structure definitions */ -/*! - * @brief Sensor field data structure - */ -struct bme680_field_data { - /*! Contains new_data, gasm_valid & heat_stab */ - uint8_t status; - /*! The index of the heater profile used */ - uint8_t gas_index; - /*! Measurement index to track order */ - uint8_t meas_index; - -#ifndef BME680_FLOAT_POINT_COMPENSATION - /*! Temperature in degree celsius x100 */ - int16_t temperature; - /*! Pressure in Pascal */ - uint32_t pressure; - /*! Humidity in % relative humidity x1000 */ - uint32_t humidity; - /*! Gas resistance in Ohms */ - uint32_t gas_resistance; -#else - /*! Temperature in degree celsius */ - float temperature; - /*! Pressure in Pascal */ - float pressure; - /*! Humidity in % relative humidity x1000 */ - float humidity; - /*! Gas resistance in Ohms */ - float gas_resistance; - -#endif - -}; - -/*! - * @brief Structure to hold the Calibration data - */ -struct bme680_calib_data { - /*! Variable to store calibrated humidity data */ - uint16_t par_h1; - /*! Variable to store calibrated humidity data */ - uint16_t par_h2; - /*! Variable to store calibrated humidity data */ - int8_t par_h3; - /*! Variable to store calibrated humidity data */ - int8_t par_h4; - /*! Variable to store calibrated humidity data */ - int8_t par_h5; - /*! Variable to store calibrated humidity data */ - uint8_t par_h6; - /*! Variable to store calibrated humidity data */ - int8_t par_h7; - /*! Variable to store calibrated gas data */ - int8_t par_gh1; - /*! Variable to store calibrated gas data */ - int16_t par_gh2; - /*! Variable to store calibrated gas data */ - int8_t par_gh3; - /*! Variable to store calibrated temperature data */ - uint16_t par_t1; - /*! Variable to store calibrated temperature data */ - int16_t par_t2; - /*! Variable to store calibrated temperature data */ - int8_t par_t3; - /*! Variable to store calibrated pressure data */ - uint16_t par_p1; - /*! Variable to store calibrated pressure data */ - int16_t par_p2; - /*! Variable to store calibrated pressure data */ - int8_t par_p3; - /*! Variable to store calibrated pressure data */ - int16_t par_p4; - /*! Variable to store calibrated pressure data */ - int16_t par_p5; - /*! Variable to store calibrated pressure data */ - int8_t par_p6; - /*! Variable to store calibrated pressure data */ - int8_t par_p7; - /*! Variable to store calibrated pressure data */ - int16_t par_p8; - /*! Variable to store calibrated pressure data */ - int16_t par_p9; - /*! Variable to store calibrated pressure data */ - uint8_t par_p10; - -#ifndef BME680_FLOAT_POINT_COMPENSATION - /*! Variable to store t_fine size */ - int32_t t_fine; -#else - /*! Variable to store t_fine size */ - float t_fine; -#endif - /*! Variable to store heater resistance range */ - uint8_t res_heat_range; - /*! Variable to store heater resistance value */ - int8_t res_heat_val; - /*! Variable to store error range */ - int8_t range_sw_err; -}; - -/*! - * @brief BME680 sensor settings structure which comprises of ODR, - * over-sampling and filter settings. - */ -struct bme680_tph_sett { - /*! Humidity oversampling */ - uint8_t os_hum; - /*! Temperature oversampling */ - uint8_t os_temp; - /*! Pressure oversampling */ - uint8_t os_pres; - /*! Filter coefficient */ - uint8_t filter; -}; - -/*! - * @brief BME680 gas sensor which comprises of gas settings - * and status parameters - */ -struct bme680_gas_sett { - /*! Variable to store nb conversion */ - uint8_t nb_conv; - /*! Variable to store heater control */ - uint8_t heatr_ctrl; - /*! Run gas enable value */ - uint8_t run_gas; - /*! Heater temperature value */ - uint16_t heatr_temp; - /*! Duration profile value */ - uint16_t heatr_dur; -}; - -/*! - * @brief BME680 device structure - */ -struct bme680_dev { - /*! Chip Id */ - uint8_t chip_id; - /*! Device Id */ - uint8_t dev_id; - /*! SPI/I2C interface */ - enum bme680_intf intf; - /*! Memory page used */ - uint8_t mem_page; - /*! Ambient temperature in Degree C */ - int8_t amb_temp; - /*! Sensor calibration data */ - struct bme680_calib_data calib; - /*! Sensor settings */ - struct bme680_tph_sett tph_sett; - /*! Gas Sensor settings */ - struct bme680_gas_sett gas_sett; - /*! Sensor power modes */ - uint8_t power_mode; - /*! New sensor fields */ - uint8_t new_fields; - /*! Store the info messages */ - uint8_t info_msg; - /*! Bus read function pointer */ - bme680_com_fptr_t read; - /*! Bus write function pointer */ - bme680_com_fptr_t write; - /*! delay function pointer */ - bme680_delay_fptr_t delay_ms; - /*! Communication function result */ - int8_t com_rslt; -}; - - - -#endif /* BME680_DEFS_H_ */ -/** @}*/ -/** @}*/ diff --git a/lib/lib_i2c/BME68x-Sensor-API/LICENSE b/lib/lib_i2c/BME68x-Sensor-API/LICENSE new file mode 100644 index 000000000..39d644246 --- /dev/null +++ b/lib/lib_i2c/BME68x-Sensor-API/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + +BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/lib/lib_i2c/BME68x-Sensor-API/README.md b/lib/lib_i2c/BME68x-Sensor-API/README.md new file mode 100644 index 000000000..77f94ffec --- /dev/null +++ b/lib/lib_i2c/BME68x-Sensor-API/README.md @@ -0,0 +1,30 @@ +# BME68X Sensor API + +> Bosch Sensortec's BME680 and BME688 sensor API + +## Sensor Overview +BME680 is an integrated environmental sensor developed specifically for mobile applications and wearables where size and low power consumption are key requirements. Expanding Bosch Sensortec’s existing family of environmental sensors, the BME680 integrates for the first time high-linearity and high-accuracy gas, pressure, humidity and temperature sensors. It consists of an 8-pin metal-lid 3.0 x 3.0 x 0.93 mm³ LGA package which is designed for optimized consumption depending on the specific operating mode, long term stability and high EMC robustness. The gas sensor within the BME680 can detect a broad range of gases to measure air quality for personal well being. Gases that can be detected by the BME680 include Volatile Organic Compounds (VOC) from paints (such as formaldehyde), lacquers, paint strippers, cleaning supplies, furnishings, office equipment, glues, adhesives and alcohol. + +### Features + +- Air quality measurement +- Personalized weather station +- Context awareness, e.g. skin moisture detection, room change detection +- Fitness monitoring / well-being +- Warning regarding dryness or high temperatures +- Measurement of volume and air flow +- Home automation control (e.g. HVAC) +- GPS enhancement (e.g. time-to-first-fix improvement, dead reckoning, slope detection) +- Indoor navigation (change of floor detection, elevator detection) +- Altitude tracking and calories expenditure for sports activities + +#### Important links: +For more information, please refer to: + +- [BME680 Product page](https://www.bosch-sensortec.com/bst/products/all_products/bme680) +- [BME680 & BME688 Github page](https://github.com/BoschSensortec/BME68x-Sensor-API) +- [BME680 gas sensor design guide](https://community.bosch-sensortec.com/t5/Knowledge-base/BME680-gas-sensor-series-design-guide/ta-p/5952) +- [Knowledge base page](https://community.bosch-sensortec.com/t5/Knowledge-base/tkb-p/bst_community-mems-tkb) +- [Community support page](https://community.bosch-sensortec.com) + +--- \ No newline at end of file diff --git a/lib/lib_i2c/BME68x-Sensor-API/bme68x.c b/lib/lib_i2c/BME68x-Sensor-API/bme68x.c new file mode 100644 index 000000000..7c3c9356b --- /dev/null +++ b/lib/lib_i2c/BME68x-Sensor-API/bme68x.c @@ -0,0 +1,1848 @@ +/** +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bme68x.c +* @date 2021-11-09 +* @version v4.4.7 +* +*/ + +#include "bme68x.h" +#include + +/* This internal API is used to read the calibration coefficients */ +static int8_t get_calib_data(struct bme68x_dev *dev); + +/* This internal API is used to read variant ID information register status */ +static int8_t read_variant_id(struct bme68x_dev *dev); + +/* This internal API is used to calculate the gas wait */ +static uint8_t calc_gas_wait(uint16_t dur); + +#ifndef BME68X_USE_FPU + +/* This internal API is used to calculate the temperature in integer */ +static int16_t calc_temperature(uint32_t temp_adc, struct bme68x_dev *dev); + +/* This internal API is used to calculate the pressure in integer */ +static uint32_t calc_pressure(uint32_t pres_adc, const struct bme68x_dev *dev); + +/* This internal API is used to calculate the humidity in integer */ +static uint32_t calc_humidity(uint16_t hum_adc, const struct bme68x_dev *dev); + +/* This internal API is used to calculate the gas resistance high */ +static uint32_t calc_gas_resistance_high(uint16_t gas_res_adc, uint8_t gas_range); + +/* This internal API is used to calculate the gas resistance low */ +static uint32_t calc_gas_resistance_low(uint16_t gas_res_adc, uint8_t gas_range, const struct bme68x_dev *dev); + +/* This internal API is used to calculate the heater resistance using integer */ +static uint8_t calc_res_heat(uint16_t temp, const struct bme68x_dev *dev); + +#else + +/* This internal API is used to calculate the temperature value in float */ +static float calc_temperature(uint32_t temp_adc, struct bme68x_dev *dev); + +/* This internal API is used to calculate the pressure value in float */ +static float calc_pressure(uint32_t pres_adc, const struct bme68x_dev *dev); + +/* This internal API is used to calculate the humidity value in float */ +static float calc_humidity(uint16_t hum_adc, const struct bme68x_dev *dev); + +/* This internal API is used to calculate the gas resistance high value in float */ +static float calc_gas_resistance_high(uint16_t gas_res_adc, uint8_t gas_range); + +/* This internal API is used to calculate the gas resistance low value in float */ +static float calc_gas_resistance_low(uint16_t gas_res_adc, uint8_t gas_range, const struct bme68x_dev *dev); + +/* This internal API is used to calculate the heater resistance value using float */ +static uint8_t calc_res_heat(uint16_t temp, const struct bme68x_dev *dev); + +#endif + +/* This internal API is used to read a single data of the sensor */ +static int8_t read_field_data(uint8_t index, struct bme68x_data *data, struct bme68x_dev *dev); + +/* This internal API is used to read all data fields of the sensor */ +static int8_t read_all_field_data(struct bme68x_data * const data[], struct bme68x_dev *dev); + +/* This internal API is used to switch between SPI memory pages */ +static int8_t set_mem_page(uint8_t reg_addr, struct bme68x_dev *dev); + +/* This internal API is used to get the current SPI memory page */ +static int8_t get_mem_page(struct bme68x_dev *dev); + +/* This internal API is used to check the bme68x_dev for null pointers */ +static int8_t null_ptr_check(const struct bme68x_dev *dev); + +/* This internal API is used to set heater configurations */ +static int8_t set_conf(const struct bme68x_heatr_conf *conf, uint8_t op_mode, uint8_t *nb_conv, struct bme68x_dev *dev); + +/* This internal API is used to limit the max value of a parameter */ +static int8_t boundary_check(uint8_t *value, uint8_t max, struct bme68x_dev *dev); + +/* This internal API is used to calculate the register value for + * shared heater duration */ +static uint8_t calc_heatr_dur_shared(uint16_t dur); + +/* This internal API is used to swap two fields */ +static void swap_fields(uint8_t index1, uint8_t index2, struct bme68x_data *field[]); + +/* This internal API is used sort the sensor data */ +static void sort_sensor_data(uint8_t low_index, uint8_t high_index, struct bme68x_data *field[]); + +/* + * @brief Function to analyze the sensor data + * + * @param[in] data Array of measurement data + * @param[in] n_meas Number of measurements + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t analyze_sensor_data(const struct bme68x_data *data, uint8_t n_meas); + +/******************************************************************************************/ +/* Global API definitions */ +/******************************************************************************************/ + +/* @brief This API reads the chip-id of the sensor which is the first step to +* verify the sensor and also calibrates the sensor +* As this API is the entry point, call this API before using other APIs. +*/ +int8_t bme68x_init(struct bme68x_dev *dev) +{ + int8_t rslt; + + rslt = bme68x_soft_reset(dev); + if (rslt == BME68X_OK) + { + rslt = bme68x_get_regs(BME68X_REG_CHIP_ID, &dev->chip_id, 1, dev); + if (rslt == BME68X_OK) + { + if (dev->chip_id == BME68X_CHIP_ID) + { + /* Read Variant ID */ + rslt = read_variant_id(dev); + + if (rslt == BME68X_OK) + { + /* Get the Calibration data */ + rslt = get_calib_data(dev); + } + } + else + { + rslt = BME68X_E_DEV_NOT_FOUND; + } + } + } + + return rslt; +} + +/* + * @brief This API writes the given data to the register address of the sensor + */ +int8_t bme68x_set_regs(const uint8_t *reg_addr, const uint8_t *reg_data, uint32_t len, struct bme68x_dev *dev) +{ + int8_t rslt; + + /* Length of the temporary buffer is 2*(length of register)*/ + uint8_t tmp_buff[BME68X_LEN_INTERLEAVE_BUFF] = { 0 }; + uint16_t index; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if ((rslt == BME68X_OK) && reg_addr && reg_data) + { + if ((len > 0) && (len <= (BME68X_LEN_INTERLEAVE_BUFF / 2))) + { + /* Interleave the 2 arrays */ + for (index = 0; index < len; index++) + { + if (dev->intf == BME68X_SPI_INTF) + { + /* Set the memory page */ + rslt = set_mem_page(reg_addr[index], dev); + tmp_buff[(2 * index)] = reg_addr[index] & BME68X_SPI_WR_MSK; + } + else + { + tmp_buff[(2 * index)] = reg_addr[index]; + } + + tmp_buff[(2 * index) + 1] = reg_data[index]; + } + + /* Write the interleaved array */ + if (rslt == BME68X_OK) + { + dev->intf_rslt = dev->write(tmp_buff[0], &tmp_buff[1], (2 * len) - 1, dev->intf_ptr); + if (dev->intf_rslt != 0) + { + rslt = BME68X_E_COM_FAIL; + } + } + } + else + { + rslt = BME68X_E_INVALID_LENGTH; + } + } + else + { + rslt = BME68X_E_NULL_PTR; + } + + return rslt; +} + +/* + * @brief This API reads the data from the given register address of sensor. + */ +int8_t bme68x_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bme68x_dev *dev) +{ + int8_t rslt; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if ((rslt == BME68X_OK) && reg_data) + { + if (dev->intf == BME68X_SPI_INTF) + { + /* Set the memory page */ + rslt = set_mem_page(reg_addr, dev); + if (rslt == BME68X_OK) + { + reg_addr = reg_addr | BME68X_SPI_RD_MSK; + } + } + + dev->intf_rslt = dev->read(reg_addr, reg_data, len, dev->intf_ptr); + if (dev->intf_rslt != 0) + { + rslt = BME68X_E_COM_FAIL; + } + } + else + { + rslt = BME68X_E_NULL_PTR; + } + + return rslt; +} + +/* + * @brief This API soft-resets the sensor. + */ +int8_t bme68x_soft_reset(struct bme68x_dev *dev) +{ + int8_t rslt; + uint8_t reg_addr = BME68X_REG_SOFT_RESET; + + /* 0xb6 is the soft reset command */ + uint8_t soft_rst_cmd = BME68X_SOFT_RESET_CMD; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME68X_OK) + { + if (dev->intf == BME68X_SPI_INTF) + { + rslt = get_mem_page(dev); + } + + /* Reset the device */ + if (rslt == BME68X_OK) + { + rslt = bme68x_set_regs(®_addr, &soft_rst_cmd, 1, dev); + + /* Wait for 5ms */ + dev->delay_us(BME68X_PERIOD_RESET, dev->intf_ptr); + if (rslt == BME68X_OK) + { + /* After reset get the memory page */ + if (dev->intf == BME68X_SPI_INTF) + { + rslt = get_mem_page(dev); + } + } + } + } + + return rslt; +} + +/* + * @brief This API is used to set the oversampling, filter and odr configuration + */ +int8_t bme68x_set_conf(struct bme68x_conf *conf, struct bme68x_dev *dev) +{ + int8_t rslt; + uint8_t odr20 = 0, odr3 = 1; + uint8_t current_op_mode; + + /* Register data starting from BME68X_REG_CTRL_GAS_1(0x71) up to BME68X_REG_CONFIG(0x75) */ + uint8_t reg_array[BME68X_LEN_CONFIG] = { 0x71, 0x72, 0x73, 0x74, 0x75 }; + uint8_t data_array[BME68X_LEN_CONFIG] = { 0 }; + + rslt = bme68x_get_op_mode(¤t_op_mode, dev); + if (rslt == BME68X_OK) + { + /* Configure only in the sleep mode */ + rslt = bme68x_set_op_mode(BME68X_SLEEP_MODE, dev); + } + + if (conf == NULL) + { + rslt = BME68X_E_NULL_PTR; + } + else if (rslt == BME68X_OK) + { + /* Read the whole configuration and write it back once later */ + rslt = bme68x_get_regs(reg_array[0], data_array, BME68X_LEN_CONFIG, dev); + dev->info_msg = BME68X_OK; + if (rslt == BME68X_OK) + { + rslt = boundary_check(&conf->filter, BME68X_FILTER_SIZE_127, dev); + } + + if (rslt == BME68X_OK) + { + rslt = boundary_check(&conf->os_temp, BME68X_OS_16X, dev); + } + + if (rslt == BME68X_OK) + { + rslt = boundary_check(&conf->os_pres, BME68X_OS_16X, dev); + } + + if (rslt == BME68X_OK) + { + rslt = boundary_check(&conf->os_hum, BME68X_OS_16X, dev); + } + + if (rslt == BME68X_OK) + { + rslt = boundary_check(&conf->odr, BME68X_ODR_NONE, dev); + } + + if (rslt == BME68X_OK) + { + data_array[4] = BME68X_SET_BITS(data_array[4], BME68X_FILTER, conf->filter); + data_array[3] = BME68X_SET_BITS(data_array[3], BME68X_OST, conf->os_temp); + data_array[3] = BME68X_SET_BITS(data_array[3], BME68X_OSP, conf->os_pres); + data_array[1] = BME68X_SET_BITS_POS_0(data_array[1], BME68X_OSH, conf->os_hum); + if (conf->odr != BME68X_ODR_NONE) + { + odr20 = conf->odr; + odr3 = 0; + } + + data_array[4] = BME68X_SET_BITS(data_array[4], BME68X_ODR20, odr20); + data_array[0] = BME68X_SET_BITS(data_array[0], BME68X_ODR3, odr3); + } + } + + if (rslt == BME68X_OK) + { + rslt = bme68x_set_regs(reg_array, data_array, BME68X_LEN_CONFIG, dev); + } + + if ((current_op_mode != BME68X_SLEEP_MODE) && (rslt == BME68X_OK)) + { + rslt = bme68x_set_op_mode(current_op_mode, dev); + } + + return rslt; +} + +/* + * @brief This API is used to get the oversampling, filter and odr + */ +int8_t bme68x_get_conf(struct bme68x_conf *conf, struct bme68x_dev *dev) +{ + int8_t rslt; + + /* starting address of the register array for burst read*/ + uint8_t reg_addr = BME68X_REG_CTRL_GAS_1; + uint8_t data_array[BME68X_LEN_CONFIG]; + + rslt = bme68x_get_regs(reg_addr, data_array, 5, dev); + if (!conf) + { + rslt = BME68X_E_NULL_PTR; + } + else if (rslt == BME68X_OK) + { + conf->os_hum = BME68X_GET_BITS_POS_0(data_array[1], BME68X_OSH); + conf->filter = BME68X_GET_BITS(data_array[4], BME68X_FILTER); + conf->os_temp = BME68X_GET_BITS(data_array[3], BME68X_OST); + conf->os_pres = BME68X_GET_BITS(data_array[3], BME68X_OSP); + if (BME68X_GET_BITS(data_array[0], BME68X_ODR3)) + { + conf->odr = BME68X_ODR_NONE; + } + else + { + conf->odr = BME68X_GET_BITS(data_array[4], BME68X_ODR20); + } + } + + return rslt; +} + +/* + * @brief This API is used to set the operation mode of the sensor + */ +int8_t bme68x_set_op_mode(const uint8_t op_mode, struct bme68x_dev *dev) +{ + int8_t rslt; + uint8_t tmp_pow_mode; + uint8_t pow_mode = 0; + uint8_t reg_addr = BME68X_REG_CTRL_MEAS; + + /* Call until in sleep */ + do + { + rslt = bme68x_get_regs(BME68X_REG_CTRL_MEAS, &tmp_pow_mode, 1, dev); + if (rslt == BME68X_OK) + { + /* Put to sleep before changing mode */ + pow_mode = (tmp_pow_mode & BME68X_MODE_MSK); + if (pow_mode != BME68X_SLEEP_MODE) + { + tmp_pow_mode &= ~BME68X_MODE_MSK; /* Set to sleep */ + rslt = bme68x_set_regs(®_addr, &tmp_pow_mode, 1, dev); + dev->delay_us(BME68X_PERIOD_POLL, dev->intf_ptr); + } + } + } while ((pow_mode != BME68X_SLEEP_MODE) && (rslt == BME68X_OK)); + + /* Already in sleep */ + if ((op_mode != BME68X_SLEEP_MODE) && (rslt == BME68X_OK)) + { + tmp_pow_mode = (tmp_pow_mode & ~BME68X_MODE_MSK) | (op_mode & BME68X_MODE_MSK); + rslt = bme68x_set_regs(®_addr, &tmp_pow_mode, 1, dev); + } + + return rslt; +} + +/* + * @brief This API is used to get the operation mode of the sensor. + */ +int8_t bme68x_get_op_mode(uint8_t *op_mode, struct bme68x_dev *dev) +{ + int8_t rslt; + uint8_t mode; + + if (op_mode) + { + rslt = bme68x_get_regs(BME68X_REG_CTRL_MEAS, &mode, 1, dev); + + /* Masking the other register bit info*/ + *op_mode = mode & BME68X_MODE_MSK; + } + else + { + rslt = BME68X_E_NULL_PTR; + } + + return rslt; +} + +/* + * @brief This API is used to get the remaining duration that can be used for heating. + */ +uint32_t bme68x_get_meas_dur(const uint8_t op_mode, struct bme68x_conf *conf, struct bme68x_dev *dev) +{ + int8_t rslt; + uint32_t meas_dur = 0; /* Calculate in us */ + uint32_t meas_cycles; + uint8_t os_to_meas_cycles[6] = { 0, 1, 2, 4, 8, 16 }; + + if (conf != NULL) + { + /* Boundary check for temperature oversampling */ + rslt = boundary_check(&conf->os_temp, BME68X_OS_16X, dev); + + if (rslt == BME68X_OK) + { + /* Boundary check for pressure oversampling */ + rslt = boundary_check(&conf->os_pres, BME68X_OS_16X, dev); + } + + if (rslt == BME68X_OK) + { + /* Boundary check for humidity oversampling */ + rslt = boundary_check(&conf->os_hum, BME68X_OS_16X, dev); + } + + if (rslt == BME68X_OK) + { + meas_cycles = os_to_meas_cycles[conf->os_temp]; + meas_cycles += os_to_meas_cycles[conf->os_pres]; + meas_cycles += os_to_meas_cycles[conf->os_hum]; + + /* TPH measurement duration */ + meas_dur = meas_cycles * UINT32_C(1963); + meas_dur += UINT32_C(477 * 4); /* TPH switching duration */ + meas_dur += UINT32_C(477 * 5); /* Gas measurement duration */ + + if (op_mode != BME68X_PARALLEL_MODE) + { + meas_dur += UINT32_C(1000); /* Wake up duration of 1ms */ + } + } + } + + return meas_dur; +} + +/* + * @brief This API reads the pressure, temperature and humidity and gas data + * from the sensor, compensates the data and store it in the bme68x_data + * structure instance passed by the user. + */ +int8_t bme68x_get_data(uint8_t op_mode, struct bme68x_data *data, uint8_t *n_data, struct bme68x_dev *dev) +{ + int8_t rslt; + uint8_t i = 0, j = 0, new_fields = 0; + struct bme68x_data *field_ptr[3] = { 0 }; + struct bme68x_data field_data[3] = { { 0 } }; + + field_ptr[0] = &field_data[0]; + field_ptr[1] = &field_data[1]; + field_ptr[2] = &field_data[2]; + + rslt = null_ptr_check(dev); + if ((rslt == BME68X_OK) && (data != NULL)) + { + /* Reading the sensor data in forced mode only */ + if (op_mode == BME68X_FORCED_MODE) + { + rslt = read_field_data(0, data, dev); + if (rslt == BME68X_OK) + { + if (data->status & BME68X_NEW_DATA_MSK) + { + new_fields = 1; + } + else + { + new_fields = 0; + rslt = BME68X_W_NO_NEW_DATA; + } + } + } + else if ((op_mode == BME68X_PARALLEL_MODE) || (op_mode == BME68X_SEQUENTIAL_MODE)) + { + /* Read the 3 fields and count the number of new data fields */ + rslt = read_all_field_data(field_ptr, dev); + + new_fields = 0; + for (i = 0; (i < 3) && (rslt == BME68X_OK); i++) + { + if (field_ptr[i]->status & BME68X_NEW_DATA_MSK) + { + new_fields++; + } + } + + /* Sort the sensor data in parallel & sequential modes*/ + for (i = 0; (i < 2) && (rslt == BME68X_OK); i++) + { + for (j = i + 1; j < 3; j++) + { + sort_sensor_data(i, j, field_ptr); + } + } + + /* Copy the sorted data */ + for (i = 0; ((i < 3) && (rslt == BME68X_OK)); i++) + { + data[i] = *field_ptr[i]; + } + + if (new_fields == 0) + { + rslt = BME68X_W_NO_NEW_DATA; + } + } + else + { + rslt = BME68X_W_DEFINE_OP_MODE; + } + + if (n_data == NULL) + { + rslt = BME68X_E_NULL_PTR; + } + else + { + *n_data = new_fields; + } + } + else + { + rslt = BME68X_E_NULL_PTR; + } + + return rslt; +} + +/* + * @brief This API is used to set the gas configuration of the sensor. + */ +int8_t bme68x_set_heatr_conf(uint8_t op_mode, const struct bme68x_heatr_conf *conf, struct bme68x_dev *dev) +{ + int8_t rslt; + uint8_t nb_conv = 0; + uint8_t hctrl, run_gas = 0; + uint8_t ctrl_gas_data[2]; + uint8_t ctrl_gas_addr[2] = { BME68X_REG_CTRL_GAS_0, BME68X_REG_CTRL_GAS_1 }; + + if (conf != NULL) + { + rslt = bme68x_set_op_mode(BME68X_SLEEP_MODE, dev); + if (rslt == BME68X_OK) + { + rslt = set_conf(conf, op_mode, &nb_conv, dev); + } + + if (rslt == BME68X_OK) + { + rslt = bme68x_get_regs(BME68X_REG_CTRL_GAS_0, ctrl_gas_data, 2, dev); + if (rslt == BME68X_OK) + { + if (conf->enable == BME68X_ENABLE) + { + hctrl = BME68X_ENABLE_HEATER; + if (dev->variant_id == BME68X_VARIANT_GAS_HIGH) + { + run_gas = BME68X_ENABLE_GAS_MEAS_H; + } + else + { + run_gas = BME68X_ENABLE_GAS_MEAS_L; + } + } + else + { + hctrl = BME68X_DISABLE_HEATER; + run_gas = BME68X_DISABLE_GAS_MEAS; + } + + ctrl_gas_data[0] = BME68X_SET_BITS(ctrl_gas_data[0], BME68X_HCTRL, hctrl); + ctrl_gas_data[1] = BME68X_SET_BITS_POS_0(ctrl_gas_data[1], BME68X_NBCONV, nb_conv); + ctrl_gas_data[1] = BME68X_SET_BITS(ctrl_gas_data[1], BME68X_RUN_GAS, run_gas); + rslt = bme68x_set_regs(ctrl_gas_addr, ctrl_gas_data, 2, dev); + } + } + } + else + { + rslt = BME68X_E_NULL_PTR; + } + + return rslt; +} + +/* + * @brief This API is used to get the gas configuration of the sensor. + */ +int8_t bme68x_get_heatr_conf(const struct bme68x_heatr_conf *conf, struct bme68x_dev *dev) +{ + int8_t rslt; + uint8_t data_array[10] = { 0 }; + uint8_t i; + + /* FIXME: Add conversion to deg C and ms and add the other parameters */ + rslt = bme68x_get_regs(BME68X_REG_RES_HEAT0, data_array, 10, dev); + if (rslt == BME68X_OK) + { + if (conf && conf->heatr_dur_prof && conf->heatr_temp_prof) + { + for (i = 0; i < 10; i++) + { + conf->heatr_temp_prof[i] = data_array[i]; + } + + rslt = bme68x_get_regs(BME68X_REG_GAS_WAIT0, data_array, 10, dev); + if (rslt == BME68X_OK) + { + for (i = 0; i < 10; i++) + { + conf->heatr_dur_prof[i] = data_array[i]; + } + } + } + else + { + rslt = BME68X_E_NULL_PTR; + } + } + + return rslt; +} + +/* + * @brief This API performs Self-test of low and high gas variants of BME68X + */ +int8_t bme68x_selftest_check(const struct bme68x_dev *dev) +{ + int8_t rslt; + uint8_t n_fields; + uint8_t i = 0; + struct bme68x_data data[BME68X_N_MEAS] = { { 0 } }; + struct bme68x_dev t_dev; + struct bme68x_conf conf; + struct bme68x_heatr_conf heatr_conf; + + /* Copy required parameters from reference bme68x_dev struct */ + t_dev.amb_temp = 25; + t_dev.read = dev->read; + t_dev.write = dev->write; + t_dev.intf = dev->intf; + t_dev.delay_us = dev->delay_us; + t_dev.intf_ptr = dev->intf_ptr; + rslt = bme68x_init(&t_dev); + if (rslt == BME68X_OK) + { + /* Set the temperature, pressure and humidity & filter settings */ + conf.os_hum = BME68X_OS_1X; + conf.os_pres = BME68X_OS_16X; + conf.os_temp = BME68X_OS_2X; + + /* Set the remaining gas sensor settings and link the heating profile */ + heatr_conf.enable = BME68X_ENABLE; + heatr_conf.heatr_dur = BME68X_HEATR_DUR1; + heatr_conf.heatr_temp = BME68X_HIGH_TEMP; + rslt = bme68x_set_heatr_conf(BME68X_FORCED_MODE, &heatr_conf, &t_dev); + if (rslt == BME68X_OK) + { + rslt = bme68x_set_conf(&conf, &t_dev); + if (rslt == BME68X_OK) + { + rslt = bme68x_set_op_mode(BME68X_FORCED_MODE, &t_dev); /* Trigger a measurement */ + if (rslt == BME68X_OK) + { + /* Wait for the measurement to complete */ + t_dev.delay_us(BME68X_HEATR_DUR1_DELAY, t_dev.intf_ptr); + rslt = bme68x_get_data(BME68X_FORCED_MODE, &data[0], &n_fields, &t_dev); + if (rslt == BME68X_OK) + { + if ((data[0].idac != 0x00) && (data[0].idac != 0xFF) && + (data[0].status & BME68X_GASM_VALID_MSK)) + { + rslt = BME68X_OK; + } + else + { + rslt = BME68X_E_SELF_TEST; + } + } + } + } + } + + heatr_conf.heatr_dur = BME68X_HEATR_DUR2; + while ((rslt == BME68X_OK) && (i < BME68X_N_MEAS)) + { + if (i % 2 == 0) + { + heatr_conf.heatr_temp = BME68X_HIGH_TEMP; /* Higher temperature */ + } + else + { + heatr_conf.heatr_temp = BME68X_LOW_TEMP; /* Lower temperature */ + } + + rslt = bme68x_set_heatr_conf(BME68X_FORCED_MODE, &heatr_conf, &t_dev); + if (rslt == BME68X_OK) + { + rslt = bme68x_set_conf(&conf, &t_dev); + if (rslt == BME68X_OK) + { + rslt = bme68x_set_op_mode(BME68X_FORCED_MODE, &t_dev); /* Trigger a measurement */ + if (rslt == BME68X_OK) + { + /* Wait for the measurement to complete */ + t_dev.delay_us(BME68X_HEATR_DUR2_DELAY, t_dev.intf_ptr); + rslt = bme68x_get_data(BME68X_FORCED_MODE, &data[i], &n_fields, &t_dev); + } + } + } + + i++; + } + + if (rslt == BME68X_OK) + { + rslt = analyze_sensor_data(data, BME68X_N_MEAS); + } + } + + return rslt; +} + +/*****************************INTERNAL APIs***********************************************/ +#ifndef BME68X_USE_FPU + +/* @brief This internal API is used to calculate the temperature value. */ +static int16_t calc_temperature(uint32_t temp_adc, struct bme68x_dev *dev) +{ + int64_t var1; + int64_t var2; + int64_t var3; + int16_t calc_temp; + + /*lint -save -e701 -e702 -e704 */ + var1 = ((int32_t)temp_adc >> 3) - ((int32_t)dev->calib.par_t1 << 1); + var2 = (var1 * (int32_t)dev->calib.par_t2) >> 11; + var3 = ((var1 >> 1) * (var1 >> 1)) >> 12; + var3 = ((var3) * ((int32_t)dev->calib.par_t3 << 4)) >> 14; + dev->calib.t_fine = (int32_t)(var2 + var3); + calc_temp = (int16_t)(((dev->calib.t_fine * 5) + 128) >> 8); + + /*lint -restore */ + return calc_temp; +} + +/* @brief This internal API is used to calculate the pressure value. */ +static uint32_t calc_pressure(uint32_t pres_adc, const struct bme68x_dev *dev) +{ + int32_t var1; + int32_t var2; + int32_t var3; + int32_t pressure_comp; + + /* This value is used to check precedence to multiplication or division + * in the pressure compensation equation to achieve least loss of precision and + * avoiding overflows. + * i.e Comparing value, pres_ovf_check = (1 << 31) >> 1 + */ + const int32_t pres_ovf_check = INT32_C(0x40000000); + + /*lint -save -e701 -e702 -e713 */ + var1 = (((int32_t)dev->calib.t_fine) >> 1) - 64000; + var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * (int32_t)dev->calib.par_p6) >> 2; + var2 = var2 + ((var1 * (int32_t)dev->calib.par_p5) << 1); + var2 = (var2 >> 2) + ((int32_t)dev->calib.par_p4 << 16); + var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) * ((int32_t)dev->calib.par_p3 << 5)) >> 3) + + (((int32_t)dev->calib.par_p2 * var1) >> 1); + var1 = var1 >> 18; + var1 = ((32768 + var1) * (int32_t)dev->calib.par_p1) >> 15; + pressure_comp = 1048576 - pres_adc; + pressure_comp = (int32_t)((pressure_comp - (var2 >> 12)) * ((uint32_t)3125)); + if (pressure_comp >= pres_ovf_check) + { + pressure_comp = ((pressure_comp / var1) << 1); + } + else + { + pressure_comp = ((pressure_comp << 1) / var1); + } + + var1 = ((int32_t)dev->calib.par_p9 * (int32_t)(((pressure_comp >> 3) * (pressure_comp >> 3)) >> 13)) >> 12; + var2 = ((int32_t)(pressure_comp >> 2) * (int32_t)dev->calib.par_p8) >> 13; + var3 = + ((int32_t)(pressure_comp >> 8) * (int32_t)(pressure_comp >> 8) * (int32_t)(pressure_comp >> 8) * + (int32_t)dev->calib.par_p10) >> 17; + pressure_comp = (int32_t)(pressure_comp) + ((var1 + var2 + var3 + ((int32_t)dev->calib.par_p7 << 7)) >> 4); + + /*lint -restore */ + return (uint32_t)pressure_comp; +} + +/* This internal API is used to calculate the humidity in integer */ +static uint32_t calc_humidity(uint16_t hum_adc, const struct bme68x_dev *dev) +{ + int32_t var1; + int32_t var2; + int32_t var3; + int32_t var4; + int32_t var5; + int32_t var6; + int32_t temp_scaled; + int32_t calc_hum; + + /*lint -save -e702 -e704 */ + temp_scaled = (((int32_t)dev->calib.t_fine * 5) + 128) >> 8; + var1 = (int32_t)(hum_adc - ((int32_t)((int32_t)dev->calib.par_h1 * 16))) - + (((temp_scaled * (int32_t)dev->calib.par_h3) / ((int32_t)100)) >> 1); + var2 = + ((int32_t)dev->calib.par_h2 * + (((temp_scaled * (int32_t)dev->calib.par_h4) / ((int32_t)100)) + + (((temp_scaled * ((temp_scaled * (int32_t)dev->calib.par_h5) / ((int32_t)100))) >> 6) / ((int32_t)100)) + + (int32_t)(1 << 14))) >> 10; + var3 = var1 * var2; + var4 = (int32_t)dev->calib.par_h6 << 7; + var4 = ((var4) + ((temp_scaled * (int32_t)dev->calib.par_h7) / ((int32_t)100))) >> 4; + var5 = ((var3 >> 14) * (var3 >> 14)) >> 10; + var6 = (var4 * var5) >> 1; + calc_hum = (((var3 + var6) >> 10) * ((int32_t)1000)) >> 12; + if (calc_hum > 100000) /* Cap at 100%rH */ + { + calc_hum = 100000; + } + else if (calc_hum < 0) + { + calc_hum = 0; + } + + /*lint -restore */ + return (uint32_t)calc_hum; +} + +/* This internal API is used to calculate the gas resistance low */ +static uint32_t calc_gas_resistance_low(uint16_t gas_res_adc, uint8_t gas_range, const struct bme68x_dev *dev) +{ + int64_t var1; + uint64_t var2; + int64_t var3; + uint32_t calc_gas_res; + uint32_t lookup_table1[16] = { + UINT32_C(2147483647), UINT32_C(2147483647), UINT32_C(2147483647), UINT32_C(2147483647), UINT32_C(2147483647), + UINT32_C(2126008810), UINT32_C(2147483647), UINT32_C(2130303777), UINT32_C(2147483647), UINT32_C(2147483647), + UINT32_C(2143188679), UINT32_C(2136746228), UINT32_C(2147483647), UINT32_C(2126008810), UINT32_C(2147483647), + UINT32_C(2147483647) + }; + uint32_t lookup_table2[16] = { + UINT32_C(4096000000), UINT32_C(2048000000), UINT32_C(1024000000), UINT32_C(512000000), UINT32_C(255744255), + UINT32_C(127110228), UINT32_C(64000000), UINT32_C(32258064), UINT32_C(16016016), UINT32_C(8000000), UINT32_C( + 4000000), UINT32_C(2000000), UINT32_C(1000000), UINT32_C(500000), UINT32_C(250000), UINT32_C(125000) + }; + + /*lint -save -e704 */ + var1 = (int64_t)((1340 + (5 * (int64_t)dev->calib.range_sw_err)) * ((int64_t)lookup_table1[gas_range])) >> 16; + var2 = (((int64_t)((int64_t)gas_res_adc << 15) - (int64_t)(16777216)) + var1); + var3 = (((int64_t)lookup_table2[gas_range] * (int64_t)var1) >> 9); + calc_gas_res = (uint32_t)((var3 + ((int64_t)var2 >> 1)) / (int64_t)var2); + + /*lint -restore */ + return calc_gas_res; +} + +/* This internal API is used to calculate the gas resistance */ +static uint32_t calc_gas_resistance_high(uint16_t gas_res_adc, uint8_t gas_range) +{ + uint32_t calc_gas_res; + uint32_t var1 = UINT32_C(262144) >> gas_range; + int32_t var2 = (int32_t)gas_res_adc - INT32_C(512); + + var2 *= INT32_C(3); + var2 = INT32_C(4096) + var2; + + /* multiplying 10000 then dividing then multiplying by 100 instead of multiplying by 1000000 to prevent overflow */ + calc_gas_res = (UINT32_C(10000) * var1) / (uint32_t)var2; + calc_gas_res = calc_gas_res * 100; + + return calc_gas_res; +} + +/* This internal API is used to calculate the heater resistance value using float */ +static uint8_t calc_res_heat(uint16_t temp, const struct bme68x_dev *dev) +{ + uint8_t heatr_res; + int32_t var1; + int32_t var2; + int32_t var3; + int32_t var4; + int32_t var5; + int32_t heatr_res_x100; + + if (temp > 400) /* Cap temperature */ + { + temp = 400; + } + + var1 = (((int32_t)dev->amb_temp * dev->calib.par_gh3) / 1000) * 256; + var2 = (dev->calib.par_gh1 + 784) * (((((dev->calib.par_gh2 + 154009) * temp * 5) / 100) + 3276800) / 10); + var3 = var1 + (var2 / 2); + var4 = (var3 / (dev->calib.res_heat_range + 4)); + var5 = (131 * dev->calib.res_heat_val) + 65536; + heatr_res_x100 = (int32_t)(((var4 / var5) - 250) * 34); + heatr_res = (uint8_t)((heatr_res_x100 + 50) / 100); + + return heatr_res; +} + +#else + +/* @brief This internal API is used to calculate the temperature value. */ +static float calc_temperature(uint32_t temp_adc, struct bme68x_dev *dev) +{ + float var1; + float var2; + float calc_temp; + + /* calculate var1 data */ + var1 = ((((float)temp_adc / 16384.0f) - ((float)dev->calib.par_t1 / 1024.0f)) * ((float)dev->calib.par_t2)); + + /* calculate var2 data */ + var2 = + (((((float)temp_adc / 131072.0f) - ((float)dev->calib.par_t1 / 8192.0f)) * + (((float)temp_adc / 131072.0f) - ((float)dev->calib.par_t1 / 8192.0f))) * ((float)dev->calib.par_t3 * 16.0f)); + + /* t_fine value*/ + dev->calib.t_fine = (var1 + var2); + + /* compensated temperature data*/ + calc_temp = ((dev->calib.t_fine) / 5120.0f); + + return calc_temp; +} + +/* @brief This internal API is used to calculate the pressure value. */ +static float calc_pressure(uint32_t pres_adc, const struct bme68x_dev *dev) +{ + float var1; + float var2; + float var3; + float calc_pres; + + var1 = (((float)dev->calib.t_fine / 2.0f) - 64000.0f); + var2 = var1 * var1 * (((float)dev->calib.par_p6) / (131072.0f)); + var2 = var2 + (var1 * ((float)dev->calib.par_p5) * 2.0f); + var2 = (var2 / 4.0f) + (((float)dev->calib.par_p4) * 65536.0f); + var1 = (((((float)dev->calib.par_p3 * var1 * var1) / 16384.0f) + ((float)dev->calib.par_p2 * var1)) / 524288.0f); + var1 = ((1.0f + (var1 / 32768.0f)) * ((float)dev->calib.par_p1)); + calc_pres = (1048576.0f - ((float)pres_adc)); + + /* Avoid exception caused by division by zero */ + if ((int)var1 != 0) + { + calc_pres = (((calc_pres - (var2 / 4096.0f)) * 6250.0f) / var1); + var1 = (((float)dev->calib.par_p9) * calc_pres * calc_pres) / 2147483648.0f; + var2 = calc_pres * (((float)dev->calib.par_p8) / 32768.0f); + var3 = ((calc_pres / 256.0f) * (calc_pres / 256.0f) * (calc_pres / 256.0f) * (dev->calib.par_p10 / 131072.0f)); + calc_pres = (calc_pres + (var1 + var2 + var3 + ((float)dev->calib.par_p7 * 128.0f)) / 16.0f); + } + else + { + calc_pres = 0; + } + + return calc_pres; +} + +/* This internal API is used to calculate the humidity in integer */ +static float calc_humidity(uint16_t hum_adc, const struct bme68x_dev *dev) +{ + float calc_hum; + float var1; + float var2; + float var3; + float var4; + float temp_comp; + + /* compensated temperature data*/ + temp_comp = ((dev->calib.t_fine) / 5120.0f); + var1 = (float)((float)hum_adc) - + (((float)dev->calib.par_h1 * 16.0f) + (((float)dev->calib.par_h3 / 2.0f) * temp_comp)); + var2 = var1 * + ((float)(((float)dev->calib.par_h2 / 262144.0f) * + (1.0f + (((float)dev->calib.par_h4 / 16384.0f) * temp_comp) + + (((float)dev->calib.par_h5 / 1048576.0f) * temp_comp * temp_comp)))); + var3 = (float)dev->calib.par_h6 / 16384.0f; + var4 = (float)dev->calib.par_h7 / 2097152.0f; + calc_hum = var2 + ((var3 + (var4 * temp_comp)) * var2 * var2); + if (calc_hum > 100.0f) + { + calc_hum = 100.0f; + } + else if (calc_hum < 0.0f) + { + calc_hum = 0.0f; + } + + return calc_hum; +} + +/* This internal API is used to calculate the gas resistance low value in float */ +static float calc_gas_resistance_low(uint16_t gas_res_adc, uint8_t gas_range, const struct bme68x_dev *dev) +{ + float calc_gas_res; + float var1; + float var2; + float var3; + float gas_res_f = gas_res_adc; + float gas_range_f = (1U << gas_range); /*lint !e790 / Suspicious truncation, integral to float */ + const float lookup_k1_range[16] = { + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, -0.8f, 0.0f, 0.0f, -0.2f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f + }; + const float lookup_k2_range[16] = { + 0.0f, 0.0f, 0.0f, 0.0f, 0.1f, 0.7f, 0.0f, -0.8f, -0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f + }; + + var1 = (1340.0f + (5.0f * dev->calib.range_sw_err)); + var2 = (var1) * (1.0f + lookup_k1_range[gas_range] / 100.0f); + var3 = 1.0f + (lookup_k2_range[gas_range] / 100.0f); + calc_gas_res = 1.0f / (float)(var3 * (0.000000125f) * gas_range_f * (((gas_res_f - 512.0f) / var2) + 1.0f)); + + return calc_gas_res; +} + +/* This internal API is used to calculate the gas resistance value in float */ +static float calc_gas_resistance_high(uint16_t gas_res_adc, uint8_t gas_range) +{ + float calc_gas_res; + uint32_t var1 = UINT32_C(262144) >> gas_range; + int32_t var2 = (int32_t)gas_res_adc - INT32_C(512); + + var2 *= INT32_C(3); + var2 = INT32_C(4096) + var2; + + calc_gas_res = 1000000.0f * (float)var1 / (float)var2; + + return calc_gas_res; +} + +/* This internal API is used to calculate the heater resistance value */ +static uint8_t calc_res_heat(uint16_t temp, const struct bme68x_dev *dev) +{ + float var1; + float var2; + float var3; + float var4; + float var5; + uint8_t res_heat; + + if (temp > 400) /* Cap temperature */ + { + temp = 400; + } + + var1 = (((float)dev->calib.par_gh1 / (16.0f)) + 49.0f); + var2 = ((((float)dev->calib.par_gh2 / (32768.0f)) * (0.0005f)) + 0.00235f); + var3 = ((float)dev->calib.par_gh3 / (1024.0f)); + var4 = (var1 * (1.0f + (var2 * (float)temp))); + var5 = (var4 + (var3 * (float)dev->amb_temp)); + res_heat = + (uint8_t)(3.4f * + ((var5 * (4 / (4 + (float)dev->calib.res_heat_range)) * + (1 / (1 + ((float)dev->calib.res_heat_val * 0.002f)))) - + 25)); + + return res_heat; +} + +#endif + +/* This internal API is used to calculate the gas wait */ +static uint8_t calc_gas_wait(uint16_t dur) +{ + uint8_t factor = 0; + uint8_t durval; + + if (dur >= 0xfc0) + { + durval = 0xff; /* Max duration*/ + } + else + { + while (dur > 0x3F) + { + dur = dur / 4; + factor += 1; + } + + durval = (uint8_t)(dur + (factor * 64)); + } + + return durval; +} + +/* This internal API is used to read a single data of the sensor */ +static int8_t read_field_data(uint8_t index, struct bme68x_data *data, struct bme68x_dev *dev) +{ + int8_t rslt = BME68X_OK; + uint8_t buff[BME68X_LEN_FIELD] = { 0 }; + uint8_t gas_range_l, gas_range_h; + uint32_t adc_temp; + uint32_t adc_pres; + uint16_t adc_hum; + uint16_t adc_gas_res_low, adc_gas_res_high; + uint8_t tries = 5; + + while ((tries) && (rslt == BME68X_OK)) + { + rslt = bme68x_get_regs(((uint8_t)(BME68X_REG_FIELD0 + (index * BME68X_LEN_FIELD_OFFSET))), + buff, + (uint16_t)BME68X_LEN_FIELD, + dev); + if (!data) + { + rslt = BME68X_E_NULL_PTR; + break; + } + + data->status = buff[0] & BME68X_NEW_DATA_MSK; + data->gas_index = buff[0] & BME68X_GAS_INDEX_MSK; + data->meas_index = buff[1]; + + /* read the raw data from the sensor */ + adc_pres = (uint32_t)(((uint32_t)buff[2] * 4096) | ((uint32_t)buff[3] * 16) | ((uint32_t)buff[4] / 16)); + adc_temp = (uint32_t)(((uint32_t)buff[5] * 4096) | ((uint32_t)buff[6] * 16) | ((uint32_t)buff[7] / 16)); + adc_hum = (uint16_t)(((uint32_t)buff[8] * 256) | (uint32_t)buff[9]); + adc_gas_res_low = (uint16_t)((uint32_t)buff[13] * 4 | (((uint32_t)buff[14]) / 64)); + adc_gas_res_high = (uint16_t)((uint32_t)buff[15] * 4 | (((uint32_t)buff[16]) / 64)); + gas_range_l = buff[14] & BME68X_GAS_RANGE_MSK; + gas_range_h = buff[16] & BME68X_GAS_RANGE_MSK; + if (dev->variant_id == BME68X_VARIANT_GAS_HIGH) + { + data->status |= buff[16] & BME68X_GASM_VALID_MSK; + data->status |= buff[16] & BME68X_HEAT_STAB_MSK; + } + else + { + data->status |= buff[14] & BME68X_GASM_VALID_MSK; + data->status |= buff[14] & BME68X_HEAT_STAB_MSK; + } + + if ((data->status & BME68X_NEW_DATA_MSK) && (rslt == BME68X_OK)) + { + rslt = bme68x_get_regs(BME68X_REG_RES_HEAT0 + data->gas_index, &data->res_heat, 1, dev); + if (rslt == BME68X_OK) + { + rslt = bme68x_get_regs(BME68X_REG_IDAC_HEAT0 + data->gas_index, &data->idac, 1, dev); + } + + if (rslt == BME68X_OK) + { + rslt = bme68x_get_regs(BME68X_REG_GAS_WAIT0 + data->gas_index, &data->gas_wait, 1, dev); + } + + if (rslt == BME68X_OK) + { + data->temperature = calc_temperature(adc_temp, dev); + data->pressure = calc_pressure(adc_pres, dev); + data->humidity = calc_humidity(adc_hum, dev); + if (dev->variant_id == BME68X_VARIANT_GAS_HIGH) + { + data->gas_resistance = calc_gas_resistance_high(adc_gas_res_high, gas_range_h); + } + else + { + data->gas_resistance = calc_gas_resistance_low(adc_gas_res_low, gas_range_l, dev); + } + + break; + } + } + + if (rslt == BME68X_OK) + { + dev->delay_us(BME68X_PERIOD_POLL, dev->intf_ptr); + } + + tries--; + } + + return rslt; +} + +/* This internal API is used to read all data fields of the sensor */ +static int8_t read_all_field_data(struct bme68x_data * const data[], struct bme68x_dev *dev) +{ + int8_t rslt = BME68X_OK; + uint8_t buff[BME68X_LEN_FIELD * 3] = { 0 }; + uint8_t gas_range_l, gas_range_h; + uint32_t adc_temp; + uint32_t adc_pres; + uint16_t adc_hum; + uint16_t adc_gas_res_low, adc_gas_res_high; + uint8_t off; + uint8_t set_val[30] = { 0 }; /* idac, res_heat, gas_wait */ + uint8_t i; + + if (!data[0] && !data[1] && !data[2]) + { + rslt = BME68X_E_NULL_PTR; + } + + if (rslt == BME68X_OK) + { + rslt = bme68x_get_regs(BME68X_REG_FIELD0, buff, (uint32_t) BME68X_LEN_FIELD * 3, dev); + } + + if (rslt == BME68X_OK) + { + rslt = bme68x_get_regs(BME68X_REG_IDAC_HEAT0, set_val, 30, dev); + } + + for (i = 0; ((i < 3) && (rslt == BME68X_OK)); i++) + { + off = (uint8_t)(i * BME68X_LEN_FIELD); + data[i]->status = buff[off] & BME68X_NEW_DATA_MSK; + data[i]->gas_index = buff[off] & BME68X_GAS_INDEX_MSK; + data[i]->meas_index = buff[off + 1]; + + /* read the raw data from the sensor */ + adc_pres = + (uint32_t) (((uint32_t) buff[off + 2] * 4096) | ((uint32_t) buff[off + 3] * 16) | + ((uint32_t) buff[off + 4] / 16)); + adc_temp = + (uint32_t) (((uint32_t) buff[off + 5] * 4096) | ((uint32_t) buff[off + 6] * 16) | + ((uint32_t) buff[off + 7] / 16)); + adc_hum = (uint16_t) (((uint32_t) buff[off + 8] * 256) | (uint32_t) buff[off + 9]); + adc_gas_res_low = (uint16_t) ((uint32_t) buff[off + 13] * 4 | (((uint32_t) buff[off + 14]) / 64)); + adc_gas_res_high = (uint16_t) ((uint32_t) buff[off + 15] * 4 | (((uint32_t) buff[off + 16]) / 64)); + gas_range_l = buff[off + 14] & BME68X_GAS_RANGE_MSK; + gas_range_h = buff[off + 16] & BME68X_GAS_RANGE_MSK; + if (dev->variant_id == BME68X_VARIANT_GAS_HIGH) + { + data[i]->status |= buff[off + 16] & BME68X_GASM_VALID_MSK; + data[i]->status |= buff[off + 16] & BME68X_HEAT_STAB_MSK; + } + else + { + data[i]->status |= buff[off + 14] & BME68X_GASM_VALID_MSK; + data[i]->status |= buff[off + 14] & BME68X_HEAT_STAB_MSK; + } + + data[i]->idac = set_val[data[i]->gas_index]; + data[i]->res_heat = set_val[10 + data[i]->gas_index]; + data[i]->gas_wait = set_val[20 + data[i]->gas_index]; + data[i]->temperature = calc_temperature(adc_temp, dev); + data[i]->pressure = calc_pressure(adc_pres, dev); + data[i]->humidity = calc_humidity(adc_hum, dev); + if (dev->variant_id == BME68X_VARIANT_GAS_HIGH) + { + data[i]->gas_resistance = calc_gas_resistance_high(adc_gas_res_high, gas_range_h); + } + else + { + data[i]->gas_resistance = calc_gas_resistance_low(adc_gas_res_low, gas_range_l, dev); + } + } + + return rslt; +} + +/* This internal API is used to switch between SPI memory pages */ +static int8_t set_mem_page(uint8_t reg_addr, struct bme68x_dev *dev) +{ + int8_t rslt; + uint8_t reg; + uint8_t mem_page; + + /* Check for null pointers in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME68X_OK) + { + if (reg_addr > 0x7f) + { + mem_page = BME68X_MEM_PAGE1; + } + else + { + mem_page = BME68X_MEM_PAGE0; + } + + if (mem_page != dev->mem_page) + { + dev->mem_page = mem_page; + dev->intf_rslt = dev->read(BME68X_REG_MEM_PAGE | BME68X_SPI_RD_MSK, ®, 1, dev->intf_ptr); + if (dev->intf_rslt != 0) + { + rslt = BME68X_E_COM_FAIL; + } + + if (rslt == BME68X_OK) + { + reg = reg & (~BME68X_MEM_PAGE_MSK); + reg = reg | (dev->mem_page & BME68X_MEM_PAGE_MSK); + dev->intf_rslt = dev->write(BME68X_REG_MEM_PAGE & BME68X_SPI_WR_MSK, ®, 1, dev->intf_ptr); + if (dev->intf_rslt != 0) + { + rslt = BME68X_E_COM_FAIL; + } + } + } + } + + return rslt; +} + +/* This internal API is used to get the current SPI memory page */ +static int8_t get_mem_page(struct bme68x_dev *dev) +{ + int8_t rslt; + uint8_t reg; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME68X_OK) + { + dev->intf_rslt = dev->read(BME68X_REG_MEM_PAGE | BME68X_SPI_RD_MSK, ®, 1, dev->intf_ptr); + if (dev->intf_rslt != 0) + { + rslt = BME68X_E_COM_FAIL; + } + else + { + dev->mem_page = reg & BME68X_MEM_PAGE_MSK; + } + } + + return rslt; +} + +/* This internal API is used to limit the max value of a parameter */ +static int8_t boundary_check(uint8_t *value, uint8_t max, struct bme68x_dev *dev) +{ + int8_t rslt; + + rslt = null_ptr_check(dev); + if ((value != NULL) && (rslt == BME68X_OK)) + { + /* Check if value is above maximum value */ + if (*value > max) + { + /* Auto correct the invalid value to maximum value */ + *value = max; + dev->info_msg |= BME68X_I_PARAM_CORR; + } + } + else + { + rslt = BME68X_E_NULL_PTR; + } + + return rslt; +} + +/* This internal API is used to check the bme68x_dev for null pointers */ +static int8_t null_ptr_check(const struct bme68x_dev *dev) +{ + int8_t rslt = BME68X_OK; + + if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_us == NULL)) + { + /* Device structure pointer is not valid */ + rslt = BME68X_E_NULL_PTR; + } + + return rslt; +} + +/* This internal API is used to set heater configurations */ +static int8_t set_conf(const struct bme68x_heatr_conf *conf, uint8_t op_mode, uint8_t *nb_conv, struct bme68x_dev *dev) +{ + int8_t rslt = BME68X_OK; + uint8_t i; + uint8_t shared_dur; + uint8_t write_len = 0; + uint8_t heater_dur_shared_addr = BME68X_REG_SHD_HEATR_DUR; + uint8_t rh_reg_addr[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + uint8_t rh_reg_data[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + uint8_t gw_reg_addr[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + uint8_t gw_reg_data[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + switch (op_mode) + { + case BME68X_FORCED_MODE: + rh_reg_addr[0] = BME68X_REG_RES_HEAT0; + rh_reg_data[0] = calc_res_heat(conf->heatr_temp, dev); + gw_reg_addr[0] = BME68X_REG_GAS_WAIT0; + gw_reg_data[0] = calc_gas_wait(conf->heatr_dur); + (*nb_conv) = 0; + write_len = 1; + break; + case BME68X_SEQUENTIAL_MODE: + if ((!conf->heatr_dur_prof) || (!conf->heatr_temp_prof)) + { + rslt = BME68X_E_NULL_PTR; + break; + } + + for (i = 0; i < conf->profile_len; i++) + { + rh_reg_addr[i] = BME68X_REG_RES_HEAT0 + i; + rh_reg_data[i] = calc_res_heat(conf->heatr_temp_prof[i], dev); + gw_reg_addr[i] = BME68X_REG_GAS_WAIT0 + i; + gw_reg_data[i] = calc_gas_wait(conf->heatr_dur_prof[i]); + } + + (*nb_conv) = conf->profile_len; + write_len = conf->profile_len; + break; + case BME68X_PARALLEL_MODE: + if ((!conf->heatr_dur_prof) || (!conf->heatr_temp_prof)) + { + rslt = BME68X_E_NULL_PTR; + break; + } + + if (conf->shared_heatr_dur == 0) + { + rslt = BME68X_W_DEFINE_SHD_HEATR_DUR; + } + + for (i = 0; i < conf->profile_len; i++) + { + rh_reg_addr[i] = BME68X_REG_RES_HEAT0 + i; + rh_reg_data[i] = calc_res_heat(conf->heatr_temp_prof[i], dev); + gw_reg_addr[i] = BME68X_REG_GAS_WAIT0 + i; + gw_reg_data[i] = (uint8_t) conf->heatr_dur_prof[i]; + } + + (*nb_conv) = conf->profile_len; + write_len = conf->profile_len; + shared_dur = calc_heatr_dur_shared(conf->shared_heatr_dur); + if (rslt == BME68X_OK) + { + rslt = bme68x_set_regs(&heater_dur_shared_addr, &shared_dur, 1, dev); + } + + break; + default: + rslt = BME68X_W_DEFINE_OP_MODE; + } + + if (rslt == BME68X_OK) + { + rslt = bme68x_set_regs(rh_reg_addr, rh_reg_data, write_len, dev); + } + + if (rslt == BME68X_OK) + { + rslt = bme68x_set_regs(gw_reg_addr, gw_reg_data, write_len, dev); + } + + return rslt; +} + +/* This internal API is used to calculate the register value for + * shared heater duration */ +static uint8_t calc_heatr_dur_shared(uint16_t dur) +{ + uint8_t factor = 0; + uint8_t heatdurval; + + if (dur >= 0x783) + { + heatdurval = 0xff; /* Max duration */ + } + else + { + /* Step size of 0.477ms */ + dur = (uint16_t)(((uint32_t)dur * 1000) / 477); + while (dur > 0x3F) + { + dur = dur >> 2; + factor += 1; + } + + heatdurval = (uint8_t)(dur + (factor * 64)); + } + + return heatdurval; +} + +/* This internal API is used sort the sensor data */ +static void sort_sensor_data(uint8_t low_index, uint8_t high_index, struct bme68x_data *field[]) +{ + int16_t meas_index1; + int16_t meas_index2; + + meas_index1 = (int16_t)field[low_index]->meas_index; + meas_index2 = (int16_t)field[high_index]->meas_index; + if ((field[low_index]->status & BME68X_NEW_DATA_MSK) && (field[high_index]->status & BME68X_NEW_DATA_MSK)) + { + int16_t diff = meas_index2 - meas_index1; + if (((diff > -3) && (diff < 0)) || (diff > 2)) + { + swap_fields(low_index, high_index, field); + } + } + else if (field[high_index]->status & BME68X_NEW_DATA_MSK) + { + swap_fields(low_index, high_index, field); + } + + /* Sorting field data + * + * The 3 fields are filled in a fixed order with data in an incrementing + * 8-bit sub-measurement index which looks like + * Field index | Sub-meas index + * 0 | 0 + * 1 | 1 + * 2 | 2 + * 0 | 3 + * 1 | 4 + * 2 | 5 + * ... + * 0 | 252 + * 1 | 253 + * 2 | 254 + * 0 | 255 + * 1 | 0 + * 2 | 1 + * + * The fields are sorted in a way so as to always deal with only a snapshot + * of comparing 2 fields at a time. The order being + * field0 & field1 + * field0 & field2 + * field1 & field2 + * Here the oldest data should be in field0 while the newest is in field2. + * In the following documentation, field0's position would referred to as + * the lowest and field2 as the highest. + * + * In order to sort we have to consider the following cases, + * + * Case A: No fields have new data + * Then do not sort, as this data has already been read. + * + * Case B: Higher field has new data + * Then the new field get's the lowest position. + * + * Case C: Both fields have new data + * We have to put the oldest sample in the lowest position. Since the + * sub-meas index contains in essence the age of the sample, we calculate + * the difference between the higher field and the lower field. + * Here we have 3 sub-cases, + * Case 1: Regular read without overwrite + * Field index | Sub-meas index + * 0 | 3 + * 1 | 4 + * + * Field index | Sub-meas index + * 0 | 3 + * 2 | 5 + * + * The difference is always <= 2. There is no need to swap as the + * oldest sample is already in the lowest position. + * + * Case 2: Regular read with an overflow and without an overwrite + * Field index | Sub-meas index + * 0 | 255 + * 1 | 0 + * + * Field index | Sub-meas index + * 0 | 254 + * 2 | 0 + * + * The difference is always <= -3. There is no need to swap as the + * oldest sample is already in the lowest position. + * + * Case 3: Regular read with overwrite + * Field index | Sub-meas index + * 0 | 6 + * 1 | 4 + * + * Field index | Sub-meas index + * 0 | 6 + * 2 | 5 + * + * The difference is always > -3. There is a need to swap as the + * oldest sample is not in the lowest position. + * + * Case 4: Regular read with overwrite and overflow + * Field index | Sub-meas index + * 0 | 0 + * 1 | 254 + * + * Field index | Sub-meas index + * 0 | 0 + * 2 | 255 + * + * The difference is always > 2. There is a need to swap as the + * oldest sample is not in the lowest position. + * + * To summarize, we have to swap when + * - The higher field has new data and the lower field does not. + * - If both fields have new data, then the difference of sub-meas index + * between the higher field and the lower field creates the + * following condition for swapping. + * - (diff > -3) && (diff < 0), combination of cases 1, 2, and 3. + * - diff > 2, case 4. + * + * Here the limits of -3 and 2 derive from the fact that there are 3 fields. + * These values decrease or increase respectively if the number of fields increases. + */ +} + +/* This internal API is used sort the sensor data */ +static void swap_fields(uint8_t index1, uint8_t index2, struct bme68x_data *field[]) +{ + struct bme68x_data *temp; + + temp = field[index1]; + field[index1] = field[index2]; + field[index2] = temp; +} + +/* This Function is to analyze the sensor data */ +static int8_t analyze_sensor_data(const struct bme68x_data *data, uint8_t n_meas) +{ + int8_t rslt = BME68X_OK; + uint8_t self_test_failed = 0, i; + uint32_t cent_res = 0; + + if ((data[0].temperature < BME68X_MIN_TEMPERATURE) || (data[0].temperature > BME68X_MAX_TEMPERATURE)) + { + self_test_failed++; + } + + if ((data[0].pressure < BME68X_MIN_PRESSURE) || (data[0].pressure > BME68X_MAX_PRESSURE)) + { + self_test_failed++; + } + + if ((data[0].humidity < BME68X_MIN_HUMIDITY) || (data[0].humidity > BME68X_MAX_HUMIDITY)) + { + self_test_failed++; + } + + for (i = 0; i < n_meas; i++) /* Every gas measurement should be valid */ + { + if (!(data[i].status & BME68X_GASM_VALID_MSK)) + { + self_test_failed++; + } + } + + if (n_meas >= 6) + { + cent_res = (uint32_t)((5 * (data[3].gas_resistance + data[5].gas_resistance)) / (2 * data[4].gas_resistance)); + } + + if (cent_res < 6) + { + self_test_failed++; + } + + if (self_test_failed) + { + rslt = BME68X_E_SELF_TEST; + } + + return rslt; +} + +/* This internal API is used to read the calibration coefficients */ +static int8_t get_calib_data(struct bme68x_dev *dev) +{ + int8_t rslt; + uint8_t coeff_array[BME68X_LEN_COEFF_ALL]; + + rslt = bme68x_get_regs(BME68X_REG_COEFF1, coeff_array, BME68X_LEN_COEFF1, dev); + if (rslt == BME68X_OK) + { + rslt = bme68x_get_regs(BME68X_REG_COEFF2, &coeff_array[BME68X_LEN_COEFF1], BME68X_LEN_COEFF2, dev); + } + + if (rslt == BME68X_OK) + { + rslt = bme68x_get_regs(BME68X_REG_COEFF3, + &coeff_array[BME68X_LEN_COEFF1 + BME68X_LEN_COEFF2], + BME68X_LEN_COEFF3, + dev); + } + + if (rslt == BME68X_OK) + { + /* Temperature related coefficients */ + dev->calib.par_t1 = + (uint16_t)(BME68X_CONCAT_BYTES(coeff_array[BME68X_IDX_T1_MSB], coeff_array[BME68X_IDX_T1_LSB])); + dev->calib.par_t2 = + (int16_t)(BME68X_CONCAT_BYTES(coeff_array[BME68X_IDX_T2_MSB], coeff_array[BME68X_IDX_T2_LSB])); + dev->calib.par_t3 = (int8_t)(coeff_array[BME68X_IDX_T3]); + + /* Pressure related coefficients */ + dev->calib.par_p1 = + (uint16_t)(BME68X_CONCAT_BYTES(coeff_array[BME68X_IDX_P1_MSB], coeff_array[BME68X_IDX_P1_LSB])); + dev->calib.par_p2 = + (int16_t)(BME68X_CONCAT_BYTES(coeff_array[BME68X_IDX_P2_MSB], coeff_array[BME68X_IDX_P2_LSB])); + dev->calib.par_p3 = (int8_t)coeff_array[BME68X_IDX_P3]; + dev->calib.par_p4 = + (int16_t)(BME68X_CONCAT_BYTES(coeff_array[BME68X_IDX_P4_MSB], coeff_array[BME68X_IDX_P4_LSB])); + dev->calib.par_p5 = + (int16_t)(BME68X_CONCAT_BYTES(coeff_array[BME68X_IDX_P5_MSB], coeff_array[BME68X_IDX_P5_LSB])); + dev->calib.par_p6 = (int8_t)(coeff_array[BME68X_IDX_P6]); + dev->calib.par_p7 = (int8_t)(coeff_array[BME68X_IDX_P7]); + dev->calib.par_p8 = + (int16_t)(BME68X_CONCAT_BYTES(coeff_array[BME68X_IDX_P8_MSB], coeff_array[BME68X_IDX_P8_LSB])); + dev->calib.par_p9 = + (int16_t)(BME68X_CONCAT_BYTES(coeff_array[BME68X_IDX_P9_MSB], coeff_array[BME68X_IDX_P9_LSB])); + dev->calib.par_p10 = (uint8_t)(coeff_array[BME68X_IDX_P10]); + + /* Humidity related coefficients */ + dev->calib.par_h1 = + (uint16_t)(((uint16_t)coeff_array[BME68X_IDX_H1_MSB] << 4) | + (coeff_array[BME68X_IDX_H1_LSB] & BME68X_BIT_H1_DATA_MSK)); + dev->calib.par_h2 = + (uint16_t)(((uint16_t)coeff_array[BME68X_IDX_H2_MSB] << 4) | ((coeff_array[BME68X_IDX_H2_LSB]) >> 4)); + dev->calib.par_h3 = (int8_t)coeff_array[BME68X_IDX_H3]; + dev->calib.par_h4 = (int8_t)coeff_array[BME68X_IDX_H4]; + dev->calib.par_h5 = (int8_t)coeff_array[BME68X_IDX_H5]; + dev->calib.par_h6 = (uint8_t)coeff_array[BME68X_IDX_H6]; + dev->calib.par_h7 = (int8_t)coeff_array[BME68X_IDX_H7]; + + /* Gas heater related coefficients */ + dev->calib.par_gh1 = (int8_t)coeff_array[BME68X_IDX_GH1]; + dev->calib.par_gh2 = + (int16_t)(BME68X_CONCAT_BYTES(coeff_array[BME68X_IDX_GH2_MSB], coeff_array[BME68X_IDX_GH2_LSB])); + dev->calib.par_gh3 = (int8_t)coeff_array[BME68X_IDX_GH3]; + + /* Other coefficients */ + dev->calib.res_heat_range = ((coeff_array[BME68X_IDX_RES_HEAT_RANGE] & BME68X_RHRANGE_MSK) / 16); + dev->calib.res_heat_val = (int8_t)coeff_array[BME68X_IDX_RES_HEAT_VAL]; + dev->calib.range_sw_err = ((int8_t)(coeff_array[BME68X_IDX_RANGE_SW_ERR] & BME68X_RSERROR_MSK)) / 16; + } + + return rslt; +} + +/* This internal API is used to read variant ID information from the register */ +static int8_t read_variant_id(struct bme68x_dev *dev) +{ + int8_t rslt; + uint8_t reg_data = 0; + + /* Read variant ID information register */ + rslt = bme68x_get_regs(BME68X_REG_VARIANT_ID, ®_data, 1, dev); + + if (rslt == BME68X_OK) + { + dev->variant_id = reg_data; + } + + return rslt; +} diff --git a/lib/lib_i2c/BME68x-Sensor-API/bme68x.h b/lib/lib_i2c/BME68x-Sensor-API/bme68x.h new file mode 100644 index 000000000..e6d482855 --- /dev/null +++ b/lib/lib_i2c/BME68x-Sensor-API/bme68x.h @@ -0,0 +1,323 @@ +/** +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bme68x.h +* @date 2021-11-09 +* @version v4.4.7 +* +*/ + +/*! + * @defgroup bme68x BME68X + * @brief Product Overview + * and Sensor API Source Code + */ + +#ifndef BME68X_H_ +#define BME68X_H_ + +#include "bme68x_defs.h" + +/* CPP guard */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \ingroup bme68x + * \defgroup bme68xApiInit Initialization + * @brief Initialize the sensor and device structure + */ + +/*! + * \ingroup bme68xApiInit + * \page bme68x_api_bme68x_init bme68x_init + * \code + * int8_t bme68x_init(struct bme68x_dev *dev); + * \endcode + * @details This API reads the chip-id of the sensor which is the first step to + * verify the sensor and also calibrates the sensor + * As this API is the entry point, call this API before using other APIs. + * + * @param[in,out] dev : Structure instance of bme68x_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bme68x_init(struct bme68x_dev *dev); + +/** + * \ingroup bme68x + * \defgroup bme68xApiRegister Registers + * @brief Generic API for accessing sensor registers + */ + +/*! + * \ingroup bme68xApiRegister + * \page bme68x_api_bme68x_set_regs bme68x_set_regs + * \code + * int8_t bme68x_set_regs(const uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, struct bme68x_dev *dev) + * \endcode + * @details This API writes the given data to the register address of the sensor + * + * @param[in] reg_addr : Register addresses to where the data is to be written + * @param[in] reg_data : Pointer to data buffer which is to be written + * in the reg_addr of sensor. + * @param[in] len : No of bytes of data to write + * @param[in,out] dev : Structure instance of bme68x_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bme68x_set_regs(const uint8_t *reg_addr, const uint8_t *reg_data, uint32_t len, struct bme68x_dev *dev); + +/*! + * \ingroup bme68xApiRegister + * \page bme68x_api_bme68x_get_regs bme68x_get_regs + * \code + * int8_t bme68x_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bme68x_dev *dev) + * \endcode + * @details This API reads the data from the given register address of sensor. + * + * @param[in] reg_addr : Register address from where the data to be read + * @param[out] reg_data : Pointer to data buffer to store the read data. + * @param[in] len : No of bytes of data to be read. + * @param[in,out] dev : Structure instance of bme68x_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bme68x_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bme68x_dev *dev); + +/** + * \ingroup bme68x + * \defgroup bme68xApiSystem System + * @brief API that performs system-level operations + */ + +/*! + * \ingroup bme68xApiSystem + * \page bme68x_api_bme68x_soft_reset bme68x_soft_reset + * \code + * int8_t bme68x_soft_reset(struct bme68x_dev *dev); + * \endcode + * @details This API soft-resets the sensor. + * + * @param[in,out] dev : Structure instance of bme68x_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bme68x_soft_reset(struct bme68x_dev *dev); + +/** + * \ingroup bme68x + * \defgroup bme68xApiOm Operation mode + * @brief API to configure operation mode + */ + +/*! + * \ingroup bme68xApiOm + * \page bme68x_api_bme68x_set_op_mode bme68x_set_op_mode + * \code + * int8_t bme68x_set_op_mode(const uint8_t op_mode, struct bme68x_dev *dev); + * \endcode + * @details This API is used to set the operation mode of the sensor + * @param[in] op_mode : Desired operation mode. + * @param[in] dev : Structure instance of bme68x_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bme68x_set_op_mode(const uint8_t op_mode, struct bme68x_dev *dev); + +/*! + * \ingroup bme68xApiOm + * \page bme68x_api_bme68x_get_op_mode bme68x_get_op_mode + * \code + * int8_t bme68x_get_op_mode(uint8_t *op_mode, struct bme68x_dev *dev); + * \endcode + * @details This API is used to get the operation mode of the sensor. + * + * @param[out] op_mode : Desired operation mode. + * @param[in,out] dev : Structure instance of bme68x_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bme68x_get_op_mode(uint8_t *op_mode, struct bme68x_dev *dev); + +/*! + * \ingroup bme68xApiConfig + * \page bme68x_api_bme68x_get_meas_dur bme68x_get_meas_dur + * \code + * uint32_t bme68x_get_meas_dur(const uint8_t op_mode, struct bme68x_conf *conf, struct bme68x_dev *dev); + * \endcode + * @details This API is used to get the remaining duration that can be used for heating. + * + * @param[in] op_mode : Desired operation mode. + * @param[in] conf : Desired sensor configuration. + * @param[in] dev : Structure instance of bme68x_dev + * + * @return Measurement duration calculated in microseconds + */ +uint32_t bme68x_get_meas_dur(const uint8_t op_mode, struct bme68x_conf *conf, struct bme68x_dev *dev); + +/** + * \ingroup bme68x + * \defgroup bme68xApiData Data Read out + * @brief Read our data from the sensor + */ + +/*! + * \ingroup bme68xApiData + * \page bme68x_api_bme68x_get_data bme68x_get_data + * \code + * int8_t bme68x_get_data(uint8_t op_mode, struct bme68x_data *data, uint8_t *n_data, struct bme68x_dev *dev); + * \endcode + * @details This API reads the pressure, temperature and humidity and gas data + * from the sensor, compensates the data and store it in the bme68x_data + * structure instance passed by the user. + * + * @param[in] op_mode : Expected operation mode. + * @param[out] data : Structure instance to hold the data. + * @param[out] n_data : Number of data instances available. + * @param[in,out] dev : Structure instance of bme68x_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bme68x_get_data(uint8_t op_mode, struct bme68x_data *data, uint8_t *n_data, struct bme68x_dev *dev); + +/** + * \ingroup bme68x + * \defgroup bme68xApiConfig Configuration + * @brief Configuration API of sensor + */ + +/*! + * \ingroup bme68xApiConfig + * \page bme68x_api_bme68x_set_conf bme68x_set_conf + * \code + * int8_t bme68x_set_conf(struct bme68x_conf *conf, struct bme68x_dev *dev); + * \endcode + * @details This API is used to set the oversampling, filter and odr configuration + * + * @param[in] conf : Desired sensor configuration. + * @param[in,out] dev : Structure instance of bme68x_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bme68x_set_conf(struct bme68x_conf *conf, struct bme68x_dev *dev); + +/*! + * \ingroup bme68xApiConfig + * \page bme68x_api_bme68x_get_conf bme68x_get_conf + * \code + * int8_t bme68x_get_conf(struct bme68x_conf *conf, struct bme68x_dev *dev); + * \endcode + * @details This API is used to get the oversampling, filter and odr + * configuration + * + * @param[out] conf : Present sensor configuration. + * @param[in,out] dev : Structure instance of bme68x_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bme68x_get_conf(struct bme68x_conf *conf, struct bme68x_dev *dev); + +/*! + * \ingroup bme68xApiConfig + * \page bme68x_api_bme68x_set_heatr_conf bme68x_set_heatr_conf + * \code + * int8_t bme68x_set_heatr_conf(uint8_t op_mode, const struct bme68x_heatr_conf *conf, struct bme68x_dev *dev); + * \endcode + * @details This API is used to set the gas configuration of the sensor. + * + * @param[in] op_mode : Expected operation mode of the sensor. + * @param[in] conf : Desired heating configuration. + * @param[in,out] dev : Structure instance of bme68x_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bme68x_set_heatr_conf(uint8_t op_mode, const struct bme68x_heatr_conf *conf, struct bme68x_dev *dev); + +/*! + * \ingroup bme68xApiConfig + * \page bme68x_api_bme68x_get_heatr_conf bme68x_get_heatr_conf + * \code + * int8_t bme68x_get_heatr_conf(const struct bme68x_heatr_conf *conf, struct bme68x_dev *dev); + * \endcode + * @details This API is used to get the gas configuration of the sensor. + * + * @param[out] conf : Current configurations of the gas sensor. + * @param[in,out] dev : Structure instance of bme68x_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bme68x_get_heatr_conf(const struct bme68x_heatr_conf *conf, struct bme68x_dev *dev); + +/*! + * \ingroup bme68xApiSystem + * \page bme68x_api_bme68x_selftest_check bme68x_selftest_check + * \code + * int8_t bme68x_selftest_check(const struct bme68x_dev *dev); + * \endcode + * @details This API performs Self-test of low gas variant of BME68X + * + * @param[in, out] dev : Structure instance of bme68x_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bme68x_selftest_check(const struct bme68x_dev *dev); + +#ifdef __cplusplus +} +#endif /* End of CPP guard */ +#endif /* BME68X_H_ */ diff --git a/lib/lib_i2c/BME68x-Sensor-API/bme68x_defs.h b/lib/lib_i2c/BME68x-Sensor-API/bme68x_defs.h new file mode 100644 index 000000000..861b2f7c2 --- /dev/null +++ b/lib/lib_i2c/BME68x-Sensor-API/bme68x_defs.h @@ -0,0 +1,972 @@ +/** +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bme68x_defs.h +* @date 2021-11-09 +* @version v4.4.7 +* +*/ + +/*! @cond DOXYGEN_SUPRESS */ + +#ifndef BME68X_DEFS_H_ +#define BME68X_DEFS_H_ + +/********************************************************* */ +/*! Header includes */ +/********************************************************* */ +#ifdef __KERNEL__ +#include +#include +#else +#include +#include +#endif + +/********************************************************* */ +/*! Common Macros */ +/********************************************************* */ +#ifdef __KERNEL__ +#if !defined(UINT8_C) && !defined(INT8_C) +#define INT8_C(x) S8_C(x) +#define UINT8_C(x) U8_C(x) +#endif + +#if !defined(UINT16_C) && !defined(INT16_C) +#define INT16_C(x) S16_C(x) +#define UINT16_C(x) U16_C(x) +#endif + +#if !defined(INT32_C) && !defined(UINT32_C) +#define INT32_C(x) S32_C(x) +#define UINT32_C(x) U32_C(x) +#endif + +#if !defined(INT64_C) && !defined(UINT64_C) +#define INT64_C(x) S64_C(x) +#define UINT64_C(x) U64_C(x) +#endif +#endif + +/*! C standard macros */ +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *) 0) +#endif +#endif + +#ifndef BME68X_DO_NOT_USE_FPU + +/* Comment or un-comment the macro to provide floating point data output */ +#define BME68X_USE_FPU +#endif + +/* Period between two polls (value can be given by user) */ +#ifndef BME68X_PERIOD_POLL +#define BME68X_PERIOD_POLL UINT32_C(10000) +#endif + +/* BME68X unique chip identifier */ +#define BME68X_CHIP_ID UINT8_C(0x61) + +/* Period for a soft reset */ +#define BME68X_PERIOD_RESET UINT32_C(10000) + +/* BME68X lower I2C address */ +#define BME68X_I2C_ADDR_LOW UINT8_C(0x76) + +/* BME68X higher I2C address */ +#define BME68X_I2C_ADDR_HIGH UINT8_C(0x77) + +/* Soft reset command */ +#define BME68X_SOFT_RESET_CMD UINT8_C(0xb6) + +/* Return code definitions */ +/* Success */ +#define BME68X_OK INT8_C(0) + +/* Errors */ +/* Null pointer passed */ +#define BME68X_E_NULL_PTR INT8_C(-1) + +/* Communication failure */ +#define BME68X_E_COM_FAIL INT8_C(-2) + +/* Sensor not found */ +#define BME68X_E_DEV_NOT_FOUND INT8_C(-3) + +/* Incorrect length parameter */ +#define BME68X_E_INVALID_LENGTH INT8_C(-4) + +/* Self test fail error */ +#define BME68X_E_SELF_TEST INT8_C(-5) + +/* Warnings */ +/* Define a valid operation mode */ +#define BME68X_W_DEFINE_OP_MODE INT8_C(1) + +/* No new data was found */ +#define BME68X_W_NO_NEW_DATA INT8_C(2) + +/* Define the shared heating duration */ +#define BME68X_W_DEFINE_SHD_HEATR_DUR INT8_C(3) + +/* Information - only available via bme68x_dev.info_msg */ +#define BME68X_I_PARAM_CORR UINT8_C(1) + +/* Register map addresses in I2C */ +/* Register for 3rd group of coefficients */ +#define BME68X_REG_COEFF3 UINT8_C(0x00) + +/* 0th Field address*/ +#define BME68X_REG_FIELD0 UINT8_C(0x1d) + +/* 0th Current DAC address*/ +#define BME68X_REG_IDAC_HEAT0 UINT8_C(0x50) + +/* 0th Res heat address */ +#define BME68X_REG_RES_HEAT0 UINT8_C(0x5a) + +/* 0th Gas wait address */ +#define BME68X_REG_GAS_WAIT0 UINT8_C(0x64) + +/* Shared heating duration address */ +#define BME68X_REG_SHD_HEATR_DUR UINT8_C(0x6E) + +/* CTRL_GAS_0 address */ +#define BME68X_REG_CTRL_GAS_0 UINT8_C(0x70) + +/* CTRL_GAS_1 address */ +#define BME68X_REG_CTRL_GAS_1 UINT8_C(0x71) + +/* CTRL_HUM address */ +#define BME68X_REG_CTRL_HUM UINT8_C(0x72) + +/* CTRL_MEAS address */ +#define BME68X_REG_CTRL_MEAS UINT8_C(0x74) + +/* CONFIG address */ +#define BME68X_REG_CONFIG UINT8_C(0x75) + +/* MEM_PAGE address */ +#define BME68X_REG_MEM_PAGE UINT8_C(0xf3) + +/* Unique ID address */ +#define BME68X_REG_UNIQUE_ID UINT8_C(0x83) + +/* Register for 1st group of coefficients */ +#define BME68X_REG_COEFF1 UINT8_C(0x8a) + +/* Chip ID address */ +#define BME68X_REG_CHIP_ID UINT8_C(0xd0) + +/* Soft reset address */ +#define BME68X_REG_SOFT_RESET UINT8_C(0xe0) + +/* Register for 2nd group of coefficients */ +#define BME68X_REG_COEFF2 UINT8_C(0xe1) + +/* Variant ID Register */ +#define BME68X_REG_VARIANT_ID UINT8_C(0xF0) + +/* Enable/Disable macros */ + +/* Enable */ +#define BME68X_ENABLE UINT8_C(0x01) + +/* Disable */ +#define BME68X_DISABLE UINT8_C(0x00) + +/* Variant ID macros */ + +/* Low Gas variant */ +#define BME68X_VARIANT_GAS_LOW UINT8_C(0x00) + +/* High Gas variant */ +#define BME68X_VARIANT_GAS_HIGH UINT8_C(0x01) + +/* Oversampling setting macros */ + +/* Switch off measurement */ +#define BME68X_OS_NONE UINT8_C(0) + +/* Perform 1 measurement */ +#define BME68X_OS_1X UINT8_C(1) + +/* Perform 2 measurements */ +#define BME68X_OS_2X UINT8_C(2) + +/* Perform 4 measurements */ +#define BME68X_OS_4X UINT8_C(3) + +/* Perform 8 measurements */ +#define BME68X_OS_8X UINT8_C(4) + +/* Perform 16 measurements */ +#define BME68X_OS_16X UINT8_C(5) + +/* IIR Filter settings */ + +/* Switch off the filter */ +#define BME68X_FILTER_OFF UINT8_C(0) + +/* Filter coefficient of 2 */ +#define BME68X_FILTER_SIZE_1 UINT8_C(1) + +/* Filter coefficient of 4 */ +#define BME68X_FILTER_SIZE_3 UINT8_C(2) + +/* Filter coefficient of 8 */ +#define BME68X_FILTER_SIZE_7 UINT8_C(3) + +/* Filter coefficient of 16 */ +#define BME68X_FILTER_SIZE_15 UINT8_C(4) + +/* Filter coefficient of 32 */ +#define BME68X_FILTER_SIZE_31 UINT8_C(5) + +/* Filter coefficient of 64 */ +#define BME68X_FILTER_SIZE_63 UINT8_C(6) + +/* Filter coefficient of 128 */ +#define BME68X_FILTER_SIZE_127 UINT8_C(7) + +/* ODR/Standby time macros */ + +/* Standby time of 0.59ms */ +#define BME68X_ODR_0_59_MS UINT8_C(0) + +/* Standby time of 62.5ms */ +#define BME68X_ODR_62_5_MS UINT8_C(1) + +/* Standby time of 125ms */ +#define BME68X_ODR_125_MS UINT8_C(2) + +/* Standby time of 250ms */ +#define BME68X_ODR_250_MS UINT8_C(3) + +/* Standby time of 500ms */ +#define BME68X_ODR_500_MS UINT8_C(4) + +/* Standby time of 1s */ +#define BME68X_ODR_1000_MS UINT8_C(5) + +/* Standby time of 10ms */ +#define BME68X_ODR_10_MS UINT8_C(6) + +/* Standby time of 20ms */ +#define BME68X_ODR_20_MS UINT8_C(7) + +/* No standby time */ +#define BME68X_ODR_NONE UINT8_C(8) + +/* Operating mode macros */ + +/* Sleep operation mode */ +#define BME68X_SLEEP_MODE UINT8_C(0) + +/* Forced operation mode */ +#define BME68X_FORCED_MODE UINT8_C(1) + +/* Parallel operation mode */ +#define BME68X_PARALLEL_MODE UINT8_C(2) + +/* Sequential operation mode */ +#define BME68X_SEQUENTIAL_MODE UINT8_C(3) + +/* SPI page macros */ + +/* SPI memory page 0 */ +#define BME68X_MEM_PAGE0 UINT8_C(0x10) + +/* SPI memory page 1 */ +#define BME68X_MEM_PAGE1 UINT8_C(0x00) + +/* Coefficient index macros */ + +/* Length for all coefficients */ +#define BME68X_LEN_COEFF_ALL UINT8_C(42) + +/* Length for 1st group of coefficients */ +#define BME68X_LEN_COEFF1 UINT8_C(23) + +/* Length for 2nd group of coefficients */ +#define BME68X_LEN_COEFF2 UINT8_C(14) + +/* Length for 3rd group of coefficients */ +#define BME68X_LEN_COEFF3 UINT8_C(5) + +/* Length of the field */ +#define BME68X_LEN_FIELD UINT8_C(17) + +/* Length between two fields */ +#define BME68X_LEN_FIELD_OFFSET UINT8_C(17) + +/* Length of the configuration register */ +#define BME68X_LEN_CONFIG UINT8_C(5) + +/* Length of the interleaved buffer */ +#define BME68X_LEN_INTERLEAVE_BUFF UINT8_C(20) + +/* Coefficient index macros */ + +/* Coefficient T2 LSB position */ +#define BME68X_IDX_T2_LSB (0) + +/* Coefficient T2 MSB position */ +#define BME68X_IDX_T2_MSB (1) + +/* Coefficient T3 position */ +#define BME68X_IDX_T3 (2) + +/* Coefficient P1 LSB position */ +#define BME68X_IDX_P1_LSB (4) + +/* Coefficient P1 MSB position */ +#define BME68X_IDX_P1_MSB (5) + +/* Coefficient P2 LSB position */ +#define BME68X_IDX_P2_LSB (6) + +/* Coefficient P2 MSB position */ +#define BME68X_IDX_P2_MSB (7) + +/* Coefficient P3 position */ +#define BME68X_IDX_P3 (8) + +/* Coefficient P4 LSB position */ +#define BME68X_IDX_P4_LSB (10) + +/* Coefficient P4 MSB position */ +#define BME68X_IDX_P4_MSB (11) + +/* Coefficient P5 LSB position */ +#define BME68X_IDX_P5_LSB (12) + +/* Coefficient P5 MSB position */ +#define BME68X_IDX_P5_MSB (13) + +/* Coefficient P7 position */ +#define BME68X_IDX_P7 (14) + +/* Coefficient P6 position */ +#define BME68X_IDX_P6 (15) + +/* Coefficient P8 LSB position */ +#define BME68X_IDX_P8_LSB (18) + +/* Coefficient P8 MSB position */ +#define BME68X_IDX_P8_MSB (19) + +/* Coefficient P9 LSB position */ +#define BME68X_IDX_P9_LSB (20) + +/* Coefficient P9 MSB position */ +#define BME68X_IDX_P9_MSB (21) + +/* Coefficient P10 position */ +#define BME68X_IDX_P10 (22) + +/* Coefficient H2 MSB position */ +#define BME68X_IDX_H2_MSB (23) + +/* Coefficient H2 LSB position */ +#define BME68X_IDX_H2_LSB (24) + +/* Coefficient H1 LSB position */ +#define BME68X_IDX_H1_LSB (24) + +/* Coefficient H1 MSB position */ +#define BME68X_IDX_H1_MSB (25) + +/* Coefficient H3 position */ +#define BME68X_IDX_H3 (26) + +/* Coefficient H4 position */ +#define BME68X_IDX_H4 (27) + +/* Coefficient H5 position */ +#define BME68X_IDX_H5 (28) + +/* Coefficient H6 position */ +#define BME68X_IDX_H6 (29) + +/* Coefficient H7 position */ +#define BME68X_IDX_H7 (30) + +/* Coefficient T1 LSB position */ +#define BME68X_IDX_T1_LSB (31) + +/* Coefficient T1 MSB position */ +#define BME68X_IDX_T1_MSB (32) + +/* Coefficient GH2 LSB position */ +#define BME68X_IDX_GH2_LSB (33) + +/* Coefficient GH2 MSB position */ +#define BME68X_IDX_GH2_MSB (34) + +/* Coefficient GH1 position */ +#define BME68X_IDX_GH1 (35) + +/* Coefficient GH3 position */ +#define BME68X_IDX_GH3 (36) + +/* Coefficient res heat value position */ +#define BME68X_IDX_RES_HEAT_VAL (37) + +/* Coefficient res heat range position */ +#define BME68X_IDX_RES_HEAT_RANGE (39) + +/* Coefficient range switching error position */ +#define BME68X_IDX_RANGE_SW_ERR (41) + +/* Gas measurement macros */ + +/* Disable gas measurement */ +#define BME68X_DISABLE_GAS_MEAS UINT8_C(0x00) + +/* Enable gas measurement low */ +#define BME68X_ENABLE_GAS_MEAS_L UINT8_C(0x01) + +/* Enable gas measurement high */ +#define BME68X_ENABLE_GAS_MEAS_H UINT8_C(0x02) + +/* Heater control macros */ + +/* Enable heater */ +#define BME68X_ENABLE_HEATER UINT8_C(0x00) + +/* Disable heater */ +#define BME68X_DISABLE_HEATER UINT8_C(0x01) + +#ifdef BME68X_USE_FPU + +/* 0 degree Celsius */ +#define BME68X_MIN_TEMPERATURE INT16_C(0) + +/* 60 degree Celsius */ +#define BME68X_MAX_TEMPERATURE INT16_C(60) + +/* 900 hecto Pascals */ +#define BME68X_MIN_PRESSURE UINT32_C(90000) + +/* 1100 hecto Pascals */ +#define BME68X_MAX_PRESSURE UINT32_C(110000) + +/* 20% relative humidity */ +#define BME68X_MIN_HUMIDITY UINT32_C(20) + +/* 80% relative humidity*/ +#define BME68X_MAX_HUMIDITY UINT32_C(80) +#else + +/* 0 degree Celsius */ +#define BME68X_MIN_TEMPERATURE INT16_C(0) + +/* 60 degree Celsius */ +#define BME68X_MAX_TEMPERATURE INT16_C(6000) + +/* 900 hecto Pascals */ +#define BME68X_MIN_PRESSURE UINT32_C(90000) + +/* 1100 hecto Pascals */ +#define BME68X_MAX_PRESSURE UINT32_C(110000) + +/* 20% relative humidity */ +#define BME68X_MIN_HUMIDITY UINT32_C(20000) + +/* 80% relative humidity*/ +#define BME68X_MAX_HUMIDITY UINT32_C(80000) + +#endif + +#define BME68X_HEATR_DUR1 UINT16_C(1000) +#define BME68X_HEATR_DUR2 UINT16_C(2000) +#define BME68X_HEATR_DUR1_DELAY UINT32_C(1000000) +#define BME68X_HEATR_DUR2_DELAY UINT32_C(2000000) +#define BME68X_N_MEAS UINT8_C(6) +#define BME68X_LOW_TEMP UINT8_C(150) +#define BME68X_HIGH_TEMP UINT16_C(350) + +/* Mask macros */ +/* Mask for number of conversions */ +#define BME68X_NBCONV_MSK UINT8_C(0X0f) + +/* Mask for IIR filter */ +#define BME68X_FILTER_MSK UINT8_C(0X1c) + +/* Mask for ODR[3] */ +#define BME68X_ODR3_MSK UINT8_C(0x80) + +/* Mask for ODR[2:0] */ +#define BME68X_ODR20_MSK UINT8_C(0xe0) + +/* Mask for temperature oversampling */ +#define BME68X_OST_MSK UINT8_C(0Xe0) + +/* Mask for pressure oversampling */ +#define BME68X_OSP_MSK UINT8_C(0X1c) + +/* Mask for humidity oversampling */ +#define BME68X_OSH_MSK UINT8_C(0X07) + +/* Mask for heater control */ +#define BME68X_HCTRL_MSK UINT8_C(0x08) + +/* Mask for run gas */ +#define BME68X_RUN_GAS_MSK UINT8_C(0x30) + +/* Mask for operation mode */ +#define BME68X_MODE_MSK UINT8_C(0x03) + +/* Mask for res heat range */ +#define BME68X_RHRANGE_MSK UINT8_C(0x30) + +/* Mask for range switching error */ +#define BME68X_RSERROR_MSK UINT8_C(0xf0) + +/* Mask for new data */ +#define BME68X_NEW_DATA_MSK UINT8_C(0x80) + +/* Mask for gas index */ +#define BME68X_GAS_INDEX_MSK UINT8_C(0x0f) + +/* Mask for gas range */ +#define BME68X_GAS_RANGE_MSK UINT8_C(0x0f) + +/* Mask for gas measurement valid */ +#define BME68X_GASM_VALID_MSK UINT8_C(0x20) + +/* Mask for heater stability */ +#define BME68X_HEAT_STAB_MSK UINT8_C(0x10) + +/* Mask for SPI memory page */ +#define BME68X_MEM_PAGE_MSK UINT8_C(0x10) + +/* Mask for reading a register in SPI */ +#define BME68X_SPI_RD_MSK UINT8_C(0x80) + +/* Mask for writing a register in SPI */ +#define BME68X_SPI_WR_MSK UINT8_C(0x7f) + +/* Mask for the H1 calibration coefficient */ +#define BME68X_BIT_H1_DATA_MSK UINT8_C(0x0f) + +/* Position macros */ + +/* Filter bit position */ +#define BME68X_FILTER_POS UINT8_C(2) + +/* Temperature oversampling bit position */ +#define BME68X_OST_POS UINT8_C(5) + +/* Pressure oversampling bit position */ +#define BME68X_OSP_POS UINT8_C(2) + +/* ODR[3] bit position */ +#define BME68X_ODR3_POS UINT8_C(7) + +/* ODR[2:0] bit position */ +#define BME68X_ODR20_POS UINT8_C(5) + +/* Run gas bit position */ +#define BME68X_RUN_GAS_POS UINT8_C(4) + +/* Heater control bit position */ +#define BME68X_HCTRL_POS UINT8_C(3) + +/* Macro to combine two 8 bit data's to form a 16 bit data */ +#define BME68X_CONCAT_BYTES(msb, lsb) (((uint16_t)msb << 8) | (uint16_t)lsb) + +/* Macro to set bits */ +#define BME68X_SET_BITS(reg_data, bitname, data) \ + ((reg_data & ~(bitname##_MSK)) | \ + ((data << bitname##_POS) & bitname##_MSK)) + +/* Macro to get bits */ +#define BME68X_GET_BITS(reg_data, bitname) ((reg_data & (bitname##_MSK)) >> \ + (bitname##_POS)) + +/* Macro to set bits starting from position 0 */ +#define BME68X_SET_BITS_POS_0(reg_data, bitname, data) \ + ((reg_data & ~(bitname##_MSK)) | \ + (data & bitname##_MSK)) + +/* Macro to get bits starting from position 0 */ +#define BME68X_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK)) + +/** + * BME68X_INTF_RET_TYPE is the read/write interface return type which can be overwritten by the build system. + * The default is set to int8_t. + */ +#ifndef BME68X_INTF_RET_TYPE +#define BME68X_INTF_RET_TYPE int8_t +#endif + +/** + * BME68X_INTF_RET_SUCCESS is the success return value read/write interface return type which can be + * overwritten by the build system. The default is set to 0. It is used to check for a successful + * execution of the read/write functions + */ +#ifndef BME68X_INTF_RET_SUCCESS +#define BME68X_INTF_RET_SUCCESS INT8_C(0) +#endif + +/********************************************************* */ +/*! Function Pointers */ +/********************************************************* */ + +/*! + * @brief Bus communication function pointer which should be mapped to + * the platform specific read functions of the user + * + * @param[in] reg_addr : 8bit register address of the sensor + * @param[out] reg_data : Data from the specified address + * @param[in] length : Length of the reg_data array + * @param[in,out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related callbacks + * @retval 0 for Success + * @retval Non-zero for Failure + */ +typedef BME68X_INTF_RET_TYPE (*bme68x_read_fptr_t)(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, + void *intf_ptr); + +/*! + * @brief Bus communication function pointer which should be mapped to + * the platform specific write functions of the user + * + * @param[in] reg_addr : 8bit register address of the sensor + * @param[out] reg_data : Data to the specified address + * @param[in] length : Length of the reg_data array + * @param[in,out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related callbacks + * @retval 0 for Success + * @retval Non-zero for Failure + * + */ +typedef BME68X_INTF_RET_TYPE (*bme68x_write_fptr_t)(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, + void *intf_ptr); + +/*! + * @brief Delay function pointer which should be mapped to + * delay function of the user + * + * @param period - The time period in microseconds + * @param[in,out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related callbacks + */ +typedef void (*bme68x_delay_us_fptr_t)(uint32_t period, void *intf_ptr); + +/* + * @brief Generic communication function pointer + * @param[in] dev_id: Place holder to store the id of the device structure + * Can be used to store the index of the Chip select or + * I2C address of the device. + * @param[in] reg_addr: Used to select the register the where data needs to + * be read from or written to. + * @param[in,out] reg_data: Data array to read/write + * @param[in] len: Length of the data array + */ + +/* + * @brief Interface selection Enumerations + */ +enum bme68x_intf { + /*! SPI interface */ + BME68X_SPI_INTF, + /*! I2C interface */ + BME68X_I2C_INTF +}; + +/* Structure definitions */ + +/* + * @brief Sensor field data structure + */ +struct bme68x_data +{ + /*! Contains new_data, gasm_valid & heat_stab */ + uint8_t status; + + /*! The index of the heater profile used */ + uint8_t gas_index; + + /*! Measurement index to track order */ + uint8_t meas_index; + + /*! Heater resistance */ + uint8_t res_heat; + + /*! Current DAC */ + uint8_t idac; + + /*! Gas wait period */ + uint8_t gas_wait; +#ifndef BME68X_USE_FPU + + /*! Temperature in degree celsius x100 */ + int16_t temperature; + + /*! Pressure in Pascal */ + uint32_t pressure; + + /*! Humidity in % relative humidity x1000 */ + uint32_t humidity; + + /*! Gas resistance in Ohms */ + uint32_t gas_resistance; +#else + + /*! Temperature in degree celsius */ + float temperature; + + /*! Pressure in Pascal */ + float pressure; + + /*! Humidity in % relative humidity x1000 */ + float humidity; + + /*! Gas resistance in Ohms */ + float gas_resistance; + +#endif + +}; + +/* + * @brief Structure to hold the calibration coefficients + */ +struct bme68x_calib_data +{ + /*! Calibration coefficient for the humidity sensor */ + uint16_t par_h1; + + /*! Calibration coefficient for the humidity sensor */ + uint16_t par_h2; + + /*! Calibration coefficient for the humidity sensor */ + int8_t par_h3; + + /*! Calibration coefficient for the humidity sensor */ + int8_t par_h4; + + /*! Calibration coefficient for the humidity sensor */ + int8_t par_h5; + + /*! Calibration coefficient for the humidity sensor */ + uint8_t par_h6; + + /*! Calibration coefficient for the humidity sensor */ + int8_t par_h7; + + /*! Calibration coefficient for the gas sensor */ + int8_t par_gh1; + + /*! Calibration coefficient for the gas sensor */ + int16_t par_gh2; + + /*! Calibration coefficient for the gas sensor */ + int8_t par_gh3; + + /*! Calibration coefficient for the temperature sensor */ + uint16_t par_t1; + + /*! Calibration coefficient for the temperature sensor */ + int16_t par_t2; + + /*! Calibration coefficient for the temperature sensor */ + int8_t par_t3; + + /*! Calibration coefficient for the pressure sensor */ + uint16_t par_p1; + + /*! Calibration coefficient for the pressure sensor */ + int16_t par_p2; + + /*! Calibration coefficient for the pressure sensor */ + int8_t par_p3; + + /*! Calibration coefficient for the pressure sensor */ + int16_t par_p4; + + /*! Calibration coefficient for the pressure sensor */ + int16_t par_p5; + + /*! Calibration coefficient for the pressure sensor */ + int8_t par_p6; + + /*! Calibration coefficient for the pressure sensor */ + int8_t par_p7; + + /*! Calibration coefficient for the pressure sensor */ + int16_t par_p8; + + /*! Calibration coefficient for the pressure sensor */ + int16_t par_p9; + + /*! Calibration coefficient for the pressure sensor */ + uint8_t par_p10; +#ifndef BME68X_USE_FPU + + /*! Variable to store the intermediate temperature coefficient */ + int32_t t_fine; +#else + + /*! Variable to store the intermediate temperature coefficient */ + float t_fine; +#endif + + /*! Heater resistance range coefficient */ + uint8_t res_heat_range; + + /*! Heater resistance value coefficient */ + int8_t res_heat_val; + + /*! Gas resistance range switching error coefficient */ + int8_t range_sw_err; +}; + +/* + * @brief BME68X sensor settings structure which comprises of ODR, + * over-sampling and filter settings. + */ +struct bme68x_conf +{ + /*! Humidity oversampling. Refer @ref osx*/ + uint8_t os_hum; + + /*! Temperature oversampling. Refer @ref osx */ + uint8_t os_temp; + + /*! Pressure oversampling. Refer @ref osx */ + uint8_t os_pres; + + /*! Filter coefficient. Refer @ref filter*/ + uint8_t filter; + + /*! + * Standby time between sequential mode measurement profiles. + * Refer @ref odr + */ + uint8_t odr; +}; + +/* + * @brief BME68X gas heater configuration + */ +struct bme68x_heatr_conf +{ + /*! Enable gas measurement. Refer @ref en_dis */ + uint8_t enable; + + /*! Store the heater temperature for forced mode degree Celsius */ + uint16_t heatr_temp; + + /*! Store the heating duration for forced mode in milliseconds */ + uint16_t heatr_dur; + + /*! Store the heater temperature profile in degree Celsius */ + uint16_t *heatr_temp_prof; + + /*! Store the heating duration profile in milliseconds */ + uint16_t *heatr_dur_prof; + + /*! Variable to store the length of the heating profile */ + uint8_t profile_len; + + /*! + * Variable to store heating duration for parallel mode + * in milliseconds + */ + uint16_t shared_heatr_dur; +}; + +/* + * @brief BME68X device structure + */ +struct bme68x_dev +{ + /*! Chip Id */ + uint8_t chip_id; + + /*! + * The interface pointer is used to enable the user + * to link their interface descriptors for reference during the + * implementation of the read and write interfaces to the + * hardware. + */ + void *intf_ptr; + + /*! + * Variant id + * ---------------------------------------- + * Value | Variant + * ---------------------------------------- + * 0 | BME68X_VARIANT_GAS_LOW + * 1 | BME68X_VARIANT_GAS_HIGH + * ---------------------------------------- + */ + uint32_t variant_id; + + /*! SPI/I2C interface */ + enum bme68x_intf intf; + + /*! Memory page used */ + uint8_t mem_page; + + /*! Ambient temperature in Degree C*/ + int8_t amb_temp; + + /*! Sensor calibration data */ + struct bme68x_calib_data calib; + + /*! Read function pointer */ + bme68x_read_fptr_t read; + + /*! Write function pointer */ + bme68x_write_fptr_t write; + + /*! Delay function pointer */ + bme68x_delay_us_fptr_t delay_us; + + /*! To store interface pointer error */ + BME68X_INTF_RET_TYPE intf_rslt; + + /*! Store the info messages */ + uint8_t info_msg; +}; + +#endif /* BME68X_DEFS_H_ */ +/*! @endcond */ diff --git a/lib/lib_i2c/BME68x-Sensor-API/examples/common/common.c b/lib/lib_i2c/BME68x-Sensor-API/examples/common/common.c new file mode 100644 index 000000000..9439ebb31 --- /dev/null +++ b/lib/lib_i2c/BME68x-Sensor-API/examples/common/common.c @@ -0,0 +1,191 @@ +/** + * Copyright (C) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "bme68x.h" +#include "coines.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definitions */ +/*! BME68X shuttle board ID */ +#define BME68X_SHUTTLE_ID 0x93 + +/******************************************************************************/ +/*! Static variable definition */ +static uint8_t dev_addr; + +/******************************************************************************/ +/*! User interface functions */ + +/*! + * I2C read function map to COINES platform + */ +BME68X_INTF_RET_TYPE bme68x_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) +{ + uint8_t dev_addr = *(uint8_t*)intf_ptr; + + return coines_read_i2c(dev_addr, reg_addr, reg_data, (uint16_t)len); +} + +/*! + * I2C write function map to COINES platform + */ +BME68X_INTF_RET_TYPE bme68x_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr) +{ + uint8_t dev_addr = *(uint8_t*)intf_ptr; + + return coines_write_i2c(dev_addr, reg_addr, (uint8_t *)reg_data, (uint16_t)len); +} + +/*! + * SPI read function map to COINES platform + */ +BME68X_INTF_RET_TYPE bme68x_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) +{ + uint8_t dev_addr = *(uint8_t*)intf_ptr; + + return coines_read_spi(dev_addr, reg_addr, reg_data, (uint16_t)len); +} + +/*! + * SPI write function map to COINES platform + */ +BME68X_INTF_RET_TYPE bme68x_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr) +{ + uint8_t dev_addr = *(uint8_t*)intf_ptr; + + return coines_write_spi(dev_addr, reg_addr, (uint8_t *)reg_data, (uint16_t)len); +} + +/*! + * Delay function map to COINES platform + */ +void bme68x_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +void bme68x_check_rslt(const char api_name[], int8_t rslt) +{ + switch (rslt) + { + case BME68X_OK: + + /* Do nothing */ + break; + case BME68X_E_NULL_PTR: + printf("API name [%s] Error [%d] : Null pointer\r\n", api_name, rslt); + break; + case BME68X_E_COM_FAIL: + printf("API name [%s] Error [%d] : Communication failure\r\n", api_name, rslt); + break; + case BME68X_E_INVALID_LENGTH: + printf("API name [%s] Error [%d] : Incorrect length parameter\r\n", api_name, rslt); + break; + case BME68X_E_DEV_NOT_FOUND: + printf("API name [%s] Error [%d] : Device not found\r\n", api_name, rslt); + break; + case BME68X_E_SELF_TEST: + printf("API name [%s] Error [%d] : Self test error\r\n", api_name, rslt); + break; + case BME68X_W_NO_NEW_DATA: + printf("API name [%s] Warning [%d] : No new data found\r\n", api_name, rslt); + break; + default: + printf("API name [%s] Error [%d] : Unknown error code\r\n", api_name, rslt); + break; + } +} + +int8_t bme68x_interface_init(struct bme68x_dev *bme, uint8_t intf) +{ + int8_t rslt = BME68X_OK; + struct coines_board_info board_info; + + if (bme != NULL) + { + int16_t result = coines_open_comm_intf(COINES_COMM_INTF_USB); + if (result < COINES_SUCCESS) + { + printf( + "\n Unable to connect with Application Board ! \n" " 1. Check if the board is connected and powered on. \n" " 2. Check if Application Board USB driver is installed. \n" + " 3. Check if board is in use by another application. (Insufficient permissions to access USB) \n"); + exit(result); + } + + result = coines_get_board_info(&board_info); + +#if defined(PC) + setbuf(stdout, NULL); +#endif + + if (result == COINES_SUCCESS) + { + if ((board_info.shuttle_id != BME68X_SHUTTLE_ID)) + { + printf("! Warning invalid sensor shuttle \n ," "This application will not support this sensor \n"); + exit(COINES_E_FAILURE); + } + } + + coines_set_shuttleboard_vdd_vddio_config(0, 0); + coines_delay_msec(100); + + /* Bus configuration : I2C */ + if (intf == BME68X_I2C_INTF) + { + printf("I2C Interface\n"); + dev_addr = BME68X_I2C_ADDR_LOW; + bme->read = bme68x_i2c_read; + bme->write = bme68x_i2c_write; + bme->intf = BME68X_I2C_INTF; + coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_STANDARD_MODE); + } + /* Bus configuration : SPI */ + else if (intf == BME68X_SPI_INTF) + { + printf("SPI Interface\n"); + dev_addr = COINES_SHUTTLE_PIN_7; + bme->read = bme68x_spi_read; + bme->write = bme68x_spi_write; + bme->intf = BME68X_SPI_INTF; + coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_7_5_MHZ, COINES_SPI_MODE0); + } + + coines_delay_msec(100); + + coines_set_shuttleboard_vdd_vddio_config(3300, 3300); + + coines_delay_msec(100); + + bme->delay_us = bme68x_delay_us; + bme->intf_ptr = &dev_addr; + bme->amb_temp = 25; /* The ambient temperature in deg C is used for defining the heater temperature */ + } + else + { + rslt = BME68X_E_NULL_PTR; + } + + return rslt; +} + +void bme68x_coines_deinit(void) +{ + fflush(stdout); + + coines_set_shuttleboard_vdd_vddio_config(0, 0); + coines_delay_msec(1000); + + /* Coines interface reset */ + coines_soft_reset(); + coines_delay_msec(1000); + coines_close_comm_intf(COINES_COMM_INTF_USB); +} diff --git a/lib/lib_i2c/BME68x-Sensor-API/examples/common/common.h b/lib/lib_i2c/BME68x-Sensor-API/examples/common/common.h new file mode 100644 index 000000000..5560f3712 --- /dev/null +++ b/lib/lib_i2c/BME68x-Sensor-API/examples/common/common.h @@ -0,0 +1,116 @@ +/** + * Copyright (C) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +#include "bme68x.h" + +/*! + * @brief Function to select the interface between SPI and I2C. + * + * @param[in] bme : Structure instance of bme68x_dev + * @param[in] intf : Interface selection parameter + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +int8_t bme68x_interface_init(struct bme68x_dev *bme, uint8_t intf); + +/*! + * @brief Function for reading the sensor's registers through I2C bus. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Pointer to the data buffer to store the read data. + * @param[in] len : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval = BME68X_INTF_RET_SUCCESS -> Success + * @retval != BME68X_INTF_RET_SUCCESS -> Failure Info + * + */ +BME68X_INTF_RET_TYPE bme68x_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr); + +/*! + * @brief Function for writing the sensor's registers through I2C bus. + * + * @param[in] reg_addr : Register address. + * @param[in] reg_data : Pointer to the data buffer whose value is to be written. + * @param[in] len : No of bytes to write. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval = BME68X_INTF_RET_SUCCESS -> Success + * @retval != BME68X_INTF_RET_SUCCESS -> Failure Info + * + */ +BME68X_INTF_RET_TYPE bme68x_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr); + +/*! + * @brief Function for reading the sensor's registers through SPI bus. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Pointer to the data buffer to store the read data. + * @param[in] len : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval = BME68X_INTF_RET_SUCCESS -> Success + * @retval != BME68X_INTF_RET_SUCCESS -> Failure Info + * + */ +BME68X_INTF_RET_TYPE bme68x_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr); + +/*! + * @brief Function for writing the sensor's registers through SPI bus. + * + * @param[in] reg_addr : Register address. + * @param[in] reg_data : Pointer to the data buffer whose data has to be written. + * @param[in] len : No of bytes to write. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval = BME68X_INTF_RET_SUCCESS -> Success + * @retval != BME68X_INTF_RET_SUCCESS -> Failure Info + * + */ +BME68X_INTF_RET_TYPE bme68x_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + * + */ +void bme68x_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief Prints the execution status of the APIs. + * + * @param[in] api_name : Name of the API whose execution status has to be printed. + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +void bme68x_check_rslt(const char api_name[], int8_t rslt); + +/*! + * @brief Deinitializes coines platform + * + * @return void. + */ +void bme68x_coines_deinit(void); + +#ifdef __cplusplus +} +#endif /*__cplusplus */ diff --git a/lib/lib_i2c/BME68x-Sensor-API/examples/forced_mode/Makefile b/lib/lib_i2c/BME68x-Sensor-API/examples/forced_mode/Makefile new file mode 100644 index 000000000..095e56614 --- /dev/null +++ b/lib/lib_i2c/BME68x-Sensor-API/examples/forced_mode/Makefile @@ -0,0 +1,15 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= forced_mode.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bme68x.c \ +../common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +../common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/lib/lib_i2c/BME68x-Sensor-API/examples/forced_mode/forced_mode.c b/lib/lib_i2c/BME68x-Sensor-API/examples/forced_mode/forced_mode.c new file mode 100644 index 000000000..4991df45a --- /dev/null +++ b/lib/lib_i2c/BME68x-Sensor-API/examples/forced_mode/forced_mode.c @@ -0,0 +1,108 @@ +/** + * Copyright (C) 2021 Bosch Sensortec GmbH + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include "bme68x.h" +#include "common.h" +#include "coines.h" + +/***********************************************************************/ +/* Macros */ +/***********************************************************************/ + +/* Macro for count of samples to be displayed */ +#define SAMPLE_COUNT UINT16_C(300) + +/***********************************************************************/ +/* Test code */ +/***********************************************************************/ + +int main(void) +{ + struct bme68x_dev bme; + int8_t rslt; + struct bme68x_conf conf; + struct bme68x_heatr_conf heatr_conf; + struct bme68x_data data; + uint32_t del_period; + uint32_t time_ms = 0; + uint8_t n_fields; + uint16_t sample_count = 1; + + /* Interface preference is updated as a parameter + * For I2C : BME68X_I2C_INTF + * For SPI : BME68X_SPI_INTF + */ + rslt = bme68x_interface_init(&bme, BME68X_I2C_INTF); + bme68x_check_rslt("bme68x_interface_init", rslt); + + rslt = bme68x_init(&bme); + bme68x_check_rslt("bme68x_init", rslt); + + /* Check if rslt == BME68X_OK, report or handle if otherwise */ + conf.filter = BME68X_FILTER_OFF; + conf.odr = BME68X_ODR_NONE; + conf.os_hum = BME68X_OS_16X; + conf.os_pres = BME68X_OS_1X; + conf.os_temp = BME68X_OS_2X; + rslt = bme68x_set_conf(&conf, &bme); + bme68x_check_rslt("bme68x_set_conf", rslt); + + /* Check if rslt == BME68X_OK, report or handle if otherwise */ + heatr_conf.enable = BME68X_ENABLE; + heatr_conf.heatr_temp = 300; + heatr_conf.heatr_dur = 100; + rslt = bme68x_set_heatr_conf(BME68X_FORCED_MODE, &heatr_conf, &bme); + bme68x_check_rslt("bme68x_set_heatr_conf", rslt); + + printf("Sample, TimeStamp(ms), Temperature(deg C), Pressure(Pa), Humidity(%%), Gas resistance(ohm), Status\n"); + + while (sample_count <= SAMPLE_COUNT) + { + rslt = bme68x_set_op_mode(BME68X_FORCED_MODE, &bme); + bme68x_check_rslt("bme68x_set_op_mode", rslt); + + /* Calculate delay period in microseconds */ + del_period = bme68x_get_meas_dur(BME68X_FORCED_MODE, &conf, &bme) + (heatr_conf.heatr_dur * 1000); + bme.delay_us(del_period, bme.intf_ptr); + + time_ms = coines_get_millis(); + + /* Check if rslt == BME68X_OK, report or handle if otherwise */ + rslt = bme68x_get_data(BME68X_FORCED_MODE, &data, &n_fields, &bme); + bme68x_check_rslt("bme68x_get_data", rslt); + + if (n_fields) + { +#ifdef BME68X_USE_FPU + printf("%u, %lu, %.2f, %.2f, %.2f, %.2f, 0x%x\n", + sample_count, + (long unsigned int)time_ms, + data.temperature, + data.pressure, + data.humidity, + data.gas_resistance, + data.status); +#else + printf("%u, %lu, %d, %lu, %lu, %lu, 0x%x\n", + sample_count, + (long unsigned int)time_ms, + (data.temperature / 100), + (long unsigned int)data.pressure, + (long unsigned int)(data.humidity / 1000), + (long unsigned int)data.gas_resistance, + data.status); +#endif + sample_count++; + } + } + + bme68x_coines_deinit(); + + return rslt; +} diff --git a/lib/lib_i2c/BME68x-Sensor-API/examples/parallel_mode/Makefile b/lib/lib_i2c/BME68x-Sensor-API/examples/parallel_mode/Makefile new file mode 100644 index 000000000..5f939662e --- /dev/null +++ b/lib/lib_i2c/BME68x-Sensor-API/examples/parallel_mode/Makefile @@ -0,0 +1,15 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= parallel_mode.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bme68x.c \ +../common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +../common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/lib/lib_i2c/BME68x-Sensor-API/examples/parallel_mode/parallel_mode.c b/lib/lib_i2c/BME68x-Sensor-API/examples/parallel_mode/parallel_mode.c new file mode 100644 index 000000000..ec4011d61 --- /dev/null +++ b/lib/lib_i2c/BME68x-Sensor-API/examples/parallel_mode/parallel_mode.c @@ -0,0 +1,141 @@ +/** + * Copyright (C) 2021 Bosch Sensortec GmbH + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include "bme68x.h" +#include "common.h" +#include "coines.h" + +/***********************************************************************/ +/* Macros */ +/***********************************************************************/ + +/* + * Macro definition for valid new data (0x80) AND + * heater stability (0x10) AND gas resistance (0x20) values + */ +#define BME68X_VALID_DATA UINT8_C(0xB0) + +/* Macro for count of samples to be displayed */ +#define SAMPLE_COUNT UINT8_C(50) + +/***********************************************************************/ +/* Test code */ +/***********************************************************************/ + +int main(void) +{ + struct bme68x_dev bme; + int8_t rslt; + struct bme68x_conf conf; + struct bme68x_heatr_conf heatr_conf; + struct bme68x_data data[3]; + uint32_t del_period; + uint8_t n_fields; + uint32_t time_ms = 0; + uint16_t sample_count = 1; + + /* Heater temperature in degree Celsius */ + uint16_t temp_prof[10] = { 320, 100, 100, 100, 200, 200, 200, 320, 320, 320 }; + + /* Multiplier to the shared heater duration */ + uint16_t mul_prof[10] = { 5, 2, 10, 30, 5, 5, 5, 5, 5, 5 }; + + /* Interface preference is updated as a parameter + * For I2C : BME68X_I2C_INTF + * For SPI : BME68X_SPI_INTF + */ + rslt = bme68x_interface_init(&bme, BME68X_I2C_INTF); + bme68x_check_rslt("bme68x_interface_init", rslt); + + rslt = bme68x_init(&bme); + bme68x_check_rslt("bme68x_init", rslt); + + /* Check if rslt == BME68X_OK, report or handle if otherwise */ + rslt = bme68x_get_conf(&conf, &bme); + bme68x_check_rslt("bme68x_get_conf", rslt); + + /* Check if rslt == BME68X_OK, report or handle if otherwise */ + conf.filter = BME68X_FILTER_OFF; + conf.odr = BME68X_ODR_NONE; + conf.os_hum = BME68X_OS_1X; + conf.os_pres = BME68X_OS_16X; + conf.os_temp = BME68X_OS_2X; + rslt = bme68x_set_conf(&conf, &bme); + bme68x_check_rslt("bme68x_set_conf", rslt); + + /* Check if rslt == BME68X_OK, report or handle if otherwise */ + heatr_conf.enable = BME68X_ENABLE; + heatr_conf.heatr_temp_prof = temp_prof; + heatr_conf.heatr_dur_prof = mul_prof; + + /* Shared heating duration in milliseconds */ + heatr_conf.shared_heatr_dur = 140 - (bme68x_get_meas_dur(BME68X_PARALLEL_MODE, &conf, &bme) / 1000); + + heatr_conf.profile_len = 10; + rslt = bme68x_set_heatr_conf(BME68X_PARALLEL_MODE, &heatr_conf, &bme); + bme68x_check_rslt("bme68x_set_heatr_conf", rslt); + + /* Check if rslt == BME68X_OK, report or handle if otherwise */ + rslt = bme68x_set_op_mode(BME68X_PARALLEL_MODE, &bme); + bme68x_check_rslt("bme68x_set_op_mode", rslt); + + printf( + "Print parallel mode data if mask for new data(0x80), gas measurement(0x20) and heater stability(0x10) are set\n\n"); + + /* Check if rslt == BME68X_OK, report or handle if otherwise */ + printf( + "Sample, TimeStamp(ms), Temperature(deg C), Pressure(Pa), Humidity(%%), Gas resistance(ohm), Status, Gas index, Meas index\n"); + while (sample_count <= SAMPLE_COUNT) + { + /* Calculate delay period in microseconds */ + del_period = bme68x_get_meas_dur(BME68X_PARALLEL_MODE, &conf, &bme) + (heatr_conf.shared_heatr_dur * 1000); + bme.delay_us(del_period, bme.intf_ptr); + + time_ms = coines_get_millis(); + + rslt = bme68x_get_data(BME68X_PARALLEL_MODE, data, &n_fields, &bme); + bme68x_check_rslt("bme68x_get_data", rslt); + + /* Check if rslt == BME68X_OK, report or handle if otherwise */ + for (uint8_t i = 0; i < n_fields; i++) + { + if (data[i].status == BME68X_VALID_DATA) + { +#ifdef BME68X_USE_FPU + printf("%u, %lu, %.2f, %.2f, %.2f, %.2f, 0x%x, %d, %d\n", + sample_count, + (long unsigned int)time_ms, + data[i].temperature, + data[i].pressure, + data[i].humidity, + data[i].gas_resistance, + data[i].status, + data[i].gas_index, + data[i].meas_index); +#else + printf("%u, %lu, %d, %lu, %lu, %lu, 0x%x, %d, %d\n", + sample_count, + (long unsigned int)time_ms, + (data[i].temperature / 100), + (long unsigned int)data[i].pressure, + (long unsigned int)(data[i].humidity / 1000), + (long unsigned int)data[i].gas_resistance, + data[i].status, + data[i].gas_index, + data[i].meas_index); +#endif + sample_count++; + } + } + } + + bme68x_coines_deinit(); + + return 0; +} diff --git a/lib/lib_i2c/BME68x-Sensor-API/examples/self_test/Makefile b/lib/lib_i2c/BME68x-Sensor-API/examples/self_test/Makefile new file mode 100644 index 000000000..71a84bf0d --- /dev/null +++ b/lib/lib_i2c/BME68x-Sensor-API/examples/self_test/Makefile @@ -0,0 +1,15 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= self_test.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bme68x.c \ +../common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +../common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/lib/lib_i2c/BME68x-Sensor-API/examples/self_test/self_test.c b/lib/lib_i2c/BME68x-Sensor-API/examples/self_test/self_test.c new file mode 100644 index 000000000..a6096a0e0 --- /dev/null +++ b/lib/lib_i2c/BME68x-Sensor-API/examples/self_test/self_test.c @@ -0,0 +1,49 @@ +/** + * Copyright (C) 2021 Bosch Sensortec GmbH + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include "bme68x.h" +#include "common.h" +#include "coines.h" + +/***********************************************************************/ +/* Test code */ +/***********************************************************************/ + +int main(void) +{ + struct bme68x_dev bme; + int8_t rslt; + + /* Interface preference is updated as a parameter + * For I2C : BME68X_I2C_INTF + * For SPI : BME68X_SPI_INTF + */ + rslt = bme68x_interface_init(&bme, BME68X_I2C_INTF); + bme68x_check_rslt("bme68x_interface_init", rslt); + + rslt = bme68x_init(&bme); + bme68x_check_rslt("bme68x_init", rslt); + + rslt = bme68x_selftest_check(&bme); + bme68x_check_rslt("bme68x_selftest_check", rslt); + + if (rslt == BME68X_OK) + { + printf("Self-test passed\n"); + } + + if (rslt == BME68X_E_SELF_TEST) + { + printf("Self-test failed\n"); + } + + bme68x_coines_deinit(); + + return rslt; +} diff --git a/lib/lib_i2c/BME68x-Sensor-API/examples/sequential_mode/Makefile b/lib/lib_i2c/BME68x-Sensor-API/examples/sequential_mode/Makefile new file mode 100644 index 000000000..cfd7a6bf3 --- /dev/null +++ b/lib/lib_i2c/BME68x-Sensor-API/examples/sequential_mode/Makefile @@ -0,0 +1,15 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= sequential_mode.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bme68x.c \ +../common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +../common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/lib/lib_i2c/BME68x-Sensor-API/examples/sequential_mode/sequential_mode.c b/lib/lib_i2c/BME68x-Sensor-API/examples/sequential_mode/sequential_mode.c new file mode 100644 index 000000000..0717cf9c1 --- /dev/null +++ b/lib/lib_i2c/BME68x-Sensor-API/examples/sequential_mode/sequential_mode.c @@ -0,0 +1,125 @@ +/** + * Copyright (C) 2021 Bosch Sensortec GmbH + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include "bme68x.h" +#include "common.h" +#include "coines.h" + +/***********************************************************************/ +/* Macros */ +/***********************************************************************/ + +/* Macro for count of samples to be displayed */ +#define SAMPLE_COUNT UINT8_C(300) + +/***********************************************************************/ +/* Test code */ +/***********************************************************************/ + +int main(void) +{ + struct bme68x_dev bme; + int8_t rslt; + struct bme68x_conf conf; + struct bme68x_heatr_conf heatr_conf; + struct bme68x_data data[3]; + uint32_t del_period; + uint32_t time_ms = 0; + uint8_t n_fields; + uint16_t sample_count = 1; + + /* Heater temperature in degree Celsius */ + uint16_t temp_prof[10] = { 200, 240, 280, 320, 360, 360, 320, 280, 240, 200 }; + + /* Heating duration in milliseconds */ + uint16_t dur_prof[10] = { 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 }; + + /* Interface preference is updated as a parameter + * For I2C : BME68X_I2C_INTF + * For SPI : BME68X_SPI_INTF + */ + rslt = bme68x_interface_init(&bme, BME68X_I2C_INTF); + bme68x_check_rslt("bme68x_interface_init", rslt); + + rslt = bme68x_init(&bme); + bme68x_check_rslt("bme68x_init", rslt); + + /* Check if rslt == BME68X_OK, report or handle if otherwise */ + rslt = bme68x_get_conf(&conf, &bme); + bme68x_check_rslt("bme68x_get_conf", rslt); + + /* Check if rslt == BME68X_OK, report or handle if otherwise */ + conf.filter = BME68X_FILTER_OFF; + conf.odr = BME68X_ODR_NONE; /* This parameter defines the sleep duration after each profile */ + conf.os_hum = BME68X_OS_16X; + conf.os_pres = BME68X_OS_1X; + conf.os_temp = BME68X_OS_2X; + rslt = bme68x_set_conf(&conf, &bme); + bme68x_check_rslt("bme68x_set_conf", rslt); + + /* Check if rslt == BME68X_OK, report or handle if otherwise */ + heatr_conf.enable = BME68X_ENABLE; + heatr_conf.heatr_temp_prof = temp_prof; + heatr_conf.heatr_dur_prof = dur_prof; + heatr_conf.profile_len = 10; + rslt = bme68x_set_heatr_conf(BME68X_SEQUENTIAL_MODE, &heatr_conf, &bme); + bme68x_check_rslt("bme68x_set_heatr_conf", rslt); + + /* Check if rslt == BME68X_OK, report or handle if otherwise */ + rslt = bme68x_set_op_mode(BME68X_SEQUENTIAL_MODE, &bme); + bme68x_check_rslt("bme68x_set_op_mode", rslt); + + /* Check if rslt == BME68X_OK, report or handle if otherwise */ + printf( + "Sample, TimeStamp(ms), Temperature(deg C), Pressure(Pa), Humidity(%%), Gas resistance(ohm), Status, Profile index, Measurement index\n"); + while (sample_count <= SAMPLE_COUNT) + { + /* Calculate delay period in microseconds */ + del_period = bme68x_get_meas_dur(BME68X_SEQUENTIAL_MODE, &conf, &bme) + (heatr_conf.heatr_dur_prof[0] * 1000); + bme.delay_us(del_period, bme.intf_ptr); + + time_ms = coines_get_millis(); + + rslt = bme68x_get_data(BME68X_SEQUENTIAL_MODE, data, &n_fields, &bme); + bme68x_check_rslt("bme68x_get_data", rslt); + + /* Check if rslt == BME68X_OK, report or handle if otherwise */ + for (uint8_t i = 0; i < n_fields; i++) + { +#ifdef BME68X_USE_FPU + printf("%u, %lu, %.2f, %.2f, %.2f, %.2f, 0x%x, %d, %d\n", + sample_count, + (long unsigned int)time_ms + (i * (del_period / 2000)), + data[i].temperature, + data[i].pressure, + data[i].humidity, + data[i].gas_resistance, + data[i].status, + data[i].gas_index, + data[i].meas_index); +#else + printf("%u, %lu, %d, %lu, %lu, %lu, 0x%x, %d, %d\n", + sample_count, + (long unsigned int)time_ms + (i * (del_period / 2000)), + (data[i].temperature / 100), + (long unsigned int)data[i].pressure, + (long unsigned int)(data[i].humidity / 1000), + (long unsigned int)data[i].gas_resistance, + data[i].status, + data[i].gas_index, + data[i].meas_index); +#endif + sample_count++; + } + } + + bme68x_coines_deinit(); + + return 0; +} diff --git a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/library.properties b/lib/lib_i2c/BME68x-Sensor-API/library.properties similarity index 50% rename from lib/lib_i2c/BME680_driver-bme680_v3.5.9/library.properties rename to lib/lib_i2c/BME68x-Sensor-API/library.properties index bf0211d28..751d48ad0 100644 --- a/lib/lib_i2c/BME680_driver-bme680_v3.5.9/library.properties +++ b/lib/lib_i2c/BME68x-Sensor-API/library.properties @@ -1,9 +1,9 @@ -name=BME680 +name=BME68x version= author= maintainer=Bosch Sensortec GmbH -sentence=Sensor driver for BME680 sensor -paragraph=Sensor driver for BME680 sensor +sentence=Sensor driver for BME68x sensor +paragraph=Sensor driver for BME68x sensor category=Sensor url= architectures=esp8266,esp32 diff --git a/lib/lib_i2c/mlx90640-library/MLX90640_API.cpp b/lib/lib_i2c/mlx90640-library/MLX90640_API.cpp index 8b1822bf4..f2a8731c3 100644 --- a/lib/lib_i2c/mlx90640-library/MLX90640_API.cpp +++ b/lib/lib_i2c/mlx90640-library/MLX90640_API.cpp @@ -42,7 +42,9 @@ int MLX90640_I2CRead(uint8_t addr, uint32_t reg, uint16_t len, uint16_t *reg_dat int MLX90640_I2CWrite(uint8_t _deviceAddress, unsigned int writeAddress, uint16_t data); // I2C -#define I2C_BUFFER_LENGTH 128 +#ifndef I2C_BUFFER_LENGTH + #define I2C_BUFFER_LENGTH 128 +#endif int MLX90640_I2CRead(uint8_t addr, uint32_t reg, uint16_t len, uint16_t *reg_data){ int bytesRemaining = len * 2; diff --git a/lib/lib_rf/rc-switch/src/RCSwitch.cpp b/lib/lib_rf/rc-switch/src/RCSwitch.cpp index aed787bea..69b3f37a3 100644 --- a/lib/lib_rf/rc-switch/src/RCSwitch.cpp +++ b/lib/lib_rf/rc-switch/src/RCSwitch.cpp @@ -149,7 +149,7 @@ static const RCSwitch::Protocol PROGMEM proto[] = { { 400, 0, { 0, 0 }, 1, { 1, 1 }, { 1, 2 }, { 2, 1 }, false, 43 }, // 31 (Mertik Maxitrol G6R-H4T1) { 365, 0, { 0, 0 }, 1, { 18, 1 }, { 3, 1 }, { 1, 3 }, true, 0 }, // 32 (1ByOne Doorbell) from @Fatbeard https://github.com/sui77/rc-switch/pull/277 { 340, 0, { 0, 0 }, 1, { 14, 4 }, { 1, 2 }, { 2, 1 }, false, 0 }, // 33 (Dooya Control DC2708L) - { 120, 0, { 0, 0 }, 1, { 1, 28 }, { 1, 3 }, { 3, 1 }, false, 0 }, // 34 DIGOO SD10 + { 120, 0, { 0, 0 }, 1, { 1, 28 }, { 1, 3 }, { 3, 1 }, false, 0 }, // 34 DIGOO SD10 - so as to use this protocol RCSWITCH_SEPARATION_LIMIT must be set to 2600 { 20, 0, { 0, 0 }, 1, { 239, 78 }, {20, 35 }, {35, 20}, false, 10000 } // 35 Dooya 5-Channel blinds remote DC1603 }; @@ -164,11 +164,7 @@ volatile unsigned int RCSwitch::nReceivedBitlength = 0; volatile unsigned int RCSwitch::nReceivedDelay = 0; volatile unsigned int RCSwitch::nReceivedProtocol = 0; int RCSwitch::nReceiveTolerance = 60; -const unsigned int RCSwitch::nSeparationLimit = 2600; // 4300 default -// separationLimit: minimum microseconds between received codes, closer codes are ignored. -// according to discussion on issue #14 it might be more suitable to set the separation -// limit to the same time as the 'low' part of the sync signal for the current protocol. -// should be set to the minimum value of pulselength * the sync signal +const unsigned int RCSwitch::nSeparationLimit = RCSWITCH_SEPARATION_LIMIT; unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES]; unsigned int RCSwitch::buftimings[4]; #endif diff --git a/lib/lib_rf/rc-switch/src/RCSwitch.h b/lib/lib_rf/rc-switch/src/RCSwitch.h index 613d654d7..6d660c0db 100644 --- a/lib/lib_rf/rc-switch/src/RCSwitch.h +++ b/lib/lib_rf/rc-switch/src/RCSwitch.h @@ -61,6 +61,12 @@ // Для keeloq нужно увеличить RCSWITCH_MAX_CHANGES до 23+1+66*2+1=157 #define RCSWITCH_MAX_CHANGES 67 // default 67 +// separationLimit: minimum microseconds between received codes, closer codes are ignored. +// according to discussion on issue #14 it might be more suitable to set the separation +// limit to the same time as the 'low' part of the sync signal for the current protocol. +// should be set to the minimum value of pulselength * the sync signal +#define RCSWITCH_SEPARATION_LIMIT 4100 + class RCSwitch { public: diff --git a/lib/lib_ssl/tls_mini/library.json b/lib/lib_ssl/tls_mini/library.json index 0faa39688..d93dfd353 100644 --- a/lib/lib_ssl/tls_mini/library.json +++ b/lib/lib_ssl/tls_mini/library.json @@ -4,8 +4,8 @@ "description": "TLS mini client derived from Arduino", "license": "MIT", "homepage": "https://github.com/arendst/Tasmota", - "frameworks": "*", - "platforms": "*", + "frameworks": "arduino", + "platforms": "espressif32, espressif8266", "authors": { "name": "Stephan Hadinger", diff --git a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp index 7be46adf0..d714c4bd0 100755 --- a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp +++ b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp @@ -21,7 +21,7 @@ */ #include "tasmota_options.h" -#if defined(USE_TLS) +#ifdef USE_TLS // #define DEBUG_TLS // #define DEBUG_ESP_SSL @@ -418,6 +418,10 @@ size_t WiFiClientSecure_light::_write(const uint8_t *buf, size_t size, bool pmem return sent_bytes; } +void WiFiClientSecure_light::setInsecure() { + _insecure = true; +} + size_t WiFiClientSecure_light::write(const uint8_t *buf, size_t size) { return _write(buf, size, false); } @@ -965,7 +969,7 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) { _freeSSL(); clearLastError(); #ifdef ESP8266 - if (!stack_thunk_light_get_stack_bot()) break; + if (!stack_thunk_light_get_stack_bot()) break; #endif // ESP8266 _ctx_present = true; diff --git a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h index 3736749ab..65a3544be 100755 --- a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h +++ b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h @@ -124,6 +124,8 @@ class WiFiClientSecure_light : public WiFiClient { return _max_thunkstack_use; } + void setInsecure(); + private: void _clear(); bool _ctx_present; @@ -152,7 +154,6 @@ class WiFiClientSecure_light : public WiFiClient { unsigned char *_recvapp_buf; size_t _recvapp_len; - bool _clientConnected(); // Is the underlying socket alive? bool _connectSSL(const char *hostName); // Do initial SSL handshake void _freeSSL(); diff --git a/lib/libesp32/Berry-HttpClientLight/library.json b/lib/libesp32/Berry-HttpClientLight/library.json index 1e1479bbb..c9e5208f9 100644 --- a/lib/libesp32/Berry-HttpClientLight/library.json +++ b/lib/libesp32/Berry-HttpClientLight/library.json @@ -4,8 +4,8 @@ "description": "Forked version of Arduino HttpClient to support BearSSL instead of mbedTLS", "license": "MIT", "homepage": "https://github.com/arendst/Tasmota", - "frameworks": "*", - "platforms": "*", + "frameworks": "arduino", + "platforms": "espressif32", "authors": { "name": "Stephan Hadinger", diff --git a/lib/libesp32/Berry-HttpClientLight/src/HttpClientLight.cpp b/lib/libesp32/Berry-HttpClientLight/src/HttpClientLight.cpp index 420cbfb71..1c1c6ac32 100644 --- a/lib/libesp32/Berry-HttpClientLight/src/HttpClientLight.cpp +++ b/lib/libesp32/Berry-HttpClientLight/src/HttpClientLight.cpp @@ -28,7 +28,6 @@ #ifdef ESP32 #include "tasmota_options.h" -#ifdef USE_BERRY #include #ifdef HTTPCLIENT_1_1_COMPATIBLE @@ -46,10 +45,10 @@ #endif // USE_WEBCLIENT_HTTPS // #ifdef HTTPCLIENT_1_1_COMPATIBLE -class TransportTraits +class TransportTraitsLight { public: - virtual ~TransportTraits() + virtual ~TransportTraitsLight() { } @@ -72,7 +71,7 @@ public: #ifdef USE_WEBCLIENT_HTTPS static const uint8_t _fingerprint_any[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; -class BearSSLTraits : public TransportTraits +class BearSSLTraits : public TransportTraitsLight { public: BearSSLTraits(int recv, int xmit) : @@ -221,7 +220,7 @@ bool HTTPClientLight::begin(String url, const char* CAcert) } _secure = true; #ifdef USE_WEBCLIENT_HTTPS - _transportTraits = TransportTraitsPtr(new BearSSLTraits(16384, 0)); + _transportTraits = TransportTraitsLightPtr(new BearSSLTraits(16384, 0)); // set buffer to 16KB half duplex, so we won't lose responses bigger than 16KB // half duplex is well suited for HTTPS: one request followed by responses #else @@ -251,7 +250,7 @@ bool HTTPClientLight::begin(String url) if (!beginInternal(url, "http")) { return begin(url, (const char*)NULL); } - _transportTraits = TransportTraitsPtr(new TransportTraits()); + _transportTraits = TransportTraitsLightPtr(new TransportTraitsLight()); if(!_transportTraits) { log_e("could not create transport traits"); return false; @@ -328,7 +327,7 @@ bool HTTPClientLight::beginInternal(String url, const char* expectedProtocol) // _host = host; // _port = port; // _uri = uri; -// // _transportTraits = TransportTraitsPtr(new TransportTraits()); TODO +// // _transportTraits = TransportTraitsLightPtr(new TransportTraitsLight()); TODO // _transportTraits = nullptr; // log_d("host: %s port: %d uri: %s", host.c_str(), port, uri.c_str()); // return true; @@ -351,7 +350,7 @@ bool HTTPClientLight::beginInternal(String url, const char* expectedProtocol) // return false; // } // _secure = true; -// _transportTraits = TransportTraitsPtr(new TLSTraits(CAcert)); +// _transportTraits = TransportTraitsLightPtr(new TLSTraits(CAcert)); // return true; // } @@ -372,7 +371,7 @@ bool HTTPClientLight::beginInternal(String url, const char* expectedProtocol) // return false; // } // _secure = true; -// _transportTraits = TransportTraitsPtr(new TLSTraits(CAcert, cli_cert, cli_key)); +// _transportTraits = TransportTraitsLightPtr(new TLSTraits(CAcert, cli_cert, cli_key)); // return true; // } #endif // HTTPCLIENT_1_1_COMPATIBLE @@ -1504,5 +1503,4 @@ const String &HTTPClientLight::getLocation(void) { return _location; } -#endif // USE_BERRY #endif // ESP32 diff --git a/lib/libesp32/Berry-HttpClientLight/src/HttpClientLight.h b/lib/libesp32/Berry-HttpClientLight/src/HttpClientLight.h index dc2bc0e58..a6d3be7eb 100644 --- a/lib/libesp32/Berry-HttpClientLight/src/HttpClientLight.h +++ b/lib/libesp32/Berry-HttpClientLight/src/HttpClientLight.h @@ -141,6 +141,11 @@ // } followRedirects_t; +#ifdef HTTPCLIENT_1_1_COMPATIBLE +class TransportTraitsLight; +typedef std::unique_ptr TransportTraitsLightPtr; +#endif + class HTTPClientLight { @@ -231,7 +236,7 @@ protected: #ifdef HTTPCLIENT_1_1_COMPATIBLE - TransportTraitsPtr _transportTraits; + TransportTraitsLightPtr _transportTraits; std::unique_ptr _tcpDeprecated; #endif diff --git a/lib/libesp32/Berry/default/be_i2s_audio_lib.c b/lib/libesp32/Berry/default/be_i2s_audio_lib.c deleted file mode 100644 index ef8720b23..000000000 --- a/lib/libesp32/Berry/default/be_i2s_audio_lib.c +++ /dev/null @@ -1,113 +0,0 @@ -/******************************************************************** - * Tasmota I2S audio classes - * - * - *******************************************************************/ -#include "be_constobj.h" - -#ifdef USE_I2S -#ifdef USE_I2S_AUDIO_BERRY - -extern int i2s_output_i2s_init(bvm *vm); -extern int i2s_output_i2s_deinit(bvm *vm); -extern int i2s_output_i2s_stop(bvm *vm); - -extern int i2s_generator_wav_init(bvm *vm); -extern int i2s_generator_wav_deinit(bvm *vm); -extern int i2s_generator_wav_begin(bvm *vm); -extern int i2s_generator_wav_loop(bvm *vm); -extern int i2s_generator_wav_stop(bvm *vm); -extern int i2s_generator_wav_isrunning(bvm *vm); - -extern int i2s_generator_mp3_init(bvm *vm); -extern int i2s_generator_mp3_deinit(bvm *vm); -extern int i2s_generator_mp3_begin(bvm *vm); -extern int i2s_generator_mp3_loop(bvm *vm); -extern int i2s_generator_mp3_stop(bvm *vm); -extern int i2s_generator_mp3_isrunning(bvm *vm); - -#ifdef USE_UFILESYS -extern int i2s_file_source_fs_init(bvm *vm); -extern int i2s_file_source_fs_deinit(bvm *vm); -#endif // USE_UFILESYS - - -#include "../generate/be_fixed_be_class_audio_output.h" -#include "../generate/be_fixed_be_class_audio_output_i2s.h" -#include "../generate/be_fixed_be_class_audio_generator.h" -#include "../generate/be_fixed_be_class_audio_generator_wav.h" -#include "../generate/be_fixed_be_class_audio_generator_mp3.h" -#include "../generate/be_fixed_be_class_audio_file_source.h" -#include "../generate/be_fixed_be_class_audio_file_source_fs.h" - -void be_load_driver_audio_lib(bvm *vm) { - be_pushntvclass(vm, &be_class_audio_output); - be_setglobal(vm, "AudioOutput"); - be_pop(vm, 1); - - be_pushntvclass(vm, &be_class_audio_output_i2s); - be_setglobal(vm, "AudioOutputI2S"); - be_pop(vm, 1); - - be_pushntvclass(vm, &be_class_audio_generator_wav); - be_setglobal(vm, "AudioGeneratorWAV"); - be_pop(vm, 1); - - be_pushntvclass(vm, &be_class_audio_generator_mp3); - be_setglobal(vm, "AudioGeneratorMP3"); - be_pop(vm, 1); - -#ifdef USE_UFILESYS - be_pushntvclass(vm, &be_class_audio_file_source_fs); - be_setglobal(vm, "AudioFileSourceFS"); - be_pop(vm, 1); -#endif // USE_UFILESYS -} - -/* @const_object_info_begin - -class be_class_audio_output (scope: global, name: AudioOutput) { - .p, var -} - -class be_class_audio_generator (scope: global, name: AudioGenerator) { - .p, var -} - -class be_class_audio_file_source (scope: global, name: AudioFileSource) { - .p, var -} - -class be_class_audio_output_i2s (scope: global, name: AudioOutputI2S, super: be_class_audio_output) { - init, func(i2s_output_i2s_init) - deinit, func(i2s_output_i2s_deinit) - stop, func(i2s_output_i2s_stop) -} - -class be_class_audio_generator_wav (scope: global, name: AudioGeneratorWAV, super: be_class_audio_generator) { - init, func(i2s_generator_wav_init) - deinit, func(i2s_generator_wav_deinit) - begin, func(i2s_generator_wav_begin) - loop, func(i2s_generator_wav_loop) - stop, func(i2s_generator_wav_stop) - isrunning, func(i2s_generator_wav_isrunning) -} - -class be_class_audio_generator_mp3 (scope: global, name: AudioGeneratorMP3, super: be_class_audio_generator) { - init, func(i2s_generator_mp3_init) - deinit, func(i2s_generator_mp3_deinit) - begin, func(i2s_generator_mp3_begin) - loop, func(i2s_generator_mp3_loop) - stop, func(i2s_generator_mp3_stop) - isrunning, func(i2s_generator_mp3_isrunning) -} - -class be_class_audio_file_source_fs (scope: global, name: AudioFileSourceFS, super: be_class_audio_file_source) { - init, func(i2s_file_source_fs_init) - deinit, func(i2s_file_source_fs_deinit) -} - -@const_object_info_end */ - -#endif // USE_I2S_AUDIO_BERRY -#endif // USE_I2S \ No newline at end of file diff --git a/lib/libesp32/Berry/default/be_lvgl_module.c b/lib/libesp32/Berry/default/be_lvgl_module.c deleted file mode 100644 index 890efd2ff..000000000 --- a/lib/libesp32/Berry/default/be_lvgl_module.c +++ /dev/null @@ -1,692 +0,0 @@ -/******************************************************************** - * Generated code, don't edit - *******************************************************************/ -/******************************************************************** - * LVGL Module - *******************************************************************/ -#include "be_constobj.h" - -#ifdef USE_LVGL - -#include "lvgl.h" -#include "be_lvgl.h" -#include "lv_theme_openhasp.h" - -extern int lv0_member(bvm *vm); // resolve virtual members - -extern int lv0_start(bvm *vm); - -extern int lv0_register_button_encoder(bvm *vm); // add buttons with encoder logic - -extern int lv0_load_montserrat_font(bvm *vm); -extern int lv0_load_seg7_font(bvm *vm); -extern int lv0_load_robotocondensed_latin1_font(bvm *vm); -extern int lv0_load_font(bvm *vm); -extern int lv0_load_freetype_font(bvm *vm); - -extern int lv0_screenshot(bvm *vm); - -static int lv_get_hor_res(void) { - return lv_disp_get_hor_res(lv_disp_get_default()); -} -static int lv_get_ver_res(void) { - return lv_disp_get_ver_res(lv_disp_get_default()); -} - -/* `lv` methods */ -const lvbe_call_c_t lv_func[] = { - - { "clamp_height", (void*) &lv_clamp_height, "i", "iiii" }, - { "clamp_width", (void*) &lv_clamp_width, "i", "iiii" }, - { "color_mix", (void*) &lv_color_mix, "lv.lv_color", "(lv.lv_color)(lv.lv_color)i" }, - { "dpx", (void*) &lv_dpx, "i", "i" }, - { "draw_arc", (void*) &lv_draw_arc, "", "iiiii(lv.lv_area)(lv.lv_draw_arc_dsc)" }, - { "draw_arc_dsc_init", (void*) &lv_draw_arc_dsc_init, "", "(lv.lv_draw_arc_dsc)" }, - { "draw_arc_get_area", (void*) &lv_draw_arc_get_area, "", "iiiiiib(lv.lv_area)" }, - { "draw_img", (void*) &lv_draw_img, "", "(lv.lv_area)(lv.lv_area).(lv.lv_draw_img_dsc)" }, - { "draw_img_dsc_init", (void*) &lv_draw_img_dsc_init, "", "(lv.lv_draw_img_dsc)" }, - { "draw_label", (void*) &lv_draw_label, "", "(lv.lv_area)(lv.lv_area)(lv.lv_draw_label_dsc)s(lv.lv_draw_label_hint)" }, - { "draw_label_dsc_init", (void*) &lv_draw_label_dsc_init, "", "(lv.lv_draw_label_dsc)" }, - { "draw_letter", (void*) &lv_draw_letter, "", "(lv.lv_point)(lv.lv_area)(lv.lv_font)i(lv.lv_color)ii" }, - { "draw_line", (void*) &lv_draw_line, "", "(lv.lv_point)(lv.lv_point)(lv.lv_area)(lv.lv_draw_line_dsc)" }, - { "draw_line_dsc_init", (void*) &lv_draw_line_dsc_init, "", "(lv.lv_draw_line_dsc)" }, - { "draw_mask_add", (void*) &lv_draw_mask_add, "i", ".." }, - { "draw_mask_angle_init", (void*) &lv_draw_mask_angle_init, "", "(lv.lv_draw_mask_angle_param)iiii" }, - { "draw_mask_fade_init", (void*) &lv_draw_mask_fade_init, "", "(lv.lv_draw_mask_fade_param)(lv.lv_area)iiii" }, - { "draw_mask_get_cnt", (void*) &lv_draw_mask_get_cnt, "i", "" }, - { "draw_mask_line_angle_init", (void*) &lv_draw_mask_line_angle_init, "", "(lv.lv_draw_mask_line_param)iiii" }, - { "draw_mask_line_points_init", (void*) &lv_draw_mask_line_points_init, "", "(lv.lv_draw_mask_line_param)iiiii" }, - { "draw_mask_map_init", (void*) &lv_draw_mask_map_init, "", "(lv.lv_draw_mask_map_param)(lv.lv_area)(lv.lv_opa)" }, - { "draw_mask_radius_init", (void*) &lv_draw_mask_radius_init, "", "(lv.lv_draw_mask_radius_param)(lv.lv_area)ib" }, - { "draw_mask_remove_custom", (void*) &lv_draw_mask_remove_custom, ".", "." }, - { "draw_mask_remove_id", (void*) &lv_draw_mask_remove_id, ".", "i" }, - { "draw_polygon", (void*) &lv_draw_polygon, "", "ii(lv.lv_area)(lv.lv_draw_rect_dsc)" }, - { "draw_rect", (void*) &lv_draw_rect, "", "(lv.lv_area)(lv.lv_area)(lv.lv_draw_rect_dsc)" }, - { "draw_rect_dsc_init", (void*) &lv_draw_rect_dsc_init, "", "(lv.lv_draw_rect_dsc)" }, - { "draw_triangle", (void*) &lv_draw_triangle, "", "i(lv.lv_area)(lv.lv_draw_rect_dsc)" }, - { "event_register_id", (void*) &lv_event_register_id, "i", "" }, - { "event_send", (void*) &lv_event_send, "i", "(lv.lv_obj)i." }, - { "event_set_cover_res", (void*) &lv_event_set_cover_res, "", "(lv.lv_event)(lv.lv_cover_res)" }, - { "event_set_ext_draw_size", (void*) &lv_event_set_ext_draw_size, "", "(lv.lv_event)i" }, - { "get_hor_res", (void*) &lv_get_hor_res, "i", "" }, - { "get_ver_res", (void*) &lv_get_ver_res, "i", "" }, - { "group_get_default", (void*) &lv_group_get_default, "lv.lv_group", "" }, - { "img_src_get_type", (void*) &lv_img_src_get_type, "i", "." }, - { "indev_get_act", (void*) &lv_indev_get_act, "lv.lv_indev", "" }, - { "indev_get_obj_act", (void*) &lv_indev_get_obj_act, "lv.lv_obj", "" }, - { "indev_read_timer_cb", (void*) &lv_indev_read_timer_cb, "", "(lv.lv_timer)" }, - { "layer_sys", (void*) &lv_layer_sys, "lv.lv_obj", "" }, - { "layer_top", (void*) &lv_layer_top, "lv.lv_obj", "" }, - { "layout_register", (void*) &lv_layout_register, "i", "^lv_layout_update_cb^." }, - { "obj_class_create_obj", (void*) &lv_obj_class_create_obj, "lv.lv_obj", "(lv._lv_obj_class)(lv.lv_obj)" }, - { "obj_del_anim_ready_cb", (void*) &lv_obj_del_anim_ready_cb, "", "(lv.lv_anim)" }, - { "obj_draw_dsc_init", (void*) &lv_obj_draw_dsc_init, "", "(lv.lv_obj_draw_part_dsc)(lv.lv_area)" }, - { "obj_enable_style_refresh", (void*) &lv_obj_enable_style_refresh, "", "b" }, - { "obj_event_base", (void*) &lv_obj_event_base, "i", "(lv.lv_obj_class)(lv.lv_event)" }, - { "obj_report_style_change", (void*) &lv_obj_report_style_change, "", "(lv.lv_style)" }, - { "obj_style_get_selector_part", (void*) &lv_obj_style_get_selector_part, "i", "i" }, - { "obj_style_get_selector_state", (void*) &lv_obj_style_get_selector_state, "i", "i" }, - { "refr_now", (void*) &lv_refr_now, "", "(lv.lv_disp)" }, - { "scr_act", (void*) &lv_scr_act, "lv.lv_obj", "" }, - { "scr_load", (void*) &lv_scr_load, "", "(lv.lv_obj)" }, - { "scr_load_anim", (void*) &lv_scr_load_anim, "", "(lv.lv_obj)iiib" }, - { "theme_apply", (void*) &lv_theme_apply, "", "(lv.lv_obj)" }, - { "theme_default_init", (void*) &lv_theme_default_init, "lv.lv_theme", "(lv.lv_disp)(lv.lv_color)(lv.lv_color)b(lv.lv_font)" }, - { "theme_default_is_inited", (void*) &lv_theme_default_is_inited, "b", "" }, - { "theme_get_color_primary", (void*) &lv_theme_get_color_primary, "lv.lv_color", "(lv.lv_obj)" }, - { "theme_get_color_secondary", (void*) &lv_theme_get_color_secondary, "lv.lv_color", "(lv.lv_obj)" }, - { "theme_get_font_large", (void*) &lv_theme_get_font_large, "lv.lv_font", "(lv.lv_obj)" }, - { "theme_get_font_normal", (void*) &lv_theme_get_font_normal, "lv.lv_font", "(lv.lv_obj)" }, - { "theme_get_font_small", (void*) &lv_theme_get_font_small, "lv.lv_font", "(lv.lv_obj)" }, - { "theme_get_from_obj", (void*) &lv_theme_get_from_obj, "lv.lv_theme", "(lv.lv_obj)" }, - { "theme_mono_init", (void*) &lv_theme_mono_init, "lv.lv_theme", "(lv.lv_disp)b(lv.lv_font)" }, - { "theme_openhasp_init", (void*) &lv_theme_openhasp_init, "lv.lv_theme", "(lv.lv_disp)(lv.lv_color)(lv.lv_color)b(lv.lv_font)" }, - { "theme_openhasp_is_inited", (void*) &lv_theme_openhasp_is_inited, "b", "" }, - { "theme_set_apply_cb", (void*) &lv_theme_set_apply_cb, "", "(lv.lv_theme)^lv_theme_apply_cb^" }, - { "theme_set_parent", (void*) &lv_theme_set_parent, "", "(lv.lv_theme)(lv.lv_theme)" }, - -}; -const size_t lv_func_size = sizeof(lv_func) / sizeof(lv_func[0]); - - - - -typedef struct be_constint_t { - const char * name; - int32_t value; -} be_constint_t; - -const be_constint_t lv0_constants[] = { - - { "ALIGN_BOTTOM_LEFT", LV_ALIGN_BOTTOM_LEFT }, - { "ALIGN_BOTTOM_MID", LV_ALIGN_BOTTOM_MID }, - { "ALIGN_BOTTOM_RIGHT", LV_ALIGN_BOTTOM_RIGHT }, - { "ALIGN_CENTER", LV_ALIGN_CENTER }, - { "ALIGN_DEFAULT", LV_ALIGN_DEFAULT }, - { "ALIGN_LEFT_MID", LV_ALIGN_LEFT_MID }, - { "ALIGN_OUT_BOTTOM_LEFT", LV_ALIGN_OUT_BOTTOM_LEFT }, - { "ALIGN_OUT_BOTTOM_MID", LV_ALIGN_OUT_BOTTOM_MID }, - { "ALIGN_OUT_BOTTOM_RIGHT", LV_ALIGN_OUT_BOTTOM_RIGHT }, - { "ALIGN_OUT_LEFT_BOTTOM", LV_ALIGN_OUT_LEFT_BOTTOM }, - { "ALIGN_OUT_LEFT_MID", LV_ALIGN_OUT_LEFT_MID }, - { "ALIGN_OUT_LEFT_TOP", LV_ALIGN_OUT_LEFT_TOP }, - { "ALIGN_OUT_RIGHT_BOTTOM", LV_ALIGN_OUT_RIGHT_BOTTOM }, - { "ALIGN_OUT_RIGHT_MID", LV_ALIGN_OUT_RIGHT_MID }, - { "ALIGN_OUT_RIGHT_TOP", LV_ALIGN_OUT_RIGHT_TOP }, - { "ALIGN_OUT_TOP_LEFT", LV_ALIGN_OUT_TOP_LEFT }, - { "ALIGN_OUT_TOP_MID", LV_ALIGN_OUT_TOP_MID }, - { "ALIGN_OUT_TOP_RIGHT", LV_ALIGN_OUT_TOP_RIGHT }, - { "ALIGN_RIGHT_MID", LV_ALIGN_RIGHT_MID }, - { "ALIGN_TOP_LEFT", LV_ALIGN_TOP_LEFT }, - { "ALIGN_TOP_MID", LV_ALIGN_TOP_MID }, - { "ALIGN_TOP_RIGHT", LV_ALIGN_TOP_RIGHT }, - { "ANIM_IMG_PART_MAIN", LV_ANIM_IMG_PART_MAIN }, - { "ANIM_OFF", LV_ANIM_OFF }, - { "ANIM_ON", LV_ANIM_ON }, - { "ARC_MODE_NORMAL", LV_ARC_MODE_NORMAL }, - { "ARC_MODE_REVERSE", LV_ARC_MODE_REVERSE }, - { "ARC_MODE_SYMMETRICAL", LV_ARC_MODE_SYMMETRICAL }, - { "BAR_MODE_NORMAL", LV_BAR_MODE_NORMAL }, - { "BAR_MODE_RANGE", LV_BAR_MODE_RANGE }, - { "BAR_MODE_SYMMETRICAL", LV_BAR_MODE_SYMMETRICAL }, - { "BASE_DIR_AUTO", LV_BASE_DIR_AUTO }, - { "BASE_DIR_LTR", LV_BASE_DIR_LTR }, - { "BASE_DIR_NEUTRAL", LV_BASE_DIR_NEUTRAL }, - { "BASE_DIR_RTL", LV_BASE_DIR_RTL }, - { "BASE_DIR_WEAK", LV_BASE_DIR_WEAK }, - { "BLEND_MODE_ADDITIVE", LV_BLEND_MODE_ADDITIVE }, - { "BLEND_MODE_NORMAL", LV_BLEND_MODE_NORMAL }, - { "BLEND_MODE_SUBTRACTIVE", LV_BLEND_MODE_SUBTRACTIVE }, - { "BORDER_SIDE_BOTTOM", LV_BORDER_SIDE_BOTTOM }, - { "BORDER_SIDE_FULL", LV_BORDER_SIDE_FULL }, - { "BORDER_SIDE_INTERNAL", LV_BORDER_SIDE_INTERNAL }, - { "BORDER_SIDE_LEFT", LV_BORDER_SIDE_LEFT }, - { "BORDER_SIDE_NONE", LV_BORDER_SIDE_NONE }, - { "BORDER_SIDE_RIGHT", LV_BORDER_SIDE_RIGHT }, - { "BORDER_SIDE_TOP", LV_BORDER_SIDE_TOP }, - { "BTNMATRIX_CTRL_CHECKABLE", LV_BTNMATRIX_CTRL_CHECKABLE }, - { "BTNMATRIX_CTRL_CHECKED", LV_BTNMATRIX_CTRL_CHECKED }, - { "BTNMATRIX_CTRL_CLICK_TRIG", LV_BTNMATRIX_CTRL_CLICK_TRIG }, - { "BTNMATRIX_CTRL_CUSTOM_1", LV_BTNMATRIX_CTRL_CUSTOM_1 }, - { "BTNMATRIX_CTRL_CUSTOM_2", LV_BTNMATRIX_CTRL_CUSTOM_2 }, - { "BTNMATRIX_CTRL_DISABLED", LV_BTNMATRIX_CTRL_DISABLED }, - { "BTNMATRIX_CTRL_HIDDEN", LV_BTNMATRIX_CTRL_HIDDEN }, - { "BTNMATRIX_CTRL_NO_REPEAT", LV_BTNMATRIX_CTRL_NO_REPEAT }, - { "BTNMATRIX_CTRL_RECOLOR", LV_BTNMATRIX_CTRL_RECOLOR }, - { "CHART_AXIS_PRIMARY_X", LV_CHART_AXIS_PRIMARY_X }, - { "CHART_AXIS_PRIMARY_Y", LV_CHART_AXIS_PRIMARY_Y }, - { "CHART_AXIS_SECONDARY_X", LV_CHART_AXIS_SECONDARY_X }, - { "CHART_AXIS_SECONDARY_Y", LV_CHART_AXIS_SECONDARY_Y }, - { "CHART_TYPE_BAR", LV_CHART_TYPE_BAR }, - { "CHART_TYPE_LINE", LV_CHART_TYPE_LINE }, - { "CHART_TYPE_NONE", LV_CHART_TYPE_NONE }, - { "CHART_TYPE_SCATTER", LV_CHART_TYPE_SCATTER }, - { "CHART_UPDATE_MODE_CIRCULAR", LV_CHART_UPDATE_MODE_CIRCULAR }, - { "CHART_UPDATE_MODE_SHIFT", LV_CHART_UPDATE_MODE_SHIFT }, - { "COLORWHEEL_MODE_HUE", LV_COLORWHEEL_MODE_HUE }, - { "COLORWHEEL_MODE_SATURATION", LV_COLORWHEEL_MODE_SATURATION }, - { "COLORWHEEL_MODE_VALUE", LV_COLORWHEEL_MODE_VALUE }, - { "COLOR_AQUA", (int32_t) 0x00FFFF }, - { "COLOR_BLACK", (int32_t) 0x000000 }, - { "COLOR_BLUE", (int32_t) 0x0000FF }, - { "COLOR_CYAN", (int32_t) 0x00FFFF }, - { "COLOR_GRAY", (int32_t) 0x808080 }, - { "COLOR_GREEN", (int32_t) 0x008000 }, - { "COLOR_LIME", (int32_t) 0x00FF00 }, - { "COLOR_MAGENTA", (int32_t) 0xFF00FF }, - { "COLOR_MAROON", (int32_t) 0x800000 }, - { "COLOR_NAVY", (int32_t) 0x000080 }, - { "COLOR_OLIVE", (int32_t) 0x808000 }, - { "COLOR_PURPLE", (int32_t) 0x800080 }, - { "COLOR_RED", (int32_t) 0xFF0000 }, - { "COLOR_SILVER", (int32_t) 0xC0C0C0 }, - { "COLOR_TEAL", (int32_t) 0x008080 }, - { "COLOR_WHITE", (int32_t) 0xFFFFFF }, - { "COLOR_YELLOW", (int32_t) 0xFFFF00 }, - { "COVER_RES_COVER", LV_COVER_RES_COVER }, - { "COVER_RES_MASKED", LV_COVER_RES_MASKED }, - { "COVER_RES_NOT_COVER", LV_COVER_RES_NOT_COVER }, - { "DIR_ALL", LV_DIR_ALL }, - { "DIR_BOTTOM", LV_DIR_BOTTOM }, - { "DIR_HOR", LV_DIR_HOR }, - { "DIR_LEFT", LV_DIR_LEFT }, - { "DIR_NONE", LV_DIR_NONE }, - { "DIR_RIGHT", LV_DIR_RIGHT }, - { "DIR_TOP", LV_DIR_TOP }, - { "DIR_VER", LV_DIR_VER }, - { "DISP_ROT_180", LV_DISP_ROT_180 }, - { "DISP_ROT_270", LV_DISP_ROT_270 }, - { "DISP_ROT_90", LV_DISP_ROT_90 }, - { "DISP_ROT_NONE", LV_DISP_ROT_NONE }, - { "DRAW_MASK_LINE_SIDE_BOTTOM", LV_DRAW_MASK_LINE_SIDE_BOTTOM }, - { "DRAW_MASK_LINE_SIDE_LEFT", LV_DRAW_MASK_LINE_SIDE_LEFT }, - { "DRAW_MASK_LINE_SIDE_RIGHT", LV_DRAW_MASK_LINE_SIDE_RIGHT }, - { "DRAW_MASK_LINE_SIDE_TOP", LV_DRAW_MASK_LINE_SIDE_TOP }, - { "DRAW_MASK_RES_CHANGED", LV_DRAW_MASK_RES_CHANGED }, - { "DRAW_MASK_RES_FULL_COVER", LV_DRAW_MASK_RES_FULL_COVER }, - { "DRAW_MASK_RES_TRANSP", LV_DRAW_MASK_RES_TRANSP }, - { "DRAW_MASK_RES_UNKNOWN", LV_DRAW_MASK_RES_UNKNOWN }, - { "DRAW_MASK_TYPE_ANGLE", LV_DRAW_MASK_TYPE_ANGLE }, - { "DRAW_MASK_TYPE_FADE", LV_DRAW_MASK_TYPE_FADE }, - { "DRAW_MASK_TYPE_LINE", LV_DRAW_MASK_TYPE_LINE }, - { "DRAW_MASK_TYPE_MAP", LV_DRAW_MASK_TYPE_MAP }, - { "DRAW_MASK_TYPE_RADIUS", LV_DRAW_MASK_TYPE_RADIUS }, - { "EVENT_ALL", LV_EVENT_ALL }, - { "EVENT_CANCEL", LV_EVENT_CANCEL }, - { "EVENT_CHILD_CHANGED", LV_EVENT_CHILD_CHANGED }, - { "EVENT_CLICKED", LV_EVENT_CLICKED }, - { "EVENT_COVER_CHECK", LV_EVENT_COVER_CHECK }, - { "EVENT_DEFOCUSED", LV_EVENT_DEFOCUSED }, - { "EVENT_DELETE", LV_EVENT_DELETE }, - { "EVENT_DRAW_MAIN", LV_EVENT_DRAW_MAIN }, - { "EVENT_DRAW_MAIN_BEGIN", LV_EVENT_DRAW_MAIN_BEGIN }, - { "EVENT_DRAW_MAIN_END", LV_EVENT_DRAW_MAIN_END }, - { "EVENT_DRAW_PART_BEGIN", LV_EVENT_DRAW_PART_BEGIN }, - { "EVENT_DRAW_PART_END", LV_EVENT_DRAW_PART_END }, - { "EVENT_DRAW_POST", LV_EVENT_DRAW_POST }, - { "EVENT_DRAW_POST_BEGIN", LV_EVENT_DRAW_POST_BEGIN }, - { "EVENT_DRAW_POST_END", LV_EVENT_DRAW_POST_END }, - { "EVENT_FOCUSED", LV_EVENT_FOCUSED }, - { "EVENT_GESTURE", LV_EVENT_GESTURE }, - { "EVENT_GET_SELF_SIZE", LV_EVENT_GET_SELF_SIZE }, - { "EVENT_HIT_TEST", LV_EVENT_HIT_TEST }, - { "EVENT_INSERT", LV_EVENT_INSERT }, - { "EVENT_KEY", LV_EVENT_KEY }, - { "EVENT_LAYOUT_CHANGED", LV_EVENT_LAYOUT_CHANGED }, - { "EVENT_LEAVE", LV_EVENT_LEAVE }, - { "EVENT_LONG_PRESSED", LV_EVENT_LONG_PRESSED }, - { "EVENT_LONG_PRESSED_REPEAT", LV_EVENT_LONG_PRESSED_REPEAT }, - { "EVENT_PRESSED", LV_EVENT_PRESSED }, - { "EVENT_PRESSING", LV_EVENT_PRESSING }, - { "EVENT_PRESS_LOST", LV_EVENT_PRESS_LOST }, - { "EVENT_READY", LV_EVENT_READY }, - { "EVENT_REFRESH", LV_EVENT_REFRESH }, - { "EVENT_REFR_EXT_DRAW_SIZE", LV_EVENT_REFR_EXT_DRAW_SIZE }, - { "EVENT_RELEASED", LV_EVENT_RELEASED }, - { "EVENT_SCROLL", LV_EVENT_SCROLL }, - { "EVENT_SCROLL_BEGIN", LV_EVENT_SCROLL_BEGIN }, - { "EVENT_SCROLL_END", LV_EVENT_SCROLL_END }, - { "EVENT_SHORT_CLICKED", LV_EVENT_SHORT_CLICKED }, - { "EVENT_SIZE_CHANGED", LV_EVENT_SIZE_CHANGED }, - { "EVENT_STYLE_CHANGED", LV_EVENT_STYLE_CHANGED }, - { "EVENT_VALUE_CHANGED", LV_EVENT_VALUE_CHANGED }, - { "FLEX_ALIGN_CENTER", LV_FLEX_ALIGN_CENTER }, - { "FLEX_ALIGN_END", LV_FLEX_ALIGN_END }, - { "FLEX_ALIGN_SPACE_AROUND", LV_FLEX_ALIGN_SPACE_AROUND }, - { "FLEX_ALIGN_SPACE_BETWEEN", LV_FLEX_ALIGN_SPACE_BETWEEN }, - { "FLEX_ALIGN_SPACE_EVENLY", LV_FLEX_ALIGN_SPACE_EVENLY }, - { "FLEX_ALIGN_START", LV_FLEX_ALIGN_START }, - { "FLEX_FLOW_COLUMN", LV_FLEX_FLOW_COLUMN }, - { "FLEX_FLOW_COLUMN_REVERSE", LV_FLEX_FLOW_COLUMN_REVERSE }, - { "FLEX_FLOW_COLUMN_WRAP", LV_FLEX_FLOW_COLUMN_WRAP }, - { "FLEX_FLOW_COLUMN_WRAP_REVERSE", LV_FLEX_FLOW_COLUMN_WRAP_REVERSE }, - { "FLEX_FLOW_ROW", LV_FLEX_FLOW_ROW }, - { "FLEX_FLOW_ROW_REVERSE", LV_FLEX_FLOW_ROW_REVERSE }, - { "FLEX_FLOW_ROW_WRAP", LV_FLEX_FLOW_ROW_WRAP }, - { "FLEX_FLOW_ROW_WRAP_REVERSE", LV_FLEX_FLOW_ROW_WRAP_REVERSE }, - { "FS_MODE_RD", LV_FS_MODE_RD }, - { "FS_MODE_WR", LV_FS_MODE_WR }, - { "FS_RES_BUSY", LV_FS_RES_BUSY }, - { "FS_RES_DENIED", LV_FS_RES_DENIED }, - { "FS_RES_FS_ERR", LV_FS_RES_FS_ERR }, - { "FS_RES_FULL", LV_FS_RES_FULL }, - { "FS_RES_HW_ERR", LV_FS_RES_HW_ERR }, - { "FS_RES_INV_PARAM", LV_FS_RES_INV_PARAM }, - { "FS_RES_LOCKED", LV_FS_RES_LOCKED }, - { "FS_RES_NOT_EX", LV_FS_RES_NOT_EX }, - { "FS_RES_NOT_IMP", LV_FS_RES_NOT_IMP }, - { "FS_RES_OK", LV_FS_RES_OK }, - { "FS_RES_OUT_OF_MEM", LV_FS_RES_OUT_OF_MEM }, - { "FS_RES_TOUT", LV_FS_RES_TOUT }, - { "FS_RES_UNKNOWN", LV_FS_RES_UNKNOWN }, - { "FS_SEEK_CUR", LV_FS_SEEK_CUR }, - { "FS_SEEK_END", LV_FS_SEEK_END }, - { "FS_SEEK_SET", LV_FS_SEEK_SET }, - { "GRAD_DIR_HOR", LV_GRAD_DIR_HOR }, - { "GRAD_DIR_NONE", LV_GRAD_DIR_NONE }, - { "GRAD_DIR_VER", LV_GRAD_DIR_VER }, - { "GRID_ALIGN_CENTER", LV_GRID_ALIGN_CENTER }, - { "GRID_ALIGN_END", LV_GRID_ALIGN_END }, - { "GRID_ALIGN_SPACE_AROUND", LV_GRID_ALIGN_SPACE_AROUND }, - { "GRID_ALIGN_SPACE_BETWEEN", LV_GRID_ALIGN_SPACE_BETWEEN }, - { "GRID_ALIGN_SPACE_EVENLY", LV_GRID_ALIGN_SPACE_EVENLY }, - { "GRID_ALIGN_START", LV_GRID_ALIGN_START }, - { "GRID_ALIGN_STRETCH", LV_GRID_ALIGN_STRETCH }, - { "GROUP_REFOCUS_POLICY_NEXT", LV_GROUP_REFOCUS_POLICY_NEXT }, - { "GROUP_REFOCUS_POLICY_PREV", LV_GROUP_REFOCUS_POLICY_PREV }, - { "IMGBTN_STATE_CHECKED_DISABLED", LV_IMGBTN_STATE_CHECKED_DISABLED }, - { "IMGBTN_STATE_CHECKED_PRESSED", LV_IMGBTN_STATE_CHECKED_PRESSED }, - { "IMGBTN_STATE_CHECKED_RELEASED", LV_IMGBTN_STATE_CHECKED_RELEASED }, - { "IMGBTN_STATE_DISABLED", LV_IMGBTN_STATE_DISABLED }, - { "IMGBTN_STATE_PRESSED", LV_IMGBTN_STATE_PRESSED }, - { "IMGBTN_STATE_RELEASED", LV_IMGBTN_STATE_RELEASED }, - { "IMG_CF_ALPHA_1BIT", LV_IMG_CF_ALPHA_1BIT }, - { "IMG_CF_ALPHA_2BIT", LV_IMG_CF_ALPHA_2BIT }, - { "IMG_CF_ALPHA_4BIT", LV_IMG_CF_ALPHA_4BIT }, - { "IMG_CF_ALPHA_8BIT", LV_IMG_CF_ALPHA_8BIT }, - { "IMG_CF_INDEXED_1BIT", LV_IMG_CF_INDEXED_1BIT }, - { "IMG_CF_INDEXED_2BIT", LV_IMG_CF_INDEXED_2BIT }, - { "IMG_CF_INDEXED_4BIT", LV_IMG_CF_INDEXED_4BIT }, - { "IMG_CF_INDEXED_8BIT", LV_IMG_CF_INDEXED_8BIT }, - { "IMG_CF_RAW", LV_IMG_CF_RAW }, - { "IMG_CF_RAW_ALPHA", LV_IMG_CF_RAW_ALPHA }, - { "IMG_CF_RAW_CHROMA_KEYED", LV_IMG_CF_RAW_CHROMA_KEYED }, - { "IMG_CF_TRUE_COLOR", LV_IMG_CF_TRUE_COLOR }, - { "IMG_CF_TRUE_COLOR_ALPHA", LV_IMG_CF_TRUE_COLOR_ALPHA }, - { "IMG_CF_TRUE_COLOR_CHROMA_KEYED", LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED }, - { "IMG_CF_UNKNOWN", LV_IMG_CF_UNKNOWN }, - { "IMG_SRC_FILE", LV_IMG_SRC_FILE }, - { "IMG_SRC_SYMBOL", LV_IMG_SRC_SYMBOL }, - { "IMG_SRC_UNKNOWN", LV_IMG_SRC_UNKNOWN }, - { "IMG_SRC_VARIABLE", LV_IMG_SRC_VARIABLE }, - { "INDEV_STATE_PRESSED", LV_INDEV_STATE_PRESSED }, - { "INDEV_STATE_RELEASED", LV_INDEV_STATE_RELEASED }, - { "INDEV_TYPE_BUTTON", LV_INDEV_TYPE_BUTTON }, - { "INDEV_TYPE_ENCODER", LV_INDEV_TYPE_ENCODER }, - { "INDEV_TYPE_KEYPAD", LV_INDEV_TYPE_KEYPAD }, - { "INDEV_TYPE_NONE", LV_INDEV_TYPE_NONE }, - { "INDEV_TYPE_POINTER", LV_INDEV_TYPE_POINTER }, - { "KEY_BACKSPACE", LV_KEY_BACKSPACE }, - { "KEY_DEL", LV_KEY_DEL }, - { "KEY_DOWN", LV_KEY_DOWN }, - { "KEY_END", LV_KEY_END }, - { "KEY_ENTER", LV_KEY_ENTER }, - { "KEY_ESC", LV_KEY_ESC }, - { "KEY_HOME", LV_KEY_HOME }, - { "KEY_LEFT", LV_KEY_LEFT }, - { "KEY_NEXT", LV_KEY_NEXT }, - { "KEY_PREV", LV_KEY_PREV }, - { "KEY_RIGHT", LV_KEY_RIGHT }, - { "KEY_UP", LV_KEY_UP }, - { "LABEL_LONG_CLIP", LV_LABEL_LONG_CLIP }, - { "LABEL_LONG_DOT", LV_LABEL_LONG_DOT }, - { "LABEL_LONG_SCROLL", LV_LABEL_LONG_SCROLL }, - { "LABEL_LONG_SCROLL_CIRCULAR", LV_LABEL_LONG_SCROLL_CIRCULAR }, - { "LABEL_LONG_WRAP", LV_LABEL_LONG_WRAP }, - { "METER_INDICATOR_TYPE_ARC", LV_METER_INDICATOR_TYPE_ARC }, - { "METER_INDICATOR_TYPE_NEEDLE_IMG", LV_METER_INDICATOR_TYPE_NEEDLE_IMG }, - { "METER_INDICATOR_TYPE_NEEDLE_LINE", LV_METER_INDICATOR_TYPE_NEEDLE_LINE }, - { "METER_INDICATOR_TYPE_SCALE_LINES", LV_METER_INDICATOR_TYPE_SCALE_LINES }, - { "OBJ_CLASS_EDITABLE_FALSE", LV_OBJ_CLASS_EDITABLE_FALSE }, - { "OBJ_CLASS_EDITABLE_INHERIT", LV_OBJ_CLASS_EDITABLE_INHERIT }, - { "OBJ_CLASS_EDITABLE_TRUE", LV_OBJ_CLASS_EDITABLE_TRUE }, - { "OBJ_CLASS_GROUP_DEF_FALSE", LV_OBJ_CLASS_GROUP_DEF_FALSE }, - { "OBJ_CLASS_GROUP_DEF_INHERIT", LV_OBJ_CLASS_GROUP_DEF_INHERIT }, - { "OBJ_CLASS_GROUP_DEF_TRUE", LV_OBJ_CLASS_GROUP_DEF_TRUE }, - { "OBJ_FLAG_ADV_HITTEST", LV_OBJ_FLAG_ADV_HITTEST }, - { "OBJ_FLAG_CHECKABLE", LV_OBJ_FLAG_CHECKABLE }, - { "OBJ_FLAG_CLICKABLE", LV_OBJ_FLAG_CLICKABLE }, - { "OBJ_FLAG_CLICK_FOCUSABLE", LV_OBJ_FLAG_CLICK_FOCUSABLE }, - { "OBJ_FLAG_EVENT_BUBBLE", LV_OBJ_FLAG_EVENT_BUBBLE }, - { "OBJ_FLAG_FLOATING", LV_OBJ_FLAG_FLOATING }, - { "OBJ_FLAG_GESTURE_BUBBLE", LV_OBJ_FLAG_GESTURE_BUBBLE }, - { "OBJ_FLAG_HIDDEN", LV_OBJ_FLAG_HIDDEN }, - { "OBJ_FLAG_IGNORE_LAYOUT", LV_OBJ_FLAG_IGNORE_LAYOUT }, - { "OBJ_FLAG_LAYOUT_1", LV_OBJ_FLAG_LAYOUT_1 }, - { "OBJ_FLAG_LAYOUT_2", LV_OBJ_FLAG_LAYOUT_2 }, - { "OBJ_FLAG_PRESS_LOCK", LV_OBJ_FLAG_PRESS_LOCK }, - { "OBJ_FLAG_SCROLLABLE", LV_OBJ_FLAG_SCROLLABLE }, - { "OBJ_FLAG_SCROLL_CHAIN", LV_OBJ_FLAG_SCROLL_CHAIN }, - { "OBJ_FLAG_SCROLL_ELASTIC", LV_OBJ_FLAG_SCROLL_ELASTIC }, - { "OBJ_FLAG_SCROLL_MOMENTUM", LV_OBJ_FLAG_SCROLL_MOMENTUM }, - { "OBJ_FLAG_SCROLL_ONE", LV_OBJ_FLAG_SCROLL_ONE }, - { "OBJ_FLAG_SCROLL_ON_FOCUS", LV_OBJ_FLAG_SCROLL_ON_FOCUS }, - { "OBJ_FLAG_SNAPABLE", LV_OBJ_FLAG_SNAPABLE }, - { "OBJ_FLAG_USER_1", LV_OBJ_FLAG_USER_1 }, - { "OBJ_FLAG_USER_2", LV_OBJ_FLAG_USER_2 }, - { "OBJ_FLAG_USER_3", LV_OBJ_FLAG_USER_3 }, - { "OBJ_FLAG_USER_4", LV_OBJ_FLAG_USER_4 }, - { "OBJ_FLAG_WIDGET_1", LV_OBJ_FLAG_WIDGET_1 }, - { "OBJ_FLAG_WIDGET_2", LV_OBJ_FLAG_WIDGET_2 }, - { "OBJ_TREE_WALK_END", LV_OBJ_TREE_WALK_END }, - { "OBJ_TREE_WALK_NEXT", LV_OBJ_TREE_WALK_NEXT }, - { "OBJ_TREE_WALK_SKIP_CHILDREN", LV_OBJ_TREE_WALK_SKIP_CHILDREN }, - { "OPA_0", LV_OPA_0 }, - { "OPA_10", LV_OPA_10 }, - { "OPA_100", LV_OPA_100 }, - { "OPA_20", LV_OPA_20 }, - { "OPA_30", LV_OPA_30 }, - { "OPA_40", LV_OPA_40 }, - { "OPA_50", LV_OPA_50 }, - { "OPA_60", LV_OPA_60 }, - { "OPA_70", LV_OPA_70 }, - { "OPA_80", LV_OPA_80 }, - { "OPA_90", LV_OPA_90 }, - { "OPA_COVER", LV_OPA_COVER }, - { "OPA_TRANSP", LV_OPA_TRANSP }, - { "PALETTE_AMBER", LV_PALETTE_AMBER }, - { "PALETTE_BLUE", LV_PALETTE_BLUE }, - { "PALETTE_BLUE_GREY", LV_PALETTE_BLUE_GREY }, - { "PALETTE_BROWN", LV_PALETTE_BROWN }, - { "PALETTE_CYAN", LV_PALETTE_CYAN }, - { "PALETTE_DEEP_ORANGE", LV_PALETTE_DEEP_ORANGE }, - { "PALETTE_DEEP_PURPLE", LV_PALETTE_DEEP_PURPLE }, - { "PALETTE_GREEN", LV_PALETTE_GREEN }, - { "PALETTE_GREY", LV_PALETTE_GREY }, - { "PALETTE_INDIGO", LV_PALETTE_INDIGO }, - { "PALETTE_LIGHT_BLUE", LV_PALETTE_LIGHT_BLUE }, - { "PALETTE_LIGHT_GREEN", LV_PALETTE_LIGHT_GREEN }, - { "PALETTE_LIME", LV_PALETTE_LIME }, - { "PALETTE_NONE", LV_PALETTE_NONE }, - { "PALETTE_ORANGE", LV_PALETTE_ORANGE }, - { "PALETTE_PINK", LV_PALETTE_PINK }, - { "PALETTE_PURPLE", LV_PALETTE_PURPLE }, - { "PALETTE_RED", LV_PALETTE_RED }, - { "PALETTE_TEAL", LV_PALETTE_TEAL }, - { "PALETTE_YELLOW", LV_PALETTE_YELLOW }, - { "PART_ANY", LV_PART_ANY }, - { "PART_CURSOR", LV_PART_CURSOR }, - { "PART_CUSTOM_FIRST", LV_PART_CUSTOM_FIRST }, - { "PART_INDICATOR", LV_PART_INDICATOR }, - { "PART_ITEMS", LV_PART_ITEMS }, - { "PART_KNOB", LV_PART_KNOB }, - { "PART_MAIN", LV_PART_MAIN }, - { "PART_SCROLLBAR", LV_PART_SCROLLBAR }, - { "PART_SELECTED", LV_PART_SELECTED }, - { "PART_TEXTAREA_PLACEHOLDER", LV_PART_TEXTAREA_PLACEHOLDER }, - { "PART_TICKS", LV_PART_TICKS }, - { "RADIUS_CIRCLE", LV_RADIUS_CIRCLE }, - { "RES_INV", LV_RES_INV }, - { "RES_OK", LV_RES_OK }, - { "ROLLER_MODE_INFINITE", LV_ROLLER_MODE_INFINITE }, - { "ROLLER_MODE_NORMAL", LV_ROLLER_MODE_NORMAL }, - { "SCROLLBAR_MODE_ACTIVE", LV_SCROLLBAR_MODE_ACTIVE }, - { "SCROLLBAR_MODE_AUTO", LV_SCROLLBAR_MODE_AUTO }, - { "SCROLLBAR_MODE_OFF", LV_SCROLLBAR_MODE_OFF }, - { "SCROLLBAR_MODE_ON", LV_SCROLLBAR_MODE_ON }, - { "SCROLL_SNAP_CENTER", LV_SCROLL_SNAP_CENTER }, - { "SCROLL_SNAP_END", LV_SCROLL_SNAP_END }, - { "SCROLL_SNAP_NONE", LV_SCROLL_SNAP_NONE }, - { "SCROLL_SNAP_START", LV_SCROLL_SNAP_START }, - { "SCR_LOAD_ANIM_FADE_ON", LV_SCR_LOAD_ANIM_FADE_ON }, - { "SCR_LOAD_ANIM_MOVE_BOTTOM", LV_SCR_LOAD_ANIM_MOVE_BOTTOM }, - { "SCR_LOAD_ANIM_MOVE_LEFT", LV_SCR_LOAD_ANIM_MOVE_LEFT }, - { "SCR_LOAD_ANIM_MOVE_RIGHT", LV_SCR_LOAD_ANIM_MOVE_RIGHT }, - { "SCR_LOAD_ANIM_MOVE_TOP", LV_SCR_LOAD_ANIM_MOVE_TOP }, - { "SCR_LOAD_ANIM_NONE", LV_SCR_LOAD_ANIM_NONE }, - { "SCR_LOAD_ANIM_OVER_BOTTOM", LV_SCR_LOAD_ANIM_OVER_BOTTOM }, - { "SCR_LOAD_ANIM_OVER_LEFT", LV_SCR_LOAD_ANIM_OVER_LEFT }, - { "SCR_LOAD_ANIM_OVER_RIGHT", LV_SCR_LOAD_ANIM_OVER_RIGHT }, - { "SCR_LOAD_ANIM_OVER_TOP", LV_SCR_LOAD_ANIM_OVER_TOP }, - { "SIZE_CONTENT", LV_SIZE_CONTENT }, - { "SLIDER_MODE_NORMAL", LV_SLIDER_MODE_NORMAL }, - { "SLIDER_MODE_RANGE", LV_SLIDER_MODE_RANGE }, - { "SLIDER_MODE_SYMMETRICAL", LV_SLIDER_MODE_SYMMETRICAL }, - { "SPAN_MODE_BREAK", LV_SPAN_MODE_BREAK }, - { "SPAN_MODE_EXPAND", LV_SPAN_MODE_EXPAND }, - { "SPAN_MODE_FIXED", LV_SPAN_MODE_FIXED }, - { "SPAN_OVERFLOW_CLIP", LV_SPAN_OVERFLOW_CLIP }, - { "SPAN_OVERFLOW_ELLIPSIS", LV_SPAN_OVERFLOW_ELLIPSIS }, - { "STATE_ANY", LV_STATE_ANY }, - { "STATE_CHECKED", LV_STATE_CHECKED }, - { "STATE_DEFAULT", LV_STATE_DEFAULT }, - { "STATE_DISABLED", LV_STATE_DISABLED }, - { "STATE_EDITED", LV_STATE_EDITED }, - { "STATE_FOCUSED", LV_STATE_FOCUSED }, - { "STATE_FOCUS_KEY", LV_STATE_FOCUS_KEY }, - { "STATE_HOVERED", LV_STATE_HOVERED }, - { "STATE_PRESSED", LV_STATE_PRESSED }, - { "STATE_SCROLLED", LV_STATE_SCROLLED }, - { "STATE_USER_1", LV_STATE_USER_1 }, - { "STATE_USER_2", LV_STATE_USER_2 }, - { "STATE_USER_3", LV_STATE_USER_3 }, - { "STATE_USER_4", LV_STATE_USER_4 }, - { "STYLE_ALIGN", LV_STYLE_ALIGN }, - { "STYLE_ANIM_SPEED", LV_STYLE_ANIM_SPEED }, - { "STYLE_ANIM_TIME", LV_STYLE_ANIM_TIME }, - { "STYLE_ARC_COLOR", LV_STYLE_ARC_COLOR }, - { "STYLE_ARC_COLOR_FILTERED", LV_STYLE_ARC_COLOR_FILTERED }, - { "STYLE_ARC_IMG_SRC", LV_STYLE_ARC_IMG_SRC }, - { "STYLE_ARC_OPA", LV_STYLE_ARC_OPA }, - { "STYLE_ARC_ROUNDED", LV_STYLE_ARC_ROUNDED }, - { "STYLE_ARC_WIDTH", LV_STYLE_ARC_WIDTH }, - { "STYLE_BASE_DIR", LV_STYLE_BASE_DIR }, - { "STYLE_BG_COLOR", LV_STYLE_BG_COLOR }, - { "STYLE_BG_COLOR_FILTERED", LV_STYLE_BG_COLOR_FILTERED }, - { "STYLE_BG_GRAD_COLOR", LV_STYLE_BG_GRAD_COLOR }, - { "STYLE_BG_GRAD_COLOR_FILTERED", LV_STYLE_BG_GRAD_COLOR_FILTERED }, - { "STYLE_BG_GRAD_DIR", LV_STYLE_BG_GRAD_DIR }, - { "STYLE_BG_GRAD_STOP", LV_STYLE_BG_GRAD_STOP }, - { "STYLE_BG_IMG_OPA", LV_STYLE_BG_IMG_OPA }, - { "STYLE_BG_IMG_RECOLOR", LV_STYLE_BG_IMG_RECOLOR }, - { "STYLE_BG_IMG_RECOLOR_FILTERED", LV_STYLE_BG_IMG_RECOLOR_FILTERED }, - { "STYLE_BG_IMG_RECOLOR_OPA", LV_STYLE_BG_IMG_RECOLOR_OPA }, - { "STYLE_BG_IMG_SRC", LV_STYLE_BG_IMG_SRC }, - { "STYLE_BG_IMG_TILED", LV_STYLE_BG_IMG_TILED }, - { "STYLE_BG_MAIN_STOP", LV_STYLE_BG_MAIN_STOP }, - { "STYLE_BG_OPA", LV_STYLE_BG_OPA }, - { "STYLE_BLEND_MODE", LV_STYLE_BLEND_MODE }, - { "STYLE_BORDER_COLOR", LV_STYLE_BORDER_COLOR }, - { "STYLE_BORDER_COLOR_FILTERED", LV_STYLE_BORDER_COLOR_FILTERED }, - { "STYLE_BORDER_OPA", LV_STYLE_BORDER_OPA }, - { "STYLE_BORDER_POST", LV_STYLE_BORDER_POST }, - { "STYLE_BORDER_SIDE", LV_STYLE_BORDER_SIDE }, - { "STYLE_BORDER_WIDTH", LV_STYLE_BORDER_WIDTH }, - { "STYLE_CLIP_CORNER", LV_STYLE_CLIP_CORNER }, - { "STYLE_COLOR_FILTER_DSC", LV_STYLE_COLOR_FILTER_DSC }, - { "STYLE_COLOR_FILTER_OPA", LV_STYLE_COLOR_FILTER_OPA }, - { "STYLE_HEIGHT", LV_STYLE_HEIGHT }, - { "STYLE_IMG_OPA", LV_STYLE_IMG_OPA }, - { "STYLE_IMG_RECOLOR", LV_STYLE_IMG_RECOLOR }, - { "STYLE_IMG_RECOLOR_FILTERED", LV_STYLE_IMG_RECOLOR_FILTERED }, - { "STYLE_IMG_RECOLOR_OPA", LV_STYLE_IMG_RECOLOR_OPA }, - { "STYLE_LAYOUT", LV_STYLE_LAYOUT }, - { "STYLE_LINE_COLOR", LV_STYLE_LINE_COLOR }, - { "STYLE_LINE_COLOR_FILTERED", LV_STYLE_LINE_COLOR_FILTERED }, - { "STYLE_LINE_DASH_GAP", LV_STYLE_LINE_DASH_GAP }, - { "STYLE_LINE_DASH_WIDTH", LV_STYLE_LINE_DASH_WIDTH }, - { "STYLE_LINE_OPA", LV_STYLE_LINE_OPA }, - { "STYLE_LINE_ROUNDED", LV_STYLE_LINE_ROUNDED }, - { "STYLE_LINE_WIDTH", LV_STYLE_LINE_WIDTH }, - { "STYLE_MAX_HEIGHT", LV_STYLE_MAX_HEIGHT }, - { "STYLE_MAX_WIDTH", LV_STYLE_MAX_WIDTH }, - { "STYLE_MIN_HEIGHT", LV_STYLE_MIN_HEIGHT }, - { "STYLE_MIN_WIDTH", LV_STYLE_MIN_WIDTH }, - { "STYLE_OPA", LV_STYLE_OPA }, - { "STYLE_OUTLINE_COLOR", LV_STYLE_OUTLINE_COLOR }, - { "STYLE_OUTLINE_COLOR_FILTERED", LV_STYLE_OUTLINE_COLOR_FILTERED }, - { "STYLE_OUTLINE_OPA", LV_STYLE_OUTLINE_OPA }, - { "STYLE_OUTLINE_PAD", LV_STYLE_OUTLINE_PAD }, - { "STYLE_OUTLINE_WIDTH", LV_STYLE_OUTLINE_WIDTH }, - { "STYLE_PAD_BOTTOM", LV_STYLE_PAD_BOTTOM }, - { "STYLE_PAD_COLUMN", LV_STYLE_PAD_COLUMN }, - { "STYLE_PAD_LEFT", LV_STYLE_PAD_LEFT }, - { "STYLE_PAD_RIGHT", LV_STYLE_PAD_RIGHT }, - { "STYLE_PAD_ROW", LV_STYLE_PAD_ROW }, - { "STYLE_PAD_TOP", LV_STYLE_PAD_TOP }, - { "STYLE_PROP_ANY", LV_STYLE_PROP_ANY }, - { "STYLE_PROP_INV", LV_STYLE_PROP_INV }, - { "STYLE_RADIUS", LV_STYLE_RADIUS }, - { "STYLE_SHADOW_COLOR", LV_STYLE_SHADOW_COLOR }, - { "STYLE_SHADOW_COLOR_FILTERED", LV_STYLE_SHADOW_COLOR_FILTERED }, - { "STYLE_SHADOW_OFS_X", LV_STYLE_SHADOW_OFS_X }, - { "STYLE_SHADOW_OFS_Y", LV_STYLE_SHADOW_OFS_Y }, - { "STYLE_SHADOW_OPA", LV_STYLE_SHADOW_OPA }, - { "STYLE_SHADOW_SPREAD", LV_STYLE_SHADOW_SPREAD }, - { "STYLE_SHADOW_WIDTH", LV_STYLE_SHADOW_WIDTH }, - { "STYLE_TEXT_ALIGN", LV_STYLE_TEXT_ALIGN }, - { "STYLE_TEXT_COLOR", LV_STYLE_TEXT_COLOR }, - { "STYLE_TEXT_COLOR_FILTERED", LV_STYLE_TEXT_COLOR_FILTERED }, - { "STYLE_TEXT_DECOR", LV_STYLE_TEXT_DECOR }, - { "STYLE_TEXT_FONT", LV_STYLE_TEXT_FONT }, - { "STYLE_TEXT_LETTER_SPACE", LV_STYLE_TEXT_LETTER_SPACE }, - { "STYLE_TEXT_LINE_SPACE", LV_STYLE_TEXT_LINE_SPACE }, - { "STYLE_TEXT_OPA", LV_STYLE_TEXT_OPA }, - { "STYLE_TRANSFORM_ANGLE", LV_STYLE_TRANSFORM_ANGLE }, - { "STYLE_TRANSFORM_HEIGHT", LV_STYLE_TRANSFORM_HEIGHT }, - { "STYLE_TRANSFORM_WIDTH", LV_STYLE_TRANSFORM_WIDTH }, - { "STYLE_TRANSFORM_ZOOM", LV_STYLE_TRANSFORM_ZOOM }, - { "STYLE_TRANSITION", LV_STYLE_TRANSITION }, - { "STYLE_TRANSLATE_X", LV_STYLE_TRANSLATE_X }, - { "STYLE_TRANSLATE_Y", LV_STYLE_TRANSLATE_Y }, - { "STYLE_WIDTH", LV_STYLE_WIDTH }, - { "STYLE_X", LV_STYLE_X }, - { "STYLE_Y", LV_STYLE_Y }, - { "$SYMBOL_AUDIO", (int32_t) "\xef\x80\x81" }, - { "$SYMBOL_BACKSPACE", (int32_t) "\xef\x95\x9A" }, - { "$SYMBOL_BATTERY_1", (int32_t) "\xef\x89\x83" }, - { "$SYMBOL_BATTERY_2", (int32_t) "\xef\x89\x82" }, - { "$SYMBOL_BATTERY_3", (int32_t) "\xef\x89\x81" }, - { "$SYMBOL_BATTERY_EMPTY", (int32_t) "\xef\x89\x84" }, - { "$SYMBOL_BATTERY_FULL", (int32_t) "\xef\x89\x80" }, - { "$SYMBOL_BELL", (int32_t) "\xef\x83\xb3" }, - { "$SYMBOL_BLUETOOTH", (int32_t) "\xef\x8a\x93" }, - { "$SYMBOL_BULLET", (int32_t) "\xE2\x80\xA2" }, - { "$SYMBOL_CALL", (int32_t) "\xef\x82\x95" }, - { "$SYMBOL_CHARGE", (int32_t) "\xef\x83\xa7" }, - { "$SYMBOL_CLOSE", (int32_t) "\xef\x80\x8d" }, - { "$SYMBOL_COPY", (int32_t) "\xef\x83\x85" }, - { "$SYMBOL_CUT", (int32_t) "\xef\x83\x84" }, - { "$SYMBOL_DIRECTORY", (int32_t) "\xef\x81\xbb" }, - { "$SYMBOL_DOWN", (int32_t) "\xef\x81\xb8" }, - { "$SYMBOL_DOWNLOAD", (int32_t) "\xef\x80\x99" }, - { "$SYMBOL_DRIVE", (int32_t) "\xef\x80\x9c" }, - { "$SYMBOL_DUMMY", (int32_t) "\xEF\xA3\xBF" }, - { "$SYMBOL_EDIT", (int32_t) "\xef\x8C\x84" }, - { "$SYMBOL_EJECT", (int32_t) "\xef\x81\x92" }, - { "$SYMBOL_EYE_CLOSE", (int32_t) "\xef\x81\xb0" }, - { "$SYMBOL_EYE_OPEN", (int32_t) "\xef\x81\xae" }, - { "$SYMBOL_FILE", (int32_t) "\xef\x85\x9b" }, - { "$SYMBOL_GPS", (int32_t) "\xef\x84\xa4" }, - { "$SYMBOL_HOME", (int32_t) "\xef\x80\x95" }, - { "$SYMBOL_IMAGE", (int32_t) "\xef\x80\xbe" }, - { "$SYMBOL_KEYBOARD", (int32_t) "\xef\x84\x9c" }, - { "$SYMBOL_LEFT", (int32_t) "\xef\x81\x93" }, - { "$SYMBOL_LIST", (int32_t) "\xef\x80\x8b" }, - { "$SYMBOL_LOOP", (int32_t) "\xef\x81\xb9" }, - { "$SYMBOL_MINUS", (int32_t) "\xef\x81\xa8" }, - { "$SYMBOL_MUTE", (int32_t) "\xef\x80\xa6" }, - { "$SYMBOL_NEW_LINE", (int32_t) "\xef\xA2\xA2" }, - { "$SYMBOL_NEXT", (int32_t) "\xef\x81\x91" }, - { "$SYMBOL_OK", (int32_t) "\xef\x80\x8c" }, - { "$SYMBOL_PASTE", (int32_t) "\xef\x83\xAA" }, - { "$SYMBOL_PAUSE", (int32_t) "\xef\x81\x8c" }, - { "$SYMBOL_PLAY", (int32_t) "\xef\x81\x8b" }, - { "$SYMBOL_PLUS", (int32_t) "\xef\x81\xa7" }, - { "$SYMBOL_POWER", (int32_t) "\xef\x80\x91" }, - { "$SYMBOL_PREV", (int32_t) "\xef\x81\x88" }, - { "$SYMBOL_REFRESH", (int32_t) "\xef\x80\xa1" }, - { "$SYMBOL_RIGHT", (int32_t) "\xef\x81\x94" }, - { "$SYMBOL_SAVE", (int32_t) "\xef\x83\x87" }, - { "$SYMBOL_SD_CARD", (int32_t) "\xef\x9F\x82" }, - { "$SYMBOL_SETTINGS", (int32_t) "\xef\x80\x93" }, - { "$SYMBOL_SHUFFLE", (int32_t) "\xef\x81\xb4" }, - { "$SYMBOL_STOP", (int32_t) "\xef\x81\x8d" }, - { "$SYMBOL_TRASH", (int32_t) "\xef\x8B\xAD" }, - { "$SYMBOL_UP", (int32_t) "\xef\x81\xb7" }, - { "$SYMBOL_UPLOAD", (int32_t) "\xef\x82\x93" }, - { "$SYMBOL_USB", (int32_t) "\xef\x8a\x87" }, - { "$SYMBOL_VIDEO", (int32_t) "\xef\x80\x88" }, - { "$SYMBOL_VOLUME_MAX", (int32_t) "\xef\x80\xa8" }, - { "$SYMBOL_VOLUME_MID", (int32_t) "\xef\x80\xa7" }, - { "$SYMBOL_WARNING", (int32_t) "\xef\x81\xb1" }, - { "$SYMBOL_WIFI", (int32_t) "\xef\x87\xab" }, - { "TABLE_CELL_CTRL_CUSTOM_1", LV_TABLE_CELL_CTRL_CUSTOM_1 }, - { "TABLE_CELL_CTRL_CUSTOM_2", LV_TABLE_CELL_CTRL_CUSTOM_2 }, - { "TABLE_CELL_CTRL_CUSTOM_3", LV_TABLE_CELL_CTRL_CUSTOM_3 }, - { "TABLE_CELL_CTRL_CUSTOM_4", LV_TABLE_CELL_CTRL_CUSTOM_4 }, - { "TABLE_CELL_CTRL_MERGE_RIGHT", LV_TABLE_CELL_CTRL_MERGE_RIGHT }, - { "TABLE_CELL_CTRL_TEXT_CROP", LV_TABLE_CELL_CTRL_TEXT_CROP }, - { "TEXTAREA_CURSOR_LAST", LV_TEXTAREA_CURSOR_LAST }, - { "TEXT_ALIGN_AUTO", LV_TEXT_ALIGN_AUTO }, - { "TEXT_ALIGN_CENTER", LV_TEXT_ALIGN_CENTER }, - { "TEXT_ALIGN_LEFT", LV_TEXT_ALIGN_LEFT }, - { "TEXT_ALIGN_RIGHT", LV_TEXT_ALIGN_RIGHT }, - { "TEXT_CMD_STATE_IN", LV_TEXT_CMD_STATE_IN }, - { "TEXT_CMD_STATE_PAR", LV_TEXT_CMD_STATE_PAR }, - { "TEXT_CMD_STATE_WAIT", LV_TEXT_CMD_STATE_WAIT }, - { "TEXT_DECOR_NONE", LV_TEXT_DECOR_NONE }, - { "TEXT_DECOR_STRIKETHROUGH", LV_TEXT_DECOR_STRIKETHROUGH }, - { "TEXT_DECOR_UNDERLINE", LV_TEXT_DECOR_UNDERLINE }, - { "TEXT_FLAG_EXPAND", LV_TEXT_FLAG_EXPAND }, - { "TEXT_FLAG_FIT", LV_TEXT_FLAG_FIT }, - { "TEXT_FLAG_NONE", LV_TEXT_FLAG_NONE }, - { "TEXT_FLAG_RECOLOR", LV_TEXT_FLAG_RECOLOR }, - { "&font_montserrat", (int32_t) &lv0_load_montserrat_font }, - { "&font_robotocondensed_latin1", (int32_t) &lv0_load_robotocondensed_latin1_font }, - { "&font_seg7", (int32_t) &lv0_load_seg7_font }, - { "&load_font", (int32_t) &lv0_load_font }, - { "&load_freetype_font", (int32_t) &lv0_load_freetype_font }, - { "&montserrat_font", (int32_t) &lv0_load_montserrat_font }, - { "®ister_button_encoder", (int32_t) &lv0_register_button_encoder }, - { "&screenshot", (int32_t) &lv0_screenshot }, - { "&seg7_font", (int32_t) &lv0_load_seg7_font }, - -}; - -const size_t lv0_constants_size = sizeof(lv0_constants)/sizeof(lv0_constants[0]); - -/* generated */ -be_local_module(lv, - "lv", - be_nested_map(2, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("member", 719708611, 6, -1), be_const_func(lv0_member) }, - { be_nested_key("start", 1697318111, 5, 0), be_const_func(lv0_start) }, - })) -); -BE_EXPORT_VARIABLE be_define_const_native_module(lv); - -#endif // USE_LVGL - -/********************************************************************/ diff --git a/lib/libesp32/Berry/default/be_md5_lib.c b/lib/libesp32/Berry/default/be_md5_lib.c deleted file mode 100644 index 2c8dfd77b..000000000 --- a/lib/libesp32/Berry/default/be_md5_lib.c +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************** - * Berry module `webserver` - * - * To use: `import webserver` - * - * Allows to respond to HTTP request - *******************************************************************/ -#include "be_constobj.h" - -extern int m_md5_init(bvm *vm); -extern int m_md5_update(bvm *vm); -extern int m_md5_finish(bvm *vm); - -#include "../generate/be_fixed_be_class_md5.h" - -void be_load_md5_lib(bvm *vm) { - be_pushntvclass(vm, &be_class_md5); - be_setglobal(vm, "MD5"); - be_pop(vm, 1); -} -/* @const_object_info_begin - -class be_class_md5 (scope: global, name: MD5) { - .p, var - - init, func(m_md5_init) - update, func(m_md5_update) - finish, func(m_md5_finish) -} -@const_object_info_end */ diff --git a/lib/libesp32/Berry/default/be_unishox_lib.c b/lib/libesp32/Berry/default/be_unishox_lib.c deleted file mode 100644 index 971f4c9e0..000000000 --- a/lib/libesp32/Berry/default/be_unishox_lib.c +++ /dev/null @@ -1,28 +0,0 @@ -/******************************************************************** - * Berry module `unishox` - * - * To use: `import unishox` - * - * Allows to respond to HTTP request - *******************************************************************/ -#include "be_constobj.h" - -#ifdef USE_UNISHOX_COMPRESSION - -extern int be_ntv_unishox_decompress(bvm *vm); -extern int be_ntv_unishox_compress(bvm *vm); - -/******************************************************************** -** Solidified module: unishox -********************************************************************/ -be_local_module(unishox, - "unishox", - be_nested_map(2, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key(decompress, -1), be_const_func(be_ntv_unishox_decompress) }, - { be_const_key(compress, -1), be_const_func(be_ntv_unishox_compress) }, - })) -); -BE_EXPORT_VARIABLE be_define_const_native_module(unishox); - -#endif // USE_UNISHOX_COMPRESSION diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_audio_output.h b/lib/libesp32/Berry/generate/be_fixed_be_class_audio_output.h deleted file mode 100644 index 192ee0677..000000000 --- a/lib/libesp32/Berry/generate/be_fixed_be_class_audio_output.h +++ /dev/null @@ -1,17 +0,0 @@ -#include "be_constobj.h" - -static be_define_const_map_slots(be_class_audio_output_map) { - { be_const_key(_X2Ep, -1), be_const_var(0) }, -}; - -static be_define_const_map( - be_class_audio_output_map, - 1 -); - -BE_EXPORT_VARIABLE be_define_const_class( - be_class_audio_output, - 1, - NULL, - AudioOutput -); diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h b/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h deleted file mode 100644 index dc2abcca8..000000000 --- a/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h +++ /dev/null @@ -1,96 +0,0 @@ -#include "be_constobj.h" - -static be_define_const_map_slots(be_class_tasmota_map) { - { be_const_key(gc, -1), be_const_closure(Tasmota_gc_closure) }, - { be_const_key(read_sensors, 7), be_const_func(l_read_sensors) }, - { be_const_key(_get_cb, -1), be_const_func(l_get_cb) }, - { be_const_key(response_append, 50), be_const_func(l_respAppend) }, - { be_const_key(try_rule, 74), be_const_closure(Tasmota_try_rule_closure) }, - { be_const_key(eth, -1), be_const_func(l_eth) }, - { be_const_key(find_key_i, -1), be_const_closure(Tasmota_find_key_i_closure) }, - { be_const_key(exec_tele, 73), be_const_closure(Tasmota_exec_tele_closure) }, - { be_const_key(remove_driver, 28), be_const_closure(Tasmota_remove_driver_closure) }, - { be_const_key(load, -1), be_const_closure(Tasmota_load_closure) }, - { be_const_key(_settings_ptr, -1), be_const_comptr(&Settings) }, - { be_const_key(cmd_res, -1), be_const_var(0) }, - { be_const_key(time_str, 43), be_const_closure(Tasmota_time_str_closure) }, - { be_const_key(set_power, -1), be_const_func(l_setpower) }, - { be_const_key(yield, 20), be_const_func(l_yield) }, - { be_const_key(set_light, -1), be_const_closure(Tasmota_set_light_closure) }, - { be_const_key(find_op, 32), be_const_closure(Tasmota_find_op_closure) }, - { be_const_key(get_power, -1), be_const_func(l_getpower) }, - { be_const_key(add_rule, -1), be_const_closure(Tasmota_add_rule_closure) }, - { be_const_key(cb_dispatch, -1), be_const_closure(Tasmota_cb_dispatch_closure) }, - { be_const_key(global, -1), be_const_var(1) }, - { be_const_key(i2c_enabled, -1), be_const_func(l_i2cenabled) }, - { be_const_key(remove_cmd, 10), be_const_closure(Tasmota_remove_cmd_closure) }, - { be_const_key(millis, 18), be_const_func(l_millis) }, - { be_const_key(publish, 69), be_const_func(l_publish) }, - { be_const_key(_drivers, -1), be_const_var(2) }, - { be_const_key(resp_cmnd, -1), be_const_func(l_respCmnd) }, - { be_const_key(time_dump, -1), be_const_func(l_time_dump) }, - { be_const_key(web_send, -1), be_const_func(l_webSend) }, - { be_const_key(hs2rgb, -1), be_const_closure(Tasmota_hs2rgb_closure) }, - { be_const_key(memory, -1), be_const_func(l_memory) }, - { be_const_key(gen_cb, 0), be_const_closure(Tasmota_gen_cb_closure) }, - { be_const_key(rtc, -1), be_const_func(l_rtc) }, - { be_const_key(get_option, -1), be_const_func(l_getoption) }, - { be_const_key(add_cmd, -1), be_const_closure(Tasmota_add_cmd_closure) }, - { be_const_key(init, -1), be_const_closure(Tasmota_init_closure) }, - { be_const_key(_timers, -1), be_const_var(3) }, - { be_const_key(_global_addr, -1), be_const_comptr(&TasmotaGlobal) }, - { be_const_key(wd, -1), be_const_var(4) }, - { be_const_key(exec_cmd, -1), be_const_closure(Tasmota_exec_cmd_closure) }, - { be_const_key(wire_scan, -1), be_const_closure(Tasmota_wire_scan_closure) }, - { be_const_key(_global_def, 61), be_const_comptr(&be_tasmota_global_struct) }, - { be_const_key(resp_cmnd_failed, 11), be_const_func(l_respCmndFailed) }, - { be_const_key(chars_in_string, -1), be_const_closure(Tasmota_chars_in_string_closure) }, - { be_const_key(web_send_decimal, -1), be_const_func(l_webSendDecimal) }, - { be_const_key(_debug_present, 4), be_const_var(5) }, - { be_const_key(cmd, -1), be_const_closure(Tasmota_cmd_closure) }, - { be_const_key(_cb, -1), be_const_var(6) }, - { be_const_key(remove_rule, -1), be_const_closure(Tasmota_remove_rule_closure) }, - { be_const_key(run_deferred, -1), be_const_closure(Tasmota_run_deferred_closure) }, - { be_const_key(strftime, -1), be_const_func(l_strftime) }, - { be_const_key(add_driver, 3), be_const_closure(Tasmota_add_driver_closure) }, - { be_const_key(kv, 60), be_const_closure(Tasmota_kv_closure) }, - { be_const_key(set_timer, 58), be_const_closure(Tasmota_set_timer_closure) }, - { be_const_key(scale_uint, -1), be_const_func(l_scaleuint) }, - { be_const_key(remove_timer, -1), be_const_closure(Tasmota_remove_timer_closure) }, - { be_const_key(settings, 49), be_const_var(7) }, - { be_const_key(arch, -1), be_const_func(l_arch) }, - { be_const_key(_ccmd, 64), be_const_var(8) }, - { be_const_key(wire1, 46), be_const_var(9) }, - { be_const_key(exec_rules, 66), be_const_closure(Tasmota_exec_rules_closure) }, - { be_const_key(strptime, -1), be_const_func(l_strptime) }, - { be_const_key(_cmd, -1), be_const_func(l_cmd) }, - { be_const_key(resp_cmnd_error, -1), be_const_func(l_respCmndError) }, - { be_const_key(time_reached, -1), be_const_func(l_timereached) }, - { be_const_key(_rules, -1), be_const_var(10) }, - { be_const_key(publish_result, -1), be_const_func(l_publish_result) }, - { be_const_key(_settings_def, -1), be_const_comptr(&be_tasmota_settings_struct) }, - { be_const_key(get_switch, -1), be_const_func(l_getswitch) }, - { be_const_key(delay, 71), be_const_func(l_delay) }, - { be_const_key(resp_cmnd_str, -1), be_const_func(l_respCmndStr) }, - { be_const_key(wifi, -1), be_const_func(l_wifi) }, - { be_const_key(save, 15), be_const_func(l_save) }, - { be_const_key(log, 37), be_const_func(l_logInfo) }, - { be_const_key(resolvecmnd, -1), be_const_func(l_resolveCmnd) }, - { be_const_key(resp_cmnd_done, -1), be_const_func(l_respCmndDone) }, - { be_const_key(get_light, 5), be_const_closure(Tasmota_get_light_closure) }, - { be_const_key(get_free_heap, -1), be_const_func(l_getFreeHeap) }, - { be_const_key(wire2, -1), be_const_var(11) }, - { be_const_key(event, 34), be_const_closure(Tasmota_event_closure) }, -}; - -static be_define_const_map( - be_class_tasmota_map, - 80 -); - -BE_EXPORT_VARIABLE be_define_const_class( - be_class_tasmota, - 12, - NULL, - Tasmota -); diff --git a/lib/libesp32/Berry/include/be_lvgl.h b/lib/libesp32/Berry/include/be_lvgl.h deleted file mode 100644 index 52b5edc2d..000000000 --- a/lib/libesp32/Berry/include/be_lvgl.h +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************** - * Tasmota LVGL Headers - *******************************************************************/ -#ifndef __BE_LVGL_H__ -#define __BE_LVGL_H__ - -#include "be_constobj.h" - -#ifdef USE_LVGL - -#include "lvgl.h" - -#ifdef __cplusplus -extern "C" { -#endif - // table of functions per class - typedef struct lvbe_call_c_t { - const char * name; - void * func; - const char * return_type; - const char * arg_type; - } lvbe_call_c_t; - - // list of classes and function tables - typedef struct lvbe_call_c_classes_t { - const char * name; - const bclass * cl; - const lvbe_call_c_t * func_table; - size_t size; - } lvbe_call_c_classes_t; - extern const lvbe_call_c_classes_t lv_classes[]; - extern const size_t lv_classes_size; - -#ifdef __cplusplus -} -#endif - -#endif // USE_LVGL - -#endif // __BE_LVGL_H__ \ No newline at end of file diff --git a/lib/libesp32/Berry/tests/string.be b/lib/libesp32/Berry/tests/string.be deleted file mode 100644 index 479af1cb4..000000000 --- a/lib/libesp32/Berry/tests/string.be +++ /dev/null @@ -1,41 +0,0 @@ -import string as s - -assert(s.find('012345', '23') == 2) -assert(s.find('012345', '23', 1) == 2) -assert(s.find('012345', '23', 1, 3) == -1) -assert(s.find('012345', '23', 2, 4) == 2) -assert(s.find('012345', '23', 3) == -1) - -assert(s.find('012345', '') == 0) -assert(s.find('012345', '', 0, 0) == 0) -assert(s.find('012345', '', 1) == 1) -assert(s.find('012345', '', 1, 1) == 1) -assert(s.find('012345', '', 1, 0) == -1) -assert(s.find('012345', '', 6) == 6) -assert(s.find('012345', '', 7) == -1) - -assert(s.count('012345', '') == 7) -assert(s.count('012345', '', 2) == 5) -assert(s.count('012345', '', 6) == 1) - -assert(s.count('121314', '1') == 3) -assert(s.count('121314', '1', 1) == 2) -assert(s.count('121314', '1', 2) == 2) -assert(s.count('121314', '1', 1, 2) == 0) -assert(s.count('121314', '1', 1, 3) == 1) - -assert(s.split('a b c d e f', '1') == ['a b c d e f']) -assert(s.split('a b c d e f', ' ') == ['a', 'b', 'c', 'd', 'e', 'f']) -assert(s.split('a b c d e f', ' ', 2) == ['a', 'b', 'c d e f']) -assert(s.split('a b c d e f', '') == ['a b c d e f']) - -assert(s.format("%%") == "%") -assert(s.format("%i%%", 12) == "12%") -assert(s.format("%i%%%i", 12, 13) == "12%13") -assert(s.format("%s%%", "foo") == "foo%") -assert(s.format("%.1f%%", 3.5) == "3.5%") - -s="azerty" -assert(s[1..2] == "ze") -assert(s[1..] == "zerty") -assert(s[1..-1] == "zerty") diff --git a/lib/libesp32/Berry/tools/coc/.gitignore b/lib/libesp32/Berry/tools/coc/.gitignore deleted file mode 100644 index be1fbe796..000000000 --- a/lib/libesp32/Berry/tools/coc/.gitignore +++ /dev/null @@ -1 +0,0 @@ -coc diff --git a/lib/libesp32/Berry/tools/coc/Makefile b/lib/libesp32/Berry/tools/coc/Makefile deleted file mode 100644 index 773994b3c..000000000 --- a/lib/libesp32/Berry/tools/coc/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -TARGET = coc -CXXFLAGS = -std=c++11 -O2 -CXX = g++ - -OBJS = coc_string.o \ - hash_map.o \ - macro_table.o \ - main.o \ - block_builder.o \ - str_build.o \ - coc_parser.o - -ifeq ($(OS), Windows_NT) # Windows - TARGET := $(TARGET).exe -endif - -all: $(TARGET) - -$(TARGET): $(OBJS) - $(Q) $(CXX) $(OBJS) -o $@ - -$(OBJS): %.o: %.cpp - $(Q) $(CXX) $(CXXFLAGS) -c $< -o $@ - -clean: - $(Q) $(RM) $(OBJS) diff --git a/lib/libesp32/Berry/tools/coc/REEADME.md b/lib/libesp32/Berry/tools/coc/REEADME.md deleted file mode 100644 index 329c66d46..000000000 --- a/lib/libesp32/Berry/tools/coc/REEADME.md +++ /dev/null @@ -1,3 +0,0 @@ -# The Constant Object Compiler (coc) - -The constant object compiler (coc) is a C preprocessor that generates the corresponding C99 code based on the constant object declaration block. diff --git a/lib/libesp32/Berry/tools/coc/block_builder.cpp b/lib/libesp32/Berry/tools/coc/block_builder.cpp deleted file mode 100755 index bd76cdbf5..000000000 --- a/lib/libesp32/Berry/tools/coc/block_builder.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "block_builder.h" -#include "hash_map.h" -#include "macro_table.h" -#include "object_block.h" -#include -#include - -static bool depend(const object_block *object, const macro_table *macro) -{ - auto it = object->attr.find("depend"); - if (it != object->attr.end()) { - return macro->query(it->second); - } - return true; -} - -block_builder::block_builder(const object_block *object, const macro_table *macro) -{ - m_block.name = object->name; - if (depend(object, macro)) { - m_block.type = object->type; - m_block.attr = object->attr; - - auto it = object->attr.find("name"); - if (it != object->attr.end()) { - m_strtab.push_back(it->second); - } - - for (auto key : object->data_ordered) { - auto second = object->data.at(key); - if (second.depend.empty() || macro->query(second.depend)) { - m_block.data[key] = second.value; - m_strtab.push_back(key); - m_block.data_ordered.push_back(key); /* record insertion order */ - } - } - } -} - -std::string block_builder::block_tostring(const block &block) -{ - std::ostringstream ostr; - if (block.type == "map") { - ostr << map_tostring(block, block.name); - } else if (block.type == "class") { - ostr << class_tostring(block); - } else if (block.type == "vartab") { - ostr << vartab_tostring(block); - } else if (block.type == "module") { - ostr << module_tostring(block); - } - return ostr.str(); -} - -std::string block_builder::class_tostring(const block &block) -{ - bool empty_map = block.data.empty(); - std::ostringstream ostr; - hash_map map(block.data); - std::string map_name(block.name + "_map"); - - if (!empty_map) { - ostr << map_tostring(block, map_name, true) << std::endl; - } - ostr << scope(block) << " be_define_const_class(\n " - << block.name << ",\n " - << map.var_count() << ",\n " - << super(block) << ",\n " - << name(block) << "\n" - ");" << std::endl; - return ostr.str(); -} - -std::string block_builder::map_tostring(const block &block, const std::string &name, bool local) -{ - std::ostringstream ostr; - hash_map map(block.data); - - hash_map::entry_table list = map.entry_list(); - ostr << "static be_define_const_map_slots(" << name << ") {\n"; - for (auto it : list) { - ostr << " { be_const_key(" << it.key << ", " - << it.next << "), " << it.value << " }," << std::endl; - } - ostr << "};\n\n"; - - ostr << (local ? "static" : scope(block)) - << " be_define_const_map(\n " - << name << ",\n " - << list.size() << "\n" - ");" << std::endl; - return ostr.str(); -} - -std::string block_builder::vartab_tostring(const block &block) -{ - std::ostringstream ostr; - struct block idxblk; - std::vector varvec; - int index = 0; - - idxblk = block; - idxblk.data.clear(); - for (auto key : block.data_ordered) { - varvec.push_back(block.data.at(key)); - idxblk.data[key] = "int(" + std::to_string(index++) + ")"; - } - - ostr << map_tostring(idxblk, block.name + "_map", true) << std::endl; - ostr << "static const bvalue __vlist_array[] = {\n"; - for (auto it : varvec) { - ostr << " be_const_" << it << "," << std::endl; - } - ostr << "};\n\n"; - - ostr << "static be_define_const_vector(\n " - << block.name << "_vector,\n " - "__vlist_array,\n " - << varvec.size() << "\n" - ");" << std::endl; - return ostr.str(); -} - -std::string block_builder::module_tostring(const block &block) -{ - std::ostringstream ostr; - std::string name("m_lib" + block.name); - std::string map_name(name + "_map"); - - ostr << map_tostring(block, map_name, true) << std::endl - << "static be_define_const_module(\n " - << name << ",\n " - "\"" << block.name << "\"\n" - ");" << std::endl; - std::string scp = scope(block); - if (scp != "static") { /* extern */ - ostr << "\n" << scp - << " be_define_const_native_module(" - << block.name << ");" << std::endl; - } - return ostr.str(); -} - -std::string block_builder::scope(const block &block) -{ - auto it = block.attr.find("scope"); - return it != block.attr.end() && it->second == "local" ? - "static" : "BE_EXPORT_VARIABLE"; -} - -std::string block_builder::super(const block &block) -{ - auto it = block.attr.find("super"); - return it == block.attr.end() ? "NULL" : "(bclass *)&" + it->second; -} - -std::string block_builder::name(const block &block) -{ - auto it = block.attr.find("name"); - return it == block.attr.end() ? block.name : it->second; -} - -void block_builder::writefile(const std::string &filename, const std::string &text) -{ - std::string pathname(filename); - std::string otext("#include \"be_constobj.h\"\n\n" + text); - - std::ostringstream buf; - std::ifstream fin(pathname); - buf << fin.rdbuf(); - if (buf.str() != otext) { - std::ofstream fout; - fout.open(pathname, std::ios::out); - fout << otext; - fout.close(); - } -} - -void block_builder::dumpfile(const std::string &path) -{ - std::string s = block_tostring(m_block); - auto it = m_block.attr.find("file"); - std::string &name = it != m_block.attr.end() ? it->second : m_block.name; - writefile(path + "/be_fixed_" + name + ".h", s); -} - -const std::vector& block_builder::strtab() const -{ - return m_strtab; -} diff --git a/lib/libesp32/Berry/tools/coc/block_builder.h b/lib/libesp32/Berry/tools/coc/block_builder.h deleted file mode 100755 index 2811419eb..000000000 --- a/lib/libesp32/Berry/tools/coc/block_builder.h +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef __BLOCK_BUILDER_H -#define __BLOCK_BUILDER_H - -#include -#include -#include -#include "object_block.h" - -class macro_table; -class object_block; - -class block_builder { -public: - block_builder(const object_block *object, const macro_table *macro); - void dumpfile(const std::string &path); - const std::vector& strtab() const; - -private: - struct block { - std::string type; - std::string name; - std::map attr; - std::map data; - std::vector data_ordered; /* used to retrieve in insertion order */ - }; - - std::string block_tostring(const block &block); - std::string class_tostring(const block &block); - std::string vartab_tostring(const block &block); - std::string module_tostring(const block &block); - std::string map_tostring(const block &block, const std::string &name, bool local = false); - std::string scope(const block &block); - std::string super(const block &block); - std::string name(const block &block); - void writefile(const std::string &filename, const std::string &text); - -private: - block m_block; - std::vector m_strtab; -}; - -#endif // !__BLOCK_BUILDER_H diff --git a/lib/libesp32/Berry/tools/coc/coc_parser.cpp b/lib/libesp32/Berry/tools/coc/coc_parser.cpp deleted file mode 100644 index 2bbd69965..000000000 --- a/lib/libesp32/Berry/tools/coc/coc_parser.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "coc_parser.h" -#include - -static inline int _isalnum(int c) -{ - return isalnum(c) || c == '_'; -} - -coc_parser::coc_parser(const std::string &text) -{ - m_ptr = text.c_str(); - while (*m_ptr) { - switch (*m_ptr) { - case '@': - parse_object(); - break; - case 'b': - scan_const_string(); - break; - default: - ++m_ptr; - } - } -} - -const std::vector& coc_parser::objects() const -{ - return m_objects; -} - -const std::vector& coc_parser::strtab() const -{ - return m_strtab; -} - -void coc_parser::scan_const_string() -{ - const char prefix[] = "be_const_str_"; - const size_t len = sizeof(prefix) - 1; - if (!strncmp(m_ptr, prefix, len)) { - m_ptr += len; - const char *p = m_ptr; - while (_isalnum(*m_ptr)) - ++m_ptr; - m_strtab.push_back(std::string(p, m_ptr - p)); - } else { - ++m_ptr; - } -} - -void coc_parser::skip_space() -{ - while (isspace(*m_ptr)) - ++m_ptr; -} - -bool coc_parser::parse_char_base(int c, bool necessary) -{ - bool res = *m_ptr == c; - if (!res && necessary) - throw "error"; - if (res) - ++m_ptr; - return res; -} - -bool coc_parser::parse_char(int c, bool necessary) -{ - skip_space(); - return parse_char_base(c, necessary); -} - -bool coc_parser::parse_char_continue(int c, bool necessary) -{ - int ch; - while (((ch = *m_ptr) == ' ') || ch == '\t') - ++m_ptr; - return parse_char_base(c, necessary); -} - -std::string coc_parser::parse_word() -{ - skip_space(); - const char *p = m_ptr; - if (_isalnum(*m_ptr)) { - while (_isalnum(*(++m_ptr))); - return std::string(p, m_ptr - p); - } - throw "error"; -} - -std::string coc_parser::parse_tocomma() -{ - int c; - skip_space(); - const char *p = m_ptr; - while (((c = *m_ptr) != ',') && !isspace(c)) - ++m_ptr; - if (p == m_ptr) - throw "error"; - return std::string(p, m_ptr - p); -} - -std::string coc_parser::parse_tonewline() -{ - int c; - skip_space(); - const char *p = m_ptr; - while (((c = *m_ptr) != '\r') && c != '\n') - ++m_ptr; - if (p == m_ptr) - throw "error"; - return std::string(p, m_ptr - p); -} - -void coc_parser::parse_object() -{ - const char begin_text[] = "@const_object_info_begin"; - const size_t begin_len = sizeof(begin_text) - 1; - if (!strncmp(m_ptr, begin_text, begin_len)) { - m_ptr += begin_len; - do { - object_block object; - parse_block(&object); - m_objects.push_back(object); - } while (!parse_char('@')); - const char end_text[] = "const_object_info_end"; - const size_t end_len = sizeof(end_text) - 1; - if (strncmp(m_ptr, end_text, end_len)) - throw "error"; - m_ptr += end_len; - } else { - ++m_ptr; - } -} - -void coc_parser::parse_block(object_block *object) -{ - object->type = parse_word(); - object->name = parse_word(); - parse_attr(object); - parse_body(object); -} - -void coc_parser::parse_attr(object_block *object) -{ - skip_char('('); - parse_attr_pair(object); - while (parse_char(',')) { - parse_attr_pair(object); - } - skip_char(')'); -} - -void coc_parser::parse_attr_pair(object_block *object) -{ - std::string key = parse_word(); - skip_char(':'); - std::string value = parse_word(); - object->attr[key] = value; -} - -void coc_parser::parse_body(object_block *object) -{ - skip_char('{'); - if (!parse_char('}')) { - do { - parse_body_item(object); - } while (!parse_char('}')); - } -} - -void coc_parser::parse_body_item(object_block *object) -{ - object_block::data_value value; - std::string key = parse_tocomma(); - parse_char_continue(',', true); - value.value = parse_tocomma(); - if (parse_char_continue(',')) - value.depend = parse_tonewline(); - object->data[key] = value; - object->data_ordered.push_back(key); -} diff --git a/lib/libesp32/Berry/tools/coc/coc_parser.h b/lib/libesp32/Berry/tools/coc/coc_parser.h deleted file mode 100644 index b17a68a67..000000000 --- a/lib/libesp32/Berry/tools/coc/coc_parser.h +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef __COC_PARSER_H -#define __COC_PARSER_H - -#include -#include -#include "object_block.h" - -class coc_parser { -public: - coc_parser(const std::string &text); - const std::vector& objects() const; - const std::vector& strtab() const; - -private: - void scan_const_string(); - void skip_space(); - void skip_char(int c) { - parse_char(c, true); - } - bool parse_char_base(int c, bool necessary); - bool parse_char(int c, bool necessary = false); - bool parse_char_continue(int c, bool necessary = false); - std::string parse_word(); - std::string parse_tocomma(); - std::string parse_tonewline(); - void parse_object(); - void parse_block(object_block *object); - void parse_attr(object_block *object); - void parse_attr_pair(object_block *object); - void parse_body(object_block *object); - void parse_body_item(object_block *object); - -private: - const char *m_ptr; - std::vector m_objects; - std::vector m_strtab; -}; - -#endif // !__COC_PARSER_H diff --git a/lib/libesp32/Berry/tools/coc/coc_string.cpp b/lib/libesp32/Berry/tools/coc/coc_string.cpp deleted file mode 100644 index 1ae9384ac..000000000 --- a/lib/libesp32/Berry/tools/coc/coc_string.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "coc_string.h" -#include - -namespace coc { - -uint32_t hashcode(const std::string &string) -{ - size_t len = string.size(); - const char *str = string.data(); - uint32_t hash = 2166136261u; - while (len--) - hash = (hash ^ (unsigned char)*str++) * 16777619u; - return hash; -} - -std::string escape_operator(const std::string &string) -{ - int c = string[0]; - if (string == "..") - return "opt_connect"; - if (c == '.') - return "dot_" + string.substr(1); - if (isalpha(c) || c == '_') - return string; - const static std::map tab = { - { "+", "opt_add" }, { "-", "opt_sub" }, - { "*", "opt_mul" }, { "/", "opt_div" }, - { "%", "opt_mod" }, { "&", "opt_and" }, - { "^", "opt_xor" }, { "|", "opt_or" }, - { "<", "opt_lt" }, { ">", "opt_gt" }, - { "<=", "opt_le" }, { ">=", "opt_ge" }, - { "==", "opt_eq" }, { "!=", "opt_neq" }, - { "<<", "opt_shl" }, { ">>", "opt_shr" }, - { "-*", "opt_neg" }, { "~", "opt_flip" }, - { "()", "opt_call" } - }; - auto it = tab.find(string); - return it != tab.end() ? it->second : string; -} - -} diff --git a/lib/libesp32/Berry/tools/coc/coc_string.h b/lib/libesp32/Berry/tools/coc/coc_string.h deleted file mode 100644 index 5fb63ce2c..000000000 --- a/lib/libesp32/Berry/tools/coc/coc_string.h +++ /dev/null @@ -1,18 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef __COC_STRING_H -#define __COC_STRING_H - -#include - -namespace coc { - uint32_t hashcode(const std::string &string); - std::string escape_operator(const std::string &string); -} - -#endif diff --git a/lib/libesp32/Berry/tools/coc/hash_map.cpp b/lib/libesp32/Berry/tools/coc/hash_map.cpp deleted file mode 100755 index e05ca4677..000000000 --- a/lib/libesp32/Berry/tools/coc/hash_map.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "hash_map.h" -#include "coc_string.h" - -#define is_empty(entry) ((entry).next == NODE_EMPTY) - -hash_map::hash_map() -{ - resize(2); -} - -hash_map::hash_map(std::map map) -{ - resize(2); - for (auto it : map) { - insert(it.first, it.second); - } -} - -hash_map::~hash_map() -{ -} - -void hash_map::resize(size_t size) -{ - entry_table bucket = m_bucket; - m_bucket.resize(size); - /* set all slot to empty */ - for (int i = 0; i < size; ++i) { - m_bucket[i].next = NODE_EMPTY; - } - m_lastfree = size - 1; - for (auto slot : bucket) { - if (!is_empty(slot)) { - insert_p(slot.key, slot.value); - } - } -} - -hash_map::entry* hash_map::findprev(entry *list, entry *slot) -{ - int next; - entry *prev = list; - for (;;) { - next = prev->next; - if (next == NODE_NULL || &m_bucket[next] == slot) { - break; - } - prev = &m_bucket[next]; - } - if (next == NODE_NULL) { - return NULL; - } - return prev; -} - -int hash_map::nextfree() -{ - while (m_lastfree >= 0) { - if (is_empty(m_bucket[m_lastfree])) { - return int(m_lastfree); - } - --m_lastfree; - } - return -1; -} - -hash_map::entry hash_map::find(const std::string &key) -{ - uint32_t hash = coc::hashcode(key); - entry null, *slot = &m_bucket[hash % m_bucket.size()]; - if (is_empty(*slot)) { - return null; - } - while (slot->key != key) { - if (slot->next == NODE_NULL) { - return null; - } - slot = &m_bucket[slot->next]; - } - return *slot; -} - -void hash_map::insert_p(const std::string &key, const std::string value) -{ - entry *slot = &m_bucket[coc::hashcode(key) % m_bucket.size()]; - if (is_empty(*slot)) { /* empty slot */ - slot->next = NODE_NULL; - } else { - int newidx = nextfree(); - /* get the main-slot index */ - entry *mainslot = &m_bucket[coc::hashcode(slot->key) % m_bucket.size()]; - entry *newslot = &m_bucket[newidx]; /* get a free slot index */ - if (mainslot == slot) { /* old is main slot */ - newslot->next = mainslot->next; - mainslot->next = newidx; - slot = newslot; - } else { /* link to list */ - entry *prev = findprev(mainslot, slot); - prev->next = newidx; /* link the previous node */ - *newslot = *slot; /* copy to new slot */ - slot->next = NODE_NULL; - } - } - slot->key = key; - slot->value = value; -} - -void hash_map::insert(const std::string &key, const std::string value) -{ - entry slot = find(key); - if (slot.next == NODE_EMPTY) { /* new entry */ - if (m_count >= m_bucket.size()) { - resize(m_bucket.size() * 2); - } - insert_p(key, value); - ++m_count; - } -} - -hash_map::entry hash_map::entry_modify(entry entry, int *var_count) -{ - entry.key = coc::escape_operator(entry.key); - if (entry.value == "var") { - entry.value = "be_const_var(" - + std::to_string(*var_count) + ")"; - ++(*var_count); - } else { - entry.value = "be_const_" + entry.value; - } - return entry; -} - -hash_map::entry_table hash_map::entry_list() -{ - entry_table list; - int var_count = 0; - - resize(m_count); - for (auto it : m_bucket) { - list.push_back(entry_modify(it, &var_count)); - } - return list; -} - -int hash_map::var_count() -{ - int count = 0; - - resize(m_count); - for (auto it : m_bucket) { - count += it.value == "var" ? 1 : 0; - } - return count; -} diff --git a/lib/libesp32/Berry/tools/coc/hash_map.h b/lib/libesp32/Berry/tools/coc/hash_map.h deleted file mode 100755 index c1aca3e5b..000000000 --- a/lib/libesp32/Berry/tools/coc/hash_map.h +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef __HASH_MAP -#define __HASH_MAP - -#include -#include -#include - -#define NODE_EMPTY -2 -#define NODE_NULL -1 - -class hash_map { -public: - struct entry { - std::string key; - std::string value; - int next = NODE_EMPTY; - }; - typedef std::vector entry_table; - - hash_map(); - hash_map(std::map map); - ~hash_map(); - void insert(const std::string &key, const std::string value); - hash_map::entry find(const std::string &key); - entry_table entry_list(); - int var_count(); - -private: - int nextfree(); - hash_map::entry* findprev(entry *list, entry *slot); - void resize(size_t size); - void insert_p(const std::string &key, const std::string value); - hash_map::entry entry_modify(entry entry, int *var_count); - -private: - size_t m_count = 0, m_lastfree = 0; - entry_table m_bucket; -}; - -#endif // !__HASH_MAP diff --git a/lib/libesp32/Berry/tools/coc/macro_table.cpp b/lib/libesp32/Berry/tools/coc/macro_table.cpp deleted file mode 100644 index ea6d7bea7..000000000 --- a/lib/libesp32/Berry/tools/coc/macro_table.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "macro_table.h" -#include -#include -#include - -std::string macro_table::readfile(const std::string &filename) -{ - std::ifstream in(filename); - std::ostringstream tmp; - tmp << in.rdbuf(); - return tmp.str(); -} - -int macro_table::parse_value(std::string str) -{ - if (!str.length()) { - return 1; /* defined a macro name but no content, considered true */ - } - if (!(str[0] >= '0' && str[0] <= '9')) { - return 1; - } - return atoi(str.c_str()); -} - -void macro_table::scan_file(const std::string &filename) -{ - std::string str(readfile(filename)); - std::regex reg("(?:\\n|$)\\s*#define\\s+(\\w+)[ \\t]+(\\w+)"); - std::sregex_iterator it(str.begin(), str.end(), reg); - std::sregex_iterator end; - while (it != end) { - m_map[it->str(1)] = parse_value(it->str(2)); - ++it; - } -} - -bool macro_table::query(const std::string &str) const -{ - std::regex reg("(!?)(\\w+)"); - std::match_results res; - if (regex_match(str, res, reg)) { - auto it = m_map.find(res[2]); - int value = it == m_map.end() ? 0 : it->second; - return res[1] == "!" ? value == 0 : value != 0; - } - return 0; -} - -std::map macro_table::table() const -{ - return m_map; -} diff --git a/lib/libesp32/Berry/tools/coc/macro_table.h b/lib/libesp32/Berry/tools/coc/macro_table.h deleted file mode 100644 index 8999f63e6..000000000 --- a/lib/libesp32/Berry/tools/coc/macro_table.h +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef __MACRO_TABLE_H -#define __MACRO_TABLE_H - -#include -#include -#include - -class macro_table { -public: - macro_table() {} - void scan_file(const std::string &filename); - bool query(const std::string &str) const; - std::map table() const; - -private: - std::string readfile(const std::string &filename); - int parse_value(std::string str); - -private: - std::map m_map; -}; - -#endif diff --git a/lib/libesp32/Berry/tools/coc/main.cpp b/lib/libesp32/Berry/tools/coc/main.cpp deleted file mode 100755 index 0b876ba65..000000000 --- a/lib/libesp32/Berry/tools/coc/main.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "main.h" -#include "block_builder.h" -#include "coc_parser.h" -#include "macro_table.h" -#include "str_build.h" -#include -#include - -void builder::parse_all(const std::string &filename) -{ - size_t pos = filename.find_last_of("."); - std::string ext = pos < filename.size() ? filename.substr(pos) : ""; - if (ext == ".c" || ext == ".cc" || ext == ".cpp") { - std::string text = readfile(filename); - coc_parser parser(text); - push_strtab(parser.strtab()); - for (auto object : parser.objects()) { - block_builder builder(&object, m_macro); - push_strtab(builder.strtab()); - builder.dumpfile(m_output); - } - } -} - -void builder::push_strtab(const std::vector &list) -{ - for (auto s : list) - m_strmap[s] = 0; -} - -std::string builder::readfile(const std::string &filename) -{ - std::ifstream in(filename); - std::ostringstream tmp; - tmp << in.rdbuf(); - return tmp.str(); -} - -#ifndef _MSC_VER -#include -#include -#include -#else -#include -#include -#endif - -#ifndef _MSC_VER -void builder::scandir(const std::string &srcpath) -{ - DIR *dp; - struct dirent *ep; - dp = opendir(srcpath.data()); - if (dp != NULL) { - while ((ep = readdir(dp)) != NULL) { - std::string fname(ep->d_name); - parse_all(srcpath + "/" + fname); - } - closedir(dp); - } -} -#else -void builder::scandir(const std::string &srcpath) -{ - HANDLE find; - WIN32_FIND_DATA data; - find = FindFirstFile((srcpath + "/*").data(), &data); - if (find != INVALID_HANDLE_VALUE) { - do { - std::string fname(data.cFileName); - parse_all(srcpath + "/" + fname); - } while (FindNextFile(find, &data) != 0); - FindClose(find); - } -} -#endif - -void builder::build() -{ - for (auto it : m_input) { - scandir(it); - } - str_build sb(m_strmap); - sb.build(m_output); -} - -builder::builder(int argc, char **argv) -{ - m_state = Input; - for (int i = 1; i < argc; ++i) { - add_arg(argv[i]); - } - m_macro = new macro_table(); - for (auto it : m_config) { - m_macro->scan_file(it); - } -} - -builder::~builder() -{ - delete m_macro; -} - -void builder::add_arg(const std::string &arg) -{ - if (arg == "-i") { - m_state = Input; - } else if (arg == "-o") { - m_state = Output; - } else if (arg == "-c") { - m_state = Config; - } else { - switch (m_state) { - case Output: - m_output = arg; - break; - case Config: - m_config.push_back(arg); - break; - case Input: - default: - m_input.push_back(arg); - break; - } - m_state = Input; - } -} - -int main(int argc, char *argv[]) -{ - builder arg(argc, argv); - arg.build(); - return 0; -} diff --git a/lib/libesp32/Berry/tools/coc/main.h b/lib/libesp32/Berry/tools/coc/main.h deleted file mode 100644 index bba65d533..000000000 --- a/lib/libesp32/Berry/tools/coc/main.h +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef __MAIN_H -#define __MAIN_H - -#include -#include -#include - -class macro_table; - -class builder { -public: - builder(int argc, char **argv); - ~builder(); - void build(); - -private: - void push_strtab(const std::vector& list); - void add_arg(const std::string& arg); - std::string info_block(const std::string &text); - void parse_all(const std::string &filename); - void scandir(const std::string &srcpath); - std::string readfile(const std::string &filename); - -private: - enum arg_state { - Input, - Output, - Config - }; - std::string m_output; - std::vector m_input; - std::vector m_config; - arg_state m_state; - macro_table *m_macro; - std::map m_strmap; -}; - -#endif diff --git a/lib/libesp32/Berry/tools/coc/object_block.h b/lib/libesp32/Berry/tools/coc/object_block.h deleted file mode 100644 index c437f2b62..000000000 --- a/lib/libesp32/Berry/tools/coc/object_block.h +++ /dev/null @@ -1,26 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef __OBJECT_BLOCK_H -#define __OBJECT_BLOCK_H - -#include -#include - -struct object_block { - struct data_value { - std::string value; - std::string depend; - }; - std::string type; - std::string name; - std::map attr; - std::map data; - std::vector data_ordered; /* preserve order of keys */ -}; - -#endif diff --git a/lib/libesp32/Berry/tools/coc/str_build.cpp b/lib/libesp32/Berry/tools/coc/str_build.cpp deleted file mode 100644 index ebc44301e..000000000 --- a/lib/libesp32/Berry/tools/coc/str_build.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "str_build.h" -#include "coc_string.h" -#include -#include - -str_build::str_build(std::map map) -{ - size_t size = map.size() / 2; - m_count = map.size(); - m_hashtable.resize(size < 4 ? 4 : size); - for (auto it : map) { - make_ceil(it.first, it.second); - } - keywords(); -} - -str_build::~str_build() -{ -} - -void str_build::build(const std::string &path) -{ - std::string prefix(path + "/be_const_strtab"); - writefile(prefix + "_def.h", build_table_def()); - writefile(prefix + ".h", build_table_ext()); -} - -void str_build::keywords() -{ - const int opif = 50; /* note the definition in be_lexer.h */ - const static std::map tab = { - { "if", opif}, { "elif", opif + 1 }, - { "else", opif + 2 }, { "while", opif + 3 }, - { "for", opif + 4 }, { "def", opif + 5 }, - { "end", opif + 6 }, { "class", opif + 7 }, - { "break", opif + 8 }, { "continue", opif + 9 }, - { "return", opif + 10 }, { "true", opif + 11 }, - { "false", opif + 12 }, { "nil", opif + 13 }, - { "var", opif + 14 }, { "do", opif + 15 }, - { "import", opif + 16 }, { "as", opif + 17 }, - { "try", opif + 18 }, { "except", opif + 19 }, - { "raise", opif + 20 }, { "static", opif + 21 } - }; - for (auto it : tab) { - make_ceil(it.first, it.second); - } -} - -void str_build::make_ceil(const std::string &string, int extra) -{ - str_info info; - info.hash = coc::hashcode(string); - info.str = string; - info.extra = extra; - m_hashtable[info.hash % m_hashtable.size()].push_back(info); -} - -void str_build::writefile(const std::string &filename, const std::string &text) -{ - std::ostringstream buf; - std::ifstream fin(filename); - buf << fin.rdbuf(); - if (buf.str() != text) { - std::ofstream fout; - fout.open(filename, std::ios::out); - fout << text; - fout.close(); - } -} - -std::string str_build::build_table_def() -{ - std::ostringstream ostr; - for (auto bucket : m_hashtable) { - size_t size = bucket.size(); - for (size_t i = 0; i < size; ++i) { - str_info info = bucket[i]; - std::string node = coc::escape_operator(info.str); - std::string next = i < size - 1 ? - "&be_const_str_" + coc::escape_operator(bucket[i + 1].str) : - "NULL"; - ostr << "be_define_const_str(" - << node << ", \"" << info.str << "\", " - << info.hash << "u, " << info.extra << ", " - << info.str.size() << ", " << next << ");" - << std::endl; - } - } - ostr << std::endl; - ostr << "static const bstring* const m_string_table[] = {" << std::endl; - size_t size = m_hashtable.size(); - for (size_t i = 0; i < size; ++i) { - auto bucket = m_hashtable[i]; - if (bucket.size()) { - ostr << " (const bstring *)&be_const_str_" - << coc::escape_operator(bucket[0].str); - } else { - ostr << " NULL"; - } - ostr << (i < size - 1 ? "," : "") << std::endl; - } - ostr << "};" << std::endl << std::endl; - ostr << - "static const struct bconststrtab m_const_string_table = {\n" - " .size = " << size << ",\n" << - " .count = " << m_count << ",\n" << - " .table = m_string_table\n" << - "};" << std::endl; - return ostr.str(); -} - -std::string str_build::build_table_ext() -{ - std::ostringstream ostr; - for (auto bucket : m_hashtable) { - for (auto info : bucket) { - ostr << "extern const bcstring be_const_str_" - << coc::escape_operator(info.str) << ";" << std::endl; - } - } - return ostr.str(); -} diff --git a/lib/libesp32/Berry/tools/coc/str_build.h b/lib/libesp32/Berry/tools/coc/str_build.h deleted file mode 100644 index 3a3527409..000000000 --- a/lib/libesp32/Berry/tools/coc/str_build.h +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef __BUILD_MAP_H -#define __BUILD_MAP_H - -#include -#include -#include - -class str_build -{ -public: - str_build(std::map map); - ~str_build(); - void build(const std::string &path); - -private: - void keywords(); - void make_ceil(const std::string &string, int extra = 0); - std::string build_table_def(); - std::string build_table_ext(); - void writefile(const std::string &filename, const std::string &text); - -private: - struct str_info { - uint32_t hash; - std::string str; - int extra; - }; - size_t m_count; - std::vector< std::vector > m_hashtable; -}; - -#endif diff --git a/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h index 4a7c3ccc9..97f9c842c 100644 --- a/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h +++ b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h @@ -53,37 +53,3 @@ void wifi_station_disconnect(); void wifi_station_dhcpc_start(); extern WiFiClass32 WiFi32; #define WiFi WiFi32 - -class WiFiUDP32 : public WiFiUDP -{ - public: - size_t write(const char*s) - { - return WiFiUDP::write((const uint8_t *)s, strlen(s)); - } - size_t write(const uint8_t *buf, size_t n) - { - return WiFiUDP::write(buf, n); - } - static void stopAll() - { - - } - static void forceSleepWake() - { - - } - uint8_t beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port) - { - return WiFiUDP::beginMulticast(multicast, port); - } - void beginPacketMulticast(IPAddress multicast, uint16_t port, IPAddress interfaceAddr) - { - if (0 == WiFiUDP::beginMulticastPacket()) { - WiFiUDP::beginMulticast(multicast, port); - } - WiFiUDP::beginMulticastPacket(); - } -}; - -#define WiFiUDP WiFiUDP32 diff --git a/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp index d11d09931..fbead560a 100644 --- a/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp +++ b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp @@ -37,3 +37,140 @@ #include "esp8266toEsp32.h" // ESP Stuff + +/*********************************************************************************************\ + * ESP32 analogWrite emulation support +\*********************************************************************************************/ + +#if CONFIG_IDF_TARGET_ESP32C3 + uint8_t _pwm_channel[PWM_SUPPORTED_CHANNELS] = { 99, 99, 99, 99, 99, 99 }; + uint32_t _pwm_frequency = 977; // Default 977Hz + uint8_t _pwm_bit_num = 10; // Default 1023 +#else // other ESP32 + uint8_t _pwm_channel[PWM_SUPPORTED_CHANNELS] = { 99, 99, 99, 99, 99, 99, 99, 99 }; + uint32_t _pwm_frequency = 977; // Default 977Hz + uint8_t _pwm_bit_num = 10; // Default 1023 +#endif // CONFIG_IDF_TARGET_ESP32C3 vs ESP32 + +uint32_t _analog_pin2chan(uint32_t pin) { + for (uint32_t channel = 0; channel < PWM_SUPPORTED_CHANNELS; channel++) { + if ((_pwm_channel[channel] < 99) && (_pwm_channel[channel] == pin)) { + return channel; + } + } + return 0; +} + +void _analogWriteFreqRange(void) { + for (uint32_t channel = 0; channel < PWM_SUPPORTED_CHANNELS; channel++) { + if (_pwm_channel[channel] < 99) { + ledcSetup(channel + PWM_CHANNEL_OFFSET, _pwm_frequency, _pwm_bit_num); + } + } +} + +// input range is in full range, ledc needs bits +uint32_t _analogGetResolution(uint32_t x) { + uint32_t bits = 0; + while (x) { + bits++; + x >>= 1; + } + return bits; +} + +void analogWriteRange(uint32_t range) { + _pwm_bit_num = _analogGetResolution(range); + _analogWriteFreqRange(); +} + +void analogWriteFreq(uint32_t freq) { + _pwm_frequency = freq; + _analogWriteFreqRange(); +} + +bool analogAttach(uint32_t pin) { + // Find if pin is already attached + uint32_t channel; + for (channel = 0; channel < PWM_SUPPORTED_CHANNELS; channel++) { + if (_pwm_channel[channel] == pin) { + // Already attached + // Serial.printf("PWM: Already attached pin %d to channel %d\n", pin, channel); + return true; + } + } + // Find an empty channel + for (channel = 0; channel < PWM_SUPPORTED_CHANNELS; channel++) { + if (99 == _pwm_channel[channel]) { + _pwm_channel[channel] = pin; + ledcAttachPin(pin, channel + PWM_CHANNEL_OFFSET); + ledcSetup(channel + PWM_CHANNEL_OFFSET, _pwm_frequency, _pwm_bit_num); + // Serial.printf("PWM: New attach pin %d to channel %d\n", pin, channel); + return true; + } + } + // No more channels available + return false; +} + +// void analogWrite(uint8_t pin, int val); +extern "C" void __wrap__Z11analogWritehi(uint8_t pin, int val) +{ + uint32_t channel = _analog_pin2chan(pin); + if ( val >> (_pwm_bit_num-1) ) ++val; + ledcWrite(channel + PWM_CHANNEL_OFFSET, val); + // Serial.printf("write %d - %d\n",channel,val); +} + +/* + The primary goal of this library is to add phase control to PWM ledc + functions. + + Phase control allows to stress less the power supply of LED lights. + By default all phases are starting at the same moment. This means + the the power supply always takes a power hit at the start of each + new cycle, even if the average power is low. + + Phase control is also of major importance for H-bridge where + both PWM lines should NEVER be active at the same time. + + Unfortunately Arduino Core does not allow any customization nor + extendibility for the ledc/analogWrite functions. We have therefore + no other choice than duplicating part of Arduino code. + + WARNING: this means it can easily break if ever Arduino internal + implementation changes. +*/ + +#include "driver/ledc.h" + +#ifdef SOC_LEDC_SUPPORT_HS_MODE +#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM<<1) +#else +#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM) +#endif + +// exported from Arduno Core +extern uint8_t channels_resolution[LEDC_CHANNELS]; + +void analogWritePhase(uint8_t pin, uint32_t duty, uint32_t phase) +{ + uint32_t chan = _analog_pin2chan(pin) + PWM_CHANNEL_OFFSET; + if (duty >> (_pwm_bit_num-1) ) ++duty; + + if(chan >= LEDC_CHANNELS){ + return; + } + uint8_t group=(chan/8), channel=(chan%8); + + //Fixing if all bits in resolution is set = LEDC FULL ON + uint32_t max_duty = (1 << channels_resolution[chan]) - 1; + phase = phase % max_duty; + + if(duty == max_duty){ // no sure whether this is needed anymore TODO + duty = max_duty + 1; + } + + ledc_set_duty_with_hpoint((ledc_mode_t)group, (ledc_channel_t)channel, duty, phase); + ledc_update_duty((ledc_mode_t)group, (ledc_channel_t)channel); +} diff --git a/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h index 40abad981..adda5f2eb 100644 --- a/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h +++ b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h @@ -28,80 +28,29 @@ #include -/*********************************************************************************************\ - * ESP32 analogWrite emulation support -\*********************************************************************************************/ - #if CONFIG_IDF_TARGET_ESP32C3 #define PWM_SUPPORTED_CHANNELS 6 #define PWM_CHANNEL_OFFSET 1 // Webcam uses channel 0, so we offset standard PWM - - uint8_t _pwm_channel[PWM_SUPPORTED_CHANNELS] = { 99, 99, 99, 99, 99, 99 }; - uint32_t _pwm_frequency = 977; // Default 977Hz - uint8_t _pwm_bit_num = 10; // Default 1023 #else // other ESP32 #define PWM_SUPPORTED_CHANNELS 8 #define PWM_CHANNEL_OFFSET 2 // Webcam uses channel 0, so we offset standard PWM - - uint8_t _pwm_channel[PWM_SUPPORTED_CHANNELS] = { 99, 99, 99, 99, 99, 99, 99, 99 }; - uint32_t _pwm_frequency = 977; // Default 977Hz - uint8_t _pwm_bit_num = 10; // Default 1023 #endif // CONFIG_IDF_TARGET_ESP32C3 vs ESP32 -inline uint32_t _analog_pin2chan(uint32_t pin) { - for (uint32_t channel = 0; channel < PWM_SUPPORTED_CHANNELS; channel++) { - if ((_pwm_channel[channel] < 99) && (_pwm_channel[channel] == pin)) { - return channel; - } - } - return 0; -} - -inline void _analogWriteFreqRange(void) { - for (uint32_t channel = 0; channel < PWM_SUPPORTED_CHANNELS; channel++) { - if (_pwm_channel[channel] < 99) { -// uint32_t duty = ledcRead(channel + PWM_CHANNEL_OFFSET); - ledcSetup(channel + PWM_CHANNEL_OFFSET, _pwm_frequency, _pwm_bit_num); -// ledcWrite(channel + PWM_CHANNEL_OFFSET, duty); - } - } -// Serial.printf("freq - range %d - %d\n",freq,range); -} +extern uint8_t _pwm_channel[PWM_SUPPORTED_CHANNELS]; +extern uint32_t _pwm_frequency; +extern uint8_t _pwm_bit_num; +void _analogWriteFreqRange(void); // input range is in full range, ledc needs bits -inline uint32_t _analogGetResolution(uint32_t x) { - uint32_t bits = 0; - while (x) { - bits++; - x >>= 1; - } - return bits; -} +uint32_t _analogGetResolution(uint32_t x); +void analogWriteRange(uint32_t range); +void analogWriteFreq(uint32_t freq); +bool analogAttach(uint32_t pin); +void analogWrite(uint8_t pin, int val); -inline void analogWriteRange(uint32_t range) { - _pwm_bit_num = _analogGetResolution(range); - _analogWriteFreqRange(); -} +// Extended version that also allows to change phase +extern void analogWritePhase(uint8_t pin, uint32_t duty, uint32_t phase = 0); -inline void analogWriteFreq(uint32_t freq) { - _pwm_frequency = freq; - _analogWriteFreqRange(); -} - -inline void analogAttach(uint32_t pin, uint32_t channel) { - _pwm_channel[channel &7] = pin; - ledcAttachPin(pin, channel + PWM_CHANNEL_OFFSET); - ledcSetup(channel + PWM_CHANNEL_OFFSET, _pwm_frequency, _pwm_bit_num); -// Serial.printf("attach %d - %d\n", channel, pin); -} - -inline void analogWrite(uint8_t pin, int val) -{ - uint32_t channel = _analog_pin2chan(pin); - if ( val >> (_pwm_bit_num-1) ) ++val; - ledcWrite(channel + PWM_CHANNEL_OFFSET, val); -// Serial.printf("write %d - %d\n",channel,val); -} /*********************************************************************************************/ diff --git a/lib/libesp32/Zip-readonly-FS/library.json b/lib/libesp32/Zip-readonly-FS/library.json index a8c83f81b..e57844d30 100644 --- a/lib/libesp32/Zip-readonly-FS/library.json +++ b/lib/libesp32/Zip-readonly-FS/library.json @@ -4,8 +4,8 @@ "description": "Simple filesystem to open an uncompressed ZIP file and read-only", "license": "MIT", "homepage": "https://github.com/arendst/Tasmota", - "frameworks": "*", - "platforms": "*", + "frameworks": "arduino", + "platforms": "espressif32", "authors": { "name": "Stephan Hadinger", diff --git a/lib/libesp32/Berry/LICENSE b/lib/libesp32/berry/LICENSE similarity index 100% rename from lib/libesp32/Berry/LICENSE rename to lib/libesp32/berry/LICENSE diff --git a/lib/libesp32/Berry/Makefile b/lib/libesp32/berry/Makefile similarity index 100% rename from lib/libesp32/Berry/Makefile rename to lib/libesp32/berry/Makefile diff --git a/lib/libesp32/Berry/README.md b/lib/libesp32/berry/README.md similarity index 100% rename from lib/libesp32/Berry/README.md rename to lib/libesp32/berry/README.md diff --git a/lib/libesp32/Berry/berry-logo.png b/lib/libesp32/berry/berry-logo.png similarity index 100% rename from lib/libesp32/Berry/berry-logo.png rename to lib/libesp32/berry/berry-logo.png diff --git a/lib/libesp32/Berry/default/be_modtab.c b/lib/libesp32/berry/default/be_modtab.c similarity index 88% rename from lib/libesp32/Berry/default/be_modtab.c rename to lib/libesp32/berry/default/be_modtab.c index 47db8b24e..989cad873 100644 --- a/lib/libesp32/Berry/default/be_modtab.c +++ b/lib/libesp32/berry/default/be_modtab.c @@ -23,6 +23,10 @@ be_extern_native_module(solidify); be_extern_native_module(introspect); be_extern_native_module(strict); +/* Berry extensions */ +#include "be_mapping.h" +be_extern_native_module(cb); + /* Tasmota specific */ be_extern_native_module(python_compat); be_extern_native_module(re); @@ -40,8 +44,15 @@ be_extern_native_module(unishox); be_extern_native_module(animate); #ifdef USE_LVGL be_extern_native_module(lv); +be_extern_native_module(lv_extra); +be_extern_native_module(lv_tasmota); #endif // USE_LVGL +#if defined(USE_MI_ESP32) && !defined(USE_BLE_ESP32) +extern void be_load_MI32_class(bvm *vm); +extern void be_load_BLE_class(bvm *vm); +#endif //USE_MI_ESP32 + /* user-defined modules declare start */ /* user-defined modules declare end */ @@ -85,6 +96,10 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { #if BE_USE_STRICT_MODULE &be_native_module(strict), #endif + + /* Berry extensions */ + &be_native_module(cb), + /* user-defined modules register start */ &be_native_module(python_compat), @@ -110,6 +125,8 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { #ifdef USE_LVGL &be_native_module(lv), + &be_native_module(lv_extra), + &be_native_module(lv_tasmota), #endif // USE_LVGL #ifdef USE_ENERGY_SENSOR &be_native_module(energy), @@ -136,6 +153,7 @@ extern void be_load_AXP192_class(bvm *vm); extern void be_load_md5_lib(bvm *vm); extern void be_load_webclient_lib(bvm *vm); extern void be_load_tcpclient_lib(bvm *vm); +extern void be_load_udp_lib(bvm *vm); extern void be_load_crypto_lib(bvm *vm); extern void be_load_Leds_ntv_class(bvm *vm); extern void be_load_Leds_class(bvm *vm); @@ -146,12 +164,11 @@ extern void be_load_ctypes_energy_definitions_lib(bvm *vm); #ifdef USE_I2S_AUDIO_BERRY extern void be_load_driver_audio_lib(bvm *vm); +extern void be_load_driver_audio_opus_decoder(bvm *vm); #endif #ifdef USE_LVGL -extern void be_load_lv_color_class(bvm *vm); -extern void be_load_lv_font_class(bvm *vm); -extern void be_load_LVGL_glob_class(bvm *vm); +#include "lv_berry.h" // custom widgets extern void be_load_lv_signal_bars_class(bvm *vm); extern void be_load_lv_wifi_bars_class(bvm *vm); @@ -191,6 +208,7 @@ BERRY_API void be_load_custom_libs(bvm *vm) #ifdef USE_WEBCLIENT be_load_webclient_lib(vm); be_load_tcpclient_lib(vm); + be_load_udp_lib(vm); #endif // USE_WEBCLIENT #if defined(USE_ONEWIRE) || defined(USE_DS18x20) be_load_onewirelib(vm); @@ -202,13 +220,11 @@ BERRY_API void be_load_custom_libs(bvm *vm) #endif // USE_WS2812 #ifdef USE_I2S_AUDIO_BERRY be_load_driver_audio_lib(vm); + be_load_driver_audio_opus_decoder(vm); #endif #ifdef USE_LVGL // LVGL - be_load_lv_color_class(vm); - be_load_lv_font_class(vm); - - be_load_LVGL_glob_class(vm); + be_load_lvgl_classes(vm); // custom widgets be_load_lv_signal_bars_class(vm); be_load_lv_wifi_bars_class(vm); @@ -218,5 +234,9 @@ BERRY_API void be_load_custom_libs(bvm *vm) be_load_lv_wifi_arcs_icon_class(vm); be_load_lv_clock_icon_class(vm); #endif // USE_LVGL +#if defined(USE_MI_ESP32) && !defined(USE_BLE_ESP32) + be_load_MI32_class(vm); + be_load_BLE_class(vm); +#endif //USE_MI_ESP32 } #endif diff --git a/lib/libesp32/Berry/default/berry_conf.h b/lib/libesp32/berry/default/berry_conf.h similarity index 95% rename from lib/libesp32/Berry/default/berry_conf.h rename to lib/libesp32/berry/default/berry_conf.h index d2284ac31..d796dce02 100644 --- a/lib/libesp32/Berry/default/berry_conf.h +++ b/lib/libesp32/berry/default/berry_conf.h @@ -65,20 +65,14 @@ **/ #define BE_DEBUG_VAR_INFO 0 -/* Macro: BE_USE_OBSERVABILITY_HOOK - * Use the obshook function to report low-level actions. - * Default: 0 - **/ -#define BE_USE_OBSERVABILITY_HOOK 1 - -/* Macro: BE_USE_OBSERVABILITY_HOOK +/* Macro: BE_USE_PERF_COUNTERS * Use the obshook function to report low-level actions. * Default: 0 **/ #define BE_USE_PERF_COUNTERS 1 /* Macro: BE_VM_OBSERVABILITY_SAMPLING - * If BE_USE_OBSERVABILITY_HOOK == 1 and BE_USE_PERF_COUNTERS == 1 + * If BE_USE_PERF_COUNTERS == 1 * then the observability hook is called regularly in the VM loop * allowing to stop infinite loops or too-long running code. * The value is a power of 2. @@ -220,6 +214,9 @@ extern "C" { extern void *berry_malloc(size_t size); extern void berry_free(void *ptr); extern void *berry_realloc(void *ptr, size_t size); + extern void *berry_malloc32(size_t size); + extern void berry_free32(void *ptr); + extern void *berry_realloc32(void *ptr, size_t size); #ifdef __cplusplus } #endif @@ -247,7 +244,7 @@ extern "C" { /* Tasmota debug specific */ #ifdef USE_BERRY_DEBUG #undef BE_DEBUG_RUNTIME_INFO - #define BE_DEBUG_RUNTIME_INFO 2 /* record line information in 16 bits */ + #define BE_DEBUG_RUNTIME_INFO 1 /* record line information in 32 bits to be places in IRAM */ #endif // USE_BERRY_DEBUG #endif diff --git a/lib/libesp32/Berry/examples/anon_func.be b/lib/libesp32/berry/examples/anon_func.be similarity index 100% rename from lib/libesp32/Berry/examples/anon_func.be rename to lib/libesp32/berry/examples/anon_func.be diff --git a/lib/libesp32/Berry/examples/bigloop.be b/lib/libesp32/berry/examples/bigloop.be similarity index 100% rename from lib/libesp32/Berry/examples/bigloop.be rename to lib/libesp32/berry/examples/bigloop.be diff --git a/lib/libesp32/Berry/examples/bintree.be b/lib/libesp32/berry/examples/bintree.be similarity index 100% rename from lib/libesp32/Berry/examples/bintree.be rename to lib/libesp32/berry/examples/bintree.be diff --git a/lib/libesp32/Berry/examples/calcpi.be b/lib/libesp32/berry/examples/calcpi.be similarity index 100% rename from lib/libesp32/Berry/examples/calcpi.be rename to lib/libesp32/berry/examples/calcpi.be diff --git a/lib/libesp32/Berry/examples/exception.be b/lib/libesp32/berry/examples/exception.be similarity index 100% rename from lib/libesp32/Berry/examples/exception.be rename to lib/libesp32/berry/examples/exception.be diff --git a/lib/libesp32/Berry/examples/fib_rec.be b/lib/libesp32/berry/examples/fib_rec.be similarity index 100% rename from lib/libesp32/Berry/examples/fib_rec.be rename to lib/libesp32/berry/examples/fib_rec.be diff --git a/lib/libesp32/Berry/examples/guess_number.be b/lib/libesp32/berry/examples/guess_number.be similarity index 100% rename from lib/libesp32/Berry/examples/guess_number.be rename to lib/libesp32/berry/examples/guess_number.be diff --git a/lib/libesp32/Berry/examples/json.be b/lib/libesp32/berry/examples/json.be similarity index 100% rename from lib/libesp32/Berry/examples/json.be rename to lib/libesp32/berry/examples/json.be diff --git a/lib/libesp32/Berry/examples/lambda.be b/lib/libesp32/berry/examples/lambda.be similarity index 100% rename from lib/libesp32/Berry/examples/lambda.be rename to lib/libesp32/berry/examples/lambda.be diff --git a/lib/libesp32/Berry/examples/listdir.be b/lib/libesp32/berry/examples/listdir.be similarity index 100% rename from lib/libesp32/Berry/examples/listdir.be rename to lib/libesp32/berry/examples/listdir.be diff --git a/lib/libesp32/Berry/examples/qsort.be b/lib/libesp32/berry/examples/qsort.be similarity index 100% rename from lib/libesp32/Berry/examples/qsort.be rename to lib/libesp32/berry/examples/qsort.be diff --git a/lib/libesp32/Berry/examples/repl.be b/lib/libesp32/berry/examples/repl.be similarity index 100% rename from lib/libesp32/Berry/examples/repl.be rename to lib/libesp32/berry/examples/repl.be diff --git a/lib/libesp32/Berry/examples/string.be b/lib/libesp32/berry/examples/string.be similarity index 100% rename from lib/libesp32/Berry/examples/string.be rename to lib/libesp32/berry/examples/string.be diff --git a/lib/libesp32/Berry/examples/strmod.be b/lib/libesp32/berry/examples/strmod.be similarity index 100% rename from lib/libesp32/Berry/examples/strmod.be rename to lib/libesp32/berry/examples/strmod.be diff --git a/lib/libesp32/berry/gen.sh b/lib/libesp32/berry/gen.sh new file mode 100755 index 000000000..f845935b8 --- /dev/null +++ b/lib/libesp32/berry/gen.sh @@ -0,0 +1,2 @@ +#!/bin/bash +python3 tools/pycoc/main.py -o generate src default ../berry_tasmota/src ../berry_mapping/src ../../libesp32_lvgl/lv_berry/src ../../libesp32_lvgl/lv_berry/generate -c default/berry_conf.h diff --git a/lib/libesp32/Berry/generate/be_const_strtab.h b/lib/libesp32/berry/generate/be_const_strtab.h similarity index 91% rename from lib/libesp32/Berry/generate/be_const_strtab.h rename to lib/libesp32/berry/generate/be_const_strtab.h index 9692c8508..6bedac03a 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab.h +++ b/lib/libesp32/berry/generate/be_const_strtab.h @@ -14,8 +14,10 @@ extern const bcstring be_const_str_BRY_X3A_X20ERROR_X2C_X20bad_X20json_X3A_X20; extern const bcstring be_const_str_BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s; extern const bcstring be_const_str_BRY_X3A_X20could_X20not_X20save_X20compiled_X20file_X20_X25s_X20_X28_X25s_X29; extern const bcstring be_const_str_BRY_X3A_X20failed_X20to_X20load_X20_persist_X2Ejson; +extern const bcstring be_const_str_BRY_X3A_X20method_X20not_X20allowed_X2C_X20use_X20a_X20closure_X20like_X20_X27_X2F_X20args_X20_X2D_X3E_X20obj_X2Efunc_X28args_X29_X27; extern const bcstring be_const_str_BUTTON_CONFIGURATION; extern const bcstring be_const_str_CFG_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s; +extern const bcstring be_const_str_CFG_X3A_X20No_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found; extern const bcstring be_const_str_CFG_X3A_X20_X27init_X2Ebat_X27_X20done_X2C_X20restarting; extern const bcstring be_const_str_CFG_X3A_X20could_X20not_X20run_X20_X25s_X20_X28_X25s_X20_X2D_X20_X25s_X29; extern const bcstring be_const_str_CFG_X3A_X20downloading_X20_X27_X25s_X27; @@ -25,7 +27,6 @@ extern const bcstring be_const_str_CFG_X3A_X20loaded_X20_X27_X25s_X27; extern const bcstring be_const_str_CFG_X3A_X20loading_X20; extern const bcstring be_const_str_CFG_X3A_X20loading_X20_X27_X25s_X27; extern const bcstring be_const_str_CFG_X3A_X20multiple_X20autoconf_X20files_X20found_X2C_X20aborting_X20_X28_X27_X25s_X27_X20_X2B_X20_X27_X25s_X27_X29; -extern const bcstring be_const_str_CFG_X3A_X20no_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found; extern const bcstring be_const_str_CFG_X3A_X20ran_X20_X20; extern const bcstring be_const_str_CFG_X3A_X20removed_X20file_X20_X27_X25s_X27; extern const bcstring be_const_str_CFG_X3A_X20removing_X20autoconf_X20files; @@ -36,6 +37,7 @@ extern const bcstring be_const_str_CFG_X3A_X20skipping_X20_X27display_X2Eini_X27 extern const bcstring be_const_str_COLOR_BLACK; extern const bcstring be_const_str_COLOR_WHITE; extern const bcstring be_const_str_EC_C25519; +extern const bcstring be_const_str_EVENT_DELETE; extern const bcstring be_const_str_EVENT_DRAW_MAIN; extern const bcstring be_const_str_EVENT_DRAW_PART_BEGIN; extern const bcstring be_const_str_EVENT_DRAW_PART_END; @@ -46,12 +48,13 @@ extern const bcstring be_const_str_HTTP_POST; extern const bcstring be_const_str_I2C_Driver; extern const bcstring be_const_str_I2C_X3A; extern const bcstring be_const_str_LVG_X3A_X20call_X20to_X20unsupported_X20callback; +extern const bcstring be_const_str_LVG_X3A_X20object_X3A; extern const bcstring be_const_str_Leds; extern const bcstring be_const_str_MD5; -extern const bcstring be_const_str_No_X20callback_X20available; extern const bcstring be_const_str_None; extern const bcstring be_const_str_OPTION_A; extern const bcstring be_const_str_OneWire; +extern const bcstring be_const_str_OpusDecoder; extern const bcstring be_const_str_PART_MAIN; extern const bcstring be_const_str_POST; extern const bcstring be_const_str_Parameter_X20error; @@ -83,7 +86,7 @@ extern const bcstring be_const_str_SERIAL_8O1; extern const bcstring be_const_str_SERIAL_8O2; extern const bcstring be_const_str_SK6812_GRBW; extern const bcstring be_const_str_STATE_DEFAULT; -extern const bcstring be_const_str_TAP_X3A_X20found_X20Tasmota_X20App_X20_X27_X25s_X27; +extern const bcstring be_const_str_TAP_X3A_X20Loaded_X20Tasmota_X20App_X20_X27_X25s_X27; extern const bcstring be_const_str_Tasmota; extern const bcstring be_const_str_Tele; extern const bcstring be_const_str_Timer; @@ -163,7 +166,7 @@ extern const bcstring be_const_str__X7B; extern const bcstring be_const_str__X7B_X7D; extern const bcstring be_const_str__X7Bs_X7DBatt_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D; extern const bcstring be_const_str__X7Bs_X7DBatt_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D; -extern const bcstring be_const_str__X7Bs_X7DTemp_X20AXP_X7Bm_X7D_X25_X2E1f_X20_XB0C_X7Be_X7D; +extern const bcstring be_const_str__X7Bs_X7DTemp_X20AXP_X7Bm_X7D_X25_X2E1f_X20_X26deg_X3BC_X7Be_X7D; extern const bcstring be_const_str__X7Bs_X7DVBus_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D; extern const bcstring be_const_str__X7Bs_X7DVBus_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D; extern const bcstring be_const_str__X7D; @@ -175,7 +178,6 @@ extern const bcstring be_const_str__archive; extern const bcstring be_const_str__available; extern const bcstring be_const_str__begin_transmission; extern const bcstring be_const_str__buffer; -extern const bcstring be_const_str__cb; extern const bcstring be_const_str__ccmd; extern const bcstring be_const_str__class; extern const bcstring be_const_str__cmd; @@ -187,7 +189,7 @@ extern const bcstring be_const_str__end_transmission; extern const bcstring be_const_str__energy; extern const bcstring be_const_str__error; extern const bcstring be_const_str__filename; -extern const bcstring be_const_str__get_cb; +extern const bcstring be_const_str__fl; extern const bcstring be_const_str__global_addr; extern const bcstring be_const_str__global_def; extern const bcstring be_const_str__lvgl; @@ -209,6 +211,9 @@ extern const bcstring be_const_str_add; extern const bcstring be_const_str_add_anim; extern const bcstring be_const_str_add_cmd; extern const bcstring be_const_str_add_driver; +extern const bcstring be_const_str_add_event_cb; +extern const bcstring be_const_str_add_fast_loop; +extern const bcstring be_const_str_add_handler; extern const bcstring be_const_str_add_header; extern const bcstring be_const_str_add_rule; extern const bcstring be_const_str_addr; @@ -222,6 +227,8 @@ extern const bcstring be_const_str_arg; extern const bcstring be_const_str_arg_X20must_X20be_X20a_X20subclass_X20of_X20lv_obj; extern const bcstring be_const_str_arg_name; extern const bcstring be_const_str_arg_size; +extern const bcstring be_const_str_argument_X20must_X20be_X20a_X20function; +extern const bcstring be_const_str_argument_X20must_X20be_X20a_X20list; extern const bcstring be_const_str_as; extern const bcstring be_const_str_asin; extern const bcstring be_const_str_assert; @@ -237,7 +244,9 @@ extern const bcstring be_const_str_b; extern const bcstring be_const_str_back_forth; extern const bcstring be_const_str_base_class; extern const bcstring be_const_str_battery_present; +extern const bcstring be_const_str_before_del; extern const bcstring be_const_str_begin; +extern const bcstring be_const_str_begin_multicast; extern const bcstring be_const_str_bool; extern const bcstring be_const_str_break; extern const bcstring be_const_str_bri; @@ -250,13 +259,14 @@ extern const bcstring be_const_str_call; extern const bcstring be_const_str_call_native; extern const bcstring be_const_str_calldepth; extern const bcstring be_const_str_can_show; -extern const bcstring be_const_str_cb_dispatch; +extern const bcstring be_const_str_cb; extern const bcstring be_const_str_cb_do_nothing; extern const bcstring be_const_str_cb_event_closure; extern const bcstring be_const_str_cb_obj; extern const bcstring be_const_str_ceil; extern const bcstring be_const_str_char; extern const bcstring be_const_str_chars_in_string; +extern const bcstring be_const_str_check_not_method; extern const bcstring be_const_str_check_privileged_access; extern const bcstring be_const_str_class; extern const bcstring be_const_str_class_init_obj; @@ -265,6 +275,7 @@ extern const bcstring be_const_str_classof; extern const bcstring be_const_str_clear; extern const bcstring be_const_str_clear_first_time; extern const bcstring be_const_str_clear_to; +extern const bcstring be_const_str_clock_icon; extern const bcstring be_const_str_close; extern const bcstring be_const_str_closure; extern const bcstring be_const_str_cmd; @@ -280,6 +291,9 @@ extern const bcstring be_const_str_connect; extern const bcstring be_const_str_connected; extern const bcstring be_const_str_connection_error; extern const bcstring be_const_str_constructor_cb; +extern const bcstring be_const_str_consume_mono; +extern const bcstring be_const_str_consume_silence; +extern const bcstring be_const_str_consume_stereo; extern const bcstring be_const_str_contains; extern const bcstring be_const_str_content_button; extern const bcstring be_const_str_content_flush; @@ -288,6 +302,7 @@ extern const bcstring be_const_str_content_send_style; extern const bcstring be_const_str_content_start; extern const bcstring be_const_str_content_stop; extern const bcstring be_const_str_continue; +extern const bcstring be_const_str_coord_arr; extern const bcstring be_const_str_copy; extern const bcstring be_const_str_cos; extern const bcstring be_const_str_cosh; @@ -303,12 +318,12 @@ extern const bcstring be_const_str_ctypes_bytes_dyn; extern const bcstring be_const_str_dac_voltage; extern const bcstring be_const_str_day; extern const bcstring be_const_str_debug; +extern const bcstring be_const_str_decode; extern const bcstring be_const_str_decompress; extern const bcstring be_const_str_decrypt; extern const bcstring be_const_str_def; extern const bcstring be_const_str_deg; extern const bcstring be_const_str_deinit; -extern const bcstring be_const_str_del; extern const bcstring be_const_str_delay; extern const bcstring be_const_str_delete_all_configs; extern const bcstring be_const_str_depower; @@ -330,6 +345,7 @@ extern const bcstring be_const_str_due; extern const bcstring be_const_str_dump; extern const bcstring be_const_str_duration; extern const bcstring be_const_str_editable; +extern const bcstring be_const_str_elements_X20must_X20be_X20a_X20lv_point; extern const bcstring be_const_str_elif; extern const bcstring be_const_str_else; extern const bcstring be_const_str_enabled; @@ -354,6 +370,8 @@ extern const bcstring be_const_str_exists; extern const bcstring be_const_str_exp; extern const bcstring be_const_str_f; extern const bcstring be_const_str_false; +extern const bcstring be_const_str_fast_loop; +extern const bcstring be_const_str_fast_loop_enabled; extern const bcstring be_const_str_file; extern const bcstring be_const_str_file_X20extension_X20is_X20not_X20_X27_X2Ebe_X27_X20or_X20_X27_X2Ebec_X27; extern const bcstring be_const_str_files; @@ -363,6 +381,8 @@ extern const bcstring be_const_str_find_op; extern const bcstring be_const_str_finish; extern const bcstring be_const_str_floor; extern const bcstring be_const_str_flush; +extern const bcstring be_const_str_font_montserrat; +extern const bcstring be_const_str_font_seg7; extern const bcstring be_const_str_for; extern const bcstring be_const_str_format; extern const bcstring be_const_str_from_to; @@ -384,6 +404,7 @@ extern const bcstring be_const_str_get_bat_power; extern const bcstring be_const_str_get_bat_voltage; extern const bcstring be_const_str_get_battery_chargin_status; extern const bcstring be_const_str_get_bri; +extern const bcstring be_const_str_get_cb_list; extern const bcstring be_const_str_get_coords; extern const bcstring be_const_str_get_current_module_name; extern const bcstring be_const_str_get_current_module_path; @@ -402,7 +423,6 @@ extern const bcstring be_const_str_get_style_bg_color; extern const bcstring be_const_str_get_style_line_color; extern const bcstring be_const_str_get_style_pad_right; extern const bcstring be_const_str_get_switch; -extern const bcstring be_const_str_get_tasmota; extern const bcstring be_const_str_get_temp; extern const bcstring be_const_str_get_vbus_current; extern const bcstring be_const_str_get_vbus_voltage; @@ -415,6 +435,7 @@ extern const bcstring be_const_str_gpio; extern const bcstring be_const_str_group_def; extern const bcstring be_const_str_h; extern const bcstring be_const_str_has; +extern const bcstring be_const_str_has_X20already_X20an_X20event_X20callback; extern const bcstring be_const_str_has_arg; extern const bcstring be_const_str_height_def; extern const bcstring be_const_str_hex; @@ -436,6 +457,7 @@ extern const bcstring be_const_str_ins_ramp; extern const bcstring be_const_str_ins_time; extern const bcstring be_const_str_insert; extern const bcstring be_const_str_instance; +extern const bcstring be_const_str_instance_X20required; extern const bcstring be_const_str_instance_size; extern const bcstring be_const_str_int; extern const bcstring be_const_str_internal_error; @@ -447,6 +469,7 @@ extern const bcstring be_const_str_is_dirty; extern const bcstring be_const_str_is_first_time; extern const bcstring be_const_str_is_running; extern const bcstring be_const_str_isinstance; +extern const bcstring be_const_str_ismethod; extern const bcstring be_const_str_isnan; extern const bcstring be_const_str_isrunning; extern const bcstring be_const_str_issubclass; @@ -467,8 +490,10 @@ extern const bcstring be_const_str_length_X20in_X20bits_X20must_X20be_X20between extern const bcstring be_const_str_light; extern const bcstring be_const_str_line_dsc; extern const bcstring be_const_str_list; +extern const bcstring be_const_str_list_handlers; extern const bcstring be_const_str_listdir; extern const bcstring be_const_str_load; +extern const bcstring be_const_str_load_freetype_font; extern const bcstring be_const_str_load_templates; extern const bcstring be_const_str_local; extern const bcstring be_const_str_log; @@ -476,11 +501,26 @@ extern const bcstring be_const_str_log10; extern const bcstring be_const_str_loop; extern const bcstring be_const_str_lower; extern const bcstring be_const_str_lv; +extern const bcstring be_const_str_lv_; +extern const bcstring be_const_str_lv_clock_icon; +extern const bcstring be_const_str_lv_coord_arr; extern const bcstring be_const_str_lv_event; extern const bcstring be_const_str_lv_event_cb; +extern const bcstring be_const_str_lv_extra; +extern const bcstring be_const_str_lv_module_init; extern const bcstring be_const_str_lv_obj; extern const bcstring be_const_str_lv_obj_class; +extern const bcstring be_const_str_lv_point; +extern const bcstring be_const_str_lv_point_arr; +extern const bcstring be_const_str_lv_signal_arcs; +extern const bcstring be_const_str_lv_signal_bars; +extern const bcstring be_const_str_lv_solidified; +extern const bcstring be_const_str_lv_wifi_arcs; +extern const bcstring be_const_str_lv_wifi_arcs_icon; +extern const bcstring be_const_str_lv_wifi_bars; +extern const bcstring be_const_str_lv_wifi_bars_icon; extern const bcstring be_const_str_lvgl_event_dispatch; +extern const bcstring be_const_str_make_cb; extern const bcstring be_const_str_map; extern const bcstring be_const_str_math; extern const bcstring be_const_str_matrix; @@ -492,6 +532,7 @@ extern const bcstring be_const_str_min; extern const bcstring be_const_str_minute; extern const bcstring be_const_str_module; extern const bcstring be_const_str_month; +extern const bcstring be_const_str_montserrat_font; extern const bcstring be_const_str_name; extern const bcstring be_const_str_nan; extern const bcstring be_const_str_nil; @@ -527,6 +568,7 @@ extern const bcstring be_const_str_pixel_count; extern const bcstring be_const_str_pixel_size; extern const bcstring be_const_str_pixels_buffer; extern const bcstring be_const_str_point; +extern const bcstring be_const_str_point_arr; extern const bcstring be_const_str_pop; extern const bcstring be_const_str_pop_path; extern const bcstring be_const_str_pow; @@ -556,9 +598,11 @@ extern const bcstring be_const_str_readline; extern const bcstring be_const_str_real; extern const bcstring be_const_str_reapply; extern const bcstring be_const_str_redirect; -extern const bcstring be_const_str_reduce; extern const bcstring be_const_str_refr_size; +extern const bcstring be_const_str_register_button_encoder; extern const bcstring be_const_str_register_obj; +extern const bcstring be_const_str_remote_ip; +extern const bcstring be_const_str_remote_port; extern const bcstring be_const_str_remove; extern const bcstring be_const_str_remove_cmd; extern const bcstring be_const_str_remove_driver; @@ -591,19 +635,25 @@ extern const bcstring be_const_str_save; extern const bcstring be_const_str_save_before_restart; extern const bcstring be_const_str_scale_uint; extern const bcstring be_const_str_scan; +extern const bcstring be_const_str_screenshot; extern const bcstring be_const_str_search; extern const bcstring be_const_str_sec; extern const bcstring be_const_str_seg7_font; extern const bcstring be_const_str_select; +extern const bcstring be_const_str_send; +extern const bcstring be_const_str_send_multicast; extern const bcstring be_const_str_serial; extern const bcstring be_const_str_set; extern const bcstring be_const_str_set_alternate; extern const bcstring be_const_str_set_auth; +extern const bcstring be_const_str_set_bits_per_sample; extern const bcstring be_const_str_set_bri; +extern const bcstring be_const_str_set_channels; extern const bcstring be_const_str_set_chg_current; extern const bcstring be_const_str_set_dc_voltage; extern const bcstring be_const_str_set_dcdc_enable; extern const bcstring be_const_str_set_first_time; +extern const bcstring be_const_str_set_gain; extern const bcstring be_const_str_set_height; extern const bcstring be_const_str_set_ldo_enable; extern const bcstring be_const_str_set_ldo_voltage; @@ -612,6 +662,8 @@ extern const bcstring be_const_str_set_matrix_pixel_color; extern const bcstring be_const_str_set_percentage; extern const bcstring be_const_str_set_pixel_color; extern const bcstring be_const_str_set_power; +extern const bcstring be_const_str_set_pwm; +extern const bcstring be_const_str_set_rate; extern const bcstring be_const_str_set_style_bg_color; extern const bcstring be_const_str_set_style_line_color; extern const bcstring be_const_str_set_style_pad_right; @@ -632,6 +684,8 @@ extern const bcstring be_const_str_setrange; extern const bcstring be_const_str_settings; extern const bcstring be_const_str_shared_key; extern const bcstring be_const_str_show; +extern const bcstring be_const_str_signal_arcs; +extern const bcstring be_const_str_signal_bars; extern const bcstring be_const_str_sin; extern const bcstring be_const_str_sinh; extern const bcstring be_const_str_size; @@ -680,6 +734,8 @@ extern const bcstring be_const_str_true; extern const bcstring be_const_str_try; extern const bcstring be_const_str_try_rule; extern const bcstring be_const_str_type; +extern const bcstring be_const_str_type_error; +extern const bcstring be_const_str_udp; extern const bcstring be_const_str_unknown_X20instruction; extern const bcstring be_const_str_update; extern const bcstring be_const_str_upper; @@ -723,6 +779,10 @@ extern const bcstring be_const_str_widget_width_def; extern const bcstring be_const_str_width; extern const bcstring be_const_str_width_def; extern const bcstring be_const_str_wifi; +extern const bcstring be_const_str_wifi_arcs; +extern const bcstring be_const_str_wifi_arcs_icon; +extern const bcstring be_const_str_wifi_bars; +extern const bcstring be_const_str_wifi_bars_icon; extern const bcstring be_const_str_wire; extern const bcstring be_const_str_wire1; extern const bcstring be_const_str_wire2; diff --git a/lib/libesp32/Berry/generate/be_const_strtab_def.h b/lib/libesp32/berry/generate/be_const_strtab_def.h similarity index 59% rename from lib/libesp32/Berry/generate/be_const_strtab_def.h rename to lib/libesp32/berry/generate/be_const_strtab_def.h index 44676a35e..a67a809c1 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab_def.h +++ b/lib/libesp32/berry/generate/be_const_strtab_def.h @@ -1,653 +1,707 @@ -be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_True); -be_define_const_str(_X0A, "\n", 252472541u, 0, 1, &be_const_str_i2c_enabled); -be_define_const_str(_X20, " ", 621580159u, 0, 1, &be_const_str_add_cmd); +be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_display_X2Eini); +be_define_const_str(_X0A, "\n", 252472541u, 0, 1, &be_const_str__X3Cp_X3ECurrent_X20configuration_X3A_X20_X3C_X2Fp_X3E_X3Cp_X3E_X3Cb_X3E_X25s_X3C_X2Fb_X3E_X3C_X2Fp_X3E); +be_define_const_str(_X20, " ", 621580159u, 0, 1, &be_const_str_widget_ctor_impl); be_define_const_str(_X21_X3D, "!=", 2428715011u, 0, 2, &be_const_str__X23autoexec_X2Ebe); -be_define_const_str(_X21_X3D_X3D, "!==", 559817114u, 0, 3, &be_const_str__X2Ew); -be_define_const_str(_X23, "#", 638357778u, 0, 1, &be_const_str_No_X20callback_X20available); -be_define_const_str(_X23autoexec_X2Ebat, "#autoexec.bat", 3382890497u, 0, 13, NULL); -be_define_const_str(_X23autoexec_X2Ebe, "#autoexec.be", 1181757091u, 0, 12, &be_const_str_assert); -be_define_const_str(_X23display_X2Eini, "#display.ini", 182218220u, 0, 12, &be_const_str_code); -be_define_const_str(_X23init_X2Ebat, "#init.bat", 3297595077u, 0, 9, &be_const_str__X2502d_X25s_X2502d); -be_define_const_str(_X23preinit_X2Ebe, "#preinit.be", 687035716u, 0, 11, &be_const_str__timers); -be_define_const_str(_X2502d_X25s_X2502d, "%02d%s%02d", 1587999717u, 0, 10, &be_const_str__X3D_X3C_X3E_X21); -be_define_const_str(_X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d, "%04d-%02d-%02dT%02d:%02d:%02d", 3425528601u, 0, 29, &be_const_str_get_object_from_ptr); -be_define_const_str(_X25s_X2Eautoconf, "%s.autoconf", 3560383524u, 0, 11, &be_const_str_RES_OK); -be_define_const_str(_X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B, "<Error: apply new or remove>", 2855507949u, 0, 34, &be_const_str_hs2rgb); -be_define_const_str(_X26lt_X3BNone_X26gt_X3B, "<None>", 2602165498u, 0, 12, &be_const_str__X2Fac); -be_define_const_str(_X28_X29, "()", 685372826u, 0, 2, NULL); -be_define_const_str(_X2B, "+", 772578730u, 0, 1, &be_const_str_lower); -be_define_const_str(_X2C, ",", 688690635u, 0, 1, &be_const_str_SERIAL_7O1); -be_define_const_str(_X2D_X2D_X3A_X2D_X2D, "--:--", 1370615441u, 0, 5, &be_const_str__X3Cp_X3ECurrent_X20configuration_X3A_X20_X3C_X2Fp_X3E_X3Cp_X3E_X3Cb_X3E_X25s_X3C_X2Fb_X3E_X3C_X2Fp_X3E); -be_define_const_str(_X2E, ".", 722245873u, 0, 1, &be_const_str_search); -be_define_const_str(_X2E_X2E, "..", 2748622605u, 0, 2, &be_const_str__debug_present); -be_define_const_str(_X2Eautoconf, ".autoconf", 2524679088u, 0, 9, &be_const_str_false); -be_define_const_str(_X2Ebe, ".be", 1325797348u, 0, 3, &be_const_str_Tasmota); -be_define_const_str(_X2Ebec, ".bec", 3985273221u, 0, 4, &be_const_str_CFG_X3A_X20downloading_X20_X27_X25s_X27); -be_define_const_str(_X2Elen, ".len", 850842136u, 0, 4, &be_const_str__X3Cselect_X20name_X3D_X27zip_X27_X3E); -be_define_const_str(_X2Ep, ".p", 1171526419u, 0, 2, NULL); -be_define_const_str(_X2Ep1, ".p1", 249175686u, 0, 3, &be_const_str__t); -be_define_const_str(_X2Ep2, ".p2", 232398067u, 0, 3, &be_const_str_BRY_X3A_X20could_X20not_X20save_X20compiled_X20file_X20_X25s_X20_X28_X25s_X29); -be_define_const_str(_X2Esize, ".size", 1965188224u, 0, 5, &be_const_str_is_first_time); -be_define_const_str(_X2Etapp, ".tapp", 1363391594u, 0, 5, &be_const_str__X7B); -be_define_const_str(_X2Ew, ".w", 1255414514u, 0, 2, &be_const_str_clear); -be_define_const_str(_X2F, "/", 705468254u, 0, 1, &be_const_str_SERIAL_7O2); -be_define_const_str(_X2F_X2Eautoconf, "/.autoconf", 2212074393u, 0, 10, &be_const_str_CFG_X3A_X20exception_X20_X27_X25s_X27_X20_X2D_X20_X27_X25s_X27); -be_define_const_str(_X2F_X3Frst_X3D, "/?rst=", 580074707u, 0, 6, &be_const_str_SERIAL_7N2); -be_define_const_str(_X2Fac, "/ac", 3904651978u, 0, 3, &be_const_str_WS2812); +be_define_const_str(_X21_X3D_X3D, "!==", 559817114u, 0, 3, &be_const_str_elements_X20must_X20be_X20a_X20lv_point); +be_define_const_str(_X23, "#", 638357778u, 0, 1, &be_const_str_line_dsc); +be_define_const_str(_X23autoexec_X2Ebat, "#autoexec.bat", 3382890497u, 0, 13, &be_const_str_pixels_buffer); +be_define_const_str(_X23autoexec_X2Ebe, "#autoexec.be", 1181757091u, 0, 12, &be_const_str_list_handlers); +be_define_const_str(_X23display_X2Eini, "#display.ini", 182218220u, 0, 12, &be_const_str_get_current_module_name); +be_define_const_str(_X23init_X2Ebat, "#init.bat", 3297595077u, 0, 9, &be_const_str_MD5); +be_define_const_str(_X23preinit_X2Ebe, "#preinit.be", 687035716u, 0, 11, &be_const_str__ptr); +be_define_const_str(_X2502d_X25s_X2502d, "%02d%s%02d", 1587999717u, 0, 10, &be_const_str_push_path); +be_define_const_str(_X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d, "%04d-%02d-%02dT%02d:%02d:%02d", 3425528601u, 0, 29, &be_const_str_bus); +be_define_const_str(_X25s_X2Eautoconf, "%s.autoconf", 3560383524u, 0, 11, &be_const_str_delay); +be_define_const_str(_X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B, "<Error: apply new or remove>", 2855507949u, 0, 34, &be_const_str_json); +be_define_const_str(_X26lt_X3BNone_X26gt_X3B, "<None>", 2602165498u, 0, 12, &be_const_str_AudioGeneratorMP3); +be_define_const_str(_X28_X29, "()", 685372826u, 0, 2, &be_const_str__dirty); +be_define_const_str(_X2B, "+", 772578730u, 0, 1, &be_const_str_a); +be_define_const_str(_X2C, ",", 688690635u, 0, 1, &be_const_str_TAP_X3A_X20Loaded_X20Tasmota_X20App_X20_X27_X25s_X27); +be_define_const_str(_X2D_X2D_X3A_X2D_X2D, "--:--", 1370615441u, 0, 5, &be_const_str_f); +be_define_const_str(_X2E, ".", 722245873u, 0, 1, &be_const_str_dirty); +be_define_const_str(_X2E_X2E, "..", 2748622605u, 0, 2, &be_const_str_content_flush); +be_define_const_str(_X2Eautoconf, ".autoconf", 2524679088u, 0, 9, &be_const_str_get_bat_voltage); +be_define_const_str(_X2Ebe, ".be", 1325797348u, 0, 3, &be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20); +be_define_const_str(_X2Ebec, ".bec", 3985273221u, 0, 4, &be_const_str_Animate_X20pc_X20is_X20out_X20of_X20range); +be_define_const_str(_X2Elen, ".len", 850842136u, 0, 4, &be_const_str_super); +be_define_const_str(_X2Ep, ".p", 1171526419u, 0, 2, &be_const_str_SERIAL_6O2); +be_define_const_str(_X2Ep1, ".p1", 249175686u, 0, 3, &be_const_str_SERIAL_8E1); +be_define_const_str(_X2Ep2, ".p2", 232398067u, 0, 3, NULL); +be_define_const_str(_X2Esize, ".size", 1965188224u, 0, 5, &be_const_str_update); +be_define_const_str(_X2Etapp, ".tapp", 1363391594u, 0, 5, &be_const_str_attrdump); +be_define_const_str(_X2Ew, ".w", 1255414514u, 0, 2, &be_const_str__X3Coption_X20value_X3D_X27_X25s_X27_X3E_X25s_X3C_X2Foption_X3E); +be_define_const_str(_X2F, "/", 705468254u, 0, 1, &be_const_str_set_style_pad_right); +be_define_const_str(_X2F_X2Eautoconf, "/.autoconf", 2212074393u, 0, 10, &be_const_str_SERIAL_8E2); +be_define_const_str(_X2F_X3Frst_X3D, "/?rst=", 580074707u, 0, 6, &be_const_str_elif); +be_define_const_str(_X2Fac, "/ac", 3904651978u, 0, 3, &be_const_str_STATE_DEFAULT); be_define_const_str(_X3A, ":", 1057798253u, 0, 1, &be_const_str_AudioFileSourceFS); -be_define_const_str(_X3C, "<", 957132539u, 0, 1, &be_const_str_digital_write); -be_define_const_str(_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "

", 3546571739u, 0, 11, &be_const_str_LVG_X3A_X20call_X20to_X20unsupported_X20callback); -be_define_const_str(_X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "

", 1863865923u, 0, 16, &be_const_str_rule); -be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, &be_const_str_set_chg_current); -be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str_find_op); -be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, NULL); -be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "
", 842307168u, 0, 77, &be_const_str_get_current_module_path); +be_define_const_str(_X3C, "<", 957132539u, 0, 1, &be_const_str_base_class); +be_define_const_str(_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "

", 3546571739u, 0, 11, &be_const_str_BRY_X3A_X20ERROR_X2C_X20bad_X20json_X3A_X20); +be_define_const_str(_X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "

", 1863865923u, 0, 16, &be_const_str_CFG_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s); +be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, &be_const_str_pc_rel); +be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str__X3Cselect_X20name_X3D_X27zip_X27_X3E); +be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, &be_const_str_as); +be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "
", 842307168u, 0, 77, NULL); be_define_const_str(_X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29, "Choose a device configuration:
", 1336654704u, 0, 49, &be_const_str_delay); -be_define_const_str(_X3Clambda_X3E, "", 607256038u, 0, 8, &be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20); -be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27Autoconfiguration_X27_X3E_X26nbsp_X3BCurrent_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, " Current auto-configuration", 4212500780u, 0, 82, &be_const_str_CFG_X3A_X20could_X20not_X20run_X20_X25s_X20_X28_X25s_X20_X2D_X20_X25s_X29); -be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27New_X20autoconf_X27_X3E_X26nbsp_X3BSelect_X20new_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, " Select new auto-configuration", 1926223891u, 0, 80, &be_const_str_CFG_X3A_X20multiple_X20autoconf_X20files_X20found_X2C_X20aborting_X20_X28_X27_X25s_X27_X20_X2B_X20_X27_X25s_X27_X29); -be_define_const_str(_X3Coption_X20value_X3D_X27_X25s_X27_X3E_X25s_X3C_X2Foption_X3E, "", 510303524u, 0, 30, &be_const_str_write); -be_define_const_str(_X3Coption_X20value_X3D_X27reset_X27_X3E_X26lt_X3BRemove_X20autoconf_X26gt_X3B_X3C_X2Foption_X3E, "", 3994619755u, 0, 54, &be_const_str_None); -be_define_const_str(_X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E, "

Exception:
'%s'
%s

", 4252565082u, 0, 59, &be_const_str_classof); -be_define_const_str(_X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "

", 2052843416u, 0, 25, &be_const_str_button_pressed); -be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3E_X26_X23129668_X3B_X20Auto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "

", 452285201u, 0, 120, NULL); -be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, "

 (This feature requires an internet connection)

", 2719266486u, 0, 74, NULL); -be_define_const_str(_X3Cp_X3ECurrent_X20configuration_X3A_X20_X3C_X2Fp_X3E_X3Cp_X3E_X3Cb_X3E_X25s_X3C_X2Fb_X3E_X3C_X2Fp_X3E, "

Current configuration:

%s

", 4115655761u, 0, 46, &be_const_str_exec_tele); -be_define_const_str(_X3Cselect_X20name_X3D_X27zip_X27_X3E, "", 4247924536u, 0, 19, &be_const_str_eth); +be_define_const_str(_X3D, "=", 940354920u, 0, 1, &be_const_str__class); +be_define_const_str(_X3D_X3C_X3E_X21, "=<>!", 2664470277u, 0, 4, &be_const_str__X3E); +be_define_const_str(_X3D_X3D, "==", 2431966415u, 0, 2, NULL); +be_define_const_str(_X3E, ">", 990687777u, 0, 1, &be_const_str_SK6812_GRBW); +be_define_const_str(_X3E_X3D, ">=", 284975636u, 0, 2, &be_const_str_find_key_i); +be_define_const_str(_X3F, "?", 973910158u, 0, 1, &be_const_str_WS2812); +be_define_const_str(AES_GCM, "AES_GCM", 3832208678u, 0, 7, &be_const_str_I2C_Driver); +be_define_const_str(AXP192, "AXP192", 757230128u, 0, 6, &be_const_str_AudioGeneratorWAV); +be_define_const_str(Animate_X20pc_X20is_X20out_X20of_X20range, "Animate pc is out of range", 1854929421u, 0, 26, &be_const_str_argument_X20must_X20be_X20a_X20list); be_define_const_str(AudioFileSource, "AudioFileSource", 2959980058u, 0, 15, &be_const_str_allocated); -be_define_const_str(AudioFileSourceFS, "AudioFileSourceFS", 1839147653u, 0, 17, &be_const_str_due); -be_define_const_str(AudioGenerator, "AudioGenerator", 1839297342u, 0, 14, &be_const_str_enabled); -be_define_const_str(AudioGeneratorMP3, "AudioGeneratorMP3", 2199818488u, 0, 17, &be_const_str_check_privileged_access); -be_define_const_str(AudioGeneratorWAV, "AudioGeneratorWAV", 2746509368u, 0, 17, &be_const_str_digital_read); -be_define_const_str(AudioOutput, "AudioOutput", 3257792048u, 0, 11, &be_const_str_get_pixel_color); -be_define_const_str(AudioOutputI2S, "AudioOutputI2S", 638031784u, 0, 14, NULL); -be_define_const_str(Auto_X2Dconfiguration, "Auto-configuration", 1665006109u, 0, 18, NULL); +be_define_const_str(AudioFileSourceFS, "AudioFileSourceFS", 1839147653u, 0, 17, &be_const_str_CFG_X3A_X20loading_X20); +be_define_const_str(AudioGenerator, "AudioGenerator", 1839297342u, 0, 14, &be_const_str_chars_in_string); +be_define_const_str(AudioGeneratorMP3, "AudioGeneratorMP3", 2199818488u, 0, 17, &be_const_str_consume_stereo); +be_define_const_str(AudioGeneratorWAV, "AudioGeneratorWAV", 2746509368u, 0, 17, &be_const_str_lv_signal_arcs); +be_define_const_str(AudioOutput, "AudioOutput", 3257792048u, 0, 11, &be_const_str_HTTP_GET); +be_define_const_str(AudioOutputI2S, "AudioOutputI2S", 638031784u, 0, 14, &be_const_str_CFG_X3A_X20running_X20); +be_define_const_str(Auto_X2Dconfiguration, "Auto-configuration", 1665006109u, 0, 18, &be_const_str_erase); be_define_const_str(BRY_X3A_X20ERROR_X2C_X20bad_X20json_X3A_X20, "BRY: ERROR, bad json: ", 2715135809u, 0, 22, &be_const_str_fromptr); -be_define_const_str(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, "BRY: Exception> '%s' - %s", 2246990964u, 0, 25, &be_const_str_SERIAL_6N2); -be_define_const_str(BRY_X3A_X20could_X20not_X20save_X20compiled_X20file_X20_X25s_X20_X28_X25s_X29, "BRY: could not save compiled file %s (%s)", 736659787u, 0, 41, NULL); -be_define_const_str(BRY_X3A_X20failed_X20to_X20load_X20_persist_X2Ejson, "BRY: failed to load _persist.json", 2991913445u, 0, 33, &be_const_str_set_time); -be_define_const_str(BUTTON_CONFIGURATION, "BUTTON_CONFIGURATION", 70820856u, 0, 20, &be_const_str_files); -be_define_const_str(CFG_X3A_X20_X27init_X2Ebat_X27_X20done_X2C_X20restarting, "CFG: 'init.bat' done, restarting", 1569670677u, 0, 32, &be_const_str_push_path); -be_define_const_str(CFG_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, "CFG: Exception> '%s' - %s", 1228874553u, 0, 25, &be_const_str_CFG_X3A_X20removed_X20file_X20_X27_X25s_X27); -be_define_const_str(CFG_X3A_X20could_X20not_X20run_X20_X25s_X20_X28_X25s_X20_X2D_X20_X25s_X29, "CFG: could not run %s (%s - %s)", 1428829580u, 0, 31, &be_const_str_COLOR_BLACK); -be_define_const_str(CFG_X3A_X20downloading_X20_X27_X25s_X27, "CFG: downloading '%s'", 589480701u, 0, 21, &be_const_str_floor); -be_define_const_str(CFG_X3A_X20exception_X20_X27_X25s_X27_X20_X2D_X20_X27_X25s_X27, "CFG: exception '%s' - '%s'", 4095407913u, 0, 26, &be_const_str_get_option); -be_define_const_str(CFG_X3A_X20loaded_X20_X20, "CFG: loaded ", 3710273538u, 0, 13, &be_const_str_delete_all_configs); -be_define_const_str(CFG_X3A_X20loaded_X20_X27_X25s_X27, "CFG: loaded '%s'", 1699028828u, 0, 16, NULL); -be_define_const_str(CFG_X3A_X20loading_X20, "CFG: loading ", 4010361503u, 0, 13, NULL); -be_define_const_str(CFG_X3A_X20loading_X20_X27_X25s_X27, "CFG: loading '%s'", 2285306097u, 0, 17, &be_const_str_SK6812_GRBW); -be_define_const_str(CFG_X3A_X20multiple_X20autoconf_X20files_X20found_X2C_X20aborting_X20_X28_X27_X25s_X27_X20_X2B_X20_X27_X25s_X27_X29, "CFG: multiple autoconf files found, aborting ('%s' + '%s')", 197663371u, 0, 58, NULL); -be_define_const_str(CFG_X3A_X20no_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found, "CFG: no '*.autoconf' file found", 127493957u, 0, 31, &be_const_str_get_free_heap); -be_define_const_str(CFG_X3A_X20ran_X20_X20, "CFG: ran ", 3579570472u, 0, 10, &be_const_str_contains); -be_define_const_str(CFG_X3A_X20removed_X20file_X20_X27_X25s_X27, "CFG: removed file '%s'", 2048602473u, 0, 22, &be_const_str_SERIAL_8E2); -be_define_const_str(CFG_X3A_X20removing_X20autoconf_X20files, "CFG: removing autoconf files", 4014704970u, 0, 28, &be_const_str_get_bat_charge_current); -be_define_const_str(CFG_X3A_X20removing_X20first_X20time_X20marker, "CFG: removing first time marker", 2125556683u, 0, 31, &be_const_str__lvgl); +be_define_const_str(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, "BRY: Exception> '%s' - %s", 2246990964u, 0, 25, &be_const_str_skip); +be_define_const_str(BRY_X3A_X20could_X20not_X20save_X20compiled_X20file_X20_X25s_X20_X28_X25s_X29, "BRY: could not save compiled file %s (%s)", 736659787u, 0, 41, &be_const_str_solidified); +be_define_const_str(BRY_X3A_X20failed_X20to_X20load_X20_persist_X2Ejson, "BRY: failed to load _persist.json", 2991913445u, 0, 33, NULL); +be_define_const_str(BRY_X3A_X20method_X20not_X20allowed_X2C_X20use_X20a_X20closure_X20like_X20_X27_X2F_X20args_X20_X2D_X3E_X20obj_X2Efunc_X28args_X29_X27, "BRY: method not allowed, use a closure like '/ args -> obj.func(args)'", 177121572u, 0, 70, &be_const_str_EVENT_DRAW_PART_END); +be_define_const_str(BUTTON_CONFIGURATION, "BUTTON_CONFIGURATION", 70820856u, 0, 20, &be_const_str_before_del); +be_define_const_str(CFG_X3A_X20_X27init_X2Ebat_X27_X20done_X2C_X20restarting, "CFG: 'init.bat' done, restarting", 1569670677u, 0, 32, &be_const_str_decode); +be_define_const_str(CFG_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, "CFG: Exception> '%s' - %s", 1228874553u, 0, 25, &be_const_str__ccmd); +be_define_const_str(CFG_X3A_X20No_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found, "CFG: No '*.autoconf' file found", 755798501u, 0, 31, NULL); +be_define_const_str(CFG_X3A_X20could_X20not_X20run_X20_X25s_X20_X28_X25s_X20_X2D_X20_X25s_X29, "CFG: could not run %s (%s - %s)", 1428829580u, 0, 31, &be_const_str_listdir); +be_define_const_str(CFG_X3A_X20downloading_X20_X27_X25s_X27, "CFG: downloading '%s'", 589480701u, 0, 21, &be_const_str_SERIAL_6N1); +be_define_const_str(CFG_X3A_X20exception_X20_X27_X25s_X27_X20_X2D_X20_X27_X25s_X27, "CFG: exception '%s' - '%s'", 4095407913u, 0, 26, &be_const_str_atan2); +be_define_const_str(CFG_X3A_X20loaded_X20_X20, "CFG: loaded ", 3710273538u, 0, 13, NULL); +be_define_const_str(CFG_X3A_X20loaded_X20_X27_X25s_X27, "CFG: loaded '%s'", 1699028828u, 0, 16, &be_const_str_c); +be_define_const_str(CFG_X3A_X20loading_X20, "CFG: loading ", 4010361503u, 0, 13, &be_const_str_due); +be_define_const_str(CFG_X3A_X20loading_X20_X27_X25s_X27, "CFG: loading '%s'", 2285306097u, 0, 17, &be_const_str_arg_size); +be_define_const_str(CFG_X3A_X20multiple_X20autoconf_X20files_X20found_X2C_X20aborting_X20_X28_X27_X25s_X27_X20_X2B_X20_X27_X25s_X27_X29, "CFG: multiple autoconf files found, aborting ('%s' + '%s')", 197663371u, 0, 58, &be_const_str_POST); +be_define_const_str(CFG_X3A_X20ran_X20_X20, "CFG: ran ", 3579570472u, 0, 10, NULL); +be_define_const_str(CFG_X3A_X20removed_X20file_X20_X27_X25s_X27, "CFG: removed file '%s'", 2048602473u, 0, 22, NULL); +be_define_const_str(CFG_X3A_X20removing_X20autoconf_X20files, "CFG: removing autoconf files", 4014704970u, 0, 28, &be_const_str_begin); +be_define_const_str(CFG_X3A_X20removing_X20first_X20time_X20marker, "CFG: removing first time marker", 2125556683u, 0, 31, &be_const_str_byte); be_define_const_str(CFG_X3A_X20return_code_X3D_X25i, "CFG: return_code=%i", 2059897320u, 0, 19, &be_const_str_OPTION_A); be_define_const_str(CFG_X3A_X20running_X20, "CFG: running ", 2478334534u, 0, 13, NULL); -be_define_const_str(CFG_X3A_X20skipping_X20_X27display_X2Eini_X27_X20because_X20already_X20present_X20in_X20file_X2Dsystem, "CFG: skipping 'display.ini' because already present in file-system", 3965549264u, 0, 66, NULL); -be_define_const_str(COLOR_BLACK, "COLOR_BLACK", 264427940u, 0, 11, NULL); -be_define_const_str(COLOR_WHITE, "COLOR_WHITE", 2536871270u, 0, 11, &be_const_str__energy); -be_define_const_str(EC_C25519, "EC_C25519", 95492591u, 0, 9, &be_const_str_gc); -be_define_const_str(EVENT_DRAW_MAIN, "EVENT_DRAW_MAIN", 1955620614u, 0, 15, &be_const_str_SERIAL_5E2); -be_define_const_str(EVENT_DRAW_PART_BEGIN, "EVENT_DRAW_PART_BEGIN", 3391865024u, 0, 21, &be_const_str_available); -be_define_const_str(EVENT_DRAW_PART_END, "EVENT_DRAW_PART_END", 3301625292u, 0, 19, &be_const_str_chars_in_string); -be_define_const_str(False, "False", 2541049336u, 0, 5, &be_const_str_set_style_line_color); -be_define_const_str(GET, "GET", 2531704439u, 0, 3, &be_const_str_onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20change_X20the_X20current_X20configuration_X20and_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E); -be_define_const_str(HTTP_GET, "HTTP_GET", 1722467738u, 0, 8, &be_const_str_I2C_Driver); -be_define_const_str(HTTP_POST, "HTTP_POST", 1999554144u, 0, 9, &be_const_str_imin); -be_define_const_str(I2C_X3A, "I2C:", 813483371u, 0, 4, &be_const_str_read24); -be_define_const_str(I2C_Driver, "I2C_Driver", 1714501658u, 0, 10, &be_const_str_addr); -be_define_const_str(LVG_X3A_X20call_X20to_X20unsupported_X20callback, "LVG: call to unsupported callback", 504176819u, 0, 33, &be_const_str_cb_dispatch); -be_define_const_str(Leds, "Leds", 2709245275u, 0, 4, &be_const_str_arg_name); +be_define_const_str(CFG_X3A_X20skipping_X20_X27display_X2Eini_X27_X20because_X20already_X20present_X20in_X20file_X2Dsystem, "CFG: skipping 'display.ini' because already present in file-system", 3965549264u, 0, 66, &be_const_str__archive); +be_define_const_str(COLOR_BLACK, "COLOR_BLACK", 264427940u, 0, 11, &be_const_str_pin_mode); +be_define_const_str(COLOR_WHITE, "COLOR_WHITE", 2536871270u, 0, 11, NULL); +be_define_const_str(EC_C25519, "EC_C25519", 95492591u, 0, 9, &be_const_str_I2C_X3A); +be_define_const_str(EVENT_DELETE, "EVENT_DELETE", 282828603u, 0, 12, &be_const_str_bool); +be_define_const_str(EVENT_DRAW_MAIN, "EVENT_DRAW_MAIN", 1955620614u, 0, 15, &be_const_str_OpusDecoder); +be_define_const_str(EVENT_DRAW_PART_BEGIN, "EVENT_DRAW_PART_BEGIN", 3391865024u, 0, 21, &be_const_str_fromstring); +be_define_const_str(EVENT_DRAW_PART_END, "EVENT_DRAW_PART_END", 3301625292u, 0, 19, &be_const_str_enabled); +be_define_const_str(False, "False", 2541049336u, 0, 5, NULL); +be_define_const_str(GET, "GET", 2531704439u, 0, 3, &be_const_str_https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_X2F_X25s_X2Eautoconf); +be_define_const_str(HTTP_GET, "HTTP_GET", 1722467738u, 0, 8, &be_const_str_lv_extra); +be_define_const_str(HTTP_POST, "HTTP_POST", 1999554144u, 0, 9, &be_const_str_matrix); +be_define_const_str(I2C_X3A, "I2C:", 813483371u, 0, 4, &be_const_str_exec_tele); +be_define_const_str(I2C_Driver, "I2C_Driver", 1714501658u, 0, 10, &be_const_str_battery_present); +be_define_const_str(LVG_X3A_X20call_X20to_X20unsupported_X20callback, "LVG: call to unsupported callback", 504176819u, 0, 33, &be_const_str_argument_X20must_X20be_X20a_X20function); +be_define_const_str(LVG_X3A_X20object_X3A, "LVG: object:", 3824079937u, 0, 12, &be_const_str_connect); +be_define_const_str(Leds, "Leds", 2709245275u, 0, 4, &be_const_str_valuer_error); be_define_const_str(MD5, "MD5", 1935726387u, 0, 3, NULL); -be_define_const_str(No_X20callback_X20available, "No callback available", 633786138u, 0, 21, &be_const_str_gpio); -be_define_const_str(None, "None", 810547195u, 0, 4, &be_const_str_SERIAL_5E1); -be_define_const_str(OPTION_A, "OPTION_A", 1133299440u, 0, 8, &be_const_str_init_draw_line_dsc); -be_define_const_str(OneWire, "OneWire", 2298990722u, 0, 7, &be_const_str_Timer); -be_define_const_str(PART_MAIN, "PART_MAIN", 2473491508u, 0, 9, &be_const_str_STATE_DEFAULT); -be_define_const_str(POST, "POST", 1929554311u, 0, 4, NULL); -be_define_const_str(Parameter_X20error, "Parameter error", 3840042038u, 0, 15, NULL); -be_define_const_str(RES_OK, "RES_OK", 1233817284u, 0, 6, &be_const_str_bri); -be_define_const_str(Restart_X201, "Restart 1", 3504455855u, 0, 9, &be_const_str_min); -be_define_const_str(SERIAL_5E1, "SERIAL_5E1", 1163775235u, 0, 10, &be_const_str_zero); -be_define_const_str(SERIAL_5E2, "SERIAL_5E2", 1180552854u, 0, 10, &be_const_str_lv_obj_class); -be_define_const_str(SERIAL_5N1, "SERIAL_5N1", 3313031680u, 0, 10, &be_const_str_ins_ramp); -be_define_const_str(SERIAL_5N2, "SERIAL_5N2", 3363364537u, 0, 10, NULL); -be_define_const_str(SERIAL_5O1, "SERIAL_5O1", 3782657917u, 0, 10, &be_const_str_flush); -be_define_const_str(SERIAL_5O2, "SERIAL_5O2", 3732325060u, 0, 10, NULL); -be_define_const_str(SERIAL_6E1, "SERIAL_6E1", 334249486u, 0, 10, NULL); +be_define_const_str(None, "None", 810547195u, 0, 4, &be_const_str_font_seg7); +be_define_const_str(OPTION_A, "OPTION_A", 1133299440u, 0, 8, NULL); +be_define_const_str(OneWire, "OneWire", 2298990722u, 0, 7, &be_const_str__fl); +be_define_const_str(OpusDecoder, "OpusDecoder", 3618742074u, 0, 11, &be_const_str_size); +be_define_const_str(PART_MAIN, "PART_MAIN", 2473491508u, 0, 9, &be_const_str_string); +be_define_const_str(POST, "POST", 1929554311u, 0, 4, &be_const_str_unknown_X20instruction); +be_define_const_str(Parameter_X20error, "Parameter error", 3840042038u, 0, 15, &be_const_str_addr); +be_define_const_str(RES_OK, "RES_OK", 1233817284u, 0, 6, &be_const_str_lv_obj_class); +be_define_const_str(Restart_X201, "Restart 1", 3504455855u, 0, 9, &be_const_str_widget_destructor); +be_define_const_str(SERIAL_5E1, "SERIAL_5E1", 1163775235u, 0, 10, &be_const_str_cb_event_closure); +be_define_const_str(SERIAL_5E2, "SERIAL_5E2", 1180552854u, 0, 10, &be_const_str_count); +be_define_const_str(SERIAL_5N1, "SERIAL_5N1", 3313031680u, 0, 10, &be_const_str__read); +be_define_const_str(SERIAL_5N2, "SERIAL_5N2", 3363364537u, 0, 10, &be_const_str_readline); +be_define_const_str(SERIAL_5O1, "SERIAL_5O1", 3782657917u, 0, 10, &be_const_str__settings_def); +be_define_const_str(SERIAL_5O2, "SERIAL_5O2", 3732325060u, 0, 10, &be_const_str_decompress); +be_define_const_str(SERIAL_6E1, "SERIAL_6E1", 334249486u, 0, 10, &be_const_str_widget_editable); be_define_const_str(SERIAL_6E2, "SERIAL_6E2", 317471867u, 0, 10, NULL); -be_define_const_str(SERIAL_6N1, "SERIAL_6N1", 198895701u, 0, 10, &be_const_str_char); -be_define_const_str(SERIAL_6N2, "SERIAL_6N2", 148562844u, 0, 10, &be_const_str_matrix); -be_define_const_str(SERIAL_6O1, "SERIAL_6O1", 266153272u, 0, 10, &be_const_str_atleast1); -be_define_const_str(SERIAL_6O2, "SERIAL_6O2", 316486129u, 0, 10, &be_const_str_content_send); -be_define_const_str(SERIAL_7E1, "SERIAL_7E1", 147718061u, 0, 10, &be_const_str_stop_iteration); -be_define_const_str(SERIAL_7E2, "SERIAL_7E2", 97385204u, 0, 10, &be_const_str_copy); -be_define_const_str(SERIAL_7N1, "SERIAL_7N1", 1891060246u, 0, 10, NULL); -be_define_const_str(SERIAL_7N2, "SERIAL_7N2", 1874282627u, 0, 10, &be_const_str_elif); -be_define_const_str(SERIAL_7O1, "SERIAL_7O1", 1823802675u, 0, 10, &be_const_str_init); -be_define_const_str(SERIAL_7O2, "SERIAL_7O2", 1840580294u, 0, 10, &be_const_str_global); -be_define_const_str(SERIAL_8E1, "SERIAL_8E1", 2371121616u, 0, 10, &be_const_str_scan); -be_define_const_str(SERIAL_8E2, "SERIAL_8E2", 2421454473u, 0, 10, &be_const_str_deregister_obj); -be_define_const_str(SERIAL_8N1, "SERIAL_8N1", 2369297235u, 0, 10, &be_const_str_resp_cmnd_done); -be_define_const_str(SERIAL_8N2, "SERIAL_8N2", 2386074854u, 0, 10, &be_const_str_sys); -be_define_const_str(SERIAL_8O1, "SERIAL_8O1", 289122742u, 0, 10, &be_const_str_get_vbus_current); -be_define_const_str(SERIAL_8O2, "SERIAL_8O2", 272345123u, 0, 10, &be_const_str_gamma10); -be_define_const_str(SK6812_GRBW, "SK6812_GRBW", 81157857u, 0, 11, NULL); -be_define_const_str(STATE_DEFAULT, "STATE_DEFAULT", 712406428u, 0, 13, &be_const_str_classname); -be_define_const_str(TAP_X3A_X20found_X20Tasmota_X20App_X20_X27_X25s_X27, "TAP: found Tasmota App '%s'", 2643152398u, 0, 27, NULL); -be_define_const_str(Tasmota, "Tasmota", 4047617668u, 0, 7, &be_const_str_top); -be_define_const_str(Tele, "Tele", 1329980653u, 0, 4, &be_const_str_exists); -be_define_const_str(Timer, "Timer", 3948127682u, 0, 5, &be_const_str_del); -be_define_const_str(True, "True", 3453902341u, 0, 4, &be_const_str_real); -be_define_const_str(Unknown_X20command, "Unknown command", 1830905432u, 0, 15, &be_const_str_get_percentage); -be_define_const_str(WS2812, "WS2812", 3539741218u, 0, 6, &be_const_str_finish); -be_define_const_str(WS2812_GRB, "WS2812_GRB", 1736405692u, 0, 10, &be_const_str_tasmota); -be_define_const_str(Wire, "Wire", 1938276536u, 0, 4, &be_const_str__begin_transmission); +be_define_const_str(SERIAL_6N1, "SERIAL_6N1", 198895701u, 0, 10, &be_const_str_arg); +be_define_const_str(SERIAL_6N2, "SERIAL_6N2", 148562844u, 0, 10, &be_const_str_gamma); +be_define_const_str(SERIAL_6O1, "SERIAL_6O1", 266153272u, 0, 10, &be_const_str_WS2812_GRB); +be_define_const_str(SERIAL_6O2, "SERIAL_6O2", 316486129u, 0, 10, &be_const_str_load); +be_define_const_str(SERIAL_7E1, "SERIAL_7E1", 147718061u, 0, 10, &be_const_str_deg); +be_define_const_str(SERIAL_7E2, "SERIAL_7E2", 97385204u, 0, 10, &be_const_str_SERIAL_7O2); +be_define_const_str(SERIAL_7N1, "SERIAL_7N1", 1891060246u, 0, 10, &be_const_str__timers); +be_define_const_str(SERIAL_7N2, "SERIAL_7N2", 1874282627u, 0, 10, NULL); +be_define_const_str(SERIAL_7O1, "SERIAL_7O1", 1823802675u, 0, 10, &be_const_str_SERIAL_8N1); +be_define_const_str(SERIAL_7O2, "SERIAL_7O2", 1840580294u, 0, 10, &be_const_str_SERIAL_8N2); +be_define_const_str(SERIAL_8E1, "SERIAL_8E1", 2371121616u, 0, 10, &be_const_str_files); +be_define_const_str(SERIAL_8E2, "SERIAL_8E2", 2421454473u, 0, 10, &be_const_str_consume_mono); +be_define_const_str(SERIAL_8N1, "SERIAL_8N1", 2369297235u, 0, 10, &be_const_str_collect); +be_define_const_str(SERIAL_8N2, "SERIAL_8N2", 2386074854u, 0, 10, &be_const_str_clear); +be_define_const_str(SERIAL_8O1, "SERIAL_8O1", 289122742u, 0, 10, &be_const_str_deinit); +be_define_const_str(SERIAL_8O2, "SERIAL_8O2", 272345123u, 0, 10, &be_const_str_dump); +be_define_const_str(SK6812_GRBW, "SK6812_GRBW", 81157857u, 0, 11, &be_const_str_arch); +be_define_const_str(STATE_DEFAULT, "STATE_DEFAULT", 712406428u, 0, 13, &be_const_str_finish); +be_define_const_str(TAP_X3A_X20Loaded_X20Tasmota_X20App_X20_X27_X25s_X27, "TAP: Loaded Tasmota App '%s'", 926477145u, 0, 28, &be_const_str__debug_present); +be_define_const_str(Tasmota, "Tasmota", 4047617668u, 0, 7, &be_const_str_instance); +be_define_const_str(Tele, "Tele", 1329980653u, 0, 4, NULL); +be_define_const_str(Timer, "Timer", 3948127682u, 0, 5, &be_const_str_Unknown_X20command); +be_define_const_str(True, "True", 3453902341u, 0, 4, &be_const_str_clock_icon); +be_define_const_str(Unknown_X20command, "Unknown command", 1830905432u, 0, 15, &be_const_str_calldepth); +be_define_const_str(WS2812, "WS2812", 3539741218u, 0, 6, &be_const_str_has_arg); +be_define_const_str(WS2812_GRB, "WS2812_GRB", 1736405692u, 0, 10, &be_const_str_debug); +be_define_const_str(Wire, "Wire", 1938276536u, 0, 4, NULL); be_define_const_str(_X5B, "[", 3725336506u, 0, 1, NULL); -be_define_const_str(_X5D, "]", 3624670792u, 0, 1, NULL); -be_define_const_str(_, "_", 3658226030u, 0, 1, NULL); -be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_pixel_count); -be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_pin_mode); -be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_engine); -be_define_const_str(_anonymous_, "_anonymous_", 1957281476u, 0, 11, &be_const_str_get_light); -be_define_const_str(_archive, "_archive", 4004559404u, 0, 8, &be_const_str_cosh); -be_define_const_str(_available, "_available", 1306196581u, 0, 10, &be_const_str_is_running); -be_define_const_str(_begin_transmission, "_begin_transmission", 2779461176u, 0, 19, &be_const_str_lv_event_cb); -be_define_const_str(_buffer, "_buffer", 2044888568u, 0, 7, &be_const_str_every_50ms); -be_define_const_str(_cb, "_cb", 4043300367u, 0, 3, NULL); -be_define_const_str(_ccmd, "_ccmd", 2163421413u, 0, 5, &be_const_str_animators); -be_define_const_str(_class, "_class", 2732146350u, 0, 6, &be_const_str__X7Bs_X7DVBus_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D); -be_define_const_str(_cmd, "_cmd", 3419822142u, 0, 4, NULL); +be_define_const_str(_X5D, "]", 3624670792u, 0, 1, &be_const_str_connected); +be_define_const_str(_, "_", 3658226030u, 0, 1, &be_const_str_get_width); +be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_animators); +be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_detect); +be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_draw_line_dsc); +be_define_const_str(_anonymous_, "_anonymous_", 1957281476u, 0, 11, &be_const_str_pc); +be_define_const_str(_archive, "_archive", 4004559404u, 0, 8, &be_const_str_set_percentage); +be_define_const_str(_available, "_available", 1306196581u, 0, 10, &be_const_str_autoexec); +be_define_const_str(_begin_transmission, "_begin_transmission", 2779461176u, 0, 19, NULL); +be_define_const_str(_buffer, "_buffer", 2044888568u, 0, 7, &be_const_str_decrypt); +be_define_const_str(_ccmd, "_ccmd", 2163421413u, 0, 5, &be_const_str_deregister_obj); +be_define_const_str(_class, "_class", 2732146350u, 0, 6, &be_const_str_get_bat_charge_current); +be_define_const_str(_cmd, "_cmd", 3419822142u, 0, 4, &be_const_str_dac_voltage); be_define_const_str(_debug_present, "_debug_present", 4063411725u, 0, 14, &be_const_str_call_native); -be_define_const_str(_def, "_def", 1985022181u, 0, 4, NULL); -be_define_const_str(_dirty, "_dirty", 283846766u, 0, 6, &be_const_str_get_coords); +be_define_const_str(_def, "_def", 1985022181u, 0, 4, &be_const_str_point); +be_define_const_str(_dirty, "_dirty", 283846766u, 0, 6, &be_const_str_button_pressed); be_define_const_str(_drivers, "_drivers", 3260328985u, 0, 8, &be_const_str__write); be_define_const_str(_end_transmission, "_end_transmission", 3237480400u, 0, 17, NULL); -be_define_const_str(_energy, "_energy", 535372070u, 0, 7, &be_const_str_quality); -be_define_const_str(_error, "_error", 1132109656u, 0, 6, &be_const_str__ptr); -be_define_const_str(_filename, "_filename", 1430813195u, 0, 9, &be_const_str_set_text); -be_define_const_str(_get_cb, "_get_cb", 1448849122u, 0, 7, &be_const_str_find); -be_define_const_str(_global_addr, "_global_addr", 533766721u, 0, 12, &be_const_str_display_X2Eini); -be_define_const_str(_global_def, "_global_def", 646007001u, 0, 11, &be_const_str_get_warning_level); -be_define_const_str(_lvgl, "_lvgl", 2689219483u, 0, 5, &be_const_str_get_height); +be_define_const_str(_energy, "_energy", 535372070u, 0, 7, &be_const_str_animate); +be_define_const_str(_error, "_error", 1132109656u, 0, 6, &be_const_str_closure); +be_define_const_str(_filename, "_filename", 1430813195u, 0, 9, &be_const_str_reset_search); +be_define_const_str(_fl, "_fl", 4042564892u, 0, 3, &be_const_str_fast_loop); +be_define_const_str(_global_addr, "_global_addr", 533766721u, 0, 12, NULL); +be_define_const_str(_global_def, "_global_def", 646007001u, 0, 11, NULL); +be_define_const_str(_lvgl, "_lvgl", 2689219483u, 0, 5, &be_const_str_create_matrix); be_define_const_str(_p, "_p", 1594591802u, 0, 2, &be_const_str_format); -be_define_const_str(_persist_X2Ejson, "_persist.json", 2008425138u, 0, 13, &be_const_str_value); -be_define_const_str(_ptr, "_ptr", 306235816u, 0, 4, &be_const_str_rtc); -be_define_const_str(_read, "_read", 346717030u, 0, 5, &be_const_str_is_dirty); -be_define_const_str(_request_from, "_request_from", 3965148604u, 0, 13, NULL); +be_define_const_str(_persist_X2Ejson, "_persist.json", 2008425138u, 0, 13, &be_const_str_instance_size); +be_define_const_str(_ptr, "_ptr", 306235816u, 0, 4, &be_const_str_fast_loop_enabled); +be_define_const_str(_read, "_read", 346717030u, 0, 5, &be_const_str_signal_bars); +be_define_const_str(_request_from, "_request_from", 3965148604u, 0, 13, &be_const_str_is_first_time); be_define_const_str(_rules, "_rules", 4266217105u, 0, 6, NULL); -be_define_const_str(_settings_def, "_settings_def", 3775560307u, 0, 13, &be_const_str_set); -be_define_const_str(_settings_ptr, "_settings_ptr", 1825772182u, 0, 13, &be_const_str_remove_cmd); -be_define_const_str(_t, "_t", 1527481326u, 0, 2, &be_const_str_draw_line_dsc_init); -be_define_const_str(_timers, "_timers", 2600100916u, 0, 7, &be_const_str_eth); -be_define_const_str(_write, "_write", 2215462825u, 0, 6, &be_const_str_v); +be_define_const_str(_settings_def, "_settings_def", 3775560307u, 0, 13, &be_const_str_setbits); +be_define_const_str(_settings_ptr, "_settings_ptr", 1825772182u, 0, 13, &be_const_str_str); +be_define_const_str(_t, "_t", 1527481326u, 0, 2, &be_const_str_page_autoconf_ctl); +be_define_const_str(_timers, "_timers", 2600100916u, 0, 7, &be_const_str_find_op); +be_define_const_str(_write, "_write", 2215462825u, 0, 6, NULL); be_define_const_str(a, "a", 3826002220u, 0, 1, &be_const_str_add); -be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_get_aps_voltage); -be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_lv); -be_define_const_str(add, "add", 993596020u, 0, 3, &be_const_str_bytes); -be_define_const_str(add_anim, "add_anim", 3980662668u, 0, 8, NULL); -be_define_const_str(add_cmd, "add_cmd", 3361630879u, 0, 7, &be_const_str_arg_X20must_X20be_X20a_X20subclass_X20of_X20lv_obj); -be_define_const_str(add_driver, "add_driver", 1654458371u, 0, 10, NULL); -be_define_const_str(add_header, "add_header", 927130612u, 0, 10, &be_const_str_couldn_X27t_X20not_X20initialize_X20noepixelbus); -be_define_const_str(add_rule, "add_rule", 596540743u, 0, 8, &be_const_str_resp_cmnd_error); -be_define_const_str(addr, "addr", 1087856498u, 0, 4, &be_const_str_battery_present); -be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_create_custom_widget); -be_define_const_str(alternate, "alternate", 1140253277u, 0, 9, &be_const_str_out_X20of_X20range); -be_define_const_str(animate, "animate", 3885786800u, 0, 7, &be_const_str_set_ldo_voltage); -be_define_const_str(animators, "animators", 279858213u, 0, 9, &be_const_str_read_bytes); -be_define_const_str(arch, "arch", 2952804297u, 0, 4, &be_const_str_arg_size); -be_define_const_str(area, "area", 2601460036u, 0, 4, &be_const_str_draw_arc); -be_define_const_str(arg, "arg", 1047474471u, 0, 3, &be_const_str_page_autoconf_mgr); -be_define_const_str(arg_X20must_X20be_X20a_X20subclass_X20of_X20lv_obj, "arg must be a subclass of lv_obj", 1641882079u, 0, 32, &be_const_str_create_segment); -be_define_const_str(arg_name, "arg_name", 1345046155u, 0, 8, &be_const_str_has); +be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_remove_timer); +be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_leds); +be_define_const_str(add, "add", 993596020u, 0, 3, &be_const_str_ins_ramp); +be_define_const_str(add_anim, "add_anim", 3980662668u, 0, 8, &be_const_str_compile); +be_define_const_str(add_cmd, "add_cmd", 3361630879u, 0, 7, &be_const_str_class); +be_define_const_str(add_driver, "add_driver", 1654458371u, 0, 10, &be_const_str_keys); +be_define_const_str(add_event_cb, "add_event_cb", 633097693u, 0, 12, &be_const_str_ctor); +be_define_const_str(add_fast_loop, "add_fast_loop", 3025842946u, 0, 13, &be_const_str_draw_line); +be_define_const_str(add_handler, "add_handler", 2055124119u, 0, 11, &be_const_str_atan); +be_define_const_str(add_header, "add_header", 927130612u, 0, 10, NULL); +be_define_const_str(add_rule, "add_rule", 596540743u, 0, 8, &be_const_str_ins_goto); +be_define_const_str(addr, "addr", 1087856498u, 0, 4, &be_const_str_cb); +be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_check_privileged_access); +be_define_const_str(alternate, "alternate", 1140253277u, 0, 9, &be_const_str_content_button); +be_define_const_str(animate, "animate", 3885786800u, 0, 7, NULL); +be_define_const_str(animators, "animators", 279858213u, 0, 9, &be_const_str_set_power); +be_define_const_str(arch, "arch", 2952804297u, 0, 4, &be_const_str_open); +be_define_const_str(area, "area", 2601460036u, 0, 4, &be_const_str_param); +be_define_const_str(arg, "arg", 1047474471u, 0, 3, NULL); +be_define_const_str(arg_X20must_X20be_X20a_X20subclass_X20of_X20lv_obj, "arg must be a subclass of lv_obj", 1641882079u, 0, 32, &be_const_str_lv_signal_bars); +be_define_const_str(arg_name, "arg_name", 1345046155u, 0, 8, &be_const_str_zero); be_define_const_str(arg_size, "arg_size", 3310243257u, 0, 8, NULL); +be_define_const_str(argument_X20must_X20be_X20a_X20function, "argument must be a function", 527172389u, 0, 27, NULL); +be_define_const_str(argument_X20must_X20be_X20a_X20list, "argument must be a list", 3056915661u, 0, 23, &be_const_str_gen_cb); be_define_const_str(as, "as", 1579491469u, 67, 2, NULL); -be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_destructor_cb); -be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_member); -be_define_const_str(asstring, "asstring", 1298225088u, 0, 8, &be_const_str_invalidate); +be_define_const_str(asin, "asin", 4272848550u, 0, 4, NULL); +be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_is_running); +be_define_const_str(asstring, "asstring", 1298225088u, 0, 8, &be_const_str_number); be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_fromb64); -be_define_const_str(atan2, "atan2", 3173440503u, 0, 5, &be_const_str_millis); -be_define_const_str(atleast1, "atleast1", 1956331672u, 0, 8, &be_const_str_connected); -be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_counters); -be_define_const_str(autoexec, "autoexec", 3676861891u, 0, 8, NULL); -be_define_const_str(autorun, "autorun", 1447527407u, 0, 7, &be_const_str_return); -be_define_const_str(available, "available", 1727918744u, 0, 9, &be_const_str_fromstring); -be_define_const_str(b, "b", 3876335077u, 0, 1, &be_const_str_display); -be_define_const_str(back_forth, "back_forth", 2665042062u, 0, 10, &be_const_str_dac_voltage); +be_define_const_str(atan2, "atan2", 3173440503u, 0, 5, NULL); +be_define_const_str(atleast1, "atleast1", 1956331672u, 0, 8, &be_const_str_cmd_res); +be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_available); +be_define_const_str(autoexec, "autoexec", 3676861891u, 0, 8, &be_const_str_send); +be_define_const_str(autorun, "autorun", 1447527407u, 0, 7, &be_const_str_minute); +be_define_const_str(available, "available", 1727918744u, 0, 9, &be_const_str_copy); +be_define_const_str(b, "b", 3876335077u, 0, 1, &be_const_str_set); +be_define_const_str(back_forth, "back_forth", 2665042062u, 0, 10, &be_const_str_write_bytes); be_define_const_str(base_class, "base_class", 1107737279u, 0, 10, NULL); -be_define_const_str(battery_present, "battery_present", 3588397058u, 0, 15, &be_const_str_run_bat); -be_define_const_str(begin, "begin", 1748273790u, 0, 5, &be_const_str_gamma8); -be_define_const_str(bool, "bool", 3365180733u, 0, 4, &be_const_str_set_power); +be_define_const_str(battery_present, "battery_present", 3588397058u, 0, 15, &be_const_str_every_50ms); +be_define_const_str(before_del, "before_del", 815924436u, 0, 10, &be_const_str_set_chg_current); +be_define_const_str(begin, "begin", 1748273790u, 0, 5, &be_const_str_clear_to); +be_define_const_str(begin_multicast, "begin_multicast", 57647915u, 0, 15, NULL); +be_define_const_str(bool, "bool", 3365180733u, 0, 4, &be_const_str_strip); be_define_const_str(break, "break", 3378807160u, 58, 5, NULL); -be_define_const_str(bri, "bri", 2112284244u, 0, 3, &be_const_str_cos); -be_define_const_str(bus, "bus", 1607822841u, 0, 3, &be_const_str_get_vbus_voltage); -be_define_const_str(button_pressed, "button_pressed", 1694209616u, 0, 14, &be_const_str_insert); -be_define_const_str(byte, "byte", 1683620383u, 0, 4, NULL); -be_define_const_str(bytes, "bytes", 1706151940u, 0, 5, NULL); -be_define_const_str(c, "c", 3859557458u, 0, 1, &be_const_str_decrypt); -be_define_const_str(call, "call", 3018949801u, 0, 4, NULL); -be_define_const_str(call_native, "call_native", 1389147405u, 0, 11, &be_const_str_https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_manifest_X2Ejson); -be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, &be_const_str_event_send); -be_define_const_str(can_show, "can_show", 960091187u, 0, 8, &be_const_str_ctypes_bytes_dyn); -be_define_const_str(cb_dispatch, "cb_dispatch", 1741510499u, 0, 11, &be_const_str_set_bri); +be_define_const_str(bri, "bri", 2112284244u, 0, 3, NULL); +be_define_const_str(bus, "bus", 1607822841u, 0, 3, &be_const_str_read_sensors); +be_define_const_str(button_pressed, "button_pressed", 1694209616u, 0, 14, &be_const_str_zip); +be_define_const_str(byte, "byte", 1683620383u, 0, 4, &be_const_str_json_fdump_list); +be_define_const_str(bytes, "bytes", 1706151940u, 0, 5, &be_const_str_set_timeouts); +be_define_const_str(c, "c", 3859557458u, 0, 1, NULL); +be_define_const_str(call, "call", 3018949801u, 0, 4, &be_const_str_content_stop); +be_define_const_str(call_native, "call_native", 1389147405u, 0, 11, &be_const_str_every_second); +be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, &be_const_str_set_alternate); +be_define_const_str(can_show, "can_show", 960091187u, 0, 8, &be_const_str_constructor_cb); +be_define_const_str(cb, "cb", 1428787088u, 0, 2, NULL); be_define_const_str(cb_do_nothing, "cb_do_nothing", 1488730702u, 0, 13, NULL); -be_define_const_str(cb_event_closure, "cb_event_closure", 3828267325u, 0, 16, NULL); -be_define_const_str(cb_obj, "cb_obj", 1195696482u, 0, 6, &be_const_str_rotate); -be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, &be_const_str_set_width); +be_define_const_str(cb_event_closure, "cb_event_closure", 3828267325u, 0, 16, &be_const_str_round_end); +be_define_const_str(cb_obj, "cb_obj", 1195696482u, 0, 6, &be_const_str_to_gamma); +be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, NULL); be_define_const_str(char, "char", 2823553821u, 0, 4, NULL); -be_define_const_str(chars_in_string, "chars_in_string", 3148785132u, 0, 15, &be_const_str_kv); -be_define_const_str(check_privileged_access, "check_privileged_access", 3692933968u, 0, 23, &be_const_str_group_def); +be_define_const_str(chars_in_string, "chars_in_string", 3148785132u, 0, 15, &be_const_str_get_cb_list); +be_define_const_str(check_not_method, "check_not_method", 2597324607u, 0, 16, &be_const_str_point_arr); +be_define_const_str(check_privileged_access, "check_privileged_access", 3692933968u, 0, 23, NULL); be_define_const_str(class, "class", 2872970239u, 57, 5, NULL); be_define_const_str(class_init_obj, "class_init_obj", 178410604u, 0, 14, &be_const_str_set_useragent); be_define_const_str(classname, "classname", 1998589948u, 0, 9, NULL); -be_define_const_str(classof, "classof", 1796577762u, 0, 7, NULL); -be_define_const_str(clear, "clear", 1550717474u, 0, 5, NULL); -be_define_const_str(clear_first_time, "clear_first_time", 632769909u, 0, 16, &be_const_str_read); -be_define_const_str(clear_to, "clear_to", 3528002130u, 0, 8, &be_const_str_geti); -be_define_const_str(close, "close", 667630371u, 0, 5, &be_const_str_depower); -be_define_const_str(closure, "closure", 1548407746u, 0, 7, &be_const_str_param); -be_define_const_str(cmd, "cmd", 4136785899u, 0, 3, &be_const_str_input); -be_define_const_str(cmd_res, "cmd_res", 921166762u, 0, 7, NULL); -be_define_const_str(code, "code", 4180765940u, 0, 4, &be_const_str_null_cb); -be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, NULL); -be_define_const_str(collect, "collect", 2399039025u, 0, 7, &be_const_str_json_fdump_any); -be_define_const_str(color, "color", 1031692888u, 0, 5, &be_const_str_has_arg); +be_define_const_str(classof, "classof", 1796577762u, 0, 7, &be_const_str_kv); +be_define_const_str(clear, "clear", 1550717474u, 0, 5, &be_const_str_scale_uint); +be_define_const_str(clear_first_time, "clear_first_time", 632769909u, 0, 16, &be_const_str_width_def); +be_define_const_str(clear_to, "clear_to", 3528002130u, 0, 8, &be_const_str_connection_error); +be_define_const_str(clock_icon, "clock_icon", 544669651u, 0, 10, &be_const_str_value_error); +be_define_const_str(close, "close", 667630371u, 0, 5, &be_const_str_get_object_from_ptr); +be_define_const_str(closure, "closure", 1548407746u, 0, 7, &be_const_str_item); +be_define_const_str(cmd, "cmd", 4136785899u, 0, 3, &be_const_str_tolower); +be_define_const_str(cmd_res, "cmd_res", 921166762u, 0, 7, &be_const_str_tan); +be_define_const_str(code, "code", 4180765940u, 0, 4, &be_const_str_detected_X20on_X20bus); +be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_w); +be_define_const_str(collect, "collect", 2399039025u, 0, 7, &be_const_str_init); +be_define_const_str(color, "color", 1031692888u, 0, 5, NULL); be_define_const_str(compile, "compile", 1000265118u, 0, 7, NULL); -be_define_const_str(compress, "compress", 2818084237u, 0, 8, NULL); +be_define_const_str(compress, "compress", 2818084237u, 0, 8, &be_const_str_from_to); be_define_const_str(concat, "concat", 4124019837u, 0, 6, NULL); -be_define_const_str(connect, "connect", 2866859257u, 0, 7, NULL); -be_define_const_str(connected, "connected", 1424938192u, 0, 9, &be_const_str_debug); -be_define_const_str(connection_error, "connection_error", 1358926260u, 0, 16, &be_const_str_json_fdump); -be_define_const_str(constructor_cb, "constructor_cb", 2489105297u, 0, 14, &be_const_str_minute); -be_define_const_str(contains, "contains", 1825239352u, 0, 8, &be_const_str_deinit); -be_define_const_str(content_button, "content_button", 1956476087u, 0, 14, &be_const_str_pixels_buffer); -be_define_const_str(content_flush, "content_flush", 214922475u, 0, 13, &be_const_str_leds); -be_define_const_str(content_send, "content_send", 1673733649u, 0, 12, &be_const_str_load); -be_define_const_str(content_send_style, "content_send_style", 1087907647u, 0, 18, &be_const_str_read8); -be_define_const_str(content_start, "content_start", 2937509069u, 0, 13, &be_const_str_https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_X2F_X25s_X2Eautoconf); -be_define_const_str(content_stop, "content_stop", 658554751u, 0, 12, NULL); +be_define_const_str(connect, "connect", 2866859257u, 0, 7, &be_const_str_display); +be_define_const_str(connected, "connected", 1424938192u, 0, 9, NULL); +be_define_const_str(connection_error, "connection_error", 1358926260u, 0, 16, NULL); +be_define_const_str(constructor_cb, "constructor_cb", 2489105297u, 0, 14, &be_const_str_ctypes_bytes_dyn); +be_define_const_str(consume_mono, "consume_mono", 3577563453u, 0, 12, &be_const_str_get_option); +be_define_const_str(consume_silence, "consume_silence", 1445390925u, 0, 15, &be_const_str_https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_manifest_X2Ejson); +be_define_const_str(consume_stereo, "consume_stereo", 1834661098u, 0, 14, &be_const_str_height_def); +be_define_const_str(contains, "contains", 1825239352u, 0, 8, NULL); +be_define_const_str(content_button, "content_button", 1956476087u, 0, 14, &be_const_str_push); +be_define_const_str(content_flush, "content_flush", 214922475u, 0, 13, NULL); +be_define_const_str(content_send, "content_send", 1673733649u, 0, 12, &be_const_str_iter); +be_define_const_str(content_send_style, "content_send_style", 1087907647u, 0, 18, NULL); +be_define_const_str(content_start, "content_start", 2937509069u, 0, 13, &be_const_str_digital_write); +be_define_const_str(content_stop, "content_stop", 658554751u, 0, 12, &be_const_str_h); be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL); -be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_json_append); -be_define_const_str(cos, "cos", 4220379804u, 0, 3, &be_const_str_count); -be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, &be_const_str_set_percentage); +be_define_const_str(coord_arr, "coord_arr", 4189963658u, 0, 9, &be_const_str_path); +be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_web_add_main_button); +be_define_const_str(cos, "cos", 4220379804u, 0, 3, NULL); +be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, &be_const_str_global); be_define_const_str(couldn_X27t_X20not_X20initialize_X20noepixelbus, "couldn't not initialize noepixelbus", 2536490812u, 0, 35, NULL); -be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_every_100ms); -be_define_const_str(counters, "counters", 4095866864u, 0, 8, &be_const_str_on); -be_define_const_str(create_custom_widget, "create_custom_widget", 1140594778u, 0, 20, &be_const_str_instance); -be_define_const_str(create_matrix, "create_matrix", 3528185923u, 0, 13, &be_const_str_dirty); -be_define_const_str(create_segment, "create_segment", 3863522719u, 0, 14, &be_const_str_exec_cmd); -be_define_const_str(ctor, "ctor", 375399343u, 0, 4, &be_const_str_tcpclient); -be_define_const_str(ctypes_bytes, "ctypes_bytes", 3879019703u, 0, 12, NULL); -be_define_const_str(ctypes_bytes_dyn, "ctypes_bytes_dyn", 915205307u, 0, 16, &be_const_str_time_dump); -be_define_const_str(dac_voltage, "dac_voltage", 1552257222u, 0, 11, &be_const_str_reverse_gamma10); -be_define_const_str(day, "day", 3830391293u, 0, 3, &be_const_str_duration); -be_define_const_str(debug, "debug", 1483009432u, 0, 5, &be_const_str_str); -be_define_const_str(decompress, "decompress", 2887031650u, 0, 10, &be_const_str_imax); -be_define_const_str(decrypt, "decrypt", 2886974618u, 0, 7, &be_const_str_onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E); +be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_isnan); +be_define_const_str(counters, "counters", 4095866864u, 0, 8, &be_const_str_yield); +be_define_const_str(create_custom_widget, "create_custom_widget", 1140594778u, 0, 20, NULL); +be_define_const_str(create_matrix, "create_matrix", 3528185923u, 0, 13, &be_const_str_select); +be_define_const_str(create_segment, "create_segment", 3863522719u, 0, 14, &be_const_str_hour); +be_define_const_str(ctor, "ctor", 375399343u, 0, 4, &be_const_str_json_fdump_map); +be_define_const_str(ctypes_bytes, "ctypes_bytes", 3879019703u, 0, 12, &be_const_str_widget_struct_default); +be_define_const_str(ctypes_bytes_dyn, "ctypes_bytes_dyn", 915205307u, 0, 16, NULL); +be_define_const_str(dac_voltage, "dac_voltage", 1552257222u, 0, 11, &be_const_str_font_montserrat); +be_define_const_str(day, "day", 3830391293u, 0, 3, &be_const_str_wifi_bars); +be_define_const_str(debug, "debug", 1483009432u, 0, 5, &be_const_str_tasmota); +be_define_const_str(decode, "decode", 3007678287u, 0, 6, &be_const_str_event_cb); +be_define_const_str(decompress, "decompress", 2887031650u, 0, 10, &be_const_str_lower); +be_define_const_str(decrypt, "decrypt", 2886974618u, 0, 7, &be_const_str_get_switch); be_define_const_str(def, "def", 3310976652u, 55, 3, NULL); -be_define_const_str(deg, "deg", 3327754271u, 0, 3, &be_const_str_set_y); -be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_tan); -be_define_const_str(del, "del", 3478752842u, 0, 3, &be_const_str_range); -be_define_const_str(delay, "delay", 1322381784u, 0, 5, &be_const_str_shared_key); -be_define_const_str(delete_all_configs, "delete_all_configs", 2382067578u, 0, 18, &be_const_str_get_bat_voltage); -be_define_const_str(depower, "depower", 3563819571u, 0, 7, &be_const_str_get_battery_chargin_status); -be_define_const_str(deregister_obj, "deregister_obj", 3909966993u, 0, 14, &be_const_str_strip); -be_define_const_str(destructor_cb, "destructor_cb", 1930283190u, 0, 13, &be_const_str_state); -be_define_const_str(detect, "detect", 8884370u, 0, 6, &be_const_str_hex); -be_define_const_str(detected_X20on_X20bus, "detected on bus", 1432002650u, 0, 15, &be_const_str_nan); +be_define_const_str(deg, "deg", 3327754271u, 0, 3, NULL); +be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_find); +be_define_const_str(delay, "delay", 1322381784u, 0, 5, &be_const_str_target); +be_define_const_str(delete_all_configs, "delete_all_configs", 2382067578u, 0, 18, NULL); +be_define_const_str(depower, "depower", 3563819571u, 0, 7, &be_const_str_floor); +be_define_const_str(deregister_obj, "deregister_obj", 3909966993u, 0, 14, &be_const_str_pixel_count); +be_define_const_str(destructor_cb, "destructor_cb", 1930283190u, 0, 13, &be_const_str_json_fdump); +be_define_const_str(detect, "detect", 8884370u, 0, 6, &be_const_str_lv_clock_icon); +be_define_const_str(detected_X20on_X20bus, "detected on bus", 1432002650u, 0, 15, NULL); be_define_const_str(digital_read, "digital_read", 3585496928u, 0, 12, NULL); -be_define_const_str(digital_write, "digital_write", 3435877979u, 0, 13, &be_const_str_set_style_text_font); -be_define_const_str(dirty, "dirty", 2667581083u, 0, 5, NULL); +be_define_const_str(digital_write, "digital_write", 3435877979u, 0, 13, &be_const_str_get_string); +be_define_const_str(dirty, "dirty", 2667581083u, 0, 5, &be_const_str_get_height); be_define_const_str(display, "display", 1164572437u, 0, 7, NULL); -be_define_const_str(display_X2Eini, "display.ini", 2646174001u, 0, 11, &be_const_str_function); +be_define_const_str(display_X2Eini, "display.ini", 2646174001u, 0, 11, NULL); be_define_const_str(do, "do", 1646057492u, 65, 2, NULL); -be_define_const_str(draw_arc, "draw_arc", 1828251676u, 0, 8, &be_const_str_io_error); -be_define_const_str(draw_line, "draw_line", 1634465686u, 0, 9, &be_const_str_item); +be_define_const_str(draw_arc, "draw_arc", 1828251676u, 0, 8, &be_const_str_ip); +be_define_const_str(draw_line, "draw_line", 1634465686u, 0, 9, &be_const_str_io_error); be_define_const_str(draw_line_dsc, "draw_line_dsc", 4220676203u, 0, 13, &be_const_str_energy_struct); -be_define_const_str(draw_line_dsc_init, "draw_line_dsc_init", 3866693646u, 0, 18, NULL); -be_define_const_str(due, "due", 3895530293u, 0, 3, &be_const_str_pow); +be_define_const_str(draw_line_dsc_init, "draw_line_dsc_init", 3866693646u, 0, 18, &be_const_str_id); +be_define_const_str(due, "due", 3895530293u, 0, 3, NULL); be_define_const_str(dump, "dump", 3663001223u, 0, 4, NULL); -be_define_const_str(duration, "duration", 799079693u, 0, 8, &be_const_str_time_reached); -be_define_const_str(editable, "editable", 60532369u, 0, 8, &be_const_str_resize); +be_define_const_str(duration, "duration", 799079693u, 0, 8, NULL); +be_define_const_str(editable, "editable", 60532369u, 0, 8, NULL); +be_define_const_str(elements_X20must_X20be_X20a_X20lv_point, "elements must be a lv_point", 1415796524u, 0, 27, &be_const_str_get_alternate); be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL); be_define_const_str(else, "else", 3183434736u, 52, 4, NULL); -be_define_const_str(enabled, "enabled", 49525662u, 0, 7, &be_const_str_widget_width_def); -be_define_const_str(encrypt, "encrypt", 2194327650u, 0, 7, &be_const_str_introspect); -be_define_const_str(end, "end", 1787721130u, 56, 3, NULL); -be_define_const_str(energy_struct, "energy_struct", 1655792843u, 0, 13, NULL); -be_define_const_str(engine, "engine", 3993360443u, 0, 6, &be_const_str_obj_event_base); -be_define_const_str(erase, "erase", 1010949589u, 0, 5, &be_const_str_lv_obj); -be_define_const_str(escape, "escape", 2652972038u, 0, 6, &be_const_str_path); -be_define_const_str(eth, "eth", 2191266556u, 0, 3, &be_const_str_set_pixel_color); -be_define_const_str(event, "event", 4264611999u, 0, 5, &be_const_str_issubclass); -be_define_const_str(event_cb, "event_cb", 3128698017u, 0, 8, &be_const_str_get_power); -be_define_const_str(event_send, "event_send", 598925582u, 0, 10, &be_const_str_lvgl_event_dispatch); -be_define_const_str(every_100ms, "every_100ms", 1546407804u, 0, 11, &be_const_str_web_send_decimal); -be_define_const_str(every_50ms, "every_50ms", 2383884008u, 0, 10, &be_const_str_length_X20in_X20bits_X20must_X20be_X20between_X200_X20and_X2032); -be_define_const_str(every_second, "every_second", 2075451465u, 0, 12, &be_const_str_serial); +be_define_const_str(enabled, "enabled", 49525662u, 0, 7, &be_const_str_save); +be_define_const_str(encrypt, "encrypt", 2194327650u, 0, 7, NULL); +be_define_const_str(end, "end", 1787721130u, 56, 3, &be_const_str_import); +be_define_const_str(energy_struct, "energy_struct", 1655792843u, 0, 13, &be_const_str_gamma10); +be_define_const_str(engine, "engine", 3993360443u, 0, 6, NULL); +be_define_const_str(erase, "erase", 1010949589u, 0, 5, &be_const_str_exec_cmd); +be_define_const_str(escape, "escape", 2652972038u, 0, 6, NULL); +be_define_const_str(eth, "eth", 2191266556u, 0, 3, &be_const_str_try); +be_define_const_str(event, "event", 4264611999u, 0, 5, &be_const_str_persist); +be_define_const_str(event_cb, "event_cb", 3128698017u, 0, 8, NULL); +be_define_const_str(event_send, "event_send", 598925582u, 0, 10, NULL); +be_define_const_str(every_100ms, "every_100ms", 1546407804u, 0, 11, &be_const_str_imin); +be_define_const_str(every_50ms, "every_50ms", 2383884008u, 0, 10, &be_const_str_get_pixel_color); +be_define_const_str(every_second, "every_second", 2075451465u, 0, 12, &be_const_str_list); be_define_const_str(except, "except", 950914032u, 69, 6, NULL); -be_define_const_str(exec_cmd, "exec_cmd", 493567399u, 0, 8, &be_const_str__X7Bs_X7DBatt_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D); -be_define_const_str(exec_rules, "exec_rules", 1445221092u, 0, 10, &be_const_str_write8); -be_define_const_str(exec_tele, "exec_tele", 1020751601u, 0, 9, NULL); +be_define_const_str(exec_cmd, "exec_cmd", 493567399u, 0, 8, NULL); +be_define_const_str(exec_rules, "exec_rules", 1445221092u, 0, 10, &be_const_str_publish_result); +be_define_const_str(exec_tele, "exec_tele", 1020751601u, 0, 9, &be_const_str_set_y); be_define_const_str(exists, "exists", 1002329533u, 0, 6, &be_const_str_get_bat_power); -be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_listdir); -be_define_const_str(f, "f", 3809224601u, 0, 1, NULL); +be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_lv_wifi_bars_icon); +be_define_const_str(f, "f", 3809224601u, 0, 1, &be_const_str_lv_coord_arr); be_define_const_str(false, "false", 184981848u, 62, 5, NULL); +be_define_const_str(fast_loop, "fast_loop", 3414422702u, 0, 9, &be_const_str_set_light); +be_define_const_str(fast_loop_enabled, "fast_loop_enabled", 2567964376u, 0, 17, NULL); be_define_const_str(file, "file", 2867484483u, 0, 4, NULL); -be_define_const_str(file_X20extension_X20is_X20not_X20_X27_X2Ebe_X27_X20or_X20_X27_X2Ebec_X27, "file extension is not '.be' or '.bec'", 3095719639u, 0, 37, &be_const_str_hour); -be_define_const_str(files, "files", 1055342736u, 0, 5, &be_const_str_page_autoconf_ctl); +be_define_const_str(file_X20extension_X20is_X20not_X20_X27_X2Ebe_X27_X20or_X20_X27_X2Ebec_X27, "file extension is not '.be' or '.bec'", 3095719639u, 0, 37, &be_const_str_has_X20already_X20an_X20event_X20callback); +be_define_const_str(files, "files", 1055342736u, 0, 5, &be_const_str_web_add_management_button); be_define_const_str(find, "find", 3186656602u, 0, 4, NULL); -be_define_const_str(find_key_i, "find_key_i", 850136726u, 0, 10, &be_const_str_w); +be_define_const_str(find_key_i, "find_key_i", 850136726u, 0, 10, &be_const_str_insert); be_define_const_str(find_op, "find_op", 3766713376u, 0, 7, NULL); -be_define_const_str(finish, "finish", 1494643858u, 0, 6, &be_const_str_isinstance); -be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_get_style_bg_color); +be_define_const_str(finish, "finish", 1494643858u, 0, 6, &be_const_str_top); +be_define_const_str(floor, "floor", 3102149661u, 0, 5, NULL); be_define_const_str(flush, "flush", 3002334877u, 0, 5, NULL); +be_define_const_str(font_montserrat, "font_montserrat", 3790091262u, 0, 15, &be_const_str_write8); +be_define_const_str(font_seg7, "font_seg7", 1551771835u, 0, 9, &be_const_str_v); be_define_const_str(for, "for", 2901640080u, 54, 3, NULL); -be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_pi); -be_define_const_str(from_to, "from_to", 21625507u, 0, 7, &be_const_str_static); +be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_setrange); +be_define_const_str(from_to, "from_to", 21625507u, 0, 7, NULL); be_define_const_str(fromb64, "fromb64", 2717019639u, 0, 7, NULL); -be_define_const_str(fromptr, "fromptr", 666189689u, 0, 7, &be_const_str_set_style_bg_color); -be_define_const_str(fromstring, "fromstring", 610302344u, 0, 10, &be_const_str_publish); -be_define_const_str(function, "function", 2664841801u, 0, 8, NULL); -be_define_const_str(gamma, "gamma", 3492353034u, 0, 5, &be_const_str_isnan); +be_define_const_str(fromptr, "fromptr", 666189689u, 0, 7, NULL); +be_define_const_str(fromstring, "fromstring", 610302344u, 0, 10, NULL); +be_define_const_str(function, "function", 2664841801u, 0, 8, &be_const_str_member); +be_define_const_str(gamma, "gamma", 3492353034u, 0, 5, NULL); be_define_const_str(gamma10, "gamma10", 3472052483u, 0, 7, NULL); -be_define_const_str(gamma8, "gamma8", 3802843830u, 0, 6, &be_const_str_memory); -be_define_const_str(gc, "gc", 1042313471u, 0, 2, &be_const_str_tasmota_X2Eset_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eset_X28_X29); -be_define_const_str(gen_cb, "gen_cb", 3245227551u, 0, 6, NULL); +be_define_const_str(gamma8, "gamma8", 3802843830u, 0, 6, &be_const_str_nil); +be_define_const_str(gc, "gc", 1042313471u, 0, 2, &be_const_str_stop_iteration); +be_define_const_str(gen_cb, "gen_cb", 3245227551u, 0, 6, &be_const_str_page_autoconf_mgr); be_define_const_str(get, "get", 1410115415u, 0, 3, NULL); -be_define_const_str(get_alternate, "get_alternate", 1450148894u, 0, 13, &be_const_str_scale_uint); +be_define_const_str(get_alternate, "get_alternate", 1450148894u, 0, 13, &be_const_str_wifi_arcs); be_define_const_str(get_aps_voltage, "get_aps_voltage", 2293036435u, 0, 15, NULL); -be_define_const_str(get_bat_charge_current, "get_bat_charge_current", 1385293050u, 0, 22, &be_const_str_read12); -be_define_const_str(get_bat_current, "get_bat_current", 1912106073u, 0, 15, NULL); -be_define_const_str(get_bat_power, "get_bat_power", 3067374853u, 0, 13, &be_const_str_json_fdump_list); -be_define_const_str(get_bat_voltage, "get_bat_voltage", 706676538u, 0, 15, &be_const_str_save_before_restart); -be_define_const_str(get_battery_chargin_status, "get_battery_chargin_status", 2233241571u, 0, 26, &be_const_str_split); +be_define_const_str(get_bat_charge_current, "get_bat_charge_current", 1385293050u, 0, 22, &be_const_str_introspect); +be_define_const_str(get_bat_current, "get_bat_current", 1912106073u, 0, 15, &be_const_str_rule); +be_define_const_str(get_bat_power, "get_bat_power", 3067374853u, 0, 13, &be_const_str_tcpclient); +be_define_const_str(get_bat_voltage, "get_bat_voltage", 706676538u, 0, 15, &be_const_str_invalidate); +be_define_const_str(get_battery_chargin_status, "get_battery_chargin_status", 2233241571u, 0, 26, &be_const_str_get_vbus_voltage); be_define_const_str(get_bri, "get_bri", 2041809895u, 0, 7, &be_const_str_math); +be_define_const_str(get_cb_list, "get_cb_list", 1605319182u, 0, 11, &be_const_str_reapply); be_define_const_str(get_coords, "get_coords", 1044089006u, 0, 10, &be_const_str_get_temp); -be_define_const_str(get_current_module_name, "get_current_module_name", 2379270740u, 0, 23, &be_const_str_get_width); -be_define_const_str(get_current_module_path, "get_current_module_path", 3206673408u, 0, 23, NULL); -be_define_const_str(get_free_heap, "get_free_heap", 625069757u, 0, 13, &be_const_str_push); -be_define_const_str(get_height, "get_height", 3571755523u, 0, 10, &be_const_str_ins_goto); +be_define_const_str(get_current_module_name, "get_current_module_name", 2379270740u, 0, 23, &be_const_str_public_key); +be_define_const_str(get_current_module_path, "get_current_module_path", 3206673408u, 0, 23, &be_const_str_web_add_button); +be_define_const_str(get_free_heap, "get_free_heap", 625069757u, 0, 13, &be_const_str_tasmota_X2Eget_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eget_X28_X29); +be_define_const_str(get_height, "get_height", 3571755523u, 0, 10, NULL); be_define_const_str(get_input_power_status, "get_input_power_status", 4102829177u, 0, 22, NULL); -be_define_const_str(get_light, "get_light", 381930476u, 0, 9, &be_const_str_setitem); -be_define_const_str(get_object_from_ptr, "get_object_from_ptr", 2345019201u, 0, 19, &be_const_str_log); +be_define_const_str(get_light, "get_light", 381930476u, 0, 9, &be_const_str_run_deferred); +be_define_const_str(get_object_from_ptr, "get_object_from_ptr", 2345019201u, 0, 19, &be_const_str_get_style_bg_color); be_define_const_str(get_option, "get_option", 2123730033u, 0, 10, NULL); -be_define_const_str(get_percentage, "get_percentage", 2880483992u, 0, 14, NULL); -be_define_const_str(get_pixel_color, "get_pixel_color", 337490048u, 0, 15, NULL); -be_define_const_str(get_power, "get_power", 3009799377u, 0, 9, &be_const_str_open); -be_define_const_str(get_size, "get_size", 2803644713u, 0, 8, NULL); -be_define_const_str(get_string, "get_string", 4195847969u, 0, 10, NULL); -be_define_const_str(get_style_bg_color, "get_style_bg_color", 964794381u, 0, 18, &be_const_str_r); -be_define_const_str(get_style_line_color, "get_style_line_color", 805371932u, 0, 20, &be_const_str_time_str); -be_define_const_str(get_style_pad_right, "get_style_pad_right", 3150287466u, 0, 19, NULL); -be_define_const_str(get_switch, "get_switch", 164821028u, 0, 10, &be_const_str_isrunning); -be_define_const_str(get_tasmota, "get_tasmota", 334356779u, 0, 11, &be_const_str_getbits); +be_define_const_str(get_percentage, "get_percentage", 2880483992u, 0, 14, &be_const_str_int); +be_define_const_str(get_pixel_color, "get_pixel_color", 337490048u, 0, 15, &be_const_str_pop_path); +be_define_const_str(get_power, "get_power", 3009799377u, 0, 9, NULL); +be_define_const_str(get_size, "get_size", 2803644713u, 0, 8, &be_const_str_obj_event_base); +be_define_const_str(get_string, "get_string", 4195847969u, 0, 10, &be_const_str_the_X20second_X20argument_X20is_X20not_X20a_X20function); +be_define_const_str(get_style_bg_color, "get_style_bg_color", 964794381u, 0, 18, &be_const_str_get_warning_level); +be_define_const_str(get_style_line_color, "get_style_line_color", 805371932u, 0, 20, &be_const_str_pi); +be_define_const_str(get_style_pad_right, "get_style_pad_right", 3150287466u, 0, 19, &be_const_str_else); +be_define_const_str(get_switch, "get_switch", 164821028u, 0, 10, NULL); be_define_const_str(get_temp, "get_temp", 3370919486u, 0, 8, NULL); -be_define_const_str(get_vbus_current, "get_vbus_current", 1205347942u, 0, 16, &be_const_str_while); -be_define_const_str(get_vbus_voltage, "get_vbus_voltage", 2398210401u, 0, 16, &be_const_str_return_X20code_X3D_X25i); -be_define_const_str(get_warning_level, "get_warning_level", 1737834441u, 0, 17, &be_const_str_map); -be_define_const_str(get_width, "get_width", 3293417300u, 0, 9, NULL); -be_define_const_str(getbits, "getbits", 3094168979u, 0, 7, &be_const_str_tag); -be_define_const_str(geti, "geti", 2381006490u, 0, 4, &be_const_str_k); -be_define_const_str(global, "global", 503252654u, 0, 6, &be_const_str_widget_constructor); -be_define_const_str(gpio, "gpio", 2638155258u, 0, 4, &be_const_str_line_dsc); -be_define_const_str(group_def, "group_def", 1524213328u, 0, 9, &be_const_str_web_send); -be_define_const_str(h, "h", 3977000791u, 0, 1, &be_const_str_value_error); -be_define_const_str(has, "has", 3988721635u, 0, 3, NULL); +be_define_const_str(get_vbus_current, "get_vbus_current", 1205347942u, 0, 16, NULL); +be_define_const_str(get_vbus_voltage, "get_vbus_voltage", 2398210401u, 0, 16, NULL); +be_define_const_str(get_warning_level, "get_warning_level", 1737834441u, 0, 17, &be_const_str_true); +be_define_const_str(get_width, "get_width", 3293417300u, 0, 9, &be_const_str_quality); +be_define_const_str(getbits, "getbits", 3094168979u, 0, 7, &be_const_str_set_bri); +be_define_const_str(geti, "geti", 2381006490u, 0, 4, &be_const_str_log10); +be_define_const_str(global, "global", 503252654u, 0, 6, &be_const_str_udp); +be_define_const_str(gpio, "gpio", 2638155258u, 0, 4, &be_const_str_no_X20GPIO_X20specified_X20for_X20neopixelbus); +be_define_const_str(group_def, "group_def", 1524213328u, 0, 9, NULL); +be_define_const_str(h, "h", 3977000791u, 0, 1, NULL); +be_define_const_str(has, "has", 3988721635u, 0, 3, &be_const_str_lv_module_init); +be_define_const_str(has_X20already_X20an_X20event_X20callback, "has already an event callback", 2421565249u, 0, 29, NULL); be_define_const_str(has_arg, "has_arg", 424878688u, 0, 7, &be_const_str_rad); -be_define_const_str(height_def, "height_def", 2348238838u, 0, 10, &be_const_str_wire2); -be_define_const_str(hex, "hex", 4273249610u, 0, 3, &be_const_str_register_obj); -be_define_const_str(hour, "hour", 3053661199u, 0, 4, &be_const_str_widget_ctor_impl); +be_define_const_str(height_def, "height_def", 2348238838u, 0, 10, NULL); +be_define_const_str(hex, "hex", 4273249610u, 0, 3, &be_const_str_lv_solidified); +be_define_const_str(hour, "hour", 3053661199u, 0, 4, &be_const_str_traceback); be_define_const_str(hs2rgb, "hs2rgb", 1040816349u, 0, 6, NULL); -be_define_const_str(https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_X2F_X25s_X2Eautoconf, "https://raw.githubusercontent.com/tasmota/autoconf/main/%s/%s.autoconf", 2743526309u, 0, 70, NULL); -be_define_const_str(https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_manifest_X2Ejson, "https://raw.githubusercontent.com/tasmota/autoconf/main/%s_manifest.json", 3657552045u, 0, 72, NULL); -be_define_const_str(i2c_enabled, "i2c_enabled", 218388101u, 0, 11, &be_const_str_keys); -be_define_const_str(id, "id", 926444256u, 0, 2, &be_const_str_print); +be_define_const_str(https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_X2F_X25s_X2Eautoconf, "https://raw.githubusercontent.com/tasmota/autoconf/main/%s/%s.autoconf", 2743526309u, 0, 70, &be_const_str_lv_wifi_arcs_icon); +be_define_const_str(https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_manifest_X2Ejson, "https://raw.githubusercontent.com/tasmota/autoconf/main/%s_manifest.json", 3657552045u, 0, 72, &be_const_str_web_add_config_button); +be_define_const_str(i2c_enabled, "i2c_enabled", 218388101u, 0, 11, NULL); +be_define_const_str(id, "id", 926444256u, 0, 2, NULL); be_define_const_str(if, "if", 959999494u, 50, 2, NULL); -be_define_const_str(imax, "imax", 3084515410u, 0, 4, NULL); +be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_read32); be_define_const_str(imin, "imin", 2714127864u, 0, 4, &be_const_str_members); be_define_const_str(import, "import", 288002260u, 66, 6, NULL); -be_define_const_str(init, "init", 380752755u, 0, 4, NULL); -be_define_const_str(init_draw_line_dsc, "init_draw_line_dsc", 2507936040u, 0, 18, &be_const_str_pop); -be_define_const_str(input, "input", 4191711099u, 0, 5, &be_const_str_json); +be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_raise); +be_define_const_str(init_draw_line_dsc, "init_draw_line_dsc", 2507936040u, 0, 18, &be_const_str_widget_ctor_cb); +be_define_const_str(input, "input", 4191711099u, 0, 5, &be_const_str_read); be_define_const_str(ins_goto, "ins_goto", 1342843963u, 0, 8, NULL); -be_define_const_str(ins_ramp, "ins_ramp", 1068049360u, 0, 8, &be_const_str_wire_scan); -be_define_const_str(ins_time, "ins_time", 2980245553u, 0, 8, &be_const_str_target_search); -be_define_const_str(insert, "insert", 3332609576u, 0, 6, NULL); +be_define_const_str(ins_ramp, "ins_ramp", 1068049360u, 0, 8, &be_const_str_break); +be_define_const_str(ins_time, "ins_time", 2980245553u, 0, 8, NULL); +be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_lv_event_cb); be_define_const_str(instance, "instance", 193386898u, 0, 8, NULL); -be_define_const_str(instance_size, "instance_size", 4280269518u, 0, 13, NULL); +be_define_const_str(instance_X20required, "instance required", 381192159u, 0, 17, NULL); +be_define_const_str(instance_size, "instance_size", 4280269518u, 0, 13, &be_const_str_value); be_define_const_str(int, "int", 2515107422u, 0, 3, NULL); -be_define_const_str(internal_error, "internal_error", 2519158169u, 0, 14, &be_const_str_offseta); -be_define_const_str(introspect, "introspect", 164638290u, 0, 10, &be_const_str_widget_dtor_impl); -be_define_const_str(invalidate, "invalidate", 2649734928u, 0, 10, &be_const_str_no_X20GPIO_X20specified_X20for_X20neopixelbus); -be_define_const_str(io_error, "io_error", 1970281036u, 0, 8, &be_const_str_readbytes); -be_define_const_str(ip, "ip", 1261996636u, 0, 2, &be_const_str_super); -be_define_const_str(is_dirty, "is_dirty", 418034110u, 0, 8, &be_const_str_rand); -be_define_const_str(is_first_time, "is_first_time", 275242384u, 0, 13, &be_const_str_local); +be_define_const_str(internal_error, "internal_error", 2519158169u, 0, 14, NULL); +be_define_const_str(introspect, "introspect", 164638290u, 0, 10, &be_const_str_k); +be_define_const_str(invalidate, "invalidate", 2649734928u, 0, 10, NULL); +be_define_const_str(io_error, "io_error", 1970281036u, 0, 8, &be_const_str_rtc); +be_define_const_str(ip, "ip", 1261996636u, 0, 2, &be_const_str_readbytes); +be_define_const_str(is_dirty, "is_dirty", 418034110u, 0, 8, &be_const_str_wire_scan); +be_define_const_str(is_first_time, "is_first_time", 275242384u, 0, 13, NULL); be_define_const_str(is_running, "is_running", 2226847261u, 0, 10, &be_const_str_reverse); -be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, NULL); -be_define_const_str(isnan, "isnan", 2981347434u, 0, 5, NULL); -be_define_const_str(isrunning, "isrunning", 1688182268u, 0, 9, &be_const_str_refr_size); -be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, NULL); -be_define_const_str(item, "item", 2671260646u, 0, 4, &be_const_str_widget_editable); -be_define_const_str(iter, "iter", 3124256359u, 0, 4, &be_const_str_class); +be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, &be_const_str_wire2); +be_define_const_str(ismethod, "ismethod", 3513438880u, 0, 8, NULL); +be_define_const_str(isnan, "isnan", 2981347434u, 0, 5, &be_const_str_wifi_arcs_icon); +be_define_const_str(isrunning, "isrunning", 1688182268u, 0, 9, &be_const_str_length_X20in_X20bits_X20must_X20be_X20between_X200_X20and_X2032); +be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, &be_const_str_loop); +be_define_const_str(item, "item", 2671260646u, 0, 4, &be_const_str_settings); +be_define_const_str(iter, "iter", 3124256359u, 0, 4, NULL); be_define_const_str(json, "json", 916562499u, 0, 4, NULL); be_define_const_str(json_append, "json_append", 3002019284u, 0, 11, NULL); -be_define_const_str(json_fdump, "json_fdump", 1694216580u, 0, 10, &be_const_str_nil); -be_define_const_str(json_fdump_any, "json_fdump_any", 3348629385u, 0, 14, &be_const_str_pixel_size); -be_define_const_str(json_fdump_list, "json_fdump_list", 3903879853u, 0, 15, &be_const_str_json_fdump_map); -be_define_const_str(json_fdump_map, "json_fdump_map", 4091954653u, 0, 14, &be_const_str_select); -be_define_const_str(k, "k", 3993778410u, 0, 1, &be_const_str_set_auth); +be_define_const_str(json_fdump, "json_fdump", 1694216580u, 0, 10, NULL); +be_define_const_str(json_fdump_any, "json_fdump_any", 3348629385u, 0, 14, NULL); +be_define_const_str(json_fdump_list, "json_fdump_list", 3903879853u, 0, 15, &be_const_str_lv_wifi_arcs); +be_define_const_str(json_fdump_map, "json_fdump_map", 4091954653u, 0, 14, &be_const_str_load_templates); +be_define_const_str(k, "k", 3993778410u, 0, 1, &be_const_str_read12); be_define_const_str(keys, "keys", 4182378701u, 0, 4, NULL); -be_define_const_str(kv, "kv", 1497177492u, 0, 2, &be_const_str_persist_X2E_p_X20is_X20not_X20a_X20map); -be_define_const_str(last_modified, "last_modified", 772177145u, 0, 13, NULL); -be_define_const_str(leds, "leds", 558858555u, 0, 4, &be_const_str__X7Bs_X7DVBus_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D); -be_define_const_str(length_X20in_X20bits_X20must_X20be_X20between_X200_X20and_X2032, "length in bits must be between 0 and 32", 2584509128u, 0, 39, &be_const_str_lv_event); -be_define_const_str(light, "light", 3801947695u, 0, 5, NULL); -be_define_const_str(line_dsc, "line_dsc", 4094490978u, 0, 8, &be_const_str_offset); +be_define_const_str(kv, "kv", 1497177492u, 0, 2, &be_const_str_reverse_gamma10); +be_define_const_str(last_modified, "last_modified", 772177145u, 0, 13, &be_const_str_min); +be_define_const_str(leds, "leds", 558858555u, 0, 4, &be_const_str_url_encode); +be_define_const_str(length_X20in_X20bits_X20must_X20be_X20between_X200_X20and_X2032, "length in bits must be between 0 and 32", 2584509128u, 0, 39, &be_const_str_lv_point_arr); +be_define_const_str(light, "light", 3801947695u, 0, 5, &be_const_str_tostring); +be_define_const_str(line_dsc, "line_dsc", 4094490978u, 0, 8, &be_const_str_sec); be_define_const_str(list, "list", 217798785u, 0, 4, NULL); +be_define_const_str(list_handlers, "list_handlers", 593774371u, 0, 13, &be_const_str_widget_event_impl); be_define_const_str(listdir, "listdir", 2005220720u, 0, 7, NULL); -be_define_const_str(load, "load", 3859241449u, 0, 4, NULL); -be_define_const_str(load_templates, "load_templates", 3513870133u, 0, 14, NULL); -be_define_const_str(local, "local", 2621662984u, 0, 5, &be_const_str_round_start); -be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_read_sensors); -be_define_const_str(log10, "log10", 2346846000u, 0, 5, NULL); -be_define_const_str(loop, "loop", 3723446379u, 0, 4, NULL); -be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_end); -be_define_const_str(lv, "lv", 1529997255u, 0, 2, &be_const_str_x); +be_define_const_str(load, "load", 3859241449u, 0, 4, &be_const_str_lv_obj); +be_define_const_str(load_freetype_font, "load_freetype_font", 2368447592u, 0, 18, NULL); +be_define_const_str(load_templates, "load_templates", 3513870133u, 0, 14, &be_const_str_resp_cmnd_error); +be_define_const_str(local, "local", 2621662984u, 0, 5, NULL); +be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_set_ldo_enable); +be_define_const_str(log10, "log10", 2346846000u, 0, 5, &be_const_str__X7Bs_X7DVBus_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D); +be_define_const_str(loop, "loop", 3723446379u, 0, 4, &be_const_str_seg7_font); +be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_lv_point); +be_define_const_str(lv, "lv", 1529997255u, 0, 2, NULL); +be_define_const_str(lv_, "lv_", 663721032u, 0, 3, NULL); +be_define_const_str(lv_clock_icon, "lv_clock_icon", 3257216210u, 0, 13, &be_const_str_nan); +be_define_const_str(lv_coord_arr, "lv_coord_arr", 1197238601u, 0, 12, NULL); be_define_const_str(lv_event, "lv_event", 2434089968u, 0, 8, &be_const_str_remove_rule); -be_define_const_str(lv_event_cb, "lv_event_cb", 2480731016u, 0, 11, &be_const_str_run_deferred); -be_define_const_str(lv_obj, "lv_obj", 4257833149u, 0, 6, &be_const_str_traceback); +be_define_const_str(lv_event_cb, "lv_event_cb", 2480731016u, 0, 11, NULL); +be_define_const_str(lv_extra, "lv_extra", 399561998u, 0, 8, NULL); +be_define_const_str(lv_module_init, "lv_module_init", 1133027755u, 0, 14, NULL); +be_define_const_str(lv_obj, "lv_obj", 4257833149u, 0, 6, NULL); be_define_const_str(lv_obj_class, "lv_obj_class", 4039656294u, 0, 12, NULL); -be_define_const_str(lvgl_event_dispatch, "lvgl_event_dispatch", 2104396622u, 0, 19, &be_const_str_set_matrix_pixel_color); -be_define_const_str(map, "map", 3751997361u, 0, 3, &be_const_str_redirect); +be_define_const_str(lv_point, "lv_point", 4120221790u, 0, 8, NULL); +be_define_const_str(lv_point_arr, "lv_point_arr", 3959768858u, 0, 12, NULL); +be_define_const_str(lv_signal_arcs, "lv_signal_arcs", 2839156988u, 0, 14, NULL); +be_define_const_str(lv_signal_bars, "lv_signal_bars", 3513972559u, 0, 14, NULL); +be_define_const_str(lv_solidified, "lv_solidified", 2274121310u, 0, 13, &be_const_str_set_channels); +be_define_const_str(lv_wifi_arcs, "lv_wifi_arcs", 2082091963u, 0, 12, &be_const_str_read13); +be_define_const_str(lv_wifi_arcs_icon, "lv_wifi_arcs_icon", 1507982909u, 0, 17, &be_const_str_offseta); +be_define_const_str(lv_wifi_bars, "lv_wifi_bars", 2109539196u, 0, 12, &be_const_str_webclient); +be_define_const_str(lv_wifi_bars_icon, "lv_wifi_bars_icon", 2805815540u, 0, 17, &be_const_str_null_cb); +be_define_const_str(lvgl_event_dispatch, "lvgl_event_dispatch", 2104396622u, 0, 19, NULL); +be_define_const_str(make_cb, "make_cb", 71252785u, 0, 7, NULL); +be_define_const_str(map, "map", 3751997361u, 0, 3, NULL); be_define_const_str(math, "math", 4001929615u, 0, 4, NULL); be_define_const_str(matrix, "matrix", 365099244u, 0, 6, NULL); be_define_const_str(member, "member", 719708611u, 0, 6, NULL); -be_define_const_str(members, "members", 937576464u, 0, 7, &be_const_str_target); -be_define_const_str(memory, "memory", 2229924270u, 0, 6, &be_const_str_resp_cmnd_str); -be_define_const_str(millis, "millis", 1214679063u, 0, 6, NULL); +be_define_const_str(members, "members", 937576464u, 0, 7, NULL); +be_define_const_str(memory, "memory", 2229924270u, 0, 6, &be_const_str_running); +be_define_const_str(millis, "millis", 1214679063u, 0, 6, &be_const_str_read_bytes); be_define_const_str(min, "min", 3381609815u, 0, 3, &be_const_str_widget_cb); -be_define_const_str(minute, "minute", 954666857u, 0, 6, NULL); -be_define_const_str(module, "module", 3617558685u, 0, 6, &be_const_str_percentage); -be_define_const_str(month, "month", 3598321157u, 0, 5, NULL); -be_define_const_str(name, "name", 2369371622u, 0, 4, NULL); +be_define_const_str(minute, "minute", 954666857u, 0, 6, &be_const_str_time_dump); +be_define_const_str(module, "module", 3617558685u, 0, 6, &be_const_str_x); +be_define_const_str(month, "month", 3598321157u, 0, 5, &be_const_str_out_X20of_X20range); +be_define_const_str(montserrat_font, "montserrat_font", 1819065874u, 0, 15, &be_const_str_round_start); +be_define_const_str(name, "name", 2369371622u, 0, 4, &be_const_str_web_add_handler); be_define_const_str(nan, "nan", 797905850u, 0, 3, NULL); be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL); -be_define_const_str(no_X20GPIO_X20specified_X20for_X20neopixelbus, "no GPIO specified for neopixelbus", 42078528u, 0, 33, &be_const_str_number); -be_define_const_str(null_cb, "null_cb", 2333536460u, 0, 7, &be_const_str_public_key); -be_define_const_str(number, "number", 467038368u, 0, 6, NULL); -be_define_const_str(obj_class_create_obj, "obj_class_create_obj", 3304390632u, 0, 20, &be_const_str_write_bytes); +be_define_const_str(no_X20GPIO_X20specified_X20for_X20neopixelbus, "no GPIO specified for neopixelbus", 42078528u, 0, 33, NULL); +be_define_const_str(null_cb, "null_cb", 2333536460u, 0, 7, &be_const_str_set_first_time); +be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_offset); +be_define_const_str(obj_class_create_obj, "obj_class_create_obj", 3304390632u, 0, 20, &be_const_str_tanh); be_define_const_str(obj_event_base, "obj_event_base", 1624064363u, 0, 14, NULL); -be_define_const_str(offset, "offset", 348705738u, 0, 6, &be_const_str_sec); -be_define_const_str(offseta, "offseta", 1663383089u, 0, 7, NULL); +be_define_const_str(offset, "offset", 348705738u, 0, 6, NULL); +be_define_const_str(offseta, "offseta", 1663383089u, 0, 7, &be_const_str_set_style_bg_color); be_define_const_str(on, "on", 1630810064u, 0, 2, NULL); -be_define_const_str(onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E, "onsubmit='return confirm(\"This will cause a restart.\");'>", 232646018u, 0, 57, NULL); -be_define_const_str(onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20change_X20the_X20current_X20configuration_X20and_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E, "onsubmit='return confirm(\"This will change the current configuration and cause a restart.\");'>", 3792412559u, 0, 94, &be_const_str_sqrt); +be_define_const_str(onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E, "onsubmit='return confirm(\"This will cause a restart.\");'>", 232646018u, 0, 57, &be_const_str_refr_size); +be_define_const_str(onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20change_X20the_X20current_X20configuration_X20and_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E, "onsubmit='return confirm(\"This will change the current configuration and cause a restart.\");'>", 3792412559u, 0, 94, NULL); be_define_const_str(open, "open", 3546203337u, 0, 4, NULL); be_define_const_str(out_X20of_X20range, "out of range", 2236631477u, 0, 12, NULL); -be_define_const_str(p1, "p1", 2689521274u, 0, 2, &be_const_str_widget_event_cb); -be_define_const_str(p2, "p2", 2672743655u, 0, 2, NULL); -be_define_const_str(page_autoconf_ctl, "page_autoconf_ctl", 2453381496u, 0, 17, &be_const_str_pc_rel); -be_define_const_str(page_autoconf_mgr, "page_autoconf_mgr", 3643937031u, 0, 17, &be_const_str_reduce); -be_define_const_str(param, "param", 1309554226u, 0, 5, &be_const_str_set_dcdc_enable); -be_define_const_str(path, "path", 2223459638u, 0, 4, &be_const_str_pop_path); -be_define_const_str(pc, "pc", 1313756516u, 0, 2, &be_const_str_zip); -be_define_const_str(pc_abs, "pc_abs", 920256495u, 0, 6, NULL); +be_define_const_str(p1, "p1", 2689521274u, 0, 2, NULL); +be_define_const_str(p2, "p2", 2672743655u, 0, 2, &be_const_str_widget_group_def); +be_define_const_str(page_autoconf_ctl, "page_autoconf_ctl", 2453381496u, 0, 17, &be_const_str_resp_cmnd); +be_define_const_str(page_autoconf_mgr, "page_autoconf_mgr", 3643937031u, 0, 17, &be_const_str_r); +be_define_const_str(param, "param", 1309554226u, 0, 5, &be_const_str_show); +be_define_const_str(path, "path", 2223459638u, 0, 4, NULL); +be_define_const_str(pc, "pc", 1313756516u, 0, 2, NULL); +be_define_const_str(pc_abs, "pc_abs", 920256495u, 0, 6, &be_const_str_resp_cmnd_done); be_define_const_str(pc_rel, "pc_rel", 991921176u, 0, 6, NULL); -be_define_const_str(percentage, "percentage", 2538831285u, 0, 10, &be_const_str_web_add_config_button); -be_define_const_str(persist, "persist", 3917083779u, 0, 7, NULL); -be_define_const_str(persist_X2E_p_X20is_X20not_X20a_X20map, "persist._p is not a map", 1176528732u, 0, 23, &be_const_str_publish_result); -be_define_const_str(pi, "pi", 1213090802u, 0, 2, &be_const_str_set_alternate); -be_define_const_str(pin, "pin", 1866532500u, 0, 3, &be_const_str_running); -be_define_const_str(pin_mode, "pin_mode", 3258314030u, 0, 8, &be_const_str_set_first_time); -be_define_const_str(pin_used, "pin_used", 4033854612u, 0, 8, &be_const_str_reapply); +be_define_const_str(percentage, "percentage", 2538831285u, 0, 10, NULL); +be_define_const_str(persist, "persist", 3917083779u, 0, 7, &be_const_str_set_height); +be_define_const_str(persist_X2E_p_X20is_X20not_X20a_X20map, "persist._p is not a map", 1176528732u, 0, 23, NULL); +be_define_const_str(pi, "pi", 1213090802u, 0, 2, &be_const_str_run); +be_define_const_str(pin, "pin", 1866532500u, 0, 3, &be_const_str_resp_cmnd_str); +be_define_const_str(pin_mode, "pin_mode", 3258314030u, 0, 8, NULL); +be_define_const_str(pin_used, "pin_used", 4033854612u, 0, 8, NULL); be_define_const_str(pixel_count, "pixel_count", 2439130743u, 0, 11, NULL); -be_define_const_str(pixel_size, "pixel_size", 2209135785u, 0, 10, NULL); -be_define_const_str(pixels_buffer, "pixels_buffer", 1229555807u, 0, 13, NULL); -be_define_const_str(point, "point", 414084241u, 0, 5, &be_const_str_setmember); -be_define_const_str(pop, "pop", 1362321360u, 0, 3, NULL); +be_define_const_str(pixel_size, "pixel_size", 2209135785u, 0, 10, &be_const_str_resolvecmnd); +be_define_const_str(pixels_buffer, "pixels_buffer", 1229555807u, 0, 13, &be_const_str_return); +be_define_const_str(point, "point", 414084241u, 0, 5, &be_const_str_real); +be_define_const_str(point_arr, "point_arr", 1140859857u, 0, 9, NULL); +be_define_const_str(pop, "pop", 1362321360u, 0, 3, &be_const_str_set_auth); be_define_const_str(pop_path, "pop_path", 2403243998u, 0, 8, NULL); be_define_const_str(pow, "pow", 1479764693u, 0, 3, NULL); be_define_const_str(preinit, "preinit", 2722007100u, 0, 7, NULL); -be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_else); -be_define_const_str(public_key, "public_key", 4169142980u, 0, 10, &be_const_str_continue); -be_define_const_str(publish, "publish", 264247304u, 0, 7, &be_const_str_web_add_main_button); -be_define_const_str(publish_result, "publish_result", 2013351252u, 0, 14, &be_const_str_set_x); -be_define_const_str(push, "push", 2272264157u, 0, 4, &be_const_str_stop); +be_define_const_str(print, "print", 372738696u, 0, 5, NULL); +be_define_const_str(public_key, "public_key", 4169142980u, 0, 10, &be_const_str_tob64); +be_define_const_str(publish, "publish", 264247304u, 0, 7, NULL); +be_define_const_str(publish_result, "publish_result", 2013351252u, 0, 14, &be_const_str_except); +be_define_const_str(push, "push", 2272264157u, 0, 4, NULL); be_define_const_str(push_path, "push_path", 1155254157u, 0, 9, NULL); -be_define_const_str(quality, "quality", 2597670950u, 0, 7, NULL); -be_define_const_str(r, "r", 4144776981u, 0, 1, &be_const_str_tele); -be_define_const_str(rad, "rad", 1358899048u, 0, 3, NULL); +be_define_const_str(quality, "quality", 2597670950u, 0, 7, &be_const_str_register_obj); +be_define_const_str(r, "r", 4144776981u, 0, 1, &be_const_str_response_append); +be_define_const_str(rad, "rad", 1358899048u, 0, 3, &be_const_str_set_rate); be_define_const_str(raise, "raise", 1593437475u, 70, 5, NULL); be_define_const_str(rand, "rand", 2711325910u, 0, 4, NULL); -be_define_const_str(range, "range", 4208725202u, 0, 5, &be_const_str_web_add_handler); +be_define_const_str(range, "range", 4208725202u, 0, 5, &be_const_str_time_str); be_define_const_str(read, "read", 3470762949u, 0, 4, NULL); -be_define_const_str(read12, "read12", 4291076970u, 0, 6, NULL); -be_define_const_str(read13, "read13", 12887293u, 0, 6, &be_const_str_set_timer); +be_define_const_str(read12, "read12", 4291076970u, 0, 6, &be_const_str_widget_dtor_impl); +be_define_const_str(read13, "read13", 12887293u, 0, 6, &be_const_str_target_search); be_define_const_str(read24, "read24", 1808533811u, 0, 6, NULL); -be_define_const_str(read32, "read32", 1741276240u, 0, 6, &be_const_str_break); -be_define_const_str(read8, "read8", 2802788167u, 0, 5, &be_const_str_readline); +be_define_const_str(read32, "read32", 1741276240u, 0, 6, &be_const_str_send_multicast); +be_define_const_str(read8, "read8", 2802788167u, 0, 5, &be_const_str_remote_port); be_define_const_str(read_bytes, "read_bytes", 3576733173u, 0, 10, &be_const_str_type); -be_define_const_str(read_sensors, "read_sensors", 892689201u, 0, 12, NULL); -be_define_const_str(readbytes, "readbytes", 2716426756u, 0, 9, &be_const_str_show); -be_define_const_str(readline, "readline", 1212709927u, 0, 8, &be_const_str_solidified); -be_define_const_str(real, "real", 3604983901u, 0, 4, &be_const_str__X7B_X7D); -be_define_const_str(reapply, "reapply", 3778939332u, 0, 7, NULL); +be_define_const_str(read_sensors, "read_sensors", 892689201u, 0, 12, &be_const_str_strftime); +be_define_const_str(readbytes, "readbytes", 2716426756u, 0, 9, NULL); +be_define_const_str(readline, "readline", 1212709927u, 0, 8, NULL); +be_define_const_str(real, "real", 3604983901u, 0, 4, NULL); +be_define_const_str(reapply, "reapply", 3778939332u, 0, 7, &be_const_str_resp_cmnd_failed); be_define_const_str(redirect, "redirect", 389758641u, 0, 8, NULL); -be_define_const_str(reduce, "reduce", 2002030311u, 0, 6, NULL); -be_define_const_str(refr_size, "refr_size", 1958144468u, 0, 9, NULL); +be_define_const_str(refr_size, "refr_size", 1958144468u, 0, 9, &be_const_str_run_bat); +be_define_const_str(register_button_encoder, "register_button_encoder", 2811301550u, 0, 23, &be_const_str_set_ldo_voltage); be_define_const_str(register_obj, "register_obj", 3982614770u, 0, 12, NULL); +be_define_const_str(remote_ip, "remote_ip", 2953154693u, 0, 9, &be_const_str_srand); +be_define_const_str(remote_port, "remote_port", 2163585967u, 0, 11, &be_const_str_wifi_bars_icon); be_define_const_str(remove, "remove", 3683784189u, 0, 6, NULL); be_define_const_str(remove_cmd, "remove_cmd", 3832315702u, 0, 10, NULL); -be_define_const_str(remove_driver, "remove_driver", 1030243768u, 0, 13, &be_const_str_string); +be_define_const_str(remove_driver, "remove_driver", 1030243768u, 0, 13, NULL); be_define_const_str(remove_rule, "remove_rule", 3456211328u, 0, 11, NULL); be_define_const_str(remove_timer, "remove_timer", 4141472215u, 0, 12, NULL); -be_define_const_str(reset, "reset", 1695364032u, 0, 5, NULL); -be_define_const_str(reset_search, "reset_search", 1350414305u, 0, 12, &be_const_str_widget_destructor); +be_define_const_str(reset, "reset", 1695364032u, 0, 5, &be_const_str_set_x); +be_define_const_str(reset_search, "reset_search", 1350414305u, 0, 12, &be_const_str_widget_dtor_cb); be_define_const_str(resize, "resize", 3514612129u, 0, 6, NULL); be_define_const_str(resolvecmnd, "resolvecmnd", 993361485u, 0, 11, NULL); -be_define_const_str(resp_cmnd, "resp_cmnd", 2869459626u, 0, 9, &be_const_str_web_add_management_button); -be_define_const_str(resp_cmnd_done, "resp_cmnd_done", 2601874875u, 0, 14, &be_const_str_raise); +be_define_const_str(resp_cmnd, "resp_cmnd", 2869459626u, 0, 9, NULL); +be_define_const_str(resp_cmnd_done, "resp_cmnd_done", 2601874875u, 0, 14, NULL); be_define_const_str(resp_cmnd_error, "resp_cmnd_error", 2404088863u, 0, 15, NULL); -be_define_const_str(resp_cmnd_failed, "resp_cmnd_failed", 2136281562u, 0, 16, NULL); -be_define_const_str(resp_cmnd_str, "resp_cmnd_str", 737845590u, 0, 13, NULL); -be_define_const_str(response_append, "response_append", 450346371u, 0, 15, NULL); +be_define_const_str(resp_cmnd_failed, "resp_cmnd_failed", 2136281562u, 0, 16, &be_const_str_rotate); +be_define_const_str(resp_cmnd_str, "resp_cmnd_str", 737845590u, 0, 13, &be_const_str_state); +be_define_const_str(response_append, "response_append", 450346371u, 0, 15, &be_const_str_return_X20code_X3D_X25i); be_define_const_str(return, "return", 2246981567u, 60, 6, NULL); -be_define_const_str(return_X20code_X3D_X25i, "return code=%i", 2127454401u, 0, 14, &be_const_str_set_ldo_enable); -be_define_const_str(reverse, "reverse", 558918661u, 0, 7, &be_const_str_sin); -be_define_const_str(reverse_gamma10, "reverse_gamma10", 739112262u, 0, 15, &be_const_str_to_gamma); -be_define_const_str(rotate, "rotate", 2784296202u, 0, 6, NULL); +be_define_const_str(return_X20code_X3D_X25i, "return code=%i", 2127454401u, 0, 14, NULL); +be_define_const_str(reverse, "reverse", 558918661u, 0, 7, &be_const_str_screenshot); +be_define_const_str(reverse_gamma10, "reverse_gamma10", 739112262u, 0, 15, NULL); +be_define_const_str(rotate, "rotate", 2784296202u, 0, 6, &be_const_str_widget_width_def); be_define_const_str(round_end, "round_end", 985288225u, 0, 9, NULL); -be_define_const_str(round_start, "round_start", 2949484384u, 0, 11, &be_const_str_wire); -be_define_const_str(rtc, "rtc", 1070575216u, 0, 3, &be_const_str_settings); +be_define_const_str(round_start, "round_start", 2949484384u, 0, 11, &be_const_str_widget_event_cb); +be_define_const_str(rtc, "rtc", 1070575216u, 0, 3, &be_const_str_set_style_line_color); be_define_const_str(rule, "rule", 4230889683u, 0, 4, NULL); -be_define_const_str(run, "run", 718098122u, 0, 3, NULL); +be_define_const_str(run, "run", 718098122u, 0, 3, &be_const_str_do); be_define_const_str(run_bat, "run_bat", 2536903298u, 0, 7, NULL); be_define_const_str(run_deferred, "run_deferred", 371594696u, 0, 12, NULL); be_define_const_str(running, "running", 343848780u, 0, 7, NULL); -be_define_const_str(save, "save", 3439296072u, 0, 4, &be_const_str_tanh); +be_define_const_str(save, "save", 3439296072u, 0, 4, NULL); be_define_const_str(save_before_restart, "save_before_restart", 1253239338u, 0, 19, NULL); -be_define_const_str(scale_uint, "scale_uint", 3090811094u, 0, 10, &be_const_str_set_style_pad_right); +be_define_const_str(scale_uint, "scale_uint", 3090811094u, 0, 10, &be_const_str_write); be_define_const_str(scan, "scan", 3974641896u, 0, 4, &be_const_str_set_dc_voltage); +be_define_const_str(screenshot, "screenshot", 3894592561u, 0, 10, &be_const_str_setmember); be_define_const_str(search, "search", 2150836393u, 0, 6, NULL); be_define_const_str(sec, "sec", 3139892658u, 0, 3, NULL); be_define_const_str(seg7_font, "seg7_font", 4099690689u, 0, 9, NULL); be_define_const_str(select, "select", 297952813u, 0, 6, NULL); -be_define_const_str(serial, "serial", 3687697785u, 0, 6, &be_const_str_url_encode); +be_define_const_str(send, "send", 1919010991u, 0, 4, NULL); +be_define_const_str(send_multicast, "send_multicast", 812185870u, 0, 14, NULL); +be_define_const_str(serial, "serial", 3687697785u, 0, 6, NULL); be_define_const_str(set, "set", 3324446467u, 0, 3, NULL); -be_define_const_str(set_alternate, "set_alternate", 1709680562u, 0, 13, &be_const_str_widget_struct_by_class); +be_define_const_str(set_alternate, "set_alternate", 1709680562u, 0, 13, &be_const_str_set_pwm); be_define_const_str(set_auth, "set_auth", 1057170930u, 0, 8, NULL); -be_define_const_str(set_bri, "set_bri", 2789118779u, 0, 7, &be_const_str_wire1); +be_define_const_str(set_bits_per_sample, "set_bits_per_sample", 3747657551u, 0, 19, NULL); +be_define_const_str(set_bri, "set_bri", 2789118779u, 0, 7, NULL); +be_define_const_str(set_channels, "set_channels", 1370190620u, 0, 12, NULL); be_define_const_str(set_chg_current, "set_chg_current", 336304386u, 0, 15, NULL); -be_define_const_str(set_dc_voltage, "set_dc_voltage", 2181981936u, 0, 14, &be_const_str_toupper); -be_define_const_str(set_dcdc_enable, "set_dcdc_enable", 1594690786u, 0, 15, &be_const_str_tomap); -be_define_const_str(set_first_time, "set_first_time", 3111247550u, 0, 14, NULL); -be_define_const_str(set_height, "set_height", 1080207399u, 0, 10, &be_const_str_width_def); +be_define_const_str(set_dc_voltage, "set_dc_voltage", 2181981936u, 0, 14, NULL); +be_define_const_str(set_dcdc_enable, "set_dcdc_enable", 1594690786u, 0, 15, &be_const_str_widget_event); +be_define_const_str(set_first_time, "set_first_time", 3111247550u, 0, 14, &be_const_str__X7D); +be_define_const_str(set_gain, "set_gain", 3847781975u, 0, 8, &be_const_str_set_text); +be_define_const_str(set_height, "set_height", 1080207399u, 0, 10, NULL); be_define_const_str(set_ldo_enable, "set_ldo_enable", 2916502041u, 0, 14, NULL); -be_define_const_str(set_ldo_voltage, "set_ldo_voltage", 4090501160u, 0, 15, &be_const_str_tob64); -be_define_const_str(set_light, "set_light", 3176076152u, 0, 9, &be_const_str_setrange); +be_define_const_str(set_ldo_voltage, "set_ldo_voltage", 4090501160u, 0, 15, &be_const_str_set_width); +be_define_const_str(set_light, "set_light", 3176076152u, 0, 9, &be_const_str_set_matrix_pixel_color); be_define_const_str(set_matrix_pixel_color, "set_matrix_pixel_color", 1197149462u, 0, 22, NULL); -be_define_const_str(set_percentage, "set_percentage", 2952022724u, 0, 14, NULL); -be_define_const_str(set_pixel_color, "set_pixel_color", 1275248356u, 0, 15, NULL); -be_define_const_str(set_power, "set_power", 549820893u, 0, 9, &be_const_str_widget_height_def); -be_define_const_str(set_style_bg_color, "set_style_bg_color", 1689513089u, 0, 18, NULL); +be_define_const_str(set_percentage, "set_percentage", 2952022724u, 0, 14, &be_const_str_sys); +be_define_const_str(set_pixel_color, "set_pixel_color", 1275248356u, 0, 15, &be_const_str_tomap); +be_define_const_str(set_power, "set_power", 549820893u, 0, 9, NULL); +be_define_const_str(set_pwm, "set_pwm", 3781811012u, 0, 7, NULL); +be_define_const_str(set_rate, "set_rate", 1154016838u, 0, 8, &be_const_str_web_send); +be_define_const_str(set_style_bg_color, "set_style_bg_color", 1689513089u, 0, 18, &be_const_str_sqrt); be_define_const_str(set_style_line_color, "set_style_line_color", 3665238976u, 0, 20, NULL); be_define_const_str(set_style_pad_right, "set_style_pad_right", 3314069054u, 0, 19, NULL); -be_define_const_str(set_style_text_font, "set_style_text_font", 1028590019u, 0, 19, NULL); +be_define_const_str(set_style_text_font, "set_style_text_font", 1028590019u, 0, 19, &be_const_str_tag); be_define_const_str(set_text, "set_text", 1849641155u, 0, 8, NULL); be_define_const_str(set_time, "set_time", 900236405u, 0, 8, NULL); -be_define_const_str(set_timeouts, "set_timeouts", 3732850900u, 0, 12, &be_const_str_import); +be_define_const_str(set_timeouts, "set_timeouts", 3732850900u, 0, 12, NULL); be_define_const_str(set_timer, "set_timer", 2135414533u, 0, 9, NULL); be_define_const_str(set_useragent, "set_useragent", 612237244u, 0, 13, NULL); -be_define_const_str(set_width, "set_width", 484671920u, 0, 9, &be_const_str__X7D); -be_define_const_str(set_x, "set_x", 1849400772u, 0, 5, &be_const_str_def); +be_define_const_str(set_width, "set_width", 484671920u, 0, 9, &be_const_str_continue); +be_define_const_str(set_x, "set_x", 1849400772u, 0, 5, NULL); be_define_const_str(set_y, "set_y", 1866178391u, 0, 5, NULL); be_define_const_str(setbits, "setbits", 2762408167u, 0, 7, NULL); -be_define_const_str(seti, "seti", 1500556254u, 0, 4, NULL); +be_define_const_str(seti, "seti", 1500556254u, 0, 4, &be_const_str_shared_key); be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, NULL); -be_define_const_str(setmember, "setmember", 1432909441u, 0, 9, &be_const_str_strptime); -be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, NULL); -be_define_const_str(settings, "settings", 1745255176u, 0, 8, NULL); -be_define_const_str(shared_key, "shared_key", 2200833624u, 0, 10, &be_const_str_wifi); -be_define_const_str(show, "show", 2840060476u, 0, 4, &be_const_str_y); +be_define_const_str(setmember, "setmember", 1432909441u, 0, 9, NULL); +be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, &be_const_str_widget_struct_by_class); +be_define_const_str(settings, "settings", 1745255176u, 0, 8, &be_const_str_year); +be_define_const_str(shared_key, "shared_key", 2200833624u, 0, 10, NULL); +be_define_const_str(show, "show", 2840060476u, 0, 4, NULL); +be_define_const_str(signal_arcs, "signal_arcs", 1505996127u, 0, 11, &be_const_str_upper); +be_define_const_str(signal_bars, "signal_bars", 3181573600u, 0, 11, NULL); be_define_const_str(sin, "sin", 3761252941u, 0, 3, NULL); -be_define_const_str(sinh, "sinh", 282220607u, 0, 4, &be_const_str_tasmota_X2Eget_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eget_X28_X29); +be_define_const_str(sinh, "sinh", 282220607u, 0, 4, &be_const_str_stop); be_define_const_str(size, "size", 597743964u, 0, 4, NULL); -be_define_const_str(skip, "skip", 1097563074u, 0, 4, NULL); +be_define_const_str(skip, "skip", 1097563074u, 0, 4, &be_const_str_web_send_decimal); be_define_const_str(solidified, "solidified", 3257553487u, 0, 10, NULL); -be_define_const_str(split, "split", 2276994531u, 0, 5, &be_const_str_strftime); +be_define_const_str(split, "split", 2276994531u, 0, 5, NULL); be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, NULL); -be_define_const_str(srand, "srand", 465518633u, 0, 5, NULL); +be_define_const_str(srand, "srand", 465518633u, 0, 5, &be_const_str_time_reached); be_define_const_str(start, "start", 1697318111u, 0, 5, NULL); -be_define_const_str(state, "state", 2016490230u, 0, 5, NULL); +be_define_const_str(state, "state", 2016490230u, 0, 5, &be_const_str_for); be_define_const_str(static, "static", 3532702267u, 71, 6, NULL); be_define_const_str(stop, "stop", 3411225317u, 0, 4, NULL); -be_define_const_str(stop_iteration, "stop_iteration", 4173793901u, 0, 14, NULL); +be_define_const_str(stop_iteration, "stop_iteration", 4173793901u, 0, 14, &be_const_str_tasmota_X2Eset_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eset_X28_X29); be_define_const_str(str, "str", 3259748752u, 0, 3, NULL); be_define_const_str(strftime, "strftime", 187738851u, 0, 8, NULL); -be_define_const_str(string, "string", 398550328u, 0, 6, NULL); +be_define_const_str(string, "string", 398550328u, 0, 6, &be_const_str_wd); be_define_const_str(strip, "strip", 4246411473u, 0, 5, NULL); -be_define_const_str(strptime, "strptime", 1277910361u, 0, 8, &be_const_str_unknown_X20instruction); -be_define_const_str(super, "super", 4152230356u, 0, 5, &be_const_str_year); -be_define_const_str(sys, "sys", 3277365014u, 0, 3, NULL); -be_define_const_str(tag, "tag", 2516003219u, 0, 3, &be_const_str_widget_instance_size); +be_define_const_str(strptime, "strptime", 1277910361u, 0, 8, &be_const_str__X7B_X7D); +be_define_const_str(super, "super", 4152230356u, 0, 5, NULL); +be_define_const_str(sys, "sys", 3277365014u, 0, 3, &be_const_str_widget_constructor); +be_define_const_str(tag, "tag", 2516003219u, 0, 3, NULL); be_define_const_str(tan, "tan", 2633446552u, 0, 3, NULL); be_define_const_str(tanh, "tanh", 153638352u, 0, 4, NULL); -be_define_const_str(target, "target", 845187144u, 0, 6, NULL); +be_define_const_str(target, "target", 845187144u, 0, 6, &be_const_str_toptr); be_define_const_str(target_search, "target_search", 1947846553u, 0, 13, NULL); be_define_const_str(tasmota, "tasmota", 424643812u, 0, 7, NULL); be_define_const_str(tasmota_X2Eget_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eget_X28_X29, "tasmota.get_light() is deprecated, use light.get()", 3525753647u, 0, 50, NULL); @@ -657,27 +711,29 @@ be_define_const_str(tele, "tele", 3474458061u, 0, 4, NULL); be_define_const_str(the_X20second_X20argument_X20is_X20not_X20a_X20function, "the second argument is not a function", 3954574469u, 0, 37, NULL); be_define_const_str(time_dump, "time_dump", 3330410747u, 0, 9, NULL); be_define_const_str(time_reached, "time_reached", 2075136773u, 0, 12, NULL); -be_define_const_str(time_str, "time_str", 2613827612u, 0, 8, &be_const_str__X7Bs_X7DTemp_X20AXP_X7Bm_X7D_X25_X2E1f_X20_XB0C_X7Be_X7D); +be_define_const_str(time_str, "time_str", 2613827612u, 0, 8, &be_const_str_web_sensor); be_define_const_str(to_gamma, "to_gamma", 1597139862u, 0, 8, NULL); be_define_const_str(tob64, "tob64", 373777640u, 0, 5, NULL); be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, NULL); be_define_const_str(tomap, "tomap", 612167626u, 0, 5, NULL); be_define_const_str(top, "top", 2802900028u, 0, 3, NULL); -be_define_const_str(toptr, "toptr", 3379847454u, 0, 5, NULL); +be_define_const_str(toptr, "toptr", 3379847454u, 0, 5, &be_const_str_type_error); be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, NULL); be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, NULL); be_define_const_str(tr, "tr", 1195724803u, 0, 2, NULL); -be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, &be_const_str_as); +be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, NULL); be_define_const_str(true, "true", 1303515621u, 61, 4, NULL); be_define_const_str(try, "try", 2887626766u, 68, 3, NULL); -be_define_const_str(try_rule, "try_rule", 1986449405u, 0, 8, &be_const_str_widget_dtor_cb); +be_define_const_str(try_rule, "try_rule", 1986449405u, 0, 8, NULL); be_define_const_str(type, "type", 1361572173u, 0, 4, NULL); -be_define_const_str(unknown_X20instruction, "unknown instruction", 1093911841u, 0, 19, &be_const_str_widget_event_impl); -be_define_const_str(update, "update", 672109684u, 0, 6, NULL); +be_define_const_str(type_error, "type_error", 3789613824u, 0, 10, NULL); +be_define_const_str(udp, "udp", 1253872004u, 0, 3, NULL); +be_define_const_str(unknown_X20instruction, "unknown instruction", 1093911841u, 0, 19, NULL); +be_define_const_str(update, "update", 672109684u, 0, 6, &be_const_str_if); be_define_const_str(upper, "upper", 176974407u, 0, 5, NULL); be_define_const_str(url_encode, "url_encode", 528392145u, 0, 10, NULL); -be_define_const_str(v, "v", 4077666505u, 0, 1, &be_const_str_valuer_error); -be_define_const_str(value, "value", 1113510858u, 0, 5, &be_const_str_web_add_button); +be_define_const_str(v, "v", 4077666505u, 0, 1, NULL); +be_define_const_str(value, "value", 1113510858u, 0, 5, NULL); be_define_const_str(value_error, "value_error", 773297791u, 0, 11, NULL); be_define_const_str(valuer_error, "valuer_error", 2567947105u, 0, 12, NULL); be_define_const_str(var, "var", 2317739966u, 64, 3, NULL); @@ -688,21 +744,21 @@ be_define_const_str(web_add_config_button, "web_add_config_button", 639674325u, be_define_const_str(web_add_console_button, "web_add_console_button", 3481436192u, 0, 22, NULL); be_define_const_str(web_add_handler, "web_add_handler", 3990174962u, 0, 15, NULL); be_define_const_str(web_add_main_button, "web_add_main_button", 3960367664u, 0, 19, NULL); -be_define_const_str(web_add_management_button, "web_add_management_button", 2738877186u, 0, 25, &be_const_str_webclient); +be_define_const_str(web_add_management_button, "web_add_management_button", 2738877186u, 0, 25, NULL); be_define_const_str(web_send, "web_send", 2989941448u, 0, 8, NULL); be_define_const_str(web_send_decimal, "web_send_decimal", 1407210204u, 0, 16, NULL); -be_define_const_str(web_sensor, "web_sensor", 2900096972u, 0, 10, &be_const_str_do); +be_define_const_str(web_sensor, "web_sensor", 2900096972u, 0, 10, NULL); be_define_const_str(webclient, "webclient", 4076389146u, 0, 9, NULL); -be_define_const_str(webserver, "webserver", 1572454038u, 0, 9, NULL); +be_define_const_str(webserver, "webserver", 1572454038u, 0, 9, &be_const_str_false); be_define_const_str(while, "while", 231090382u, 53, 5, NULL); -be_define_const_str(widget_cb, "widget_cb", 2763583055u, 0, 9, &be_const_str_width); -be_define_const_str(widget_constructor, "widget_constructor", 2543785934u, 0, 18, &be_const_str_yield); -be_define_const_str(widget_ctor_cb, "widget_ctor_cb", 876007560u, 0, 14, &be_const_str_for); +be_define_const_str(widget_cb, "widget_cb", 2763583055u, 0, 9, NULL); +be_define_const_str(widget_constructor, "widget_constructor", 2543785934u, 0, 18, &be_const_str__X7B); +be_define_const_str(widget_ctor_cb, "widget_ctor_cb", 876007560u, 0, 14, NULL); be_define_const_str(widget_ctor_impl, "widget_ctor_impl", 194252479u, 0, 16, &be_const_str_write_file); be_define_const_str(widget_destructor, "widget_destructor", 4207388345u, 0, 17, NULL); be_define_const_str(widget_dtor_cb, "widget_dtor_cb", 3151545845u, 0, 14, NULL); be_define_const_str(widget_dtor_impl, "widget_dtor_impl", 520430610u, 0, 16, NULL); -be_define_const_str(widget_editable, "widget_editable", 3821793286u, 0, 15, &be_const_str_try); +be_define_const_str(widget_editable, "widget_editable", 3821793286u, 0, 15, &be_const_str_y); be_define_const_str(widget_event, "widget_event", 1951408186u, 0, 12, NULL); be_define_const_str(widget_event_cb, "widget_event_cb", 1508466754u, 0, 15, NULL); be_define_const_str(widget_event_impl, "widget_event_impl", 2178430561u, 0, 17, NULL); @@ -715,16 +771,20 @@ be_define_const_str(widget_width_def, "widget_width_def", 3986078862u, 0, 16, NU be_define_const_str(width, "width", 2508680735u, 0, 5, NULL); be_define_const_str(width_def, "width_def", 1143717879u, 0, 9, NULL); be_define_const_str(wifi, "wifi", 120087624u, 0, 4, NULL); +be_define_const_str(wifi_arcs, "wifi_arcs", 3838492904u, 0, 9, NULL); +be_define_const_str(wifi_arcs_icon, "wifi_arcs_icon", 767180544u, 0, 14, NULL); +be_define_const_str(wifi_bars, "wifi_bars", 653141243u, 0, 9, NULL); +be_define_const_str(wifi_bars_icon, "wifi_bars_icon", 3641522557u, 0, 14, NULL); be_define_const_str(wire, "wire", 4082753944u, 0, 4, NULL); be_define_const_str(wire1, "wire1", 3212721419u, 0, 5, NULL); be_define_const_str(wire2, "wire2", 3229499038u, 0, 5, NULL); -be_define_const_str(wire_scan, "wire_scan", 2671275880u, 0, 9, NULL); +be_define_const_str(wire_scan, "wire_scan", 2671275880u, 0, 9, &be_const_str_end); be_define_const_str(write, "write", 3190202204u, 0, 5, NULL); -be_define_const_str(write8, "write8", 3133991532u, 0, 6, NULL); +be_define_const_str(write8, "write8", 3133991532u, 0, 6, &be_const_str_def); be_define_const_str(write_bit, "write_bit", 2660990436u, 0, 9, NULL); -be_define_const_str(write_bytes, "write_bytes", 1227543792u, 0, 11, &be_const_str_except); +be_define_const_str(write_bytes, "write_bytes", 1227543792u, 0, 11, NULL); be_define_const_str(write_file, "write_file", 3177658879u, 0, 10, NULL); -be_define_const_str(write_gpio, "write_gpio", 2267940334u, 0, 10, &be_const_str_if); +be_define_const_str(write_gpio, "write_gpio", 2267940334u, 0, 10, &be_const_str_x1); be_define_const_str(x, "x", 4245442695u, 0, 1, NULL); be_define_const_str(x1, "x1", 274927234u, 0, 2, NULL); be_define_const_str(y, "y", 4228665076u, 0, 1, NULL); @@ -732,381 +792,411 @@ be_define_const_str(y1, "y1", 2355101727u, 0, 2, NULL); be_define_const_str(year, "year", 2927578396u, 0, 4, NULL); be_define_const_str(yield, "yield", 1821831854u, 0, 5, NULL); be_define_const_str(zero, "zero", 2339366755u, 0, 4, NULL); -be_define_const_str(zip, "zip", 2877453236u, 0, 3, &be_const_str__X7Bs_X7DBatt_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D); +be_define_const_str(zip, "zip", 2877453236u, 0, 3, NULL); be_define_const_str(_X7B, "{", 4262220314u, 0, 1, NULL); be_define_const_str(_X7Bs_X7DBatt_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D, "{s}Batt Current{m}%.1f mA{e}", 866537156u, 0, 28, NULL); be_define_const_str(_X7Bs_X7DBatt_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D, "{s}Batt Voltage{m}%.3f V{e}", 3184308199u, 0, 27, NULL); -be_define_const_str(_X7Bs_X7DTemp_X20AXP_X7Bm_X7D_X25_X2E1f_X20_XB0C_X7Be_X7D, "{s}Temp AXP{m}%.1f \u00b0C{e}", 2304457292u, 0, 24, NULL); +be_define_const_str(_X7Bs_X7DTemp_X20AXP_X7Bm_X7D_X25_X2E1f_X20_X26deg_X3BC_X7Be_X7D, "{s}Temp AXP{m}%.1f °C{e}", 2622904081u, 0, 28, NULL); be_define_const_str(_X7Bs_X7DVBus_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D, "{s}VBus Current{m}%.1f mA{e}", 1032721155u, 0, 28, NULL); be_define_const_str(_X7Bs_X7DVBus_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D, "{s}VBus Voltage{m}%.3f V{e}", 165651270u, 0, 27, NULL); be_define_const_str(_X7B_X7D, "{}", 1415952421u, 0, 2, NULL); be_define_const_str(_X7D, "}", 4161554600u, 0, 1, NULL); static const bstring* const m_string_table[] = { - (const bstring *)&be_const_str__X3D, - (const bstring *)&be_const_str_point, - (const bstring *)&be_const_str_run, - NULL, - (const bstring *)&be_const_str_class_init_obj, - (const bstring *)&be_const_str_try_rule, - (const bstring *)&be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dzip_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, - (const bstring *)&be_const_str_setbits, - (const bstring *)&be_const_str_AXP192, - (const bstring *)&be_const_str_tolower, - (const bstring *)&be_const_str__X2B, - (const bstring *)&be_const_str_I2C_X3A, - (const bstring *)&be_const_str_exec_rules, - (const bstring *)&be_const_str_read13, - (const bstring *)&be_const_str__X2F, - (const bstring *)&be_const_str_pc_abs, - (const bstring *)&be_const_str__error, - (const bstring *)&be_const_str__X23autoexec_X2Ebat, - (const bstring *)&be_const_str__X23, - (const bstring *)&be_const_str__X2Ep, - (const bstring *)&be_const_str__X3Clegend_X3E_X3Cb_X20title_X3D_X27Autoconfiguration_X27_X3E_X26nbsp_X3BCurrent_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, - (const bstring *)&be_const_str_SERIAL_6N1, - (const bstring *)&be_const_str_cb_do_nothing, - (const bstring *)&be_const_str_CFG_X3A_X20loading_X20, - (const bstring *)&be_const_str_HTTP_POST, - (const bstring *)&be_const_str__rules, - NULL, - NULL, - NULL, - (const bstring *)&be_const_str_the_X20second_X20argument_X20is_X20not_X20a_X20function, - (const bstring *)&be_const_str_begin, - (const bstring *)&be_const_str_POST, - (const bstring *)&be_const_str_web_add_console_button, - (const bstring *)&be_const_str__X2F_X2Eautoconf, - NULL, - (const bstring *)&be_const_str__filename, - (const bstring *)&be_const_str_write_bit, - (const bstring *)&be_const_str_SERIAL_5O1, - (const bstring *)&be_const_str_AES_GCM, - (const bstring *)&be_const_str_set_height, - (const bstring *)&be_const_str__end_transmission, - (const bstring *)&be_const_str__X2D_X2D_X3A_X2D_X2D, - (const bstring *)&be_const_str_cb_obj, - (const bstring *)&be_const_str_CFG_X3A_X20removing_X20first_X20time_X20marker, - (const bstring *)&be_const_str__archive, - (const bstring *)&be_const_str_module, - (const bstring *)&be_const_str_SERIAL_7N1, - (const bstring *)&be_const_str_sinh, - (const bstring *)&be_const_str__X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, - (const bstring *)&be_const_str_SERIAL_6O2, - (const bstring *)&be_const_str_detected_X20on_X20bus, - (const bstring *)&be_const_str_response_append, - (const bstring *)&be_const_str_WS2812_GRB, - (const bstring *)&be_const_str__X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29, - (const bstring *)&be_const_str_toptr, - (const bstring *)&be_const_str_get_bri, - NULL, - (const bstring *)&be_const_str_arch, - NULL, - (const bstring *)&be_const_str__X3C_X2Fform_X3E_X3C_X2Fp_X3E, - (const bstring *)&be_const_str_connection_error, - (const bstring *)&be_const_str_, - (const bstring *)&be_const_str_calldepth, - (const bstring *)&be_const_str___iterator__, - (const bstring *)&be_const_str__X2Esize, - (const bstring *)&be_const_str_widget_group_def, - (const bstring *)&be_const_str_resp_cmnd, - (const bstring *)&be_const_str__X2Ep2, - (const bstring *)&be_const_str_get_switch, - (const bstring *)&be_const_str_clear_first_time, - NULL, - (const bstring *)&be_const_str_EC_C25519, - (const bstring *)&be_const_str_save, - NULL, - NULL, - (const bstring *)&be_const_str_SERIAL_8N1, - (const bstring *)&be_const_str_ip, - (const bstring *)&be_const_str_alternate, - (const bstring *)&be_const_str_compile, - (const bstring *)&be_const_str_file_X20extension_X20is_X20not_X20_X27_X2Ebe_X27_X20or_X20_X27_X2Ebec_X27, - (const bstring *)&be_const_str_animate, - (const bstring *)&be_const_str__X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d, - NULL, - (const bstring *)&be_const_str_SERIAL_8O2, - (const bstring *)&be_const_str__X25s_X2Eautoconf, - NULL, - (const bstring *)&be_const_str__dirty, - (const bstring *)&be_const_str_y1, - (const bstring *)&be_const_str_remove_driver, - (const bstring *)&be_const_str_get_string, - (const bstring *)&be_const_str_CFG_X3A_X20removing_X20autoconf_X20files, - (const bstring *)&be_const_str_autoexec, - (const bstring *)&be_const_str_get_style_line_color, - (const bstring *)&be_const_str_bool, - (const bstring *)&be_const_str_write_gpio, - (const bstring *)&be_const_str__X3D_X3D, - (const bstring *)&be_const_str_id, - (const bstring *)&be_const_str_SERIAL_5N2, - NULL, - (const bstring *)&be_const_str_persist, - (const bstring *)&be_const_str_set_timeouts, - NULL, - (const bstring *)&be_const_str_AudioGenerator, - (const bstring *)&be_const_str_byte, - (const bstring *)&be_const_str_EVENT_DRAW_PART_BEGIN, - (const bstring *)&be_const_str_collect, - (const bstring *)&be_const_str_widget_event, - (const bstring *)&be_const_str_SERIAL_6E2, - (const bstring *)&be_const_str_add_anim, - (const bstring *)&be_const_str_erase, - (const bstring *)&be_const_str___lower__, - (const bstring *)&be_const_str_arg, - (const bstring *)&be_const_str_CFG_X3A_X20ran_X20_X20, - (const bstring *)&be_const_str_srand, - (const bstring *)&be_const_str_skip, - (const bstring *)&be_const_str_Leds, - NULL, - (const bstring *)&be_const_str__X23init_X2Ebat, - (const bstring *)&be_const_str__X3Clambda_X3E, - (const bstring *)&be_const_str_GET, - (const bstring *)&be_const_str_widget_ctor_cb, - (const bstring *)&be_const_str__global_addr, + (const bstring *)&be_const_str_CFG_X3A_X20return_code_X3D_X25i, + (const bstring *)&be_const_str__available, (const bstring *)&be_const_str_OneWire, - (const bstring *)&be_const_str__X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, - (const bstring *)&be_const_str_update, NULL, NULL, - NULL, - (const bstring *)&be_const_str_AudioOutput, - NULL, - (const bstring *)&be_const_str_decompress, - NULL, - (const bstring *)&be_const_str_EVENT_DRAW_PART_END, - (const bstring *)&be_const_str_load_templates, - (const bstring *)&be_const_str_get_alternate, - (const bstring *)&be_const_str_acos, - (const bstring *)&be_const_str__X2Elen, - (const bstring *)&be_const_str_constructor_cb, - (const bstring *)&be_const_str_CFG_X3A_X20loaded_X20_X20, - NULL, - (const bstring *)&be_const_str_get_current_module_name, - (const bstring *)&be_const_str__X2Ebec, - (const bstring *)&be_const_str__settings_ptr, - (const bstring *)&be_const_str_dump, - NULL, - (const bstring *)&be_const_str__drivers, - (const bstring *)&be_const_str__X28_X29, - NULL, - (const bstring *)&be_const_str__X2Ebe, - (const bstring *)&be_const_str_content_start, - (const bstring *)&be_const_str__class, - (const bstring *)&be_const_str_h, - (const bstring *)&be_const_str_Unknown_X20command, - (const bstring *)&be_const_str_CFG_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, - (const bstring *)&be_const_str_p1, - NULL, - NULL, - (const bstring *)&be_const_str_b, - (const bstring *)&be_const_str_Parameter_X20error, - (const bstring *)&be_const_str_event, - (const bstring *)&be_const_str_read32, - (const bstring *)&be_const_str_f, - (const bstring *)&be_const_str_resp_cmnd_failed, - (const bstring *)&be_const_str_create_matrix, - (const bstring *)&be_const_str_SERIAL_7E2, - (const bstring *)&be_const_str_resolvecmnd, - (const bstring *)&be_const_str_draw_line, - (const bstring *)&be_const_str_autorun, - (const bstring *)&be_const_str__X2Eautoconf, - (const bstring *)&be_const_str_editable, - NULL, - NULL, - NULL, - (const bstring *)&be_const_str__X3A, - (const bstring *)&be_const_str_EVENT_DRAW_MAIN, - (const bstring *)&be_const_str_remove_timer, - (const bstring *)&be_const_str_Wire, - (const bstring *)&be_const_str__X3E, - (const bstring *)&be_const_str__X26lt_X3BNone_X26gt_X3B, - (const bstring *)&be_const_str__X3C, - (const bstring *)&be_const_str_pin, - (const bstring *)&be_const_str__def, - (const bstring *)&be_const_str_int, - (const bstring *)&be_const_str_atan2, - (const bstring *)&be_const_str_AudioOutputI2S, - (const bstring *)&be_const_str_last_modified, - (const bstring *)&be_const_str_get_style_pad_right, - (const bstring *)&be_const_str__settings_def, - (const bstring *)&be_const_str_CFG_X3A_X20loaded_X20_X27_X25s_X27, - (const bstring *)&be_const_str__X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B, - NULL, - (const bstring *)&be_const_str_start, - (const bstring *)&be_const_str_reset, - (const bstring *)&be_const_str__X2E, - (const bstring *)&be_const_str__X21_X3D_X3D, - (const bstring *)&be_const_str__X2C, - (const bstring *)&be_const_str__X23preinit_X2Ebe, - (const bstring *)&be_const_str_month, - (const bstring *)&be_const_str_instance_size, - (const bstring *)&be_const_str__X20, - (const bstring *)&be_const_str_exp, - (const bstring *)&be_const_str_bus, - (const bstring *)&be_const_str_cmd_res, - (const bstring *)&be_const_str_draw_line_dsc, - (const bstring *)&be_const_str_BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, - (const bstring *)&be_const_str_tostring, - (const bstring *)&be_const_str_var, - (const bstring *)&be_const_str_upper, - (const bstring *)&be_const_str_color, - (const bstring *)&be_const_str_internal_error, - (const bstring *)&be_const_str_encrypt, - (const bstring *)&be_const_str__X21_X3D, - NULL, - NULL, - (const bstring *)&be_const_str_CFG_X3A_X20running_X20, - (const bstring *)&be_const_str_Restart_X201, - (const bstring *)&be_const_str_BUTTON_CONFIGURATION, - NULL, - (const bstring *)&be_const_str_HTTP_GET, - (const bstring *)&be_const_str_loop, - (const bstring *)&be_const_str_SERIAL_5O2, - (const bstring *)&be_const_str__X0A, - (const bstring *)&be_const_str_back_forth, - (const bstring *)&be_const_str_add_rule, - (const bstring *)&be_const_str_CFG_X3A_X20skipping_X20_X27display_X2Eini_X27_X20because_X20already_X20present_X20in_X20file_X2Dsystem, - (const bstring *)&be_const_str_list, - (const bstring *)&be_const_str_closure, - (const bstring *)&be_const_str__X2F_X3Frst_X3D, - NULL, - (const bstring *)&be_const_str__X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, - (const bstring *)&be_const_str_COLOR_WHITE, - NULL, - (const bstring *)&be_const_str_SERIAL_6O1, - (const bstring *)&be_const_str_widget_struct_default, - (const bstring *)&be_const_str_gamma, - (const bstring *)&be_const_str_abs, - (const bstring *)&be_const_str_pc, - (const bstring *)&be_const_str_concat, - (const bstring *)&be_const_str_height_def, - NULL, - (const bstring *)&be_const_str_log10, - (const bstring *)&be_const_str_call, - (const bstring *)&be_const_str__p, - (const bstring *)&be_const_str_file, - (const bstring *)&be_const_str__request_from, - (const bstring *)&be_const_str_BRY_X3A_X20failed_X20to_X20load_X20_persist_X2Ejson, + (const bstring *)&be_const_str_try_rule, (const bstring *)&be_const_str__X2Ep1, - (const bstring *)&be_const_str_content_send_style, - (const bstring *)&be_const_str_AudioGeneratorWAV, - (const bstring *)&be_const_str_seg7_font, - NULL, - (const bstring *)&be_const_str_add_driver, - (const bstring *)&be_const_str_pin_used, - (const bstring *)&be_const_str_Tele, - (const bstring *)&be_const_str_SERIAL_8N2, - NULL, - (const bstring *)&be_const_str__X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, - (const bstring *)&be_const_str_get_input_power_status, - (const bstring *)&be_const_str__persist_X2Ejson, - NULL, - (const bstring *)&be_const_str__X23display_X2Eini, - (const bstring *)&be_const_str_Animate_X20pc_X20is_X20out_X20of_X20range, - (const bstring *)&be_const_str_SERIAL_8O1, - (const bstring *)&be_const_str_ctypes_bytes, - (const bstring *)&be_const_str__X3Clabel_X3EChoose_X20a_X20device_X20configuration_X3A_X3C_X2Flabel_X3E_X3Cbr_X3E, - (const bstring *)&be_const_str_round_end, - (const bstring *)&be_const_str_codedump, - (const bstring *)&be_const_str_MD5, - (const bstring *)&be_const_str_PART_MAIN, - NULL, - (const bstring *)&be_const_str_asin, - (const bstring *)&be_const_str_content_stop, - (const bstring *)&be_const_str_set_light, - (const bstring *)&be_const_str_get_bat_current, - (const bstring *)&be_const_str_x1, - NULL, - NULL, (const bstring *)&be_const_str_compress, - (const bstring *)&be_const_str_escape, - (const bstring *)&be_const_str_atan, + (const bstring *)&be_const_str__buffer, + (const bstring *)&be_const_str_add_handler, (const bstring *)&be_const_str_SERIAL_5N1, - (const bstring *)&be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3E_X26_X23129668_X3B_X20Auto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, + NULL, (const bstring *)&be_const_str__X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E, (const bstring *)&be_const_str_tr, - (const bstring *)&be_const_str__X3Coption_X20value_X3D_X27_X25s_X27_X3E_X25s_X3C_X2Foption_X3E, - (const bstring *)&be_const_str__X2E_X2E, - (const bstring *)&be_const_str_SERIAL_6E1, - (const bstring *)&be_const_str_content_button, - (const bstring *)&be_const_str_asstring, + (const bstring *)&be_const_str_CFG_X3A_X20skipping_X20_X27display_X2Eini_X27_X20because_X20already_X20present_X20in_X20file_X2Dsystem, + (const bstring *)&be_const_str_pc_abs, + (const bstring *)&be_const_str__X23preinit_X2Ebe, + (const bstring *)&be_const_str__X2F_X3Frst_X3D, + (const bstring *)&be_const_str__persist_X2Ejson, + (const bstring *)&be_const_str_arg_X20must_X20be_X20a_X20subclass_X20of_X20lv_obj, + (const bstring *)&be_const_str__X3Clegend_X3E_X3Cb_X20title_X3D_X27Autoconfiguration_X27_X3E_X26nbsp_X3BCurrent_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, + (const bstring *)&be_const_str_map, + (const bstring *)&be_const_str_atleast1, NULL, - (const bstring *)&be_const_str_detect, - (const bstring *)&be_const_str_close, - (const bstring *)&be_const_str_add_header, + (const bstring *)&be_const_str_RES_OK, + (const bstring *)&be_const_str_SERIAL_5E1, + (const bstring *)&be_const_str__X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E, + (const bstring *)&be_const_str__X3D_X3C_X3E_X21, + NULL, + (const bstring *)&be_const_str_LVG_X3A_X20call_X20to_X20unsupported_X20callback, + (const bstring *)&be_const_str_destructor_cb, + (const bstring *)&be_const_str__X7Bs_X7DTemp_X20AXP_X7Bm_X7D_X25_X2E1f_X20_X26deg_X3BC_X7Be_X7D, + (const bstring *)&be_const_str_range, + (const bstring *)&be_const_str_get_bat_current, + (const bstring *)&be_const_str_class_init_obj, + NULL, + (const bstring *)&be_const_str_draw_line_dsc_init, + NULL, + (const bstring *)&be_const_str_AES_GCM, + NULL, + (const bstring *)&be_const_str__X2B, + NULL, + (const bstring *)&be_const_str_exec_rules, + (const bstring *)&be_const_str_search, + NULL, + (const bstring *)&be_const_str_SERIAL_7O1, + (const bstring *)&be_const_str_False, + NULL, + (const bstring *)&be_const_str__X2Eautoconf, + (const bstring *)&be_const_str__X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, + (const bstring *)&be_const_str_COLOR_WHITE, + (const bstring *)&be_const_str_redirect, + (const bstring *)&be_const_str__settings_ptr, (const bstring *)&be_const_str_day, (const bstring *)&be_const_str_seti, - (const bstring *)&be_const_str_light, - (const bstring *)&be_const_str__X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E, - (const bstring *)&be_const_str_event_cb, - (const bstring *)&be_const_str_AudioFileSource, - (const bstring *)&be_const_str_get_tasmota, - (const bstring *)&be_const_str_preinit, - (const bstring *)&be_const_str__available, - (const bstring *)&be_const_str_name, + (const bstring *)&be_const_str_None, + (const bstring *)&be_const_str__X7Bs_X7DBatt_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D, + (const bstring *)&be_const_str__X2502d_X25s_X2502d, + (const bstring *)&be_const_str__X2Fac, NULL, + (const bstring *)&be_const_str_encrypt, + (const bstring *)&be_const_str_CFG_X3A_X20multiple_X20autoconf_X20files_X20found_X2C_X20aborting_X20_X28_X27_X25s_X27_X20_X2B_X20_X27_X25s_X27_X29, NULL, - (const bstring *)&be_const_str_reset_search, - (const bstring *)&be_const_str__X3C_X3D, - (const bstring *)&be_const_str_from_to, + (const bstring *)&be_const_str___iterator__, + (const bstring *)&be_const_str__X2Esize, + (const bstring *)&be_const_str_begin_multicast, + (const bstring *)&be_const_str__X3Cp_X3E_X3Csmall_X3E_X26nbsp_X3B_X28This_X20feature_X20requires_X20an_X20internet_X20connection_X29_X3C_X2Fsmall_X3E_X3C_X2Fp_X3E, + (const bstring *)&be_const_str_LVG_X3A_X20object_X3A, + (const bstring *)&be_const_str_CFG_X3A_X20loaded_X20_X27_X25s_X27, + (const bstring *)&be_const_str_input, NULL, - (const bstring *)&be_const_str_remove, - (const bstring *)&be_const_str__read, - (const bstring *)&be_const_str_deg, - (const bstring *)&be_const_str_obj_class_create_obj, - (const bstring *)&be_const_str_ins_time, - (const bstring *)&be_const_str__X2Etapp, - (const bstring *)&be_const_str_content_flush, - (const bstring *)&be_const_str_area, - (const bstring *)&be_const_str_CFG_X3A_X20no_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found, - (const bstring *)&be_const_str_webserver, - (const bstring *)&be_const_str_iter, - (const bstring *)&be_const_str_ceil, + (const bstring *)&be_const_str_read24, + (const bstring *)&be_const_str_back_forth, + NULL, + (const bstring *)&be_const_str_publish, + (const bstring *)&be_const_str_json_fdump_any, + (const bstring *)&be_const_str__X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, + (const bstring *)&be_const_str__X23autoexec_X2Ebat, + (const bstring *)&be_const_str_save_before_restart, + (const bstring *)&be_const_str_editable, + (const bstring *)&be_const_str__X23display_X2Eini, (const bstring *)&be_const_str__global_def, - (const bstring *)&be_const_str__get_cb, - (const bstring *)&be_const_str___upper__, - (const bstring *)&be_const_str_size, - (const bstring *)&be_const_str_cb_event_closure, - (const bstring *)&be_const_str_find_key_i, - (const bstring *)&be_const_str__cb, - (const bstring *)&be_const_str_AudioGeneratorMP3, - (const bstring *)&be_const_str_BRY_X3A_X20ERROR_X2C_X20bad_X20json_X3A_X20, - (const bstring *)&be_const_str_clear_to, - (const bstring *)&be_const_str__X3Clegend_X3E_X3Cb_X20title_X3D_X27New_X20autoconf_X27_X3E_X26nbsp_X3BSelect_X20new_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, - (const bstring *)&be_const_str_web_sensor, - (const bstring *)&be_const_str__ccmd, + (const bstring *)&be_const_str_cb_do_nothing, + (const bstring *)&be_const_str__X3A, + (const bstring *)&be_const_str_every_100ms, + (const bstring *)&be_const_str__rules, + (const bstring *)&be_const_str__X28_X29, + (const bstring *)&be_const_str_CFG_X3A_X20loading_X20_X27_X25s_X27, + (const bstring *)&be_const_str__X26lt_X3BNone_X26gt_X3B, + (const bstring *)&be_const_str_wire1, + (const bstring *)&be_const_str_init_draw_line_dsc, + (const bstring *)&be_const_str_strptime, + (const bstring *)&be_const_str_get_style_line_color, NULL, - (const bstring *)&be_const_str_p2, - (const bstring *)&be_const_str_SERIAL_8E1, - (const bstring *)&be_const_str_connect, - (const bstring *)&be_const_str_c, - (const bstring *)&be_const_str_cmd, - (const bstring *)&be_const_str_a, + NULL, + (const bstring *)&be_const_str_Restart_X201, + (const bstring *)&be_const_str_print, + (const bstring *)&be_const_str_BRY_X3A_X20could_X20not_X20save_X20compiled_X20file_X20_X25s_X20_X28_X25s_X29, + (const bstring *)&be_const_str_onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E, + (const bstring *)&be_const_str__X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B, + (const bstring *)&be_const_str_SERIAL_5O2, (const bstring *)&be_const_str_SERIAL_7E1, - (const bstring *)&be_const_str__cmd, - (const bstring *)&be_const_str_ctor, - (const bstring *)&be_const_str_attrdump, - (const bstring *)&be_const_str_every_second, - (const bstring *)&be_const_str__X5B, + (const bstring *)&be_const_str_reset, + (const bstring *)&be_const_str_ins_time, + (const bstring *)&be_const_str_on, + (const bstring *)&be_const_str__X2E_X2E, + (const bstring *)&be_const_str__error, (const bstring *)&be_const_str_can_show, + (const bstring *)&be_const_str_asstring, + (const bstring *)&be_const_str__X20, + (const bstring *)&be_const_str_hex, + (const bstring *)&be_const_str__X2Ebec, + (const bstring *)&be_const_str_SERIAL_6O1, + (const bstring *)&be_const_str_duration, + (const bstring *)&be_const_str_BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, + (const bstring *)&be_const_str_arg_name, + (const bstring *)&be_const_str_get_coords, + (const bstring *)&be_const_str_get_power, + (const bstring *)&be_const_str_group_def, + (const bstring *)&be_const_str_set_style_text_font, + (const bstring *)&be_const_str_CFG_X3A_X20removing_X20autoconf_X20files, + (const bstring *)&be_const_str_sin, + (const bstring *)&be_const_str_Timer, + (const bstring *)&be_const_str_file, NULL, + (const bstring *)&be_const_str__X3D_X3D, + NULL, + (const bstring *)&be_const_str_read8, + (const bstring *)&be_const_str_lv_event, + (const bstring *)&be_const_str_cmd, + (const bstring *)&be_const_str_is_dirty, + (const bstring *)&be_const_str_set_bits_per_sample, + (const bstring *)&be_const_str_persist_X2E_p_X20is_X20not_X20a_X20map, + (const bstring *)&be_const_str_CFG_X3A_X20removing_X20first_X20time_X20marker, + (const bstring *)&be_const_str_json_append, + (const bstring *)&be_const_str_serial, + (const bstring *)&be_const_str_area, + (const bstring *)&be_const_str_alternate, + (const bstring *)&be_const_str_add_anim, + (const bstring *)&be_const_str_add_cmd, + (const bstring *)&be_const_str_COLOR_BLACK, + (const bstring *)&be_const_str_log, + (const bstring *)&be_const_str_SERIAL_8O1, + (const bstring *)&be_const_str_ctypes_bytes, + (const bstring *)&be_const_str_SERIAL_6N2, + (const bstring *)&be_const_str_has, + (const bstring *)&be_const_str_setitem, + (const bstring *)&be_const_str_y1, + (const bstring *)&be_const_str__X2Ebe, + NULL, + (const bstring *)&be_const_str_preinit, + (const bstring *)&be_const_str__X21_X3D, + (const bstring *)&be_const_str_get_percentage, + (const bstring *)&be_const_str__X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, + (const bstring *)&be_const_str_p1, + (const bstring *)&be_const_str_last_modified, + (const bstring *)&be_const_str_write_bit, + NULL, + (const bstring *)&be_const_str_escape, + (const bstring *)&be_const_str_issubclass, + NULL, + NULL, + (const bstring *)&be_const_str_cb_obj, + (const bstring *)&be_const_str_add_event_cb, + (const bstring *)&be_const_str_cosh, + (const bstring *)&be_const_str__X2C, + (const bstring *)&be_const_str_SERIAL_7N1, + (const bstring *)&be_const_str_SERIAL_6E2, + (const bstring *)&be_const_str_webserver, (const bstring *)&be_const_str_Auto_X2Dconfiguration, - (const bstring *)&be_const_str__, - (const bstring *)&be_const_str_gen_cb, - (const bstring *)&be_const_str__X5D, - (const bstring *)&be_const_str_get_size, + (const bstring *)&be_const_str___lower__, + (const bstring *)&be_const_str_get_battery_chargin_status, + (const bstring *)&be_const_str_while, + (const bstring *)&be_const_str_pow, + (const bstring *)&be_const_str_bri, + (const bstring *)&be_const_str_make_cb, + (const bstring *)&be_const_str__anonymous_, NULL, + (const bstring *)&be_const_str_AudioFileSource, + (const bstring *)&be_const_str_widget_instance_size, + (const bstring *)&be_const_str__X3D, + (const bstring *)&be_const_str__def, + (const bstring *)&be_const_str_web_add_console_button, + (const bstring *)&be_const_str_widget_height_def, + (const bstring *)&be_const_str_montserrat_font, + (const bstring *)&be_const_str_set_time, + (const bstring *)&be_const_str_scan, + (const bstring *)&be_const_str__X2Ep2, + (const bstring *)&be_const_str_isrunning, + (const bstring *)&be_const_str_remove, + NULL, + (const bstring *)&be_const_str__X0A, + (const bstring *)&be_const_str_obj_class_create_obj, + (const bstring *)&be_const_str__X2E, + (const bstring *)&be_const_str__X21_X3D_X3D, + (const bstring *)&be_const_str_module, + (const bstring *)&be_const_str__X2Elen, + (const bstring *)&be_const_str_month, + (const bstring *)&be_const_str_get_current_module_path, + (const bstring *)&be_const_str_create_segment, + (const bstring *)&be_const_str_register_button_encoder, + (const bstring *)&be_const_str_split, + (const bstring *)&be_const_str_remove_cmd, + (const bstring *)&be_const_str_remote_ip, + (const bstring *)&be_const_str__X25s_X2Eautoconf, + (const bstring *)&be_const_str_abs, + (const bstring *)&be_const_str__begin_transmission, + (const bstring *)&be_const_str_signal_arcs, + (const bstring *)&be_const_str__X3F, + (const bstring *)&be_const_str_content_start, + (const bstring *)&be_const_str_memory, + (const bstring *)&be_const_str_, + (const bstring *)&be_const_str_load_freetype_font, + (const bstring *)&be_const_str_EVENT_DELETE, + NULL, + (const bstring *)&be_const_str_get, + (const bstring *)&be_const_str_toupper, + (const bstring *)&be_const_str_flush, + (const bstring *)&be_const_str_coord_arr, + (const bstring *)&be_const_str_event, + (const bstring *)&be_const_str_bytes, + (const bstring *)&be_const_str__X2D_X2D_X3A_X2D_X2D, + NULL, + (const bstring *)&be_const_str__lvgl, + (const bstring *)&be_const_str__X2Ew, + (const bstring *)&be_const_str_consume_silence, + (const bstring *)&be_const_str_set_pixel_color, + (const bstring *)&be_const_str_sinh, + (const bstring *)&be_const_str_delete_all_configs, + NULL, + (const bstring *)&be_const_str_CFG_X3A_X20could_X20not_X20run_X20_X25s_X20_X28_X25s_X20_X2D_X20_X25s_X29, + (const bstring *)&be_const_str_char, + (const bstring *)&be_const_str_couldn_X27t_X20not_X20initialize_X20noepixelbus, + (const bstring *)&be_const_str_get_size, + (const bstring *)&be_const_str_SERIAL_5E2, + (const bstring *)&be_const_str_get_aps_voltage, + (const bstring *)&be_const_str_codedump, + (const bstring *)&be_const_str_CFG_X3A_X20_X27init_X2Ebat_X27_X20done_X2C_X20restarting, + (const bstring *)&be_const_str_classname, + (const bstring *)&be_const_str_getbits, + (const bstring *)&be_const_str_gamma8, + (const bstring *)&be_const_str__X3Clegend_X3E_X3Cb_X20title_X3D_X27New_X20autoconf_X27_X3E_X26nbsp_X3BSelect_X20new_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, + (const bstring *)&be_const_str_event_send, + (const bstring *)&be_const_str__X2F_X2Eautoconf, + (const bstring *)&be_const_str_write_gpio, + (const bstring *)&be_const_str_set_gain, + (const bstring *)&be_const_str__X3C_X3D, + (const bstring *)&be_const_str_SERIAL_5N2, + (const bstring *)&be_const_str_Parameter_X20error, + NULL, + (const bstring *)&be_const_str_ismethod, + (const bstring *)&be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3E_X26_X23129668_X3B_X20Auto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, + (const bstring *)&be_const_str_classof, + (const bstring *)&be_const_str_add_rule, + (const bstring *)&be_const_str_SERIAL_7E2, + (const bstring *)&be_const_str_acos, + (const bstring *)&be_const_str_add_fast_loop, + NULL, + (const bstring *)&be_const_str_gpio, + (const bstring *)&be_const_str_file_X20extension_X20is_X20not_X20_X27_X2Ebe_X27_X20or_X20_X27_X2Ebec_X27, + (const bstring *)&be_const_str_code, + (const bstring *)&be_const_str__X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d, + (const bstring *)&be_const_str__X5D, + (const bstring *)&be_const_str___upper__, + (const bstring *)&be_const_str_cos, + NULL, + NULL, + (const bstring *)&be_const_str_check_not_method, + (const bstring *)&be_const_str_remove_driver, + (const bstring *)&be_const_str__X3C_X2Fform_X3E_X3C_X2Fp_X3E, + (const bstring *)&be_const_str_pop, + (const bstring *)&be_const_str_function, + NULL, + (const bstring *)&be_const_str_millis, + (const bstring *)&be_const_str__request_from, + (const bstring *)&be_const_str_width, + NULL, + (const bstring *)&be_const_str_b, + (const bstring *)&be_const_str_AXP192, + NULL, + (const bstring *)&be_const_str_rand, + (const bstring *)&be_const_str_start, + (const bstring *)&be_const_str__cmd, + (const bstring *)&be_const_str_exists, + (const bstring *)&be_const_str_counters, + (const bstring *)&be_const_str_pixel_size, + (const bstring *)&be_const_str_set_dcdc_enable, + (const bstring *)&be_const_str_autorun, + NULL, + (const bstring *)&be_const_str_content_send, + (const bstring *)&be_const_str__, + (const bstring *)&be_const_str_close, + (const bstring *)&be_const_str_get_vbus_current, + (const bstring *)&be_const_str_engine, + (const bstring *)&be_const_str__X3Clabel_X3EChoose_X20a_X20device_X20configuration_X3A_X3C_X2Flabel_X3E_X3Cbr_X3E, (const bstring *)&be_const_str__X3Coption_X20value_X3D_X27reset_X27_X3E_X26lt_X3BRemove_X20autoconf_X26gt_X3B_X3C_X2Foption_X3E, (const bstring *)&be_const_str__X3E_X3D, NULL, - (const bstring *)&be_const_str__X3F, - (const bstring *)&be_const_str_base_class + (const bstring *)&be_const_str__X3Clambda_X3E, + (const bstring *)&be_const_str_onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20change_X20the_X20current_X20configuration_X20and_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E, + (const bstring *)&be_const_str_pin, + (const bstring *)&be_const_str_assert, + (const bstring *)&be_const_str_lvgl_event_dispatch, + NULL, + (const bstring *)&be_const_str_local, + (const bstring *)&be_const_str__filename, + (const bstring *)&be_const_str__t, + (const bstring *)&be_const_str_content_send_style, + NULL, + (const bstring *)&be_const_str_instance_X20required, + (const bstring *)&be_const_str__end_transmission, + (const bstring *)&be_const_str_EC_C25519, + (const bstring *)&be_const_str_lv_, + (const bstring *)&be_const_str_Tele, + (const bstring *)&be_const_str_EVENT_DRAW_PART_BEGIN, + (const bstring *)&be_const_str_percentage, + (const bstring *)&be_const_str_draw_arc, + (const bstring *)&be_const_str_get_input_power_status, + (const bstring *)&be_const_str__X23, + (const bstring *)&be_const_str__X7Bs_X7DBatt_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D, + (const bstring *)&be_const_str_exp, + (const bstring *)&be_const_str_tele, + (const bstring *)&be_const_str_CFG_X3A_X20ran_X20_X20, + (const bstring *)&be_const_str_SERIAL_8O2, + (const bstring *)&be_const_str_EVENT_DRAW_MAIN, + (const bstring *)&be_const_str_light, + (const bstring *)&be_const_str_Wire, + (const bstring *)&be_const_str_concat, + (const bstring *)&be_const_str_Tasmota, + (const bstring *)&be_const_str_GET, + (const bstring *)&be_const_str_geti, + (const bstring *)&be_const_str_True, + (const bstring *)&be_const_str_name, + (const bstring *)&be_const_str_CFG_X3A_X20removed_X20file_X20_X27_X25s_X27, + (const bstring *)&be_const_str_wire, + (const bstring *)&be_const_str_p2, + (const bstring *)&be_const_str_lv_wifi_bars, + (const bstring *)&be_const_str_SERIAL_5O1, + (const bstring *)&be_const_str_digital_read, + (const bstring *)&be_const_str_hs2rgb, + (const bstring *)&be_const_str_imax, + (const bstring *)&be_const_str_CFG_X3A_X20No_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found, + (const bstring *)&be_const_str_BRY_X3A_X20method_X20not_X20allowed_X2C_X20use_X20a_X20closure_X20like_X20_X27_X2F_X20args_X20_X2D_X3E_X20obj_X2Efunc_X28args_X29_X27, + (const bstring *)&be_const_str_set_timer, + (const bstring *)&be_const_str__X2Etapp, + (const bstring *)&be_const_str_lv, + (const bstring *)&be_const_str__X5B, + (const bstring *)&be_const_str_SERIAL_7N2, + (const bstring *)&be_const_str_CFG_X3A_X20loaded_X20_X20, + (const bstring *)&be_const_str__X2Ep, + (const bstring *)&be_const_str__energy, + (const bstring *)&be_const_str_depower, + (const bstring *)&be_const_str_contains, + NULL, + (const bstring *)&be_const_str_HTTP_POST, + (const bstring *)&be_const_str__drivers, + (const bstring *)&be_const_str_get_light, + NULL, + (const bstring *)&be_const_str_PART_MAIN, + (const bstring *)&be_const_str_internal_error, + (const bstring *)&be_const_str_asin, + (const bstring *)&be_const_str_call, + (const bstring *)&be_const_str__p, + (const bstring *)&be_const_str_CFG_X3A_X20exception_X20_X27_X25s_X27_X20_X2D_X20_X27_X25s_X27, + (const bstring *)&be_const_str_AudioOutputI2S, + (const bstring *)&be_const_str_BRY_X3A_X20failed_X20to_X20load_X20_persist_X2Ejson, + (const bstring *)&be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dzip_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, + (const bstring *)&be_const_str_static, + (const bstring *)&be_const_str_AudioOutput, + (const bstring *)&be_const_str_clear_first_time, + NULL, + (const bstring *)&be_const_str_add_driver, + (const bstring *)&be_const_str_pin_used, + NULL, + (const bstring *)&be_const_str__X2F, + (const bstring *)&be_const_str__X7Bs_X7DVBus_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D, + (const bstring *)&be_const_str_SERIAL_6E1, + (const bstring *)&be_const_str_get_free_heap, + (const bstring *)&be_const_str__X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, + (const bstring *)&be_const_str_resize, + (const bstring *)&be_const_str_ceil, + (const bstring *)&be_const_str_CFG_X3A_X20downloading_X20_X27_X25s_X27, + (const bstring *)&be_const_str_add_header, + (const bstring *)&be_const_str__X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29, + (const bstring *)&be_const_str_wifi, + (const bstring *)&be_const_str_get_bri, + (const bstring *)&be_const_str_var, + (const bstring *)&be_const_str__X23init_X2Ebat, + (const bstring *)&be_const_str_create_custom_widget, + (const bstring *)&be_const_str__X3C }; static const struct bconststrtab m_const_string_table = { - .size = 360, - .count = 743, + .size = 390, + .count = 803, .table = m_string_table }; diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_aes_gcm.h b/lib/libesp32/berry/generate/be_fixed_be_class_aes_gcm.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_aes_gcm.h rename to lib/libesp32/berry/generate/be_fixed_be_class_aes_gcm.h diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_audio_file_source.h b/lib/libesp32/berry/generate/be_fixed_be_class_audio_file_source.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_audio_file_source.h rename to lib/libesp32/berry/generate/be_fixed_be_class_audio_file_source.h diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_audio_file_source_fs.h b/lib/libesp32/berry/generate/be_fixed_be_class_audio_file_source_fs.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_audio_file_source_fs.h rename to lib/libesp32/berry/generate/be_fixed_be_class_audio_file_source_fs.h diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_audio_generator.h b/lib/libesp32/berry/generate/be_fixed_be_class_audio_generator.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_audio_generator.h rename to lib/libesp32/berry/generate/be_fixed_be_class_audio_generator.h diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_audio_generator_mp3.h b/lib/libesp32/berry/generate/be_fixed_be_class_audio_generator_mp3.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_audio_generator_mp3.h rename to lib/libesp32/berry/generate/be_fixed_be_class_audio_generator_mp3.h diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_audio_generator_wav.h b/lib/libesp32/berry/generate/be_fixed_be_class_audio_generator_wav.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_audio_generator_wav.h rename to lib/libesp32/berry/generate/be_fixed_be_class_audio_generator_wav.h diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_audio_opus_decoder.h b/lib/libesp32/berry/generate/be_fixed_be_class_audio_opus_decoder.h new file mode 100644 index 000000000..cf6611e28 --- /dev/null +++ b/lib/libesp32/berry/generate/be_fixed_be_class_audio_opus_decoder.h @@ -0,0 +1,20 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(be_class_audio_opus_decoder_map) { + { be_const_key(deinit, -1), be_const_func(be_audio_opus_decoder_deinit) }, + { be_const_key(decode, 2), be_const_func(be_audio_opus_decoder_decode) }, + { be_const_key(_X2Ep, -1), be_const_var(0) }, + { be_const_key(init, 1), be_const_func(be_audio_opus_decoder_init) }, +}; + +static be_define_const_map( + be_class_audio_opus_decoder_map, + 4 +); + +BE_EXPORT_VARIABLE be_define_const_class( + be_class_audio_opus_decoder, + 1, + NULL, + OpusDecoder +); diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_audio_output.h b/lib/libesp32/berry/generate/be_fixed_be_class_audio_output.h new file mode 100644 index 000000000..7cf34b574 --- /dev/null +++ b/lib/libesp32/berry/generate/be_fixed_be_class_audio_output.h @@ -0,0 +1,28 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(be_class_audio_output_map) { + { be_const_key(set_bits_per_sample, -1), be_const_func(be_audio_output_set_bits_per_sample) }, + { be_const_key(flush, -1), be_const_func(be_audio_output_flush) }, + { be_const_key(consume_stereo, -1), be_const_func(be_audio_output_consume_stereo) }, + { be_const_key(init, -1), be_const_func(be_audio_output_init) }, + { be_const_key(consume_mono, -1), be_const_func(be_audio_output_consume_mono) }, + { be_const_key(stop, -1), be_const_func(be_audio_output_stop) }, + { be_const_key(begin, -1), be_const_func(be_audio_output_begin) }, + { be_const_key(_X2Ep, -1), be_const_var(0) }, + { be_const_key(set_channels, -1), be_const_func(be_audio_output_set_channels) }, + { be_const_key(consume_silence, 4), be_const_func(be_audio_output_consume_silence) }, + { be_const_key(set_rate, 2), be_const_func(be_audio_output_set_rate) }, + { be_const_key(set_gain, 0), be_const_func(be_audio_output_set_gain) }, +}; + +static be_define_const_map( + be_class_audio_output_map, + 12 +); + +BE_EXPORT_VARIABLE be_define_const_class( + be_class_audio_output, + 1, + NULL, + AudioOutput +); diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_audio_output_i2s.h b/lib/libesp32/berry/generate/be_fixed_be_class_audio_output_i2s.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_audio_output_i2s.h rename to lib/libesp32/berry/generate/be_fixed_be_class_audio_output_i2s.h diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_bytes.h b/lib/libesp32/berry/generate/be_fixed_be_class_bytes.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_bytes.h rename to lib/libesp32/berry/generate/be_fixed_be_class_bytes.h diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_ctypes.h b/lib/libesp32/berry/generate/be_fixed_be_class_ctypes.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_ctypes.h rename to lib/libesp32/berry/generate/be_fixed_be_class_ctypes.h diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_ctypes_dyn.h b/lib/libesp32/berry/generate/be_fixed_be_class_ctypes_dyn.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_ctypes_dyn.h rename to lib/libesp32/berry/generate/be_fixed_be_class_ctypes_dyn.h diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_ec_c25519.h b/lib/libesp32/berry/generate/be_fixed_be_class_ec_c25519.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_ec_c25519.h rename to lib/libesp32/berry/generate/be_fixed_be_class_ec_c25519.h diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_list.h b/lib/libesp32/berry/generate/be_fixed_be_class_list.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_list.h rename to lib/libesp32/berry/generate/be_fixed_be_class_list.h diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_map.h b/lib/libesp32/berry/generate/be_fixed_be_class_map.h similarity index 54% rename from lib/libesp32/Berry/generate/be_fixed_be_class_map.h rename to lib/libesp32/berry/generate/be_fixed_be_class_map.h index f884630e3..db15432d4 100644 --- a/lib/libesp32/Berry/generate/be_fixed_be_class_map.h +++ b/lib/libesp32/berry/generate/be_fixed_be_class_map.h @@ -1,25 +1,24 @@ #include "be_constobj.h" static be_define_const_map_slots(be_class_map_map) { - { be_const_key(setitem, -1), be_const_func(m_setitem) }, - { be_const_key(remove, 8), be_const_func(m_remove) }, - { be_const_key(insert, -1), be_const_func(m_insert) }, - { be_const_key(tostring, 4), be_const_func(m_tostring) }, + { be_const_key(tostring, -1), be_const_func(m_tostring) }, + { be_const_key(contains, -1), be_const_func(m_contains) }, + { be_const_key(item, 4), be_const_func(m_item) }, + { be_const_key(setitem, 9), be_const_func(m_setitem) }, { be_const_key(has, -1), be_const_func(m_contains) }, - { be_const_key(init, -1), be_const_func(m_init) }, - { be_const_key(contains, 9), be_const_func(m_contains) }, - { be_const_key(_X2Ep, 13), be_const_var(0) }, - { be_const_key(reduce, -1), be_const_func(m_reduce) }, - { be_const_key(size, -1), be_const_func(m_size) }, - { be_const_key(find, -1), be_const_func(m_find) }, { be_const_key(keys, -1), be_const_func(m_keys) }, - { be_const_key(item, -1), be_const_func(m_item) }, + { be_const_key(init, -1), be_const_func(m_init) }, + { be_const_key(remove, 5), be_const_func(m_remove) }, + { be_const_key(size, -1), be_const_func(m_size) }, { be_const_key(iter, -1), be_const_func(m_iter) }, + { be_const_key(insert, -1), be_const_func(m_insert) }, + { be_const_key(_X2Ep, -1), be_const_var(0) }, + { be_const_key(find, 8), be_const_func(m_find) }, }; static be_define_const_map( be_class_map_map, - 14 + 13 ); BE_EXPORT_VARIABLE be_define_const_class( diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_md5.h b/lib/libesp32/berry/generate/be_fixed_be_class_md5.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_md5.h rename to lib/libesp32/berry/generate/be_fixed_be_class_md5.h diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_range.h b/lib/libesp32/berry/generate/be_fixed_be_class_range.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_range.h rename to lib/libesp32/berry/generate/be_fixed_be_class_range.h diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_tasmota.h b/lib/libesp32/berry/generate/be_fixed_be_class_tasmota.h new file mode 100644 index 000000000..f30503ab8 --- /dev/null +++ b/lib/libesp32/berry/generate/be_fixed_be_class_tasmota.h @@ -0,0 +1,97 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(be_class_tasmota_map) { + { be_const_key(get_power, -1), be_const_func(l_getpower) }, + { be_const_key(gc, -1), be_const_closure(Tasmota_gc_closure) }, + { be_const_key(response_append, -1), be_const_func(l_respAppend) }, + { be_const_key(resp_cmnd_done, 29), be_const_func(l_respCmndDone) }, + { be_const_key(try_rule, -1), be_const_closure(Tasmota_try_rule_closure) }, + { be_const_key(get_light, 8), be_const_closure(Tasmota_get_light_closure) }, + { be_const_key(_global_def, -1), be_const_comptr(&be_tasmota_global_struct) }, + { be_const_key(eth, 76), be_const_func(l_eth) }, + { be_const_key(time_dump, -1), be_const_func(l_time_dump) }, + { be_const_key(cmd_res, -1), be_const_var(0) }, + { be_const_key(_drivers, 18), be_const_var(1) }, + { be_const_key(find_key_i, -1), be_const_closure(Tasmota_find_key_i_closure) }, + { be_const_key(set_timer, -1), be_const_closure(Tasmota_set_timer_closure) }, + { be_const_key(load, 9), be_const_closure(Tasmota_load_closure) }, + { be_const_key(set_light, 15), be_const_closure(Tasmota_set_light_closure) }, + { be_const_key(fast_loop, -1), be_const_closure(Tasmota_fast_loop_closure) }, + { be_const_key(settings, -1), be_const_var(2) }, + { be_const_key(web_send_decimal, -1), be_const_func(l_webSendDecimal) }, + { be_const_key(strptime, -1), be_const_func(l_strptime) }, + { be_const_key(init, 20), be_const_closure(Tasmota_init_closure) }, + { be_const_key(get_option, -1), be_const_func(l_getoption) }, + { be_const_key(memory, 37), be_const_func(l_memory) }, + { be_const_key(find_op, -1), be_const_closure(Tasmota_find_op_closure) }, + { be_const_key(yield, -1), be_const_func(l_yield) }, + { be_const_key(publish_result, 19), be_const_func(l_publish_result) }, + { be_const_key(_timers, 33), be_const_var(3) }, + { be_const_key(_ccmd, 75), be_const_var(4) }, + { be_const_key(read_sensors, 26), be_const_func(l_read_sensors) }, + { be_const_key(rtc, -1), be_const_func(l_rtc) }, + { be_const_key(delay, 73), be_const_func(l_delay) }, + { be_const_key(event, 35), be_const_closure(Tasmota_event_closure) }, + { be_const_key(web_send, 12), be_const_func(l_webSend) }, + { be_const_key(i2c_enabled, 78), be_const_func(l_i2cenabled) }, + { be_const_key(_settings_ptr, -1), be_const_comptr(&Settings) }, + { be_const_key(resp_cmnd_error, -1), be_const_func(l_respCmndError) }, + { be_const_key(cmd, -1), be_const_closure(Tasmota_cmd_closure) }, + { be_const_key(_cmd, 62), be_const_func(l_cmd) }, + { be_const_key(wifi, 71), be_const_func(l_wifi) }, + { be_const_key(wire_scan, -1), be_const_closure(Tasmota_wire_scan_closure) }, + { be_const_key(resp_cmnd, 17), be_const_func(l_respCmnd) }, + { be_const_key(wire2, -1), be_const_var(5) }, + { be_const_key(get_switch, 51), be_const_func(l_getswitch) }, + { be_const_key(chars_in_string, -1), be_const_closure(Tasmota_chars_in_string_closure) }, + { be_const_key(remove_cmd, 7), be_const_closure(Tasmota_remove_cmd_closure) }, + { be_const_key(_fl, 1), be_const_var(6) }, + { be_const_key(hs2rgb, -1), be_const_closure(Tasmota_hs2rgb_closure) }, + { be_const_key(wd, 38), be_const_var(7) }, + { be_const_key(get_free_heap, -1), be_const_func(l_getFreeHeap) }, + { be_const_key(strftime, -1), be_const_func(l_strftime) }, + { be_const_key(_global_addr, 65), be_const_comptr(&TasmotaGlobal) }, + { be_const_key(exec_tele, -1), be_const_closure(Tasmota_exec_tele_closure) }, + { be_const_key(time_reached, -1), be_const_func(l_timereached) }, + { be_const_key(_settings_def, -1), be_const_comptr(&be_tasmota_settings_struct) }, + { be_const_key(remove_rule, 67), be_const_closure(Tasmota_remove_rule_closure) }, + { be_const_key(gen_cb, -1), be_const_closure(Tasmota_gen_cb_closure) }, + { be_const_key(exec_cmd, -1), be_const_closure(Tasmota_exec_cmd_closure) }, + { be_const_key(time_str, 14), be_const_closure(Tasmota_time_str_closure) }, + { be_const_key(exec_rules, -1), be_const_closure(Tasmota_exec_rules_closure) }, + { be_const_key(resp_cmnd_str, -1), be_const_func(l_respCmndStr) }, + { be_const_key(global, 4), be_const_var(8) }, + { be_const_key(kv, 2), be_const_closure(Tasmota_kv_closure) }, + { be_const_key(add_fast_loop, -1), be_const_closure(Tasmota_add_fast_loop_closure) }, + { be_const_key(resp_cmnd_failed, -1), be_const_func(l_respCmndFailed) }, + { be_const_key(log, -1), be_const_func(l_logInfo) }, + { be_const_key(add_cmd, -1), be_const_closure(Tasmota_add_cmd_closure) }, + { be_const_key(remove_timer, -1), be_const_closure(Tasmota_remove_timer_closure) }, + { be_const_key(millis, 58), be_const_func(l_millis) }, + { be_const_key(scale_uint, -1), be_const_func(l_scaleuint) }, + { be_const_key(run_deferred, -1), be_const_closure(Tasmota_run_deferred_closure) }, + { be_const_key(_debug_present, 30), be_const_var(9) }, + { be_const_key(remove_driver, -1), be_const_closure(Tasmota_remove_driver_closure) }, + { be_const_key(set_power, -1), be_const_func(l_setpower) }, + { be_const_key(check_not_method, -1), be_const_closure(Tasmota_check_not_method_closure) }, + { be_const_key(resolvecmnd, 74), be_const_func(l_resolveCmnd) }, + { be_const_key(arch, -1), be_const_func(l_arch) }, + { be_const_key(save, -1), be_const_func(l_save) }, + { be_const_key(add_rule, -1), be_const_closure(Tasmota_add_rule_closure) }, + { be_const_key(publish, -1), be_const_func(l_publish) }, + { be_const_key(wire1, 77), be_const_var(10) }, + { be_const_key(_rules, 28), be_const_var(11) }, + { be_const_key(add_driver, -1), be_const_closure(Tasmota_add_driver_closure) }, +}; + +static be_define_const_map( + be_class_tasmota_map, + 81 +); + +BE_EXPORT_VARIABLE be_define_const_class( + be_class_tasmota, + 12, + NULL, + Tasmota +); diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota_onewire.h b/lib/libesp32/berry/generate/be_fixed_be_class_tasmota_onewire.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_tasmota_onewire.h rename to lib/libesp32/berry/generate/be_fixed_be_class_tasmota_onewire.h diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota_serial.h b/lib/libesp32/berry/generate/be_fixed_be_class_tasmota_serial.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_tasmota_serial.h rename to lib/libesp32/berry/generate/be_fixed_be_class_tasmota_serial.h diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota_wire.h b/lib/libesp32/berry/generate/be_fixed_be_class_tasmota_wire.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_tasmota_wire.h rename to lib/libesp32/berry/generate/be_fixed_be_class_tasmota_wire.h diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_tcpclient.h b/lib/libesp32/berry/generate/be_fixed_be_class_tcpclient.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_tcpclient.h rename to lib/libesp32/berry/generate/be_fixed_be_class_tcpclient.h diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_udp.h b/lib/libesp32/berry/generate/be_fixed_be_class_udp.h new file mode 100644 index 000000000..892215f3a --- /dev/null +++ b/lib/libesp32/berry/generate/be_fixed_be_class_udp.h @@ -0,0 +1,26 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(be_class_udp_map) { + { be_const_key(send_multicast, 6), be_const_func(be_udp_send_mcast) }, + { be_const_key(send, -1), be_const_func(be_udp_send) }, + { be_const_key(deinit, -1), be_const_func(be_udp_deinit) }, + { be_const_key(remote_ip, -1), be_const_var(0) }, + { be_const_key(read, -1), be_const_func(be_udp_read) }, + { be_const_key(begin_multicast, 8), be_const_func(be_udp_begin_mcast) }, + { be_const_key(begin, -1), be_const_func(be_udp_begin) }, + { be_const_key(remote_port, -1), be_const_var(1) }, + { be_const_key(init, -1), be_const_func(be_udp_init) }, + { be_const_key(_X2Ep, 4), be_const_var(2) }, +}; + +static be_define_const_map( + be_class_udp_map, + 10 +); + +BE_EXPORT_VARIABLE be_define_const_class( + be_class_udp, + 3, + NULL, + udp +); diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_webclient.h b/lib/libesp32/berry/generate/be_fixed_be_class_webclient.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_be_class_webclient.h rename to lib/libesp32/berry/generate/be_fixed_be_class_webclient.h diff --git a/lib/libesp32/berry/generate/be_fixed_cb.h b/lib/libesp32/berry/generate/be_fixed_cb.h new file mode 100644 index 000000000..3eaf867d1 --- /dev/null +++ b/lib/libesp32/berry/generate/be_fixed_cb.h @@ -0,0 +1,21 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(m_libcb_map) { + { be_const_key(make_cb, -1), be_const_func(be_cb_make_cb) }, + { be_const_key(list_handlers, 3), be_const_func(be_cb_list_handlers) }, + { be_const_key(get_cb_list, -1), be_const_func(be_cb_get_cb_list) }, + { be_const_key(gen_cb, -1), be_const_func(be_cb_gen_cb) }, + { be_const_key(add_handler, -1), be_const_func(be_cb_add_handler) }, +}; + +static be_define_const_map( + m_libcb_map, + 5 +); + +static be_define_const_module( + m_libcb, + "cb" +); + +BE_EXPORT_VARIABLE be_define_const_native_module(cb); diff --git a/lib/libesp32/Berry/generate/be_fixed_debug.h b/lib/libesp32/berry/generate/be_fixed_debug.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_debug.h rename to lib/libesp32/berry/generate/be_fixed_debug.h diff --git a/lib/libesp32/Berry/generate/be_fixed_flash.h b/lib/libesp32/berry/generate/be_fixed_flash.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_flash.h rename to lib/libesp32/berry/generate/be_fixed_flash.h diff --git a/lib/libesp32/Berry/generate/be_fixed_gc.h b/lib/libesp32/berry/generate/be_fixed_gc.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_gc.h rename to lib/libesp32/berry/generate/be_fixed_gc.h diff --git a/lib/libesp32/Berry/generate/be_fixed_global.h b/lib/libesp32/berry/generate/be_fixed_global.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_global.h rename to lib/libesp32/berry/generate/be_fixed_global.h diff --git a/lib/libesp32/Berry/generate/be_fixed_gpio.h b/lib/libesp32/berry/generate/be_fixed_gpio.h similarity index 58% rename from lib/libesp32/Berry/generate/be_fixed_gpio.h rename to lib/libesp32/berry/generate/be_fixed_gpio.h index d87b01643..064796356 100644 --- a/lib/libesp32/Berry/generate/be_fixed_gpio.h +++ b/lib/libesp32/berry/generate/be_fixed_gpio.h @@ -1,18 +1,19 @@ #include "be_constobj.h" static be_define_const_map_slots(m_libgpio_map) { - { be_const_key(pin, -1), be_const_func(gp_pin) }, - { be_const_key(member, -1), be_const_func(gp_member) }, + { be_const_key(digital_read, -1), be_const_func(gp_digital_read) }, { be_const_key(digital_write, -1), be_const_func(gp_digital_write) }, - { be_const_key(pin_mode, 1), be_const_func(gp_pin_mode) }, - { be_const_key(pin_used, -1), be_const_func(gp_pin_used) }, { be_const_key(dac_voltage, -1), be_const_func(gp_dac_voltage) }, - { be_const_key(digital_read, 3), be_const_func(gp_digital_read) }, + { be_const_key(member, 1), be_const_func(gp_member) }, + { be_const_key(set_pwm, 5), be_const_ctype_func(gp_set_duty) }, + { be_const_key(pin, 7), be_const_func(gp_pin) }, + { be_const_key(pin_mode, 2), be_const_func(gp_pin_mode) }, + { be_const_key(pin_used, -1), be_const_func(gp_pin_used) }, }; static be_define_const_map( m_libgpio_map, - 7 + 8 ); static be_define_const_module( diff --git a/lib/libesp32/Berry/generate/be_fixed_introspect.h b/lib/libesp32/berry/generate/be_fixed_introspect.h similarity index 61% rename from lib/libesp32/Berry/generate/be_fixed_introspect.h rename to lib/libesp32/berry/generate/be_fixed_introspect.h index e6d5624f5..619cdfcd0 100644 --- a/lib/libesp32/Berry/generate/be_fixed_introspect.h +++ b/lib/libesp32/berry/generate/be_fixed_introspect.h @@ -1,16 +1,17 @@ #include "be_constobj.h" static be_define_const_map_slots(m_libintrospect_map) { - { be_const_key(get, -1), be_const_func(m_findmember) }, - { be_const_key(toptr, 3), be_const_func(m_toptr) }, + { be_const_key(members, 3), be_const_func(m_attrlist) }, { be_const_key(set, -1), be_const_func(m_setmember) }, - { be_const_key(fromptr, -1), be_const_func(m_fromptr) }, - { be_const_key(members, 1), be_const_func(m_attrlist) }, + { be_const_key(get, -1), be_const_func(m_findmember) }, + { be_const_key(toptr, -1), be_const_func(m_toptr) }, + { be_const_key(ismethod, -1), be_const_func(m_ismethod) }, + { be_const_key(fromptr, 2), be_const_func(m_fromptr) }, }; static be_define_const_map( m_libintrospect_map, - 5 + 6 ); static be_define_const_module( diff --git a/lib/libesp32/Berry/generate/be_fixed_json.h b/lib/libesp32/berry/generate/be_fixed_json.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_json.h rename to lib/libesp32/berry/generate/be_fixed_json.h diff --git a/lib/libesp32/Berry/generate/be_fixed_light.h b/lib/libesp32/berry/generate/be_fixed_light.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_light.h rename to lib/libesp32/berry/generate/be_fixed_light.h diff --git a/lib/libesp32/berry/generate/be_fixed_lv_tasmota.h b/lib/libesp32/berry/generate/be_fixed_lv_tasmota.h new file mode 100644 index 000000000..115726731 --- /dev/null +++ b/lib/libesp32/berry/generate/be_fixed_lv_tasmota.h @@ -0,0 +1,25 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(m_liblv_tasmota_map) { + { be_const_key(seg7_font, -1), be_const_func(lv0_load_seg7_font) }, + { be_const_key(font_seg7, -1), be_const_func(lv0_load_seg7_font) }, + { be_const_key(start, -1), be_const_func(lv0_start) }, + { be_const_key(font_montserrat, -1), be_const_func(lv0_load_montserrat_font) }, + { be_const_key(montserrat_font, -1), be_const_func(lv0_load_montserrat_font) }, + { be_const_key(load_freetype_font, -1), be_const_func(lv0_load_freetype_font) }, + { be_const_key(init, 0), be_const_closure(lv_tasmota_init_closure) }, + { be_const_key(screenshot, 1), be_const_func(lv0_screenshot) }, + { be_const_key(register_button_encoder, -1), be_const_func(lv0_register_button_encoder) }, +}; + +static be_define_const_map( + m_liblv_tasmota_map, + 9 +); + +static be_define_const_module( + m_liblv_tasmota, + "lv_tasmota" +); + +BE_EXPORT_VARIABLE be_define_const_native_module(lv_tasmota); diff --git a/lib/libesp32/Berry/generate/be_fixed_m_builtin.h b/lib/libesp32/berry/generate/be_fixed_m_builtin.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_m_builtin.h rename to lib/libesp32/berry/generate/be_fixed_m_builtin.h diff --git a/lib/libesp32/Berry/generate/be_fixed_math.h b/lib/libesp32/berry/generate/be_fixed_math.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_math.h rename to lib/libesp32/berry/generate/be_fixed_math.h diff --git a/lib/libesp32/Berry/generate/be_fixed_os.h b/lib/libesp32/berry/generate/be_fixed_os.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_os.h rename to lib/libesp32/berry/generate/be_fixed_os.h diff --git a/lib/libesp32/Berry/generate/be_fixed_path.h b/lib/libesp32/berry/generate/be_fixed_path.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_path.h rename to lib/libesp32/berry/generate/be_fixed_path.h diff --git a/lib/libesp32/Berry/generate/be_fixed_solidify.h b/lib/libesp32/berry/generate/be_fixed_solidify.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_solidify.h rename to lib/libesp32/berry/generate/be_fixed_solidify.h diff --git a/lib/libesp32/Berry/generate/be_fixed_strict.h b/lib/libesp32/berry/generate/be_fixed_strict.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_strict.h rename to lib/libesp32/berry/generate/be_fixed_strict.h diff --git a/lib/libesp32/Berry/generate/be_fixed_string.h b/lib/libesp32/berry/generate/be_fixed_string.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_string.h rename to lib/libesp32/berry/generate/be_fixed_string.h diff --git a/lib/libesp32/Berry/generate/be_fixed_sys.h b/lib/libesp32/berry/generate/be_fixed_sys.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_sys.h rename to lib/libesp32/berry/generate/be_fixed_sys.h diff --git a/lib/libesp32/Berry/generate/be_fixed_tasmota_path.h b/lib/libesp32/berry/generate/be_fixed_tasmota_path.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_tasmota_path.h rename to lib/libesp32/berry/generate/be_fixed_tasmota_path.h diff --git a/lib/libesp32/Berry/generate/be_fixed_time.h b/lib/libesp32/berry/generate/be_fixed_time.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_time.h rename to lib/libesp32/berry/generate/be_fixed_time.h diff --git a/lib/libesp32/berry/generate/be_fixed_unishox.h b/lib/libesp32/berry/generate/be_fixed_unishox.h new file mode 100644 index 000000000..0fbaafa5b --- /dev/null +++ b/lib/libesp32/berry/generate/be_fixed_unishox.h @@ -0,0 +1,18 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(m_libunishox_map) { + { be_const_key(decompress, -1), be_const_func(be_ntv_unishox_decompress) }, + { be_const_key(compress, -1), be_const_func(be_ntv_unishox_compress) }, +}; + +static be_define_const_map( + m_libunishox_map, + 2 +); + +static be_define_const_module( + m_libunishox, + "unishox" +); + +BE_EXPORT_VARIABLE be_define_const_native_module(unishox); diff --git a/lib/libesp32/Berry/generate/be_fixed_webserver.h b/lib/libesp32/berry/generate/be_fixed_webserver.h similarity index 100% rename from lib/libesp32/Berry/generate/be_fixed_webserver.h rename to lib/libesp32/berry/generate/be_fixed_webserver.h diff --git a/lib/libesp32/Berry/library.json b/lib/libesp32/berry/library.json similarity index 83% rename from lib/libesp32/Berry/library.json rename to lib/libesp32/berry/library.json index 705592bd5..38df6e3fc 100644 --- a/lib/libesp32/Berry/library.json +++ b/lib/libesp32/berry/library.json @@ -14,17 +14,19 @@ }, "version": "7.0", "license": "MIT License", - "frameworks": "*", - "platforms": "*", + "frameworks": "arduino", + "platforms": "espressif32", "build": { + "includeDir": "generate", "srcFilter": [ "+<*.c>", "+<../default/*.c>", "+<../default/*.cpp>", "+<../default/*.hpp>", + "+<../generate/*.h>", "+<*.cpp>", "+<*.h>" ], "flags": [ "-I$PROJECT_DIR/tasmota", "-DCOMPILE_BERRY_LIB" ] } -} \ No newline at end of file +} diff --git a/lib/libesp32/Berry/src/be_api.c b/lib/libesp32/berry/src/be_api.c similarity index 100% rename from lib/libesp32/Berry/src/be_api.c rename to lib/libesp32/berry/src/be_api.c diff --git a/lib/libesp32/Berry/src/be_baselib.c b/lib/libesp32/berry/src/be_baselib.c similarity index 99% rename from lib/libesp32/Berry/src/be_baselib.c rename to lib/libesp32/berry/src/be_baselib.c index 6e92b47be..f09c5f812 100644 --- a/lib/libesp32/Berry/src/be_baselib.c +++ b/lib/libesp32/berry/src/be_baselib.c @@ -234,7 +234,8 @@ static int l_int(bvm *vm) } else if (be_isbool(vm, 1)) { be_pushint(vm, be_tobool(vm, 1) ? 1 : 0); } else if (be_iscomptr(vm, 1)) { - be_pushint(vm, (int) be_tocomptr(vm, 1)); + intptr_t p = (intptr_t) be_tocomptr(vm, 1); + be_pushint(vm, (int) p); } else { be_return_nil(vm); } diff --git a/lib/libesp32/Berry/src/be_bytecode.c b/lib/libesp32/berry/src/be_bytecode.c similarity index 100% rename from lib/libesp32/Berry/src/be_bytecode.c rename to lib/libesp32/berry/src/be_bytecode.c diff --git a/lib/libesp32/Berry/src/be_bytecode.h b/lib/libesp32/berry/src/be_bytecode.h similarity index 100% rename from lib/libesp32/Berry/src/be_bytecode.h rename to lib/libesp32/berry/src/be_bytecode.h diff --git a/lib/libesp32/Berry/src/be_byteslib.c b/lib/libesp32/berry/src/be_byteslib.c similarity index 93% rename from lib/libesp32/Berry/src/be_byteslib.c rename to lib/libesp32/berry/src/be_byteslib.c index 0c3085faa..94c8823ae 100644 --- a/lib/libesp32/Berry/src/be_byteslib.c +++ b/lib/libesp32/berry/src/be_byteslib.c @@ -246,7 +246,7 @@ static unsigned int decode_base64(unsigned char input[], unsigned char output[]) static void buf_set_len(buf_impl* attr, const size_t len) { uint16_t old_len = attr->len; - attr->len = ((int32_t)len <= attr->size) ? len : attr->size; + attr->len = ((int32_t)len <= attr->size) ? (int32_t)len : attr->size; if (old_len < attr->len) { memset((void*) &attr->bufptr[old_len], 0, attr->len - old_len); } @@ -650,6 +650,9 @@ buf_impl bytes_check_data(bvm *vm, size_t add_size) { buf_impl attr = m_read_attributes(vm, 1); /* check if the `size` is big enough */ if (attr.len + (int32_t)add_size > attr.size) { + if (attr.fixed) { + be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); + } /* it does not fit so we need to realocate the buffer */ bytes_resize(vm, &attr, attr.len + add_size); } @@ -1268,38 +1271,38 @@ be_local_closure(getbits, /* name */ &be_const_str_getbits, &be_const_str_solidified, ( &(const binstruction[32]) { /* code */ - 0x180C0500, // 0000 LE R3 R2 K0 - 0x740E0002, // 0001 JMPT R3 #0005 - 0x540E001F, // 0002 LDINT R3 32 - 0x240C0403, // 0003 GT R3 R2 R3 - 0x780E0000, // 0004 JMPF R3 #0006 - 0xB0060302, // 0005 RAISE 1 K1 K2 - 0x580C0000, // 0006 LDCONST R3 K0 - 0x3C100303, // 0007 SHR R4 R1 K3 - 0x54160007, // 0008 LDINT R5 8 - 0x10040205, // 0009 MOD R1 R1 R5 - 0x58140000, // 000A LDCONST R5 K0 - 0x24180500, // 000B GT R6 R2 K0 - 0x781A0011, // 000C JMPF R6 #001F - 0x541A0007, // 000D LDINT R6 8 - 0x04180C01, // 000E SUB R6 R6 R1 - 0x241C0C02, // 000F GT R7 R6 R2 - 0x781E0000, // 0010 JMPF R7 #0012 - 0x5C180400, // 0011 MOVE R6 R2 - 0x381E0806, // 0012 SHL R7 K4 R6 - 0x041C0F04, // 0013 SUB R7 R7 K4 - 0x381C0E01, // 0014 SHL R7 R7 R1 - 0x94200004, // 0015 GETIDX R8 R0 R4 - 0x2C201007, // 0016 AND R8 R8 R7 - 0x3C201001, // 0017 SHR R8 R8 R1 - 0x38201005, // 0018 SHL R8 R8 R5 - 0x300C0608, // 0019 OR R3 R3 R8 - 0x00140A06, // 001A ADD R5 R5 R6 - 0x04080406, // 001B SUB R2 R2 R6 - 0x58040000, // 001C LDCONST R1 K0 - 0x00100904, // 001D ADD R4 R4 K4 - 0x7001FFEB, // 001E JMP #000B - 0x80040600, // 001F RET 1 R3 + 0x180C0500, // 0000 LE R3 R2 K0 + 0x740E0002, // 0001 JMPT R3 #0005 + 0x540E001F, // 0002 LDINT R3 32 + 0x240C0403, // 0003 GT R3 R2 R3 + 0x780E0000, // 0004 JMPF R3 #0006 + 0xB0060302, // 0005 RAISE 1 K1 K2 + 0x580C0000, // 0006 LDCONST R3 K0 + 0x3C100303, // 0007 SHR R4 R1 K3 + 0x54160007, // 0008 LDINT R5 8 + 0x10040205, // 0009 MOD R1 R1 R5 + 0x58140000, // 000A LDCONST R5 K0 + 0x24180500, // 000B GT R6 R2 K0 + 0x781A0011, // 000C JMPF R6 #001F + 0x541A0007, // 000D LDINT R6 8 + 0x04180C01, // 000E SUB R6 R6 R1 + 0x241C0C02, // 000F GT R7 R6 R2 + 0x781E0000, // 0010 JMPF R7 #0012 + 0x5C180400, // 0011 MOVE R6 R2 + 0x381E0806, // 0012 SHL R7 K4 R6 + 0x041C0F04, // 0013 SUB R7 R7 K4 + 0x381C0E01, // 0014 SHL R7 R7 R1 + 0x94200004, // 0015 GETIDX R8 R0 R4 + 0x2C201007, // 0016 AND R8 R8 R7 + 0x3C201001, // 0017 SHR R8 R8 R1 + 0x38201005, // 0018 SHL R8 R8 R5 + 0x300C0608, // 0019 OR R3 R3 R8 + 0x00140A06, // 001A ADD R5 R5 R6 + 0x04080406, // 001B SUB R2 R2 R6 + 0x58040000, // 001C LDCONST R1 K0 + 0x00100904, // 001D ADD R4 R4 K4 + 0x7001FFEB, // 001E JMP #000B + 0x80040600, // 001F RET 1 R3 }) ) ); @@ -1328,43 +1331,43 @@ be_local_closure(setbits, /* name */ &be_const_str_setbits, &be_const_str_solidified, ( &(const binstruction[37]) { /* code */ - 0x14100500, // 0000 LT R4 R2 K0 - 0x74120002, // 0001 JMPT R4 #0005 - 0x5412001F, // 0002 LDINT R4 32 - 0x24100404, // 0003 GT R4 R2 R4 - 0x78120000, // 0004 JMPF R4 #0006 - 0xB0060302, // 0005 RAISE 1 K1 K2 - 0x60100009, // 0006 GETGBL R4 G9 - 0x5C140600, // 0007 MOVE R5 R3 - 0x7C100200, // 0008 CALL R4 1 - 0x5C0C0800, // 0009 MOVE R3 R4 - 0x3C100303, // 000A SHR R4 R1 K3 - 0x54160007, // 000B LDINT R5 8 - 0x10040205, // 000C MOD R1 R1 R5 - 0x24140500, // 000D GT R5 R2 K0 - 0x78160014, // 000E JMPF R5 #0024 - 0x54160007, // 000F LDINT R5 8 - 0x04140A01, // 0010 SUB R5 R5 R1 - 0x24180A02, // 0011 GT R6 R5 R2 - 0x781A0000, // 0012 JMPF R6 #0014 - 0x5C140400, // 0013 MOVE R5 R2 - 0x381A0805, // 0014 SHL R6 K4 R5 - 0x04180D04, // 0015 SUB R6 R6 K4 - 0x541E00FE, // 0016 LDINT R7 255 - 0x38200C01, // 0017 SHL R8 R6 R1 - 0x041C0E08, // 0018 SUB R7 R7 R8 - 0x94200004, // 0019 GETIDX R8 R0 R4 - 0x2C201007, // 001A AND R8 R8 R7 - 0x2C240606, // 001B AND R9 R3 R6 - 0x38241201, // 001C SHL R9 R9 R1 - 0x30201009, // 001D OR R8 R8 R9 - 0x98000808, // 001E SETIDX R0 R4 R8 - 0x3C0C0605, // 001F SHR R3 R3 R5 - 0x04080405, // 0020 SUB R2 R2 R5 - 0x58040000, // 0021 LDCONST R1 K0 - 0x00100904, // 0022 ADD R4 R4 K4 - 0x7001FFE8, // 0023 JMP #000D - 0x80040000, // 0024 RET 1 R0 + 0x14100500, // 0000 LT R4 R2 K0 + 0x74120002, // 0001 JMPT R4 #0005 + 0x5412001F, // 0002 LDINT R4 32 + 0x24100404, // 0003 GT R4 R2 R4 + 0x78120000, // 0004 JMPF R4 #0006 + 0xB0060302, // 0005 RAISE 1 K1 K2 + 0x60100009, // 0006 GETGBL R4 G9 + 0x5C140600, // 0007 MOVE R5 R3 + 0x7C100200, // 0008 CALL R4 1 + 0x5C0C0800, // 0009 MOVE R3 R4 + 0x3C100303, // 000A SHR R4 R1 K3 + 0x54160007, // 000B LDINT R5 8 + 0x10040205, // 000C MOD R1 R1 R5 + 0x24140500, // 000D GT R5 R2 K0 + 0x78160014, // 000E JMPF R5 #0024 + 0x54160007, // 000F LDINT R5 8 + 0x04140A01, // 0010 SUB R5 R5 R1 + 0x24180A02, // 0011 GT R6 R5 R2 + 0x781A0000, // 0012 JMPF R6 #0014 + 0x5C140400, // 0013 MOVE R5 R2 + 0x381A0805, // 0014 SHL R6 K4 R5 + 0x04180D04, // 0015 SUB R6 R6 K4 + 0x541E00FE, // 0016 LDINT R7 255 + 0x38200C01, // 0017 SHL R8 R6 R1 + 0x041C0E08, // 0018 SUB R7 R7 R8 + 0x94200004, // 0019 GETIDX R8 R0 R4 + 0x2C201007, // 001A AND R8 R8 R7 + 0x2C240606, // 001B AND R9 R3 R6 + 0x38241201, // 001C SHL R9 R9 R1 + 0x30201009, // 001D OR R8 R8 R9 + 0x98000808, // 001E SETIDX R0 R4 R8 + 0x3C0C0605, // 001F SHR R3 R3 R5 + 0x04080405, // 0020 SUB R2 R2 R5 + 0x58040000, // 0021 LDCONST R1 K0 + 0x00100904, // 0022 ADD R4 R4 K4 + 0x7001FFE8, // 0023 JMP #000D + 0x80040000, // 0024 RET 1 R0 }) ) ); diff --git a/lib/libesp32/Berry/src/be_class.c b/lib/libesp32/berry/src/be_class.c similarity index 100% rename from lib/libesp32/Berry/src/be_class.c rename to lib/libesp32/berry/src/be_class.c diff --git a/lib/libesp32/Berry/src/be_class.h b/lib/libesp32/berry/src/be_class.h similarity index 100% rename from lib/libesp32/Berry/src/be_class.h rename to lib/libesp32/berry/src/be_class.h diff --git a/lib/libesp32/Berry/src/be_code.c b/lib/libesp32/berry/src/be_code.c similarity index 100% rename from lib/libesp32/Berry/src/be_code.c rename to lib/libesp32/berry/src/be_code.c diff --git a/lib/libesp32/Berry/src/be_code.h b/lib/libesp32/berry/src/be_code.h similarity index 100% rename from lib/libesp32/Berry/src/be_code.h rename to lib/libesp32/berry/src/be_code.h diff --git a/lib/libesp32/Berry/src/be_constobj.h b/lib/libesp32/berry/src/be_constobj.h similarity index 92% rename from lib/libesp32/Berry/src/be_constobj.h rename to lib/libesp32/berry/src/be_constobj.h index 8716d7fe2..301b06af8 100644 --- a/lib/libesp32/Berry/src/be_constobj.h +++ b/lib/libesp32/berry/src/be_constobj.h @@ -35,12 +35,12 @@ extern "C" { #define be_const_func(_func) { \ .v.nf = (_func), \ - .type = BE_FUNCTION \ + .type = BE_NTVFUNC \ } #define be_const_static_func(_func) { \ .v.nf = (_func), \ - .type = BE_FUNCTION | BE_FUNC_STATIC \ + .type = BE_NTVFUNC | BE_FUNC_STATIC \ } #define be_const_nil() { \ @@ -201,15 +201,6 @@ const bntvmodule be_native_module(_module) = { \ .members = _members \ } -// #define be_local_instance(_name, _class_ptr, _members) \ -// static const binstance i_##_name = { \ -// be_const_header(BE_INSTANCE), \ -// .super = NULL, \ -// .sub = NULL, \ -// ._class = (bclass*) _class_ptr, \ -// .members = _members \ -// } - #define be_nested_map(_size, _slots) \ & (const bmap) { \ be_const_header(BE_MAP), \ @@ -233,13 +224,6 @@ const bntvmodule be_native_module(_module) = { \ BE_STRING \ } -#define be_nested_str_literal(_str) \ - { \ - { .s=(be_nested_const_str(_str, 0, sizeof(_str)-1 )) \ - }, \ - BE_STRING \ - } - #define be_str_literal(_str) \ be_nested_const_str(_str, 0, sizeof(_str)-1 ) @@ -267,12 +251,12 @@ const bntvmodule be_native_module(_module) = { \ #define be_const_func(_func) { \ bvaldata(_func), \ - BE_FUNCTION \ + BE_NTVFUNC \ } #define be_const_static_func(_func) { \ bvaldata(_func), \ - BE_FUNCTION | BE_FUNC_STATIC \ + BE_NTVFUNC | BE_FUNC_STATIC \ } #define be_const_nil() { \ @@ -365,7 +349,7 @@ const bvector _name = { \ } #define be_define_const_native_module(_module) \ -const bntvmodule be_native_module(_module) = { \ +const bntvmodule be_native_module_##_module = { \ #_module, \ 0, 0, \ (bmodule*)&(m_lib##_module) \ diff --git a/lib/libesp32/Berry/src/be_debug.c b/lib/libesp32/berry/src/be_debug.c similarity index 100% rename from lib/libesp32/Berry/src/be_debug.c rename to lib/libesp32/berry/src/be_debug.c diff --git a/lib/libesp32/Berry/src/be_debug.h b/lib/libesp32/berry/src/be_debug.h similarity index 100% rename from lib/libesp32/Berry/src/be_debug.h rename to lib/libesp32/berry/src/be_debug.h diff --git a/lib/libesp32/Berry/src/be_debuglib.c b/lib/libesp32/berry/src/be_debuglib.c similarity index 100% rename from lib/libesp32/Berry/src/be_debuglib.c rename to lib/libesp32/berry/src/be_debuglib.c diff --git a/lib/libesp32/Berry/src/be_decoder.h b/lib/libesp32/berry/src/be_decoder.h similarity index 100% rename from lib/libesp32/Berry/src/be_decoder.h rename to lib/libesp32/berry/src/be_decoder.h diff --git a/lib/libesp32/Berry/src/be_exec.c b/lib/libesp32/berry/src/be_exec.c similarity index 98% rename from lib/libesp32/Berry/src/be_exec.c rename to lib/libesp32/berry/src/be_exec.c index 7b741e4ff..14dbe903c 100644 --- a/lib/libesp32/Berry/src/be_exec.c +++ b/lib/libesp32/berry/src/be_exec.c @@ -393,10 +393,7 @@ void be_stack_expansion(bvm *vm, int n) stack_resize(vm, size + 1); be_raise(vm, "runtime_error", STACK_OVER_MSG(BE_STACK_TOTAL_MAX)); } -#if BE_USE_OBSERVABILITY_HOOK - if (vm->obshook != NULL) - (*vm->obshook)(vm, BE_OBS_STACK_RESIZE_START, size * sizeof(bvalue), (size + n) * sizeof(bvalue)); -#endif + if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_STACK_RESIZE_START, size * sizeof(bvalue), (size + n) * sizeof(bvalue)); stack_resize(vm, size + n); } diff --git a/lib/libesp32/Berry/src/be_exec.h b/lib/libesp32/berry/src/be_exec.h similarity index 100% rename from lib/libesp32/Berry/src/be_exec.h rename to lib/libesp32/berry/src/be_exec.h diff --git a/lib/libesp32/Berry/src/be_filelib.c b/lib/libesp32/berry/src/be_filelib.c similarity index 100% rename from lib/libesp32/Berry/src/be_filelib.c rename to lib/libesp32/berry/src/be_filelib.c diff --git a/lib/libesp32/Berry/src/be_func.c b/lib/libesp32/berry/src/be_func.c similarity index 100% rename from lib/libesp32/Berry/src/be_func.c rename to lib/libesp32/berry/src/be_func.c diff --git a/lib/libesp32/Berry/src/be_func.h b/lib/libesp32/berry/src/be_func.h similarity index 100% rename from lib/libesp32/Berry/src/be_func.h rename to lib/libesp32/berry/src/be_func.h diff --git a/lib/libesp32/Berry/src/be_gc.c b/lib/libesp32/berry/src/be_gc.c similarity index 98% rename from lib/libesp32/Berry/src/be_gc.c rename to lib/libesp32/berry/src/be_gc.c index b3cf7ab98..19e88cb12 100644 --- a/lib/libesp32/Berry/src/be_gc.c +++ b/lib/libesp32/berry/src/be_gc.c @@ -544,10 +544,7 @@ void be_gc_collect(bvm *vm) vm->counter_gc_kept = 0; vm->counter_gc_freed = 0; #endif -#if BE_USE_OBSERVABILITY_HOOK - if (vm->obshook != NULL) - (*vm->obshook)(vm, BE_OBS_GC_START, vm->gc.usage); -#endif + if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_GC_START, vm->gc.usage); /* step 1: set root-set reference objects to unscanned */ premark_internal(vm); /* object internal the VM */ premark_global(vm); /* global objects */ @@ -564,8 +561,9 @@ void be_gc_collect(bvm *vm) reset_fixedlist(vm); /* step 5: calculate the next GC threshold */ vm->gc.threshold = next_threshold(vm->gc); -#if BE_USE_OBSERVABILITY_HOOK - if (vm->obshook != NULL) - (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage, vm->counter_gc_kept, vm->counter_gc_freed); +#if BE_USE_PERF_COUNTERS + if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage, vm->counter_gc_kept, vm->counter_gc_freed); +#else + if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage); #endif } diff --git a/lib/libesp32/Berry/src/be_gc.h b/lib/libesp32/berry/src/be_gc.h similarity index 100% rename from lib/libesp32/Berry/src/be_gc.h rename to lib/libesp32/berry/src/be_gc.h diff --git a/lib/libesp32/Berry/src/be_gclib.c b/lib/libesp32/berry/src/be_gclib.c similarity index 100% rename from lib/libesp32/Berry/src/be_gclib.c rename to lib/libesp32/berry/src/be_gclib.c diff --git a/lib/libesp32/Berry/src/be_globallib.c b/lib/libesp32/berry/src/be_globallib.c similarity index 100% rename from lib/libesp32/Berry/src/be_globallib.c rename to lib/libesp32/berry/src/be_globallib.c diff --git a/lib/libesp32/Berry/src/be_introspectlib.c b/lib/libesp32/berry/src/be_introspectlib.c similarity index 88% rename from lib/libesp32/Berry/src/be_introspectlib.c rename to lib/libesp32/berry/src/be_introspectlib.c index 61f614daf..b7b58424c 100644 --- a/lib/libesp32/Berry/src/be_introspectlib.c +++ b/lib/libesp32/berry/src/be_introspectlib.c @@ -114,7 +114,7 @@ static int m_fromptr(bvm *vm) v = (void*) be_toint(vm, 1); } if (v) { - bgcobject * ptr = (bgcobject*) v; + bgcobject *ptr = (bgcobject*)v; if (var_basetype(ptr) >= BE_GCOBJECT) { bvalue *top = be_incrtop(vm); var_setobj(top, ptr->type, ptr); @@ -127,6 +127,22 @@ static int m_fromptr(bvm *vm) be_return_nil(vm); } +/* checks if the function (berry bytecode bproto only) is hinted as a method */ +static int m_ismethod(bvm *vm) +{ + int top = be_top(vm); + if (top >= 1) { + bvalue *v = be_indexof(vm, 1); + if (var_isclosure(v)) { + bclosure *cl = var_toobj(v); + bproto *pr = cl->proto; + be_pushbool(vm, pr->varg & BE_VA_METHOD); + be_return(vm); + } + } + be_return_nil(vm); +} + #if !BE_USE_PRECOMPILED_OBJECT be_native_module_attr_table(introspect) { be_native_module_function("members", m_attrlist), @@ -136,6 +152,8 @@ be_native_module_attr_table(introspect) { be_native_module_function("toptr", m_toptr), be_native_module_function("fromptr", m_fromptr), + + be_native_module_function("ismethod", m_ismethod), }; be_define_native_module(introspect, NULL); @@ -149,6 +167,8 @@ module introspect (scope: global, depend: BE_USE_INTROSPECT_MODULE) { toptr, func(m_toptr) fromptr, func(m_fromptr) + + ismethod, func(m_ismethod) } @const_object_info_end */ #include "../generate/be_fixed_introspect.h" diff --git a/lib/libesp32/Berry/src/be_jsonlib.c b/lib/libesp32/berry/src/be_jsonlib.c similarity index 100% rename from lib/libesp32/Berry/src/be_jsonlib.c rename to lib/libesp32/berry/src/be_jsonlib.c diff --git a/lib/libesp32/Berry/src/be_lexer.c b/lib/libesp32/berry/src/be_lexer.c similarity index 100% rename from lib/libesp32/Berry/src/be_lexer.c rename to lib/libesp32/berry/src/be_lexer.c diff --git a/lib/libesp32/Berry/src/be_lexer.h b/lib/libesp32/berry/src/be_lexer.h similarity index 100% rename from lib/libesp32/Berry/src/be_lexer.h rename to lib/libesp32/berry/src/be_lexer.h diff --git a/lib/libesp32/Berry/src/be_libs.c b/lib/libesp32/berry/src/be_libs.c similarity index 100% rename from lib/libesp32/Berry/src/be_libs.c rename to lib/libesp32/berry/src/be_libs.c diff --git a/lib/libesp32/Berry/src/be_libs.h b/lib/libesp32/berry/src/be_libs.h similarity index 100% rename from lib/libesp32/Berry/src/be_libs.h rename to lib/libesp32/berry/src/be_libs.h diff --git a/lib/libesp32/Berry/src/be_list.c b/lib/libesp32/berry/src/be_list.c similarity index 100% rename from lib/libesp32/Berry/src/be_list.c rename to lib/libesp32/berry/src/be_list.c diff --git a/lib/libesp32/Berry/src/be_list.h b/lib/libesp32/berry/src/be_list.h similarity index 100% rename from lib/libesp32/Berry/src/be_list.h rename to lib/libesp32/berry/src/be_list.h diff --git a/lib/libesp32/Berry/src/be_listlib.c b/lib/libesp32/berry/src/be_listlib.c similarity index 100% rename from lib/libesp32/Berry/src/be_listlib.c rename to lib/libesp32/berry/src/be_listlib.c diff --git a/lib/libesp32/Berry/src/be_map.c b/lib/libesp32/berry/src/be_map.c similarity index 99% rename from lib/libesp32/Berry/src/be_map.c rename to lib/libesp32/berry/src/be_map.c index 37f9efc62..e425a09f5 100644 --- a/lib/libesp32/Berry/src/be_map.c +++ b/lib/libesp32/berry/src/be_map.c @@ -203,6 +203,7 @@ static void resize(bvm *vm, bmap *map, int size) slots = be_malloc(vm, datasize(size)); for (i = 0; i < size; ++i) { setnil(slots + i); + next(slots + i) = LASTNODE; } map->size = size; map->slots = slots; diff --git a/lib/libesp32/Berry/src/be_map.h b/lib/libesp32/berry/src/be_map.h similarity index 100% rename from lib/libesp32/Berry/src/be_map.h rename to lib/libesp32/berry/src/be_map.h diff --git a/lib/libesp32/Berry/src/be_maplib.c b/lib/libesp32/berry/src/be_maplib.c similarity index 74% rename from lib/libesp32/Berry/src/be_maplib.c rename to lib/libesp32/berry/src/be_maplib.c index a8fc7309e..fc9f09fe7 100644 --- a/lib/libesp32/Berry/src/be_maplib.c +++ b/lib/libesp32/berry/src/be_maplib.c @@ -212,62 +212,6 @@ static int m_keys(bvm *vm) be_return(vm); } -/* apply a function/closure to each element of a map */ -/* `map.reduce(f:function [, initializer:any]) -> any` */ -/* Calls for each element `f(key, value, acc) -> any` */ -/* `acc` is initialized with `initilizer` if present or `nil` */ -/* the return value of the function becomes the next value passed in arg `acc` */ -static int m_reduce(bvm *vm) -{ - int argc = be_top(vm); - if (argc > 1 && be_isfunction(vm, 2)) { - bbool has_initializer = (argc > 2); - /* get map internal object */ - be_getmember(vm, 1, ".p"); - bvalue *v = be_indexof(vm, -1); - bmap *map = cast(bmap*, var_toobj(v)); - /* get the number of slots if any */ - int slots_initial = be_map_size(map); - /* place-holder for on-going value and return value */ - if (has_initializer) { - be_pushvalue(vm, 3); - } else { - be_pushnil(vm); /* if no initializer use `nil` */ - } - for (int i = 0; i < slots_initial; i++) { - bmapnode * node = map->slots + i; - if (!var_isnil(&node->key)) { /* is the key present in this slot? */ - be_pushvalue(vm, 2); /* push function */ - - bvalue kv; /* push key on stack */ - kv.type = node->key.type; - kv.v = node->key.v; - bvalue *reg = vm->top; - var_setval(reg, &kv); - be_incrtop(vm); - - reg = vm->top; /* push value on stack */ - var_setval(reg, &node->value); - be_incrtop(vm); - - be_pushvalue(vm, -4); - - be_call(vm, 3); - be_pop(vm, 3); /* pop args, keep return value */ - be_remove(vm, -2); /* remove previous accumulator, keep return value from function */ - } - /* check if the map has been resized during the call */ - if (be_map_size(map) != slots_initial) { - be_raise(vm, "stop_iteration", "map resized within apply"); - break; /* abort */ - } - } - be_return(vm); - } - be_raise(vm, "value_error", "needs function as first argument"); - be_return_nil(vm); -} - #if !BE_USE_PRECOMPILED_OBJECT void be_load_maplib(bvm *vm) { @@ -285,7 +229,6 @@ void be_load_maplib(bvm *vm) { "insert", m_insert }, { "iter", m_iter }, { "keys", m_keys }, - { "reduce", m_reduce }, { NULL, NULL } }; be_regclass(vm, "map", members); @@ -306,7 +249,6 @@ class be_class_map (scope: global, name: map) { insert, func(m_insert) iter, func(m_iter) keys, func(m_keys) - reduce, func(m_reduce) } @const_object_info_end */ #include "../generate/be_fixed_be_class_map.h" diff --git a/lib/libesp32/Berry/src/be_mathlib.c b/lib/libesp32/berry/src/be_mathlib.c similarity index 100% rename from lib/libesp32/Berry/src/be_mathlib.c rename to lib/libesp32/berry/src/be_mathlib.c diff --git a/lib/libesp32/Berry/src/be_mem.c b/lib/libesp32/berry/src/be_mem.c similarity index 100% rename from lib/libesp32/Berry/src/be_mem.c rename to lib/libesp32/berry/src/be_mem.c diff --git a/lib/libesp32/Berry/src/be_mem.h b/lib/libesp32/berry/src/be_mem.h similarity index 100% rename from lib/libesp32/Berry/src/be_mem.h rename to lib/libesp32/berry/src/be_mem.h diff --git a/lib/libesp32/Berry/src/be_module.c b/lib/libesp32/berry/src/be_module.c similarity index 100% rename from lib/libesp32/Berry/src/be_module.c rename to lib/libesp32/berry/src/be_module.c diff --git a/lib/libesp32/Berry/src/be_module.h b/lib/libesp32/berry/src/be_module.h similarity index 100% rename from lib/libesp32/Berry/src/be_module.h rename to lib/libesp32/berry/src/be_module.h diff --git a/lib/libesp32/Berry/src/be_object.c b/lib/libesp32/berry/src/be_object.c similarity index 97% rename from lib/libesp32/Berry/src/be_object.c rename to lib/libesp32/berry/src/be_object.c index 6c246231c..ed338f790 100644 --- a/lib/libesp32/Berry/src/be_object.c +++ b/lib/libesp32/berry/src/be_object.c @@ -20,7 +20,7 @@ const char* be_vtype2str(bvalue *v) case BE_INT: return "int"; case BE_REAL: return "real"; case BE_BOOL: return "bool"; - case BE_CLOSURE: case BE_NTVCLOS: + case BE_CLOSURE: case BE_NTVCLOS: case BE_CTYPE_FUNC: case BE_NTVFUNC: return "function"; case BE_PROTO: return "proto"; case BE_CLASS: return "class"; diff --git a/lib/libesp32/Berry/src/be_object.h b/lib/libesp32/berry/src/be_object.h similarity index 95% rename from lib/libesp32/Berry/src/be_object.h rename to lib/libesp32/berry/src/be_object.h index e19d766d6..df7c7a9af 100644 --- a/lib/libesp32/Berry/src/be_object.h +++ b/lib/libesp32/berry/src/be_object.h @@ -34,12 +34,17 @@ #define BE_NTVFUNC ((0 << 5) | BE_FUNCTION) #define BE_CLOSURE ((1 << 5) | BE_FUNCTION) #define BE_NTVCLOS ((2 << 5) | BE_FUNCTION) +#define BE_CTYPE_FUNC ((3 << 5) | BE_FUNCTION) #define BE_FUNC_STATIC (1 << 7) #define func_isstatic(o) (((o)->type & BE_FUNC_STATIC) != 0) #define func_setstatic(o) ((o)->type |= BE_FUNC_STATIC) #define func_clearstatic(o) ((o)->type &= ~BE_FUNC_STATIC) +/* values for bproto.varg */ +#define BE_VA_VARARG (1 << 0) /* function has variable number of arguments */ +#define BE_VA_METHOD (1 << 1) /* function is a method (this is only a hint) */ + #define array_count(a) (sizeof(a) / sizeof((a)[0])) #define bcommon_header \ @@ -210,6 +215,7 @@ typedef const char* (*breader)(void*, size_t*); #define var_isclosure(_v) var_istype(_v, BE_CLOSURE) #define var_isntvclos(_v) var_istype(_v, BE_NTVCLOS) #define var_isntvfunc(_v) var_istype(_v, BE_NTVFUNC) +#define var_isctypefunc(_v) var_istype(_v, BE_CTYPEFUNC) #define var_isfunction(_v) (var_basetype(_v) == BE_FUNCTION) #define var_isproto(_v) var_istype(_v, BE_PROTO) #define var_isclass(_v) var_istype(_v, BE_CLASS) @@ -232,6 +238,7 @@ typedef const char* (*breader)(void*, size_t*); #define var_setclosure(_v, _o) var_setobj(_v, BE_CLOSURE, _o) #define var_setntvclos(_v, _o) var_setobj(_v, BE_NTVCLOS, _o) #define var_setntvfunc(_v, _o) { (_v)->v.nf = (_o); var_settype(_v, BE_NTVFUNC); } +#define var_setctypefunc(_v, _o) { (_v)->v.nf = (_o); var_settype(_v, BE_CTYPEFUNC); } #define var_setlist(_v, _o) var_setobj(_v, BE_LIST, _o) #define var_setmap(_v, _o) var_setobj(_v, BE_MAP, _o) #define var_setmodule(_v, _o) var_setobj(_v, BE_MODULE, _o) diff --git a/lib/libesp32/Berry/src/be_opcodes.h b/lib/libesp32/berry/src/be_opcodes.h similarity index 100% rename from lib/libesp32/Berry/src/be_opcodes.h rename to lib/libesp32/berry/src/be_opcodes.h diff --git a/lib/libesp32/Berry/src/be_oslib.c b/lib/libesp32/berry/src/be_oslib.c similarity index 100% rename from lib/libesp32/Berry/src/be_oslib.c rename to lib/libesp32/berry/src/be_oslib.c diff --git a/lib/libesp32/Berry/src/be_parser.c b/lib/libesp32/berry/src/be_parser.c similarity index 99% rename from lib/libesp32/Berry/src/be_parser.c rename to lib/libesp32/berry/src/be_parser.c index d2f2d7af5..af59f5749 100644 --- a/lib/libesp32/Berry/src/be_parser.c +++ b/lib/libesp32/berry/src/be_parser.c @@ -174,7 +174,7 @@ void end_varinfo(bparser *parser, int beginpc) if (beginpc == -1) /* use block->beginpc by default */ beginpc = binfo->beginpc; /* skip the variable of the previous blocks */ - for (; it->beginpc < beginpc; ++it); + for (; (it <= end) && (it->beginpc < beginpc); ++it); for (; it <= end; ++it) { if (!it->endpc) /* write to endpc only once */ it->endpc = finfo->pc; @@ -313,14 +313,14 @@ static void end_func(bparser *parser) be_code_ret(finfo, NULL); /* append a return to last code */ end_block(parser); /* close block */ setupvals(finfo); /* close upvals */ - proto->code = be_vector_release(vm, &finfo->code); /* compact all vectors and return NULL if empty */ + proto->code = be_vector_release_32(vm, &finfo->code); /* compact all vectors and return NULL if empty */ proto->codesize = finfo->pc; - proto->ktab = be_vector_release(vm, &finfo->kvec); + proto->ktab = be_vector_release_32(vm, &finfo->kvec); proto->nconst = be_vector_count(&finfo->kvec); proto->ptab = be_vector_release(vm, &finfo->pvec); proto->nproto = be_vector_count(&finfo->pvec); #if BE_DEBUG_RUNTIME_INFO - proto->lineinfo = be_vector_release(vm, &finfo->linevec); + proto->lineinfo = be_vector_release_32(vm, &finfo->linevec); proto->nlineinfo = be_vector_count(&finfo->linevec); #endif #if BE_DEBUG_VAR_INFO @@ -557,7 +557,7 @@ static void func_vararg(bparser *parser) { str = next_token(parser).u.s; match_token(parser, TokenId); /* match and skip ID */ new_var(parser, str, &v); /* new variable */ - parser->finfo->proto->varg = 1; /* set varg flag */ + parser->finfo->proto->varg |= BE_VA_VARARG; /* set varg flag */ } /* Parse function or method definition variable list */ @@ -606,6 +606,7 @@ static bproto* funcbody(bparser *parser, bstring *name, int type) finfo.proto->name = name; if (type & FUNC_METHOD) { /* If method, add an implicit first argument `self` */ new_localvar(parser, parser_newstr(parser, "self")); + finfo.proto->varg |= BE_VA_METHOD; } func_varlist(parser); /* parse arg list */ stmtlist(parser); /* parse statement without final `end` */ diff --git a/lib/libesp32/Berry/src/be_parser.h b/lib/libesp32/berry/src/be_parser.h similarity index 100% rename from lib/libesp32/Berry/src/be_parser.h rename to lib/libesp32/berry/src/be_parser.h diff --git a/lib/libesp32/Berry/src/be_rangelib.c b/lib/libesp32/berry/src/be_rangelib.c similarity index 100% rename from lib/libesp32/Berry/src/be_rangelib.c rename to lib/libesp32/berry/src/be_rangelib.c diff --git a/lib/libesp32/Berry/src/be_repl.c b/lib/libesp32/berry/src/be_repl.c similarity index 100% rename from lib/libesp32/Berry/src/be_repl.c rename to lib/libesp32/berry/src/be_repl.c diff --git a/lib/libesp32/Berry/src/be_repl.h b/lib/libesp32/berry/src/be_repl.h similarity index 100% rename from lib/libesp32/Berry/src/be_repl.h rename to lib/libesp32/berry/src/be_repl.h diff --git a/lib/libesp32/Berry/src/be_solidifylib.c b/lib/libesp32/berry/src/be_solidifylib.c similarity index 95% rename from lib/libesp32/Berry/src/be_solidifylib.c rename to lib/libesp32/berry/src/be_solidifylib.c index 581131b75..4d4e3bcb6 100644 --- a/lib/libesp32/Berry/src/be_solidifylib.c +++ b/lib/libesp32/berry/src/be_solidifylib.c @@ -38,11 +38,11 @@ extern const bclass be_class_map; be_writestring(__lbuf); \ } while (0) -/******************************************************************** +/********************************************************************\ * Encode string to identifiers * * `_X` is used as an escape marker -/********************************************************************/ +\********************************************************************/ static unsigned toidentifier_length(const char *s) { unsigned len = 1; @@ -115,7 +115,6 @@ static void m_solidify_map(bvm *vm, bmap * map, const char *class_name) be_raise(vm, "internal_error", error); } int key_next = node->key.next; - size_t len = strlen(str(node->key.v.s)); if (0xFFFFFF == key_next) { key_next = -1; /* more readable */ } @@ -192,10 +191,16 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co } break; case BE_CLOSURE: - logfmt("be_const_%sclosure(%s%s%s_closure)", - func_isstatic(value) ? "static_" : "", - classname ? classname : "", classname ? "_" : "", - str(((bclosure*) var_toobj(value))->proto->name)); + { + const char * func_name = str(((bclosure*) var_toobj(value))->proto->name); + size_t id_len = toidentifier_length(func_name); + char func_name_id[id_len]; + toidentifier(func_name_id, func_name); + logfmt("be_const_%sclosure(%s%s%s_closure)", + func_isstatic(value) ? "static_" : "", + classname ? classname : "", classname ? "_" : "", + func_name_id); + } break; case BE_CLASS: logfmt("be_const_class(be_class_%s)", str(((bclass*) var_toobj(value))->name)); @@ -365,9 +370,14 @@ static void m_solidify_closure(bvm *vm, bclosure *cl, const char * classname, in logfmt("** Solidified function: %s\n", func_name); logfmt("********************************************************************/\n"); - logfmt("be_local_closure(%s%s%s, /* name */\n", - classname ? classname : "", classname ? "_" : "", - func_name); + { + size_t id_len = toidentifier_length(func_name); + char func_name_id[id_len]; + toidentifier(func_name_id, func_name); + logfmt("be_local_closure(%s%s%s, /* name */\n", + classname ? classname : "", classname ? "_" : "", + func_name_id); + } m_solidify_proto(vm, pr, func_name, builtins, indent); logfmt("\n"); diff --git a/lib/libesp32/Berry/src/be_strictlib.c b/lib/libesp32/berry/src/be_strictlib.c similarity index 100% rename from lib/libesp32/Berry/src/be_strictlib.c rename to lib/libesp32/berry/src/be_strictlib.c diff --git a/lib/libesp32/Berry/src/be_string.c b/lib/libesp32/berry/src/be_string.c similarity index 100% rename from lib/libesp32/Berry/src/be_string.c rename to lib/libesp32/berry/src/be_string.c diff --git a/lib/libesp32/Berry/src/be_string.h b/lib/libesp32/berry/src/be_string.h similarity index 100% rename from lib/libesp32/Berry/src/be_string.h rename to lib/libesp32/berry/src/be_string.h diff --git a/lib/libesp32/Berry/src/be_strlib.c b/lib/libesp32/berry/src/be_strlib.c similarity index 99% rename from lib/libesp32/Berry/src/be_strlib.c rename to lib/libesp32/berry/src/be_strlib.c index e0636c100..1196a5aad 100644 --- a/lib/libesp32/Berry/src/be_strlib.c +++ b/lib/libesp32/berry/src/be_strlib.c @@ -87,7 +87,7 @@ static bstring* sim2str(bvm *vm, bvalue *v) case BE_REAL: sprintf(sbuf, "%g", var_toreal(v)); break; - case BE_CLOSURE: case BE_NTVCLOS: case BE_NTVFUNC: + case BE_CLOSURE: case BE_NTVCLOS: case BE_NTVFUNC: case BE_CTYPE_FUNC: sprintf(sbuf, "", var_toobj(v)); break; case BE_CLASS: @@ -578,7 +578,7 @@ static int str_format(bvm *vm) break; case 's': { const char *s = be_tostring(vm, index); - int len = be_strlen(vm, 2); + int len = be_strlen(vm, index); if (len > 100 && strlen(mode) == 2) { be_pushvalue(vm, index); } else { diff --git a/lib/libesp32/Berry/src/be_strlib.h b/lib/libesp32/berry/src/be_strlib.h similarity index 100% rename from lib/libesp32/Berry/src/be_strlib.h rename to lib/libesp32/berry/src/be_strlib.h diff --git a/lib/libesp32/Berry/src/be_sys.h b/lib/libesp32/berry/src/be_sys.h similarity index 100% rename from lib/libesp32/Berry/src/be_sys.h rename to lib/libesp32/berry/src/be_sys.h diff --git a/lib/libesp32/Berry/src/be_syslib.c b/lib/libesp32/berry/src/be_syslib.c similarity index 100% rename from lib/libesp32/Berry/src/be_syslib.c rename to lib/libesp32/berry/src/be_syslib.c diff --git a/lib/libesp32/Berry/src/be_timelib.c b/lib/libesp32/berry/src/be_timelib.c similarity index 100% rename from lib/libesp32/Berry/src/be_timelib.c rename to lib/libesp32/berry/src/be_timelib.c diff --git a/lib/libesp32/Berry/src/be_var.c b/lib/libesp32/berry/src/be_var.c similarity index 100% rename from lib/libesp32/Berry/src/be_var.c rename to lib/libesp32/berry/src/be_var.c diff --git a/lib/libesp32/Berry/src/be_var.h b/lib/libesp32/berry/src/be_var.h similarity index 100% rename from lib/libesp32/Berry/src/be_var.h rename to lib/libesp32/berry/src/be_var.h diff --git a/lib/libesp32/Berry/src/be_vector.c b/lib/libesp32/berry/src/be_vector.c similarity index 79% rename from lib/libesp32/Berry/src/be_vector.c rename to lib/libesp32/berry/src/be_vector.c index b73479601..63cbeff3c 100644 --- a/lib/libesp32/Berry/src/be_vector.c +++ b/lib/libesp32/berry/src/be_vector.c @@ -81,7 +81,11 @@ void be_vector_resize(bvm *vm, bvector *vector, int count) vector->capacity = newcap; } vector->count = count; - vector->end = (char*)vector->data + size * ((size_t)count - 1); + if (count == 0) { + vector->end = (char*)vector->data - size; + } else { + vector->end = (char*)vector->data + size * ((size_t)count - 1); + } } } @@ -110,6 +114,32 @@ void* be_vector_release(bvm *vm, bvector *vector) return vector->data; } +/* free not used */ +void* be_vector_release_32(bvm *vm, bvector *vector) +{ + size_t size = vector->size; + int count = be_vector_count(vector); + if (count == 0) { + be_free(vm, vector->data, vector->capacity * size); + vector->capacity = 0; + vector->data = NULL; + vector->end = NULL; + } else if (count < vector->capacity) { + vector->data = be_realloc(vm, + vector->data, vector->capacity * size, count * size); // TODO - can we skip that step? + void* iram = berry_malloc32(count * size); + if (iram) { + memcpy(iram, vector->data, count * size); + free(vector->data); + vector->data = iram; + } + // vm->gc.usage = vm->gc.usage + count * size - vector->capacity * size; /* update allocated count */ + vector->end = (char*)vector->data + ((size_t)count - 1) * size; + vector->capacity = count; + } + return vector->data; +} + /* use binary search to find the vector capacity between 0-1024 */ static int binary_search(int value) { diff --git a/lib/libesp32/Berry/src/be_vector.h b/lib/libesp32/berry/src/be_vector.h similarity index 95% rename from lib/libesp32/Berry/src/be_vector.h rename to lib/libesp32/berry/src/be_vector.h index 15f399cc6..3991986ca 100644 --- a/lib/libesp32/Berry/src/be_vector.h +++ b/lib/libesp32/berry/src/be_vector.h @@ -38,6 +38,7 @@ void be_vector_remove_end(bvector *vector); void be_vector_resize(bvm *vm, bvector *vector, int count); void be_vector_clear(bvector *vector); void* be_vector_release(bvm *vm, bvector *vector); +void* be_vector_release_32(bvm *vm, bvector *vector); /* specialized call for 32 bits aligned accesses */ int be_nextsize(int value); #endif diff --git a/lib/libesp32/Berry/src/be_vm.c b/lib/libesp32/berry/src/be_vm.c similarity index 95% rename from lib/libesp32/Berry/src/be_vm.c rename to lib/libesp32/berry/src/be_vm.c index 26c15a1a3..3032fa8ae 100644 --- a/lib/libesp32/Berry/src/be_vm.c +++ b/lib/libesp32/berry/src/be_vm.c @@ -55,7 +55,7 @@ #define COUNTER_HOOK() #endif -#if BE_USE_PERF_COUNTERS && BE_USE_OBSERVABILITY_HOOK +#if BE_USE_PERF_COUNTERS #define VM_HEARTBEAT() \ if ((vm->counter_ins & ((1<<(BE_VM_OBSERVABILITY_SAMPLING - 1))-1) ) == 0) { /* call every 2^BE_VM_OBSERVABILITY_SAMPLING instructions */ \ if (vm->obshook != NULL) \ @@ -461,9 +461,8 @@ BERRY_API bvm* be_vm_new(void) be_gc_setpause(vm, 1); be_loadlibs(vm); vm->compopt = 0; -#if BE_USE_OBSERVABILITY_HOOK vm->obshook = NULL; -#endif + vm->ctypefunc = NULL; #if BE_USE_PERF_COUNTERS vm->counter_ins = 0; vm->counter_enter = 0; @@ -598,8 +597,13 @@ newframe: /* a new call frame */ if (var_isint(a) && var_isint(b)) { var_setint(dst, ibinop(+, a, b)); } else if (var_isnumber(a) && var_isnumber(b)) { - breal x = var2real(a), y = var2real(b); - var_setreal(dst, x + y); + union bvaldata x, y; // TASMOTA workaround for ESP32 rev0 bug + x.i = a->v.i; + if (var_isint(a)) { x.r = (breal) x.i; } + y.i = b->v.i; + if (var_isint(b)) { y.r = (breal) y.i; } + // breal x = var2real(a), y = var2real(b); + var_setreal(dst, x.r + y.r); } else if (var_isstr(a) && var_isstr(b)) { /* strcat */ bstring *s = be_strcat(vm, var_tostr(a), var_tostr(b)); reg = vm->reg; @@ -1062,7 +1066,13 @@ newframe: /* a new call frame */ if (!IGET_RA(ins)) { be_except_block_setup(vm); if (be_setjmp(vm->errjmp->b)) { + bvalue *top = vm->top; + bvalue e1 = top[0]; + bvalue e2 = top[1]; be_except_block_resume(vm); + top = vm->top; + top[0] = e1; + top[1] = e2; goto newframe; } reg = vm->reg; @@ -1101,29 +1111,6 @@ newframe: /* a new call frame */ goto recall; /* call '()' method */ } case BE_CLOSURE: { - // bvalue *v, *end; - // bproto *proto = var2cl(var)->proto; /* get proto for closure */ - // push_closure(vm, var, proto->nstack, mode); /* prepare stack for closure */ - // reg = vm->reg; /* `reg` has changed, now new base register */ - // v = reg + argc; /* end of provided arguments */ - // end = reg + proto->argc; /* end of expected arguments */ - // for (; v < end; ++v) { /* set all not provided arguments to nil */ - // var_setnil(v); - // } - // if (proto->varg) { /* there are vararg at the last argument, build the list */ - // /* code below uses mostly low-level calls for performance */ - // be_stack_require(vm, argc + 2); /* make sure we don't overflow the stack */ - // bvalue *top_save = vm->top; /* save original stack, we need fresh slots to create the 'list' instance */ - // vm->top = v; /* move top of stack right after last argument */ - // be_newobject(vm, "list"); /* this creates 2 objects on stack: list instance, BE_LIST object */ - // blist *list = var_toobj(vm->top-1); /* get low-level BE_LIST structure */ - // v = reg + proto->argc - 1; /* last argument */ - // for (; v < reg + argc; v++) { - // be_list_push(vm, list, v); /* push all varargs into list */ - // } - // *(reg + proto->argc - 1) = *(vm->top-2); /* change the vararg argument to now contain the list instance */ - // vm->top = top_save; /* restore top of stack pointer */ - // } prep_closure(vm, var - reg, argc, mode); reg = vm->reg; /* `reg` has changed, now new base register */ goto newframe; /* continue execution of the closure */ @@ -1142,6 +1129,17 @@ newframe: /* a new call frame */ ret_native(vm); break; } + case BE_CTYPE_FUNC: { + if (vm->ctypefunc) { + push_native(vm, var, argc, mode); + const void* args = var_toobj(var); + vm->ctypefunc(vm, args); + ret_native(vm); + } else { + vm_error(vm, "internal_error", "missing ctype_func handler"); + } + break; + } case BE_MODULE: { bvalue attr; var_setstr(&attr, str_literal(vm, "()")); @@ -1195,7 +1193,7 @@ static void prep_closure(bvm *vm, int pos, int argc, int mode) for (v = vm->reg + argc; v <= end; ++v) { var_setnil(v); } - if (proto->varg) { /* there are vararg at the last argument, build the list */ + if (proto->varg & BE_VA_VARARG) { /* there are vararg at the last argument, build the list */ /* code below uses mostly low-level calls for performance */ be_stack_require(vm, argc + 2); /* make sure we don't overflow the stack */ bvalue *top_save = vm->top; /* save original stack, we need fresh slots to create the 'list' instance */ @@ -1269,7 +1267,15 @@ BERRY_API void be_set_obs_hook(bvm *vm, bobshook hook) (void)vm; /* avoid comiler warning */ (void)hook; /* avoid comiler warning */ -#if BE_USE_OBSERVABILITY_HOOK vm->obshook = hook; -#endif +} + +BERRY_API void be_set_ctype_func_hanlder(bvm *vm, bctypefunc handler) +{ + vm->ctypefunc = handler; +} + +BERRY_API bctypefunc be_get_ctype_func_hanlder(bvm *vm) +{ + return vm->ctypefunc; } diff --git a/lib/libesp32/Berry/src/be_vm.h b/lib/libesp32/berry/src/be_vm.h similarity index 98% rename from lib/libesp32/Berry/src/be_vm.h rename to lib/libesp32/berry/src/be_vm.h index 4d98c590f..35176cead 100644 --- a/lib/libesp32/Berry/src/be_vm.h +++ b/lib/libesp32/berry/src/be_vm.h @@ -100,10 +100,9 @@ struct bvm { bmap *ntvclass; /* native class table */ blist *registry; /* registry list */ struct bgc gc; + bctypefunc ctypefunc; /* handler to ctype_func */ bbyte compopt; /* compilation options */ -#if BE_USE_OBSERVABILITY_HOOK bobshook obshook; -#endif #if BE_USE_PERF_COUNTERS uint32_t counter_ins; /* instructions counter */ uint32_t counter_enter; /* counter for times the VM was entered */ diff --git a/lib/libesp32/Berry/src/berry.h b/lib/libesp32/berry/src/berry.h similarity index 98% rename from lib/libesp32/Berry/src/berry.h rename to lib/libesp32/berry/src/berry.h index e69a3bbe8..41619aa10 100644 --- a/lib/libesp32/Berry/src/berry.h +++ b/lib/libesp32/berry/src/berry.h @@ -402,12 +402,15 @@ typedef void(*bntvhook)(bvm *vm, bhookinfo *info); typedef void(*bobshook)(bvm *vm, int event, ...); enum beobshookevents { + BE_OBS_PCALL_ERROR, /* called when be_callp() returned an error, most likely an exception */ BE_OBS_GC_START, /* start of GC, arg = allocated size */ BE_OBS_GC_END, /* end of GC, arg = allocated size */ BE_OBS_VM_HEARTBEAT, /* VM heartbeat called every million instructions */ BE_OBS_STACK_RESIZE_START, /* Berry stack resized */ }; +typedef int (*bctypefunc)(bvm*, const void*); + /* FFI functions */ #define be_writestring(s) be_writebuffer((s), strlen(s)) #define be_writenewline() be_writebuffer("\n", 1) @@ -549,6 +552,8 @@ BERRY_API void be_vm_delete(bvm *vm); /* Observability hook */ BERRY_API void be_set_obs_hook(bvm *vm, bobshook hook); +BERRY_API void be_set_ctype_func_hanlder(bvm *vm, bctypefunc handler); +BERRY_API bctypefunc be_get_ctype_func_hanlder(bvm *vm); /* code load APIs */ BERRY_API int be_loadbuffer(bvm *vm, diff --git a/lib/libesp32/Berry/src/berry_conf.h b/lib/libesp32/berry/src/berry_conf.h similarity index 100% rename from lib/libesp32/Berry/src/berry_conf.h rename to lib/libesp32/berry/src/berry_conf.h diff --git a/lib/libesp32/Berry/testall.be b/lib/libesp32/berry/testall.be similarity index 100% rename from lib/libesp32/Berry/testall.be rename to lib/libesp32/berry/testall.be diff --git a/lib/libesp32/Berry/tests/assignment.be b/lib/libesp32/berry/tests/assignment.be similarity index 100% rename from lib/libesp32/Berry/tests/assignment.be rename to lib/libesp32/berry/tests/assignment.be diff --git a/lib/libesp32/berry/tests/bitwise.be b/lib/libesp32/berry/tests/bitwise.be new file mode 100644 index 000000000..e10fe1678 --- /dev/null +++ b/lib/libesp32/berry/tests/bitwise.be @@ -0,0 +1,14 @@ +# and, or, xor +a = 11 +assert(a & 0xFE == 10) +assert(a | 32 == 43) +assert(a ^ 33 == 42) + +# same with literal +assert(11 & 0xFE == 10) +assert(11 | 32 == 43) +assert(11 ^ 33 == 42) + +# flip +assert(~a == -12) +assert(~11 == -12) diff --git a/lib/libesp32/Berry/tests/bool.be b/lib/libesp32/berry/tests/bool.be similarity index 100% rename from lib/libesp32/Berry/tests/bool.be rename to lib/libesp32/berry/tests/bool.be diff --git a/lib/libesp32/Berry/tests/bytes.be b/lib/libesp32/berry/tests/bytes.be similarity index 100% rename from lib/libesp32/Berry/tests/bytes.be rename to lib/libesp32/berry/tests/bytes.be diff --git a/lib/libesp32/Berry/tests/bytes_b64.be b/lib/libesp32/berry/tests/bytes_b64.be similarity index 100% rename from lib/libesp32/Berry/tests/bytes_b64.be rename to lib/libesp32/berry/tests/bytes_b64.be diff --git a/lib/libesp32/Berry/tests/bytes_fixed.be b/lib/libesp32/berry/tests/bytes_fixed.be similarity index 100% rename from lib/libesp32/Berry/tests/bytes_fixed.be rename to lib/libesp32/berry/tests/bytes_fixed.be diff --git a/lib/libesp32/berry/tests/call.be b/lib/libesp32/berry/tests/call.be new file mode 100644 index 000000000..c0964d7d8 --- /dev/null +++ b/lib/libesp32/berry/tests/call.be @@ -0,0 +1,102 @@ +#- -# +#- witness function dumping first 3 args -# +#- -# +def f(a,b,c) return [a,b,c] end + +#- simple calls with fixed args -# +assert(call(f) == [nil, nil, nil]) +assert(call(f, 1) == [1, nil, nil]) +assert(call(f, 1, 2) == [1, 2, nil]) +assert(call(f, 1, 2, 3, 4) == [1, 2, 3]) + +#- call with var args -# +assert(call(f, []) == [nil, nil, nil]) +assert(call(f, [1]) == [1, nil, nil]) +assert(call(f, [1, 2]) == [1, 2, nil]) +assert(call(f, [1, 2, 3, 4]) == [1, 2, 3]) + +#- mixed args -# +assert(call(f, 1, []) == [1, nil, nil]) +assert(call(f, 1, [2]) == [1, 2, nil]) +assert(call(f, 1, [2, "foo", 4]) == [1, 2, "foo"]) + +#- non terminal list -# +assert(call(f, 1, [2, 3, 4], "foo") == [1, [2, 3, 4], "foo"]) + +#- -# +#- same tests with vararg function -# +#- -# +def g(a, *b) + if size(b) == 0 return [a, nil, nil] + elif size(b) == 1 return [a, b[0], nil] + elif size(b) > 1 return [a, b[0], b[1]] + end +end + +#- simple calls with fixed args -# +assert(call(g) == [nil, nil, nil]) +assert(call(g, 1) == [1, nil, nil]) +assert(call(g, 1, 2) == [1, 2, nil]) +assert(call(g, 1, 2, 3, 4) == [1, 2, 3]) + +#- call with var args -# +assert(call(g, []) == [nil, nil, nil]) +assert(call(g, [1]) == [1, nil, nil]) +assert(call(g, [1, 2]) == [1, 2, nil]) +assert(call(g, [1, 2, 3, 4]) == [1, 2, 3]) + +#- mixed args -# +assert(call(g, 1, []) == [1, nil, nil]) +assert(call(g, 1, [2]) == [1, 2, nil]) +assert(call(g, 1, [2, "foo", 4]) == [1, 2, "foo"]) + +#- non terminal list -# +assert(call(g, 1, [2, 3, 4], "foo") == [1, [2, 3, 4], "foo"]) + +#- -# +#- test with vararg only -# +#- -# +def c(*a) return size(a) end + +#- simple calls with fixed args -# +assert(call(c) == 0) +assert(call(c, 1) == 1) +assert(call(c, 1, 2) == 2) +assert(call(c, 1, 2, 3, 4) == 4) + +#- call with var args -# +assert(call(c, []) == 0) +assert(call(c, [1]) == 1) +assert(call(c, [1, 2]) == 2) +assert(call(c, [1, 2, 3, 4]) == 4) + +#- mixed args -# +assert(call(c, 1, []) == 1) +assert(call(c, 1, [2]) == 2) +assert(call(c, 1, [2, "foo", 4]) == 4) + +#- non terminal list -# +assert(call(c, 1, [2, 3, 4], "foo") == 3) + +#- -# +#- test with native function -# +#- -# +import string + +assert(call(string.format, "a") == "a") +assert(call(string.format, "%i", 1) == "1") +assert(call(string.format, "%i - %i", 1, 2) == "1 - 2") + +assert(call(string.format, "%i - %i", [1, 2]) == "1 - 2") +assert(call(string.format, "%i - %i", [1, 2, 3]) == "1 - 2") + +assert(call(string.format, "%i - %i", 1, [1, 2, 3]) == "1 - 1") + +#- -# +#- try with an insanely high number of arguments to check that we don't blow up the stack -# +#- -# +l50 = [] +for i:1..50 l50.push(i) end + +assert(call(g, l50) == [1, 2, 3]) +assert(call(c, l50) == 50) diff --git a/lib/libesp32/Berry/tests/checkspace.be b/lib/libesp32/berry/tests/checkspace.be similarity index 100% rename from lib/libesp32/Berry/tests/checkspace.be rename to lib/libesp32/berry/tests/checkspace.be diff --git a/lib/libesp32/Berry/tests/class.be b/lib/libesp32/berry/tests/class.be similarity index 100% rename from lib/libesp32/Berry/tests/class.be rename to lib/libesp32/berry/tests/class.be diff --git a/lib/libesp32/Berry/tests/class_const.be b/lib/libesp32/berry/tests/class_const.be similarity index 100% rename from lib/libesp32/Berry/tests/class_const.be rename to lib/libesp32/berry/tests/class_const.be diff --git a/lib/libesp32/berry/tests/class_static.be b/lib/libesp32/berry/tests/class_static.be new file mode 100644 index 000000000..e8f4c1920 --- /dev/null +++ b/lib/libesp32/berry/tests/class_static.be @@ -0,0 +1,122 @@ +def assert_attribute_error(f) + try + f() + assert(false, 'unexpected execution flow') + except .. as e, m + assert(e == 'attribute_error') + end +end + +class A + static a + def init() self.b = 2 end + def f() end + var b + static c, s, r +end + +assert(A.a == nil) +assert(A.c == nil) +assert(A.s == nil) +assert_attribute_error(/-> A.b) +assert_attribute_error(/-> A.d) + +a = A() +assert(a.b == 2) +assert(a.a == nil) +assert(a.c == nil) + +A.a = 1 +A.c = 3 +A.s = "foo" +A.r = 3.5 +assert(a.a == 1) +assert(a.c == 3) +assert(A.a == 1) +assert(A.c == 3) +import gc gc.collect() +assert(A.s == "foo") +assert(a.s == "foo") +assert(A.r == 3.5) +assert(a.r == 3.5) + +#- test valid or invalid methods and members -# + +def assert_attribute_error(c) + try + compile(c)() + assert(false, 'unexpected execution flow') + except .. as e, m + assert(e == 'attribute_error') + end +end + +class A + var a, g + static h + def init() self.a = 1 end + def f(x, y) return type(self) end +end +a=A() +a.g = def (x, y) return type(x) end +A.h = def (x, y) return type(x) end + +assert(type(a.g) == 'function') +assert(type(a.h) == 'function') + +assert(a.g(1) == 'int') +assert(a.h(1) == 'int') +assert(A.h(1) == 'int') + + +class A + var a + static def g(x, y) return [x,y] end + static h = def (x, y) return [x,y] end + def init() self.a = 1 end + def f(x, y) return type(self) end +end +a=A() +assert(type(a.g) == 'function') +assert(type(a.h) == 'function') +assert(type(A.g) == 'function') +assert(type(A.h) == 'function') +assert(a.g(1,2) == [1,2]) +assert(a.h(1,2) == [1,2]) +assert(A.g(1,2) == [1,2]) +assert(A.h(1,2) == [1,2]) +a.a = def (x,y) return [x,y] end +assert(a.a(1,2) == [1,2]) + + +#- test static initializers -# +class A + static a = 1, b, c = 3.5, d = 42, e = "foo", f = [1], g = {} + var aa,ab +end + +assert(A.a == 1) +assert(A.b == nil) +assert(A.c == 3.5) +assert(A.d == 42) +assert(A.e == "foo") +assert(A.f == [1]) + +a = A() +assert(a.a == 1) +assert(a.b == nil) +assert(a.c == 3.5) +assert(a.d == 42) +assert(a.e == "foo") +assert(a.f == [1]) +assert(a.g == A.g) +assert(a.aa == nil) +assert(a.ab == nil) + +#- used to fail for subclasses -# +class A static a=1 end +class B:A static a=A def f() end static b=1 static c=A end +assert(A.a == 1) +assert(B.a == A) +assert(B.b == 1) +assert(B.c == A) diff --git a/lib/libesp32/Berry/tests/closure.be b/lib/libesp32/berry/tests/closure.be similarity index 100% rename from lib/libesp32/Berry/tests/closure.be rename to lib/libesp32/berry/tests/closure.be diff --git a/lib/libesp32/Berry/tests/compiler.be b/lib/libesp32/berry/tests/compiler.be similarity index 100% rename from lib/libesp32/Berry/tests/compiler.be rename to lib/libesp32/berry/tests/compiler.be diff --git a/lib/libesp32/Berry/tests/compound.be b/lib/libesp32/berry/tests/compound.be similarity index 59% rename from lib/libesp32/Berry/tests/compound.be rename to lib/libesp32/berry/tests/compound.be index bda74c9e2..b75c2dc52 100644 --- a/lib/libesp32/Berry/tests/compound.be +++ b/lib/libesp32/berry/tests/compound.be @@ -16,4 +16,13 @@ assert(a.a == 6) b=A() assert(b.a == 1) b.g(10) -assert(b.a == 6) \ No newline at end of file +assert(b.a == 6) + +# bug in compound assignments +class A var a,b end +c=A() +c.a = {"x": 1, "y": 2} +c.b = "x" +assert(c.a[c.b] == 1) +c.a[c.b] += 2 # this is where the bug happens +assert(c.a[c.b] == 3) diff --git a/lib/libesp32/Berry/tests/cond_expr.be b/lib/libesp32/berry/tests/cond_expr.be similarity index 100% rename from lib/libesp32/Berry/tests/cond_expr.be rename to lib/libesp32/berry/tests/cond_expr.be diff --git a/lib/libesp32/Berry/tests/debug.be b/lib/libesp32/berry/tests/debug.be similarity index 100% rename from lib/libesp32/Berry/tests/debug.be rename to lib/libesp32/berry/tests/debug.be diff --git a/lib/libesp32/berry/tests/exceptions.be b/lib/libesp32/berry/tests/exceptions.be new file mode 100644 index 000000000..dc2ad54e4 --- /dev/null +++ b/lib/libesp32/berry/tests/exceptions.be @@ -0,0 +1,7 @@ + +try + for k: 0..1 assert({'a':1}.contains('b'), 'failure') end +except .. as e,m + assert(e == "assert_failed") + assert(m == "failure") +end diff --git a/lib/libesp32/Berry/tests/for.be b/lib/libesp32/berry/tests/for.be similarity index 100% rename from lib/libesp32/Berry/tests/for.be rename to lib/libesp32/berry/tests/for.be diff --git a/lib/libesp32/Berry/tests/function.be b/lib/libesp32/berry/tests/function.be similarity index 100% rename from lib/libesp32/Berry/tests/function.be rename to lib/libesp32/berry/tests/function.be diff --git a/lib/libesp32/Berry/tests/global.be b/lib/libesp32/berry/tests/global.be similarity index 100% rename from lib/libesp32/Berry/tests/global.be rename to lib/libesp32/berry/tests/global.be diff --git a/lib/libesp32/Berry/tests/introspect.be b/lib/libesp32/berry/tests/introspect.be similarity index 100% rename from lib/libesp32/Berry/tests/introspect.be rename to lib/libesp32/berry/tests/introspect.be diff --git a/lib/libesp32/berry/tests/introspect_ismethod.be b/lib/libesp32/berry/tests/introspect_ismethod.be new file mode 100644 index 000000000..5692285a1 --- /dev/null +++ b/lib/libesp32/berry/tests/introspect_ismethod.be @@ -0,0 +1,29 @@ +# test for introspect.ismethod +import introspect + +# ismethod should return nil for any non-Berry closure +assert(introspect.ismethod() == nil) +assert(introspect.ismethod(true) == nil) +assert(introspect.ismethod("a") == nil) +assert(introspect.ismethod([]) == nil) +assert(introspect.ismethod({}) == nil) +assert(introspect.ismethod(introspect) == nil) # module +assert(introspect.ismethod(introspect.ismethod) == nil) # native method + +def h() end + +class A + def f() end + static def g() end + var h +end +a=A() +a.h = h + +assert(introspect.ismethod(h) == false) +assert(introspect.ismethod(A.f) == true) +assert(introspect.ismethod(A.g) == false) + +assert(introspect.ismethod(a.f) == true) +assert(introspect.ismethod(a.g) == false) +assert(introspect.ismethod(a.h) == false) diff --git a/lib/libesp32/Berry/tests/json.be b/lib/libesp32/berry/tests/json.be similarity index 92% rename from lib/libesp32/Berry/tests/json.be rename to lib/libesp32/berry/tests/json.be index ee009755b..6e1aaaf8d 100644 --- a/lib/libesp32/Berry/tests/json.be +++ b/lib/libesp32/berry/tests/json.be @@ -51,3 +51,8 @@ assert_dump({1: 'x'}, '{"1":"x"}'); assert_dump([1, 'x'], '[\n 1,\n "x"\n]', 'format'); assert_dump({1: 'x'}, '{\n "1": "x"\n}', 'format'); assert_dump({1: 'x', 'k': 'v'}, '{"k":"v","1":"x"}'); + +class map2 : map def init() super(self).init() end end +var m = map2() +m['key'] = 1 +assert_dump(m, '{"key":1}') diff --git a/lib/libesp32/Berry/tests/lexer.be b/lib/libesp32/berry/tests/lexer.be similarity index 95% rename from lib/libesp32/Berry/tests/lexer.be rename to lib/libesp32/berry/tests/lexer.be index abdb4d903..2114cab54 100644 --- a/lib/libesp32/Berry/tests/lexer.be +++ b/lib/libesp32/berry/tests/lexer.be @@ -38,7 +38,6 @@ check(45.e+2, 4500) test_source('x = 5; 0...x;', 'unexpected symbol near \'.\'') test_source('x = 5; 0...x;', 'unexpected symbol near \'.\'') -# test_source('45..', 'unexpected symbol near \'EOS\'') test_source('0xg', 'invalid hexadecimal number') test_source('"\\x5g"', 'invalid hexadecimal number') test_source('0x5g', 'malformed number') diff --git a/lib/libesp32/Berry/tests/lexergc.be b/lib/libesp32/berry/tests/lexergc.be similarity index 100% rename from lib/libesp32/Berry/tests/lexergc.be rename to lib/libesp32/berry/tests/lexergc.be diff --git a/lib/libesp32/Berry/tests/list.be b/lib/libesp32/berry/tests/list.be similarity index 100% rename from lib/libesp32/Berry/tests/list.be rename to lib/libesp32/berry/tests/list.be diff --git a/lib/libesp32/berry/tests/map.be b/lib/libesp32/berry/tests/map.be new file mode 100644 index 000000000..ca0c4399d --- /dev/null +++ b/lib/libesp32/berry/tests/map.be @@ -0,0 +1,32 @@ +m = { 'a':1, 'b':3.5, 'c': "foo", 0:1} + +assert(type(m) == 'instance') +assert(classname(m) == 'map') + +# accessor +assert(m['a'] == 1) +assert(m['b'] == 3.5) +assert(m['c'] == 'foo') +assert(m[0] == 1) + +# find +assert(m.find('a') == 1) +assert(m.find('z') == nil) +assert(m.find('z', 4) == 4) + +# contains +assert(m.contains('a')) +assert(m.contains(0)) +assert(!m.contains('z')) +assert(!m.contains()) + +# set +m['y'] = -1 +assert(m['y'] == -1) + +# remove +m={1:2} +m.remove(2) +assert(str(m) == '{1: 2}') +m.remove(1) +assert(str(m) == '{}') diff --git a/lib/libesp32/berry/tests/math.be b/lib/libesp32/berry/tests/math.be new file mode 100644 index 000000000..12facca63 --- /dev/null +++ b/lib/libesp32/berry/tests/math.be @@ -0,0 +1,14 @@ +import math + +#- nan -# +n = math.nan +assert(str(n) == 'nan') +assert(math.isnan(n)) +assert(math.isnan(n+n)) +assert(math.isnan(n+1)) +assert(math.isnan(n*0)) + +assert(!math.isnan(0)) +assert(!math.isnan(1.5)) + +assert(n != n) #- nan is never identical to itself -# diff --git a/lib/libesp32/Berry/tests/member_indirect.be b/lib/libesp32/berry/tests/member_indirect.be similarity index 100% rename from lib/libesp32/Berry/tests/member_indirect.be rename to lib/libesp32/berry/tests/member_indirect.be diff --git a/lib/libesp32/Berry/tests/os.be b/lib/libesp32/berry/tests/os.be similarity index 100% rename from lib/libesp32/Berry/tests/os.be rename to lib/libesp32/berry/tests/os.be diff --git a/lib/libesp32/Berry/tests/overload.be b/lib/libesp32/berry/tests/overload.be similarity index 100% rename from lib/libesp32/Berry/tests/overload.be rename to lib/libesp32/berry/tests/overload.be diff --git a/lib/libesp32/Berry/tests/relop.be b/lib/libesp32/berry/tests/relop.be similarity index 100% rename from lib/libesp32/Berry/tests/relop.be rename to lib/libesp32/berry/tests/relop.be diff --git a/lib/libesp32/berry/tests/string.be b/lib/libesp32/berry/tests/string.be new file mode 100644 index 000000000..6c551bf4e --- /dev/null +++ b/lib/libesp32/berry/tests/string.be @@ -0,0 +1,82 @@ +import string as s + +assert(s.find('012345', '23') == 2) +assert(s.find('012345', '23', 1) == 2) +assert(s.find('012345', '23', 1, 3) == -1) +assert(s.find('012345', '23', 2, 4) == 2) +assert(s.find('012345', '23', 3) == -1) + +assert(s.find('012345', '') == 0) +assert(s.find('012345', '', 0, 0) == 0) +assert(s.find('012345', '', 1) == 1) +assert(s.find('012345', '', 1, 1) == 1) +assert(s.find('012345', '', 1, 0) == -1) +assert(s.find('012345', '', 6) == 6) +assert(s.find('012345', '', 7) == -1) + +assert(s.count('012345', '') == 7) +assert(s.count('012345', '', 2) == 5) +assert(s.count('012345', '', 6) == 1) + +assert(s.count('121314', '1') == 3) +assert(s.count('121314', '1', 1) == 2) +assert(s.count('121314', '1', 2) == 2) +assert(s.count('121314', '1', 1, 2) == 0) +assert(s.count('121314', '1', 1, 3) == 1) + +assert(s.split('a b c d e f', '1') == ['a b c d e f']) +assert(s.split('a b c d e f', ' ') == ['a', 'b', 'c', 'd', 'e', 'f']) +assert(s.split('a b c d e f', ' ', 2) == ['a', 'b', 'c d e f']) +assert(s.split('a b c d e f', '') == ['a b c d e f']) + +assert(s.format("%%") == "%") +assert(s.format("%i%%", 12) == "12%") +assert(s.format("%i%%%i", 12, 13) == "12%13") +assert(s.format("%s%%", "foo") == "foo%") +assert(s.format("%.1f%%", 3.5) == "3.5%") + +s="azerty" +assert(s[1..2] == "ze") +assert(s[1..] == "zerty") +assert(s[1..-1] == "zerty") + +#- string ranges -# +s="azertyuiop" +assert(s[0] == "a") +assert(s[0..1] == "az") +assert(s[0..2] == "aze") +assert(s[0..10] == s) +assert(s[0..size(s)] == s) +assert(s[0..50] == s) #- upper limit is allowed to be out of range -# + +#- negative indices start from the end -# +s="azertyuiop" +assert(s[-1] == "p") +assert(s[-2] == "o") +assert(s[0..-2] == "azertyuio") +assert(s[-4..-2] == "uio") +assert(s[-2..-4] == "") #- if range is in wrong order, returns empty string -# +assert(s[-40..-2] == "azertyuio") #- borders are allowed to be out of range -# + +# escape +import string +assert(string.escape("A") == '"A"') +assert(string.escape("A", true) == "'A'") +assert(string.escape("\"") == '"\\""') +assert(string.escape("\"", true) == '\'"\'') + +var s ='"a\'b"\'' +assert(string.escape(s) == '"\\"a\'b\\"\'"') +assert(string.escape(s, true) == '\'"a\\\'b"\\\'\'') + +# tr +assert(string.tr("azer", "abcde", "ABCDE") == 'AzEr') +assert(string.tr("azer", "", "") == 'azer') +assert(string.tr("azer", "aaa", "ABC") == 'Azer') # only first match works +assert(string.tr("A_b", "_", " ") == 'A b') +# tr used to remove characters +assert(string.tr("qwerty", "qwe", "_") == '_rty') + +# the following should not crash +var s1 = 'A string of more than 128 bytes 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' +var s2 = string.format("%i, %s", 1, s1) diff --git a/lib/libesp32/Berry/tests/subobject.be b/lib/libesp32/berry/tests/subobject.be similarity index 100% rename from lib/libesp32/Berry/tests/subobject.be rename to lib/libesp32/berry/tests/subobject.be diff --git a/lib/libesp32/Berry/tests/suffix.be b/lib/libesp32/berry/tests/suffix.be similarity index 100% rename from lib/libesp32/Berry/tests/suffix.be rename to lib/libesp32/berry/tests/suffix.be diff --git a/lib/libesp32/Berry/tests/super_auto.be b/lib/libesp32/berry/tests/super_auto.be similarity index 100% rename from lib/libesp32/Berry/tests/super_auto.be rename to lib/libesp32/berry/tests/super_auto.be diff --git a/lib/libesp32/Berry/tests/super_leveled.be b/lib/libesp32/berry/tests/super_leveled.be similarity index 100% rename from lib/libesp32/Berry/tests/super_leveled.be rename to lib/libesp32/berry/tests/super_leveled.be diff --git a/lib/libesp32/Berry/tests/vararg.be b/lib/libesp32/berry/tests/vararg.be similarity index 100% rename from lib/libesp32/Berry/tests/vararg.be rename to lib/libesp32/berry/tests/vararg.be diff --git a/lib/libesp32/Berry/tests/virtual_methods.be b/lib/libesp32/berry/tests/virtual_methods.be similarity index 100% rename from lib/libesp32/Berry/tests/virtual_methods.be rename to lib/libesp32/berry/tests/virtual_methods.be diff --git a/lib/libesp32/Berry/tests/virtual_methods2.be b/lib/libesp32/berry/tests/virtual_methods2.be similarity index 100% rename from lib/libesp32/Berry/tests/virtual_methods2.be rename to lib/libesp32/berry/tests/virtual_methods2.be diff --git a/lib/libesp32/Berry/tools/grammar/berry.bytecode b/lib/libesp32/berry/tools/grammar/berry.bytecode similarity index 100% rename from lib/libesp32/Berry/tools/grammar/berry.bytecode rename to lib/libesp32/berry/tools/grammar/berry.bytecode diff --git a/lib/libesp32/Berry/tools/grammar/berry.ebnf b/lib/libesp32/berry/tools/grammar/berry.ebnf similarity index 100% rename from lib/libesp32/Berry/tools/grammar/berry.ebnf rename to lib/libesp32/berry/tools/grammar/berry.ebnf diff --git a/lib/libesp32/Berry/tools/grammar/const_obj.ebnf b/lib/libesp32/berry/tools/grammar/const_obj.ebnf similarity index 100% rename from lib/libesp32/Berry/tools/grammar/const_obj.ebnf rename to lib/libesp32/berry/tools/grammar/const_obj.ebnf diff --git a/lib/libesp32/Berry/tools/grammar/json.ebnf b/lib/libesp32/berry/tools/grammar/json.ebnf similarity index 100% rename from lib/libesp32/Berry/tools/grammar/json.ebnf rename to lib/libesp32/berry/tools/grammar/json.ebnf diff --git a/lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/.vsixmanifest b/lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/.vsixmanifest similarity index 100% rename from lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/.vsixmanifest rename to lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/.vsixmanifest diff --git a/lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/CHANGELOG.md b/lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/CHANGELOG.md similarity index 100% rename from lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/CHANGELOG.md rename to lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/CHANGELOG.md diff --git a/lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/README.md b/lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/README.md similarity index 100% rename from lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/README.md rename to lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/README.md diff --git a/lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/berry-configuration.json b/lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/berry-configuration.json similarity index 100% rename from lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/berry-configuration.json rename to lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/berry-configuration.json diff --git a/lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/berry-icon.png b/lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/berry-icon.png similarity index 100% rename from lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/berry-icon.png rename to lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/berry-icon.png diff --git a/lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/package.json b/lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/package.json similarity index 100% rename from lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/package.json rename to lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/package.json diff --git a/lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/syntaxes/berry.json b/lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/syntaxes/berry.json similarity index 100% rename from lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/syntaxes/berry.json rename to lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/syntaxes/berry.json diff --git a/lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/syntaxes/bytecode.json b/lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/syntaxes/bytecode.json similarity index 100% rename from lib/libesp32/Berry/tools/plugins/vscode/skiars.berry-0.1.0/syntaxes/bytecode.json rename to lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/syntaxes/bytecode.json diff --git a/lib/libesp32/Berry/tools/pycoc/block_builder.py b/lib/libesp32/berry/tools/pycoc/block_builder.py similarity index 100% rename from lib/libesp32/Berry/tools/pycoc/block_builder.py rename to lib/libesp32/berry/tools/pycoc/block_builder.py diff --git a/lib/libesp32/Berry/tools/pycoc/coc_parser.py b/lib/libesp32/berry/tools/pycoc/coc_parser.py similarity index 75% rename from lib/libesp32/Berry/tools/pycoc/coc_parser.py rename to lib/libesp32/berry/tools/pycoc/coc_parser.py index c31e35814..e73ef7665 100644 --- a/lib/libesp32/Berry/tools/pycoc/coc_parser.py +++ b/lib/libesp32/berry/tools/pycoc/coc_parser.py @@ -74,12 +74,25 @@ class coc_parser: self.text = self.text[r.end(0):] return r[0] + # parse until the next comma or space (trim preceding spaces before) + # does not skip the comma def parse_tocomma(self): self.skip_space() r = re.match(r"[^,\s]*", self.text) self.text = self.text[r.end(0):] return r[0] + # parse until the next closing parenthesis or a single token if no parenthesis (trim preceding spaces before) + # matches: + # 'int' + # 'func(aa)' + # 'mapped_func(aa,"ee", "aa") + def parse_value(self): + self.skip_space() + r = re.match(r"(\S+\(.*?\))|([^,\s]*)", self.text) + self.text = self.text[r.end(0):] + return r[0] + def parse_tonewline(self): self.skip_space() r = re.match(r"[^\r\n]*", self.text) @@ -87,6 +100,7 @@ class coc_parser: return r[0] def parse_object(self): + self.text = re.sub("\s+//.*?$", "", self.text, flags=re.MULTILINE) # remove trailing comments while True: obj = self.parse_block() self.objects.append(obj) @@ -105,11 +119,15 @@ class coc_parser: self.strtab.add(literal) # print(f"str '{ident}' -> {literal}") + ################################################################################# + # Parse a block of definition like module, class... + ################################################################################# def parse_block(self): obj = object_block() obj.type = self.parse_word() obj.name = self.parse_word() # print(f"parse_block: type={obj.type} name={obj.name}") + # # ex: 'parse_block: type=module name=gpio' self.parse_attr(obj) self.parse_body(obj) return obj @@ -127,6 +145,9 @@ class coc_parser: value = self.parse_word() obj.attr[key] = value + ################################################################################# + # Parse the body definition of a class, module... + ################################################################################# def parse_body(self, obj): self.skip_char("{") if not self.parse_char("}"): @@ -134,12 +155,16 @@ class coc_parser: self.parse_body_item(obj) if self.parse_char("}"): break + ################################################################################# + # Parse each line item in the module/class/vartab + ################################################################################# def parse_body_item(self, obj): value = data_value() key = self.parse_tocomma() # print(f"Key={key}") - self.parse_char_continue(",", True) - value.value = self.parse_tocomma() + self.parse_char_continue(",", True) # skip the ',' after the key + value.value = self.parse_value() + # print(f"value.value={value.value}") if self.parse_char_continue(","): value.depend = self.parse_tonewline() obj.data[key] = value diff --git a/lib/libesp32/Berry/tools/pycoc/coc_string.py b/lib/libesp32/berry/tools/pycoc/coc_string.py similarity index 100% rename from lib/libesp32/Berry/tools/pycoc/coc_string.py rename to lib/libesp32/berry/tools/pycoc/coc_string.py diff --git a/lib/libesp32/Berry/tools/pycoc/coc_string_test.py b/lib/libesp32/berry/tools/pycoc/coc_string_test.py similarity index 100% rename from lib/libesp32/Berry/tools/pycoc/coc_string_test.py rename to lib/libesp32/berry/tools/pycoc/coc_string_test.py diff --git a/lib/libesp32/Berry/tools/pycoc/hash_map.py b/lib/libesp32/berry/tools/pycoc/hash_map.py similarity index 90% rename from lib/libesp32/Berry/tools/pycoc/hash_map.py rename to lib/libesp32/berry/tools/pycoc/hash_map.py index 5686a0342..9d3da5365 100644 --- a/lib/libesp32/Berry/tools/pycoc/hash_map.py +++ b/lib/libesp32/berry/tools/pycoc/hash_map.py @@ -111,6 +111,9 @@ class hash_map: self.insert_p(key, value) self.count += 1 + ################################################################################# + # Compute entries in the hash for modules or classes + ################################################################################# # return a list (entiry, var_count) def entry_modify(self, ent, var_count): ent.key = escape_operator(ent.key) @@ -121,6 +124,7 @@ class hash_map: ent.value = "be_const_" + ent.value return (ent, var_count) + # generate the final map def entry_list(self): l = [] var_count = 0 @@ -128,6 +132,9 @@ class hash_map: self.resize(self.count) for it in self.bucket: (ent, var_count) = self.entry_modify(it, var_count) + # print(f"ent={ent} var_count={var_count}") + # # ex: ent= var_count=0 + # # ex: ent= var_count=0 l.append(ent) return l diff --git a/lib/libesp32/Berry/tools/pycoc/macro_table.py b/lib/libesp32/berry/tools/pycoc/macro_table.py similarity index 100% rename from lib/libesp32/Berry/tools/pycoc/macro_table.py rename to lib/libesp32/berry/tools/pycoc/macro_table.py diff --git a/lib/libesp32/Berry/tools/pycoc/main.py b/lib/libesp32/berry/tools/pycoc/main.py similarity index 100% rename from lib/libesp32/Berry/tools/pycoc/main.py rename to lib/libesp32/berry/tools/pycoc/main.py diff --git a/lib/libesp32/Berry/tools/pycoc/str_build.py b/lib/libesp32/berry/tools/pycoc/str_build.py similarity index 100% rename from lib/libesp32/Berry/tools/pycoc/str_build.py rename to lib/libesp32/berry/tools/pycoc/str_build.py diff --git a/lib/libesp32/berry_mapping/.gitignore b/lib/libesp32/berry_mapping/.gitignore new file mode 100644 index 000000000..73aa65c88 --- /dev/null +++ b/lib/libesp32/berry_mapping/.gitignore @@ -0,0 +1,73 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex +/berry +*.bec + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Test files +*.gcda +*.gcno +*.info +test_report/ + +# Ctags +tags + +# other +*.out.* +*.user +.vscode +.DS_Store +generate/ +temp/ +.idea +__pycache__ diff --git a/lib/libesp32/berry_mapping/LICENSE b/lib/libesp32/berry_mapping/LICENSE new file mode 100644 index 000000000..a509e8d3a --- /dev/null +++ b/lib/libesp32/berry_mapping/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2021 Stephan Hadinger, Guan Wenliang + +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. \ No newline at end of file diff --git a/lib/libesp32/berry_mapping/README.md b/lib/libesp32/berry_mapping/README.md new file mode 100644 index 000000000..f9ec646d3 --- /dev/null +++ b/lib/libesp32/berry_mapping/README.md @@ -0,0 +1,211 @@ +# Berry mapping to C functions, aka "ctype functions" + +This library provides a simplified and semi-automated way to map C functions to Berry functions with minimal effort and minimal code size. + +This library was originally designed for LVGL mapping to Berry, which implies mapping of hundreds of C function. It was later extended as a generalized `C` mapping mechanism. + +Warning: for this library to work, the `C` stack needs to have the same size for `int` and `void*` pointers (all 32 bits or all 64 bits). Otherwise the layout of the calling stack is too complex to handle. On ESP32 and most embedded 32 bits systems, this should not be an issue. + +## Quick example + +Let's create a simple module skeleton with 3 functions: + +- `addint`: simple function that adds two ints +- `ftoc`: converts Fahrenheit real to Celsius real +- `yesno` that transforms an int into a constant string + +Below we have the three pure `C` functions that we want to map: + +``` C +/* sum two ints */ +int addint(int a, int b) +{ + return a + b; +} + +/* returns 'yes' or 'no' depending on v being true */ +const char* yesno(int v) +{ + return v ? "yes" : "no"; +} + +/* fahrenheit to celsius, forcing to float to avoid using double libs */ +const float f2c(float f) +{ + return (f - 32.0f) / 1.8f; +} +``` + +The following mapping is done with this lib: + +``` C +#include "be_mapping.c" + +int f_addint(bvm *vm) { + return be_call_c_func(vm, (void*) &addint, "i", "ii"); +} + +int f_ftoc(bvm *vm) { + return be_call_c_func(vm, (void*) &ftoc, "f", "f"); +} + +int f_yesno(bvm *vm) { + return be_call_c_func(vm, (void*) &yesno, "s", "i"); +} +``` + +Now we add a typical module stub declaring the three functions in a module named `demo`. + +``` C +#include "be_constobj.h" + +/* @const_object_info_begin +module test (scope: global) { + addint, func(f_addint) + ftoc, func(f_ftoc) + yesno, func(f_yesno) +} +@const_object_info_end */ +#include "../generate/be_fixed_demo.h" +``` + +## Argument types + +The core function is `be_call_c_func()` and does the conversion from Berry argument to C argument, with optional type checking. + +When calling a `C` function, here are the steps applied: + +1. Automatically convert Berry typed argument to implicit `C` types (see below) +2. (optional) Apply type checking and abort the call if arguments are invalid +3. Call the `C` function +4. Apply conversion from `C` result to Berry type + + +### Conversion from Berry types to C types + +`be_call_c_func()` does introspection on Berry types for each argument and applies automatic conversion + +Berry type|converted to C type +:---|:--- +`int`|`intptr_t` (i.e. `int` large enough to hold a pointer.

If a type `r` (real) is expected, the value is silently converted to `breal` +`real`|`breal` (either `float` or `double`) +`bool`|`intptr_t` with value `1` if `true` or `0` if `false` +`string`|`const char*` C string `NULL` terminated (cannot be modified) +`nil`|`void*` with value `NULL` +`comptr`|`void*` native pointer +`instance` of `bytes`|In case of an instance of type `bytes` or any subclass, the argument is converted to the pointer to the internal buffer `_buffer`. This is equivalent to a `C` `struct` +`instance` of any other class|In case of an instance, the engine search for an instance variable `_p` or `.p`, and applies the conversion recursively.
This is handy when an instance contains a pointer to a native C structure as `comptr`. + +### Argument type checking + +This phase is optional and checks that there is the right number of arguments and the right types, according to the type definition described as a string. + +Note: callbacks need an explicit type definition to be handled correctly + +Argument type|Berry type expected +:---|:--- +`i`|`int` +`f`|`real` (if arg is `int` it is silently converted to `real`) +`b`|`bool` (no implicit conversion, use `bool()` to force bool type) +`s`|`string` +`c`|`comptr` (native pointer) +`.`|**any** - no type checking for this argument +`-`|**skip** - skip this argument (handy to discard the `self` implicit argument for methods) +`~`|send the length of the previous bytes() buffer (or raise an exception if no length known) +`()`|`instance` deriving from `` (i.e. of this class or any subclass +`^^`|`function` which is converted to a `C` callback by calling `cb.make_cb()`. The optional `callback_type` string is passed as second argument to `cb.make_cb()` and Berrt `arg #1` (typically `self`) is passed as 3rd argument
See below for callbacks +`[<...>]`|arguments in brackets are optional (note: the closing bracket is not strictly necessary but makes it more readable) + +Example: + +`-ib(lv_obj)` means: 1/ skip arg1, 2/ arg2 must be `int`, 3/ arg3 must be `bool`, 4/ arg4 must be an instance of `lv_obj` or subclass and its attribute `_p` or `.p` is passed. The final `C` function is passed 3 arguments. +`ii[.]` means: the first two arguments must be `int` and there can be an optional third argument of any type. + +### Return type + +The return type defines how the `C` result (intptr_t) is converted to any other Berry type. + +Return type definition|Berry return type +:---|:--- +`''` (empty string)|`nil` - no return value, equivalent to `C` `void` +`i`|`int` +`f`|(float) `real` (warning `intptr_t` and `breal` must be of same size) +`s`|`string` - `const char*` is converted to `C` string, a copy of the string is made so the original string can be modified +`b`|`bool` - any non-zero value is converted to `true` +`c`|`comptr` - native pointer +`` or ``|Instanciate a new instance for this class, pass the return value as `comptr` (native pointer), and pass a second argument as `comptr(-1)` as a marker for an instance cretion (to distinguish from an simple encapsulation of a pointer) +`+` of `=`|Used in class constructor `init()` functions, the return value is passed as `comptr` and stored in the instance variable with name ``. The variables are typically `_p` or `.p`. `=` prefix indicates that a `NULL` value is accepted, while the `+` prefix raises an exception if the function returns `NULL`. This is typically used when encapsulating a pointer to a `C++` object that is not supposed to be `NULL`. +`&`|`bytes()` object, pointer to buffer returned, and size passed with an additional (size_t*) argument after arguments + +## Pre-compiled ctype functions + +It is possible to pre-compile Berry modules or classes that reference directly a ctype function definition. + +Example: + +``` C +/* return type is "i", arg type is "ifs" for int-float-string +int my_ext_func(int x, float s, const char* s) { + /* do whatever */ + return 0; +} + +/* @const_object_info_begin +module my_module (scope: global) { + my_func, ctype_func(my_ext_func, "i", "ifs") +} +@const_object_info_end */ +#include "be_fixed_my_module.h" +``` + +With this scheme, the definition is passed automatically to the ctype handler. +It relies on an extensibility scheme of Berry. + +You need to register the ctype function handler at the launch of the Berry VM: + +``` C +#include "berry.h" +#include "be_mapping.h" + +void berry_launch(boid) +{ + bvm *vm = be_vm_new(); /* Construct a VM */ + be_set_ctype_func_hanlder(berry.vm, be_call_ctype_func); /* register the ctype function handler */ +} +``` + +## Callbacks + +The library introduces a new module `cb` used to create `C` callbacks that are mapped to Berry functions (native functions, native closures, Berry functions or closures). + +Due to the nature of `C` callbacks, each callback must point to a different `C` address. For this reason, the library pre-defines `20` callback addresses of stubs. This should be enough for most use-case; increasing this limit requires to define additional stubs and increases slightly the code size. + +The low-level `cb.gen_cb()` takes a Berry callable and returns a `C` callback address. The callback supports up to 5 `C` parameters. For each call, there are 5 Berry arguments passed as `int` converted from `intptr_t`. Each argument can be converted to a `comptr` with `introspect.toptr()` or converted to a `bytes()` structure. + +``` +> def inc(x) return x+1 end +> import cb +> print(cb.gen_cb(f)) + +``` + +It is easy to convert an argument to a `bytes()` or `cbytes()` object. In such case, you need to create a `bytes()` object with 2 arguments: first a `comptr` pointer, second the buffer size (note: the buffer will have a fixed size). The `bytes()` buffer is mapped to the `C` structure in memory and can be read or written as long as the address is valid. + +``` +> # let's assume the callback receives as first argument a pointer to a buffer of 8 bytes +> def get_buf(a) + import introspect + var b = bytes(introspect.toptr(a), 8) + print(b) + end +> var c = cb.gen_cb(get_buf) + +> # let's try manually the conversion with a dummy address +> import introspect +> get_buf(introspect.toptr(0x3ffb2340)) +bytes('BD9613807023FB3F') +``` + +However some callbacks need more information to reuse the same callback in different locations. The `C` mapper will actually call `cb.make_cb(closure, name, self)` and let modules the opportunity to register specific callback handlers. + +You can register a hanlder with `cb.add_handler(handler)` where `handler` receives the 3 following arguments `handler(cb:function, name:string, obj:instance)`. The handler must return a `comptr` if it has sucessfully allocated a callback, or return `nil` if it ignores this callback (based on its name for example). `gen_cb()` is called eventually if no handler handled it. diff --git a/lib/libesp32/berry_mapping/library.json b/lib/libesp32/berry_mapping/library.json new file mode 100644 index 000000000..fe28d70ef --- /dev/null +++ b/lib/libesp32/berry_mapping/library.json @@ -0,0 +1,17 @@ +{ + "name": "Berry mapping to C", + "version": "1.0", + "description": "Mapping to C functions", + "license": "MIT", + "homepage": "https://github.com/berry-lang/berry_mapping", + "frameworks": "arduino", + "platforms": "espressif32", + "authors": + { + "name": "Stephan Hadinger", + "maintainer": true + }, + "build": { + "flags": [ "-I$PROJECT_DIR/include" ] + } + } \ No newline at end of file diff --git a/lib/libesp32/berry_mapping/src/be_cb_module.c b/lib/libesp32/berry_mapping/src/be_cb_module.c new file mode 100644 index 000000000..6b147da21 --- /dev/null +++ b/lib/libesp32/berry_mapping/src/be_cb_module.c @@ -0,0 +1,281 @@ +/******************************************************************** + * Callback module + * + * To use: `import cb` + * + *******************************************************************/ +#include "be_constobj.h" + +#include "be_mapping.h" +#include "be_gc.h" +#include "be_exec.h" +#include "be_vm.h" +#include "be_mem.h" + +/*********************************************************************************************\ + * Callback structures + * + * We allow 4 parameters, or 3 if method (first arg is `self`) + * This could be extended if needed +\*********************************************************************************************/ +typedef int32_t (*berry_callback_t)(int32_t v0, int32_t v1, int32_t v2, int32_t v3); +static int32_t call_berry_cb(int32_t num, int32_t v0, int32_t v1, int32_t v2, int32_t v3); + +#define BERRY_CB(n) int32_t berry_cb_##n(int32_t v0, int32_t v1, int32_t v2, int32_t v3) { return call_berry_cb(n, v0, v1, v2, v3); } +// list the callbacks +BERRY_CB(0); +BERRY_CB(1); +BERRY_CB(2); +BERRY_CB(3); +BERRY_CB(4); +BERRY_CB(5); +BERRY_CB(6); +BERRY_CB(7); +BERRY_CB(8); +BERRY_CB(9); +BERRY_CB(10); +BERRY_CB(11); +BERRY_CB(12); +BERRY_CB(13); +BERRY_CB(14); +BERRY_CB(15); +BERRY_CB(16); +BERRY_CB(17); +BERRY_CB(18); +BERRY_CB(19); + +// array of callbacks +static const berry_callback_t berry_callback_array[BE_MAX_CB] = { + berry_cb_0, + berry_cb_1, + berry_cb_2, + berry_cb_3, + berry_cb_4, + berry_cb_5, + berry_cb_6, + berry_cb_7, + berry_cb_8, + berry_cb_9, + berry_cb_10, + berry_cb_11, + berry_cb_12, + berry_cb_13, + berry_cb_14, + berry_cb_15, + berry_cb_16, + berry_cb_17, + berry_cb_18, + berry_cb_19, +}; + +typedef struct be_callback_hook { + bvm *vm; + bvalue f; +} be_callback_hook; + +typedef struct be_callback_handler_list_t { + bvm *vm; + bvalue f; + struct be_callback_handler_list_t *next; +} be_callback_handler_list_t; + +static be_callback_hook be_cb_hooks[BE_MAX_CB] = {0}; + +static int32_t be_cb_gen_cb(bvm *vm); +static be_callback_handler_list_t be_callback_default_gen_cb = { + NULL, + be_const_func(&be_cb_gen_cb), + NULL +}; + +static be_callback_handler_list_t *be_callback_handler_list_head = &be_callback_default_gen_cb; /* linked list of handlers */ + +/*********************************************************************************************\ + * `add_handler`: Add an external handler to `make_cb()` + * + * This is typically used by LVGL mapping to handle widget callbacks, the handler + * needs to record additional infomation to disambiguate the call + * + * arg1: function (or closure) +\*********************************************************************************************/ +static int32_t be_cb_add_handler(bvm *vm) { + int32_t top = be_top(vm); + if (top >= 1 && be_isfunction(vm, 1)) { + bvalue *v = be_indexof(vm, 1); + + be_callback_handler_list_t *elt = be_os_malloc(sizeof(be_callback_handler_list_t)); + if (!elt) { be_throw(vm, BE_MALLOC_FAIL); } + + if (be_isgcobj(v)) { + be_gc_fix_set(vm, v->v.gc, btrue); // mark the function as non-gc + } + elt->vm = vm; + elt->f = *v; + elt->next = be_callback_handler_list_head; /* insert as new head */ + be_callback_handler_list_head = elt; + be_return_nil(vm); + } + be_raise(vm, "value_error", "arg must be a function"); +} + +/*********************************************************************************************\ + * `list_handlers`: List all cb handlers registered for this VM + * + * Used for debugging only + * + * No args +\*********************************************************************************************/ +static int32_t be_cb_list_handlers(bvm *vm) { + be_newobject(vm, "list"); + for (be_callback_handler_list_t *elt = be_callback_handler_list_head; elt != NULL; elt = elt->next) { + if (elt->vm == vm) { /* on purpose don't show the default handler, just pretend it's not there since it's default */ + bvalue *top = be_incrtop(vm); + *top = elt->f; + be_data_push(vm, -2); + be_pop(vm, 1); + } + } + be_pop(vm, 1); + be_return(vm); +} + +/*********************************************************************************************\ + * `make_cb`: high-level call for creating a callback. + * + * This function is called by `be_mapping` when generating a callback with a type name. + * LVGL typically needs to register typed callbacks + * + * arg1: function (or closure) + * arg2: type name for callback (optional) + * argN: any other callback specific arguments (unlimited number, passed as-is) +\*********************************************************************************************/ +static int32_t be_cb_make_cb(bvm *vm) { + int32_t argc = be_top(vm); + if (argc >= 1 && be_isfunction(vm, 1)) { + + bvalue *v = be_indexof(vm, 1); + for (be_callback_handler_list_t *elt = be_callback_handler_list_head; elt != NULL; elt = elt->next) { + if (elt->vm == vm || elt->vm == NULL) { // if elt->vm is NULL then we accept any VM + // call the handler and check result + bvalue *top = be_incrtop(vm); + *top = elt->f; + // var_setobj(top, elt->f->type, elt->f); // push function - arg0 + for (int i=1; i<=argc; i++) { // push all arguments including function + be_pushvalue(vm, i); + } + be_call(vm, argc); // call handler + be_pop(vm, argc); // remove arguments, top of stack has the result + // if top of stack is `comptr` then it is successful + if (be_iscomptr(vm, -1)) { + be_return(vm); + } else { + be_pop(vm, 1); // remove top, rinse and repeat + } + } + } + + // if we are here, it means that no handler has handled the request + } + be_raise(vm, "value_error", "arg must be a function"); +} + +/*********************************************************************************************\ + * `gen_cb`: Generate a new callback + * + * arg1: function (or closure) +\*********************************************************************************************/ +static int32_t be_cb_gen_cb(bvm *vm) { + int32_t top = be_top(vm); + if (top >= 1 && be_isfunction(vm, 1)) { + // find first available slot + int32_t slot; + for (slot = 0; slot < BE_MAX_CB; slot++) { + if (be_cb_hooks[slot].f.type == BE_NIL) break; + } + bvalue *v = be_indexof(vm, 1); + if (slot < BE_MAX_CB) { + if (be_isgcobj(v)) { + be_gc_fix_set(vm, v->v.gc, btrue); // mark the function as non-gc + } + // record pointers + be_cb_hooks[slot].vm = vm; + be_cb_hooks[slot].f = *v; + be_pushcomptr(vm, (void*) berry_callback_array[slot]); + be_return(vm); + } else { + be_raise(vm, "internal_error", "no more callbacks available, increase BE_MAX_CB"); + } + } + be_raise(vm, "value_error", "arg must be a function"); +} + +/*********************************************************************************************\ + * `get_cb_list`: Return the list of callbacks for this vm + * +\*********************************************************************************************/ +static int32_t be_cb_get_cb_list(bvm *vm) { + be_newobject(vm, "list"); + int32_t i; + for (uint32_t i=0; i < BE_MAX_CB; i++) { + if (be_cb_hooks[i].vm) { + if (vm == be_cb_hooks[i].vm) { // make sure it corresponds to this vm + bvalue *top = be_incrtop(vm); + *top = be_cb_hooks[i].f; + // be_pushcomptr(vm, be_cb_hooks[i].f); + be_data_push(vm, -2); + be_pop(vm, 1); + } + } else { + break; + } + } + be_pop(vm, 1); + be_return(vm); +} + +/*********************************************************************************************\ + * Callback structures + * + * We allow 4 parameters, or 3 if method (first arg is `self`) + * This could be extended if needed +\*********************************************************************************************/ +static int32_t call_berry_cb(int32_t num, int32_t v0, int32_t v1, int32_t v2, int32_t v3) { + // call berry cb dispatcher + int32_t ret = 0; + // retrieve vm and function + if (num < 0 || num >= BE_MAX_CB || be_cb_hooks[num].vm == NULL) return 0; // invalid call, avoid a crash + + bvm * vm = be_cb_hooks[num].vm; + bvalue *f = &be_cb_hooks[num].f; + + // push function (don't check type) + bvalue *top = be_incrtop(vm); + *top = *f; + // push args + be_pushint(vm, v0); + be_pushint(vm, v1); + be_pushint(vm, v2); + be_pushint(vm, v3); + + ret = be_pcall(vm, 4); // 4 arguments + if (ret != 0) { + if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_PCALL_ERROR); + be_pop(vm, be_top(vm)); // clear Berry stack + return 0; + } + ret = be_toint(vm, -5); + be_pop(vm, 5); // remove result + return ret; +} + +/* @const_object_info_begin +module cb (scope: global) { + gen_cb, func(be_cb_gen_cb) + get_cb_list, func(be_cb_get_cb_list) + + add_handler, func(be_cb_add_handler) + list_handlers, func(be_cb_list_handlers) + make_cb, func(be_cb_make_cb) +} +@const_object_info_end */ +#include "../../berry/generate/be_fixed_cb.h" diff --git a/lib/libesp32/berry_mapping/src/be_class_wrapper.c b/lib/libesp32/berry_mapping/src/be_class_wrapper.c new file mode 100644 index 000000000..30812e2b2 --- /dev/null +++ b/lib/libesp32/berry_mapping/src/be_class_wrapper.c @@ -0,0 +1,483 @@ +/*********************************************************************************************\ + * Class wrappers for native objects + * + * These class are simple wrappers (containers) for a pointer of an external object. + * The pointer is stored interanlly by the class. + * + * The constructor of this class must accept the first argument to be `comptr`, + * in such case, the constructor must store the pointer. + * The class is not supposed to free the object at `deinit` time. +\*********************************************************************************************/ + +#include "be_mapping.h" +#include "be_exec.h" +#include + +typedef intptr_t (*fn_any_callable)(intptr_t p0, intptr_t p1, intptr_t p2, intptr_t p3, + intptr_t p4, intptr_t p5, intptr_t p6, intptr_t p7); + +/*********************************************************************************************\ + * Converision from real <-> int + * + * Warning, works only if sizeof(intptr_t) == sizeof(breal) + * On ESP32, int=32bits, real=float (32bits) +\*********************************************************************************************/ +static intptr_t realasint(breal v) { + intptr_t i; + i = *((intptr_t*) &v); + return i; +} + +static breal intasreal(intptr_t v) { + breal r; + r = *((breal*) &v); + return r; +} + +/*********************************************************************************************\ + * Create an object of `class_name` given an external poinrt `ptr`. + * + * Instanciates the class and calls `init()` with `ptr` wrapped in `comptr` as single arg. + * Both arguments but nost bu NULL. + * + * On return, the created instance is top of stack. +\*********************************************************************************************/ +void be_create_class_wrapper(bvm *vm, const char * class_name, void * ptr) { + if (ptr == NULL) { + be_throw(vm, BE_MALLOC_FAIL); + } + + be_getglobal(vm, class_name); // stack = class + be_call(vm, 0); // instanciate, stack = instance + be_getmember(vm, -1, "init"); // stack = instance, init_func + be_pushvalue(vm, -2); // stack = instance, init_func, instance + be_pushcomptr(vm, ptr); // stack = instance, init_func, instance, ptr + be_call(vm, 2); // stack = instance, ret, instance, ptr + be_pop(vm, 3); // stack = instance +} + + +/*********************************************************************************************\ + * Find an object by global or composite name. + * + * I.e. `lv.lv_object` will check for a global called `lv` and a member `lv_object` + * + * Only supports one level of depth, meaning a class within a module. + * Does not check the type of the object found. + * + * Arguments: + * `name`: can be NULL, in such case considers the member as not found + * + * Case 1: (no dot in name) `lv_wifi_bars` will look for a global variable `lv_wifi_bars` + * Case 2: (dot in name) `lvgl.lv_obj` will get global `lvgl` and look for `lv_obj` within this module + * + * Returns the number of elements pushed on the stack: 1 for module, 2 for instance method, 0 if not found +\*********************************************************************************************/ +int be_find_global_or_module_member(bvm *vm, const char * name) { + char *saveptr; + + if (name == NULL) { + be_pushnil(vm); + return 0; + } + char name_buf[strlen(name)+1]; + strcpy(name_buf, name); + + char * prefix = strtok_r(name_buf, ".", &saveptr); + char * suffix = strtok_r(NULL, ".", &saveptr); + if (suffix) { + if (!be_getglobal(vm, prefix)) { + // global not found, try module + be_pop(vm, 1); + if (!be_getmodule(vm, prefix)) { + return 0; + } + } + if (!be_isnil(vm, -1)) { + if (be_getmember(vm, -1, suffix)) { + if (be_isinstance(vm, -2)) { // instance, so we need to push method + instance + be_pushvalue(vm, -2); + be_remove(vm, -3); + return 2; + } else { // not instane, so keep only the top object + be_remove(vm, -2); + return 1; + } + } else { + be_pop(vm, 2); + return 0; + } + } + be_pop(vm, 1); // remove nil + return 0; + } else { // no suffix, get the global object + if (be_getglobal(vm, prefix)) { + return 1; + } + be_pop(vm, 1); + return 0; + } +} + + +/*********************************************************************************************\ + * Automatically parse Berry stack and call the C function accordingly + * + * This function takes the n incoming arguments and pushes them as arguments + * on the stack for the C function: + * - be_int -> int32_t + * - be_bool -> int32_t with value 0/1 + * - be_string -> const char * + * - be_instance -> gets the member "_p" and pushes as void* + * + * This works because C silently ignores any unwanted arguments. + * There is a strong requirements that all ints and pointers are 32 bits. + * Float is not supported but could be added. Double cannot be supported because they are 64 bits + * + * Optional argument: + * - return_type: the C function return value is int32_t and is converted to the + * relevant Berry object depending on this char: + * '' (default): nil, no value + * 'i' be_int + * 'b' be_bool + * 's' be_str + * '&' bytes() object, pointer to buffer returned, and size passed with an additional (size_t*) argument + * + * - arg_type: optionally check the types of input arguments, or throw an error + * string of argument types, '[' indicates that the following parameters are optional + * '.' don't care + * 'i' be_int + * 'b' be_bool + * 's' be_string + * 'f' be_real (float) + * 'c' C comptr (general pointer) + * '-': skip argument and ignore + * '~': send the length of the previous bytes() buffer (or raise an exception if no length known) + * 'lv_obj' be_instance of type or subtype + * '^lv_event_cb^' callback of a named class - will call `_lvgl.gen_cb(arg_type, closure, self)` and expects a callback address in return + * + * Ex: ".ii" takes 3 arguments, first one is any type, followed by 2 ints +\*********************************************************************************************/ +// general form of lv_obj_t* function, up to 4 parameters +// We can only send 32 bits arguments (no 64 bits nor double) and we expect pointers to be 32 bits + +// read a single value at stack position idx, convert to int. +// if object instance, get `_p` member and convert it recursively +intptr_t be_convert_single_elt(bvm *vm, int idx, const char * arg_type, int *buf_len) { + // berry_log_C("be_convert_single_elt(idx=%i, argtype='%s', type=%s)", idx, arg_type ? arg_type : "", be_typename(vm, idx)); + int ret = 0; + char provided_type = 0; + idx = be_absindex(vm, idx); // make sure we have an absolute index + + // berry_log_C(">> 0 idx=%i arg_type=%s", idx, arg_type ? arg_type : "NULL"); + if (arg_type == NULL) { arg_type = "."; } // if no type provided, replace with wildchar + size_t arg_type_len = strlen(arg_type); + + // handle callbacks first, since a wrong parameter will always yield to a crash + if (arg_type_len > 1 && arg_type[0] == '^') { // it is a callback + arg_type++; // skip first character + if (be_isclosure(vm, idx)) { + ret = be_find_global_or_module_member(vm, "cb.make_cb"); + if (ret) { + be_pushvalue(vm, idx); + be_pushvalue(vm, 1); + be_pushstring(vm, arg_type); + be_call(vm, 2 + ret); + const void * func = be_tocomptr(vm, -(3 + ret)); + be_pop(vm, 3 + ret); + + // berry_log_C("func=%p", func); + return (int32_t) func; + } else { + be_raisef(vm, "type_error", "Can't find callback generator: 'cb.make_cb'"); + } + } else { + be_raise(vm, "type_error", "Closure expected for callback type"); + } + } + + // first convert the value to int32 + if (be_isint(vm, idx)) { + if (arg_type[0] == 'f') { + ret = realasint((float)be_toint(vm, idx)); provided_type = 'f'; + } else { + ret = be_toint(vm, idx); provided_type = 'i'; } + } + else if (be_isbool(vm, idx)) { ret = be_tobool(vm, idx); provided_type = 'b'; } + else if (be_isstring(vm, idx)) { ret = (intptr_t) be_tostring(vm, idx); provided_type = 's'; } + else if (be_iscomptr(vm, idx)) { ret = (intptr_t) be_tocomptr(vm, idx); provided_type = 'c'; } + else if (be_isnil(vm, idx)) { ret = 0; provided_type = 'c'; } + else if (be_isreal(vm, idx)) { ret = realasint(be_toreal(vm, idx)); provided_type = 'f'; } + + // check if simple type was a match + if (provided_type) { + bbool type_ok = bfalse; + type_ok = (arg_type[0] == '.'); // any type is accepted + type_ok = type_ok || (arg_type[0] == provided_type); // or type is a match + type_ok = type_ok || (ret == 0 && arg_type_len != 1); // or NULL is accepted for an instance + + if (!type_ok) { + be_raisef(vm, "type_error", "Unexpected argument type '%c', expected '%s'", provided_type, arg_type); + } + // berry_log_C("be_convert_single_elt provided type=%i", ret); + return ret; + } + + // non-simple type + if (be_isinstance(vm, idx)) { + // check if the instance is a subclass of `bytes()`` + if (be_isbytes(vm, idx)) { + size_t len; + intptr_t ret = (intptr_t) be_tobytes(vm, idx, &len); + if (buf_len) { *buf_len = (int) len; } + return ret; + } else { + // we accept either `_p` or `.p` attribute to retrieve a pointer + if (!be_getmember(vm, idx, "_p")) { + be_pop(vm, 1); // remove `nil` + be_getmember(vm, idx, ".p"); + } // else `nil` is on top of stack + int32_t ret = be_convert_single_elt(vm, -1, NULL, NULL); // recurse + be_pop(vm, 1); + + if (arg_type_len > 1) { + // Check type + be_classof(vm, idx); + int class_found = be_find_global_or_module_member(vm, arg_type); + // Stack: class_of_idx, class_of_target (or nil) + if (class_found) { + if (!be_isderived(vm, -2)) { + be_raisef(vm, "type_error", "Unexpected class type '%s', expected '%s'", be_classname(vm, idx), arg_type); + } + } else { + be_raisef(vm, "value_error", "Unable to find class '%s' (%d)", arg_type, arg_type_len); + } + be_pop(vm, 2); + } else if (arg_type[0] != '.') { + be_raisef(vm, "value_error", "Unexpected instance type '%s', expected '%s'", be_classname(vm, idx), arg_type); + } + + return ret; + } + } else { + be_raisef(vm, "value_error", "Unexpected '%s'", be_typename(vm, idx)); + } + + return ret; +} + +/*********************************************************************************************\ + * Calling any LVGL function with auto-mapping + * +\*********************************************************************************************/ + +// check input parameters, and create callbacks if needed +// change values in place +// +// Format: +// - either a lowercase character encoding for a simple type +// - 'b': bool +// - 'i': int (int32_t) +// - 's': string (const char *) +// - '.': any argument (no check) +// - '-': skip argument and ignore +// - '~': send the length of the previous bytes() buffer (or raise an exception if no length known) +// - if return type is '&' (bytes), an implicit additional parameter is passed as (size_t*) to return the length in bytes +// +// - a class name surroungded by parenthesis +// - '(lv_button)' -> lv_button class or derived +// - '[lv_event_cb]' -> callback type, still prefixed with '^' to mark that it is cb +// +// Returns the number of parameters sent to the function +// +int be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_type, intptr_t p[8]) { + bbool arg_type_check = (arg_type != NULL); // is type checking activated + int32_t arg_idx = 0; // position in arg_type string + bbool arg_optional = bfalse; // are remaining types optional? + char type_short_name[32]; + + uint32_t p_idx = 0; // index in p[], is incremented with each parameter except '-' + int32_t buf_len = -1; // stores the length of a bytes() buffer to be used as '~' attribute + + // special case when no parameters are passed but all are optional + if (NULL != arg_type && arg_type[arg_idx] == '[') { + arg_optional = btrue; + arg_idx++; + } + + for (uint32_t i = 0; i < argc; i++) { + type_short_name[0] = 0; // clear string + // extract individual type + if (NULL != arg_type) { + switch (arg_type[arg_idx]) { + case '-': + arg_idx++; + continue; // ignore current parameter and advance + case '.': + case 'a'...'z': + type_short_name[0] = arg_type[arg_idx]; + type_short_name[1] = 0; + arg_idx++; + break; + case '(': + case '^': + { + uint32_t prefix = 0; + if (arg_type[arg_idx] == '^') { + type_short_name[0] = '^'; + type_short_name[1] = 0; + prefix = 1; + } + uint32_t offset = 0; + arg_idx++; + while (arg_type[arg_idx + offset] != ')' && arg_type[arg_idx + offset] != '^' && arg_type[arg_idx + offset] != 0 && offset+prefix+1 < sizeof(type_short_name)) { + type_short_name[offset+prefix] = arg_type[arg_idx + offset]; + type_short_name[offset+prefix+1] = 0; + offset++; + } + if (arg_type[arg_idx + offset] == 0) { + arg_type = NULL; // no more parameters, stop iterations + } + arg_idx += offset + 1; + } + break; + case 0: + arg_type = NULL; // stop iterations + break; + } + if (arg_type && (arg_type[arg_idx] == '[' || arg_type[arg_idx] == ']')) { // '[' is a marker that following parameters are optional and default to NULL + arg_optional = btrue; + arg_idx++; + } + } + // berry_log_C(">> be_call_c_func arg %i, type %s", i, arg_type_check ? type_short_name : ""); + p[p_idx] = be_convert_single_elt(vm, i + arg_start, arg_type_check ? type_short_name : NULL, &buf_len); + // berry_log_C("< ret[%i]=%i", p_idx, p[p_idx]); + p_idx++; + + if (arg_type && arg_type[arg_idx] == '~') { // if next argument is virtual + if (buf_len < 0) { + be_raisef(vm, "value_error", "no bytes() length known"); + } + p[p_idx] = buf_len; // add the previous buffer len + p_idx++; + arg_idx++; // skip this arg + } + } + + // check if we are missing arguments + if (!arg_optional && arg_type && arg_type[arg_idx] != 0) { + be_raisef(vm, "value_error", "Missing arguments, remaining type '%s'", &arg_type[arg_idx]); + } + return p_idx; +} + +// +// Internal function +// +// Called for constructors, i.e. C function mapped to Berry `init()` +// +// Pre-conditions: +// The instance must be at stack position `1` (default when calling `init()`) +// +// Arguments: +// vm: point to Berry vm (as usual) +// ptr: the C pointer for internal data (can be NULL), will be stored in an instance variable +// name: name of instance variable to store the pointer as `comptr`. +// If NULL, this function does nothing +// the name can be prefixed with `+` or `=`, if so first char is ignored. +// Ex: `+_p` stores in instance variable `_p` +// `+` forbids any NULL value (raises an exception) while `=` allows a NULL value +static void be_set_ctor_ptr(bvm *vm, void * ptr, const char *name) { + if (name == NULL) return; // do nothing if no name of attribute + if (name[0] == '+' && ptr == NULL) { be_raise(vm, "value_error", "argument cannot be NULL"); } + if (name[0] == '+' || name[0] == '=') { name++; } // skip prefix '^' if any + if (strlen(name) == 0) return; // do nothing if name is empty + + be_pushcomptr(vm, ptr); + if (be_setmember(vm, 1, name)) { + be_pop(vm, 1); + } else { + be_raisef(vm, "attribute_error", "Missing member '%s' in ctor", name); + } +} + +/*********************************************************************************************\ + * CType handler for Berry +\*********************************************************************************************/ +int be_call_ctype_func(bvm *vm, const void *definition) { + be_ctype_args_t* args = (be_ctype_args_t*) definition; + return be_call_c_func(vm, args->func, args->return_type, args->arg_type); +} + +/*********************************************************************************************\ + * Call a C function with auto-mapping + * + * Arguments: + * vm: pointer to Berry vm (as ususal) + * func: pointer to C function + * return_type: how to convert the result into a Berry type + * arg_type: string describing the optional and mandatory parameters + * + * Note: the C function mapping supports max 8 arguments and does not directly support + * pointers to values (although it is possible to mimick with classes) +\*********************************************************************************************/ +int be_call_c_func(bvm *vm, const void * func, const char * return_type, const char * arg_type) { + intptr_t p[8] = {0,0,0,0,0,0,0,0}; + int argc = be_top(vm); // Get the number of arguments + + // the following describe the active payload for the C function (start and count) + // this is because the `init()` constructor first arg is not passed to the C function + int arg_start = 1; // start with standard values + int arg_count = argc; + + // check if we call a constructor, in this case we store the return type into the new object + // check if we call a constructor with a comptr as first arg + if (return_type && (return_type[0] == '+' || return_type[0] == '=')) { + if (argc > 1 && be_iscomptr(vm, 2)) { + void * obj = be_tocomptr(vm, 2); + be_set_ctor_ptr(vm, obj, return_type); + be_return_nil(vm); + } else { + // we need to discard the first arg + arg_start++; + arg_count--; + } + } + + fn_any_callable f = (fn_any_callable) func; + size_t return_len = 0; // when returning a bytes buffer, this holds the length of the buffer, while the return value of the function is `void*` + int c_args = be_check_arg_type(vm, arg_start, arg_count, arg_type, p); + if (return_type != NULL && return_type[0] == '&') { + if (c_args < 8) { p[c_args] = (intptr_t) &return_len; } + } + intptr_t ret = 0; + if (f) ret = (*f)(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + // berry_log_C("be_call_c_func '%s' -> '%s': (%i,%i,%i,%i,%i,%i) -> %i", return_type, arg_type, p[0], p[1], p[2], p[3], p[4], p[5], ret); + + if ((return_type == NULL) || (strlen(return_type) == 0)) { be_return_nil(vm); } // does not return + else if (return_type[0] == '+' || return_type[0] == '=') { + void * obj = (void*) ret; + be_set_ctor_ptr(vm, obj, return_type); + be_return_nil(vm); + } + else if (strlen(return_type) == 1) { + switch (return_type[0]) { + case '.': // fallback next + case 'i': be_pushint(vm, ret); break; + case 'b': be_pushbool(vm, ret); break; + case 'c': be_pushcomptr(vm, (void*) ret); break; + case 's': be_pushstring(vm, (const char*) ret); break; + case '&': be_pushbytes(vm, (void*) ret, return_len); break; + default: be_raise(vm, "internal_error", "Unsupported return type"); break; + } + be_return(vm); + } else { // class name + be_find_global_or_module_member(vm, return_type); + be_pushcomptr(vm, (void*) ret); // stack = class, ptr + be_pushcomptr(vm, (void*) -1); // stack = class, ptr, -1 + be_call(vm, 2); // instanciate with 2 arguments, stack = instance, ptr, -1 + be_pop(vm, 2); // stack = instance + be_return(vm); + } +} diff --git a/lib/libesp32/berry_mapping/src/be_const_members.c b/lib/libesp32/berry_mapping/src/be_const_members.c new file mode 100644 index 000000000..a41efdfd3 --- /dev/null +++ b/lib/libesp32/berry_mapping/src/be_const_members.c @@ -0,0 +1,99 @@ +/*********************************************************************************************\ + * Add const virtual members to classes and modules from C static tables + * + * This allows to creates hundreds of constant members (integers, strings...) + * stored in a C array instead of explicit berry members. + * + * It has the following advantages: + * - consumes much less flash memory, especially with hundreds of members + * - allows C preprocessor to compute the value at compile time (instead of pure numerical numbers) + * - allows to compute pointer addresses to C structures + * + * Takes a pointer to be_const_member_t array and size + * Returns true if a match was found. In such case the result is on Berry stack + * + * Encoding depend on prefix (which is skipped when matching names): + * - `COLOR_WHITE` int value + * - `$SYMBOL_OK"` string pointer + * - `&seg7_font` comptr + * - `*my_func` native function - the function is called and return value passed back. + * This allows to create dynamic virtual members that are the result of a call. +\*********************************************************************************************/ + +#include "be_mapping.h" +#include "be_exec.h" +#include +/*********************************************************************************************\ + * Takes a pointer to be_const_member_t array and size + * Returns true if a match was found. In such case the result is on Berry stack + * + * Can be called directly by `member()` function, takes the name of the member from + * berry stack at position 1. + * + * Encoding depend on prefix (which is skipped when matching names): + * - `COLOR_WHITE` int value + * - `$SYMBOL_OK"` string pointer + * - `&seg7_font` comptr + * - `*my_func` native function - the function is called and return value passed back. + * This allows to create dynamic virtual members that are the result of a call. + * + * The array must be lexically sorted, but the sort function must ignore the prefix `$`, `&`, `*` +\*********************************************************************************************/ +static bbool be_const_member_dual(bvm *vm, const be_const_member_t * definitions, size_t def_len, bbool is_method) { + int32_t arg_idx = is_method ? 2 : 1; // index for name argument, 1 if module, 2 if method since 1 is self. + int32_t argc = be_top(vm); // Get the number of arguments + if (argc == arg_idx && be_isstring(vm, arg_idx)) { + const char * needle = be_tostring(vm, arg_idx); + int32_t idx; + + idx = be_map_bin_search(needle, &definitions[0].name, sizeof(definitions[0]), def_len); + if (idx >= 0) { + // we did have a match + const char * key = definitions[idx].name; + switch (key[0]) { + // switch depending on the first char of the key, indicating the type + case '$': // string + be_pushstring(vm, (const char*) definitions[idx].value); + break; + case '&': // native function + be_pushntvfunction(vm, (bntvfunc) definitions[idx].value); + break; + case '*': // call to a native function + { + bntvfunc f = (bntvfunc) definitions[idx].value; + int ret = f(vm); + if ((ret == BE_OK) && !be_isnil(vm, -1)) { + return btrue; + } else { + return bfalse; + } + break; + } + case '>': // call to a ctype function + { + be_ctype_var_args_t* args = (be_ctype_var_args_t*) definitions[idx].value; + int ret = be_call_c_func(vm, args->func, args->return_type, NULL); + if ((ret == BE_OK) && !be_isnil(vm, -1)) { + return btrue; + } else { + return bfalse; + } + break; + } + default: // int + be_pushint(vm, definitions[idx].value); + break; + } + return btrue; + } + } + return bfalse; +} + +bbool be_const_module_member(bvm *vm, const be_const_member_t * definitions, size_t def_len) { + return be_const_member_dual(vm, definitions, def_len, bfalse); // call for module, non-method +} + +bbool be_const_class_member(bvm *vm, const be_const_member_t * definitions, size_t def_len) { + return be_const_member_dual(vm, definitions, def_len, btrue); // call for method +} diff --git a/lib/libesp32/berry_mapping/src/be_mapping.h b/lib/libesp32/berry_mapping/src/be_mapping.h new file mode 100644 index 000000000..96ac67563 --- /dev/null +++ b/lib/libesp32/berry_mapping/src/be_mapping.h @@ -0,0 +1,103 @@ + + +#ifndef __BE_MAPPING__ +#define __BE_MAPPING__ + +#include "berry.h" + +// include this header to force compilation fo this module +#define BE_MAX_CB 20 // max number of callbacks, each callback requires a distinct address + +#ifdef __cplusplus + #define be_const_ctype_func(_f) { \ + bvaldata((const void*) &ctype_func_def##_f), \ + BE_CTYPE_FUNC \ + } +#else // __cplusplus +typedef const void* be_constptr; + #define be_const_ctype_func(_f) { \ + .v.nf = (const void*) &ctype_func_def##_f, \ + .type = BE_CTYPE_FUNC \ + } +#endif // __cplusplus + +#define BE_FUNC_CTYPE_DECLARE(_name, _ret_arg, _in_arg) \ + static const be_ctype_args_t ctype_func_def##_name = { (const void*) &_name, _ret_arg, _in_arg }; +#define BE_VAR_CTYPE_DECLARE(_name, _ret_arg) \ + static const be_ctype_var_args_t ctype_func_def##_name = { (const void*) &_name, _ret_arg }; + +#define be_cconst_int(_v) ((intptr_t)(_v)) +#define be_cconst_string(_v) ((intptr_t)(_v)) +#define be_cconst_ptr(_v) ((intptr_t)(_v)) +#define be_cconst_func(_v) ((intptr_t)(_v)) +#define be_ctype(_name) ((intptr_t) &ctype_func_def##_name) + +/* C arguments are coded as an array of 3 pointers */ +typedef struct be_ctype_args_t { + const void* func; + const char* return_type; + const char* arg_type; +} be_ctype_args_t; + +/* ctype constant function as an array of 2 pointers: function and return type. arg_type is always NULL */ +typedef struct be_ctype_var_args_t { + const void* func; + const char* return_type; +} be_ctype_var_args_t; + + +typedef struct be_const_member_t { + const char * name; + intptr_t value; +} be_const_member_t; + +// table of functions per class +typedef struct be_ntv_func_def_t { + const char * name; + be_ctype_args_t args; +} be_ntv_func_def_t; + +struct bclass; +// list of classes and function tables +typedef struct be_ntv_class_def_t { + const char * name; + const struct bclass * cl; + const be_ntv_func_def_t * func_table; + size_t size; +} be_ntv_class_def_t; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************************************\ + * Support for Berry int constants + * as virtual members + \*********************************************************************************************/ + +void be_raisef(bvm *vm, const char *except, const char *msg, ...); + +extern void be_map_insert_int(bvm *vm, const char *key, bint value); +extern void be_map_insert_bool(bvm *vm, const char *key, bbool value); +extern void be_map_insert_real(bvm *vm, const char *key, breal value); +extern void be_map_insert_str(bvm *vm, const char *key, const char *value); +extern void be_map_insert_list_uint8(bvm *vm, const char *key, const uint8_t *value, size_t size); + +extern int be_map_bin_search(const char * needle, const void * table, size_t elt_size, size_t total_elements); + +extern void be_create_class_wrapper(bvm *vm, const char * class_name, void * ptr); +extern int be_find_global_or_module_member(bvm *vm, const char * cl_name); + +extern bbool be_const_module_member(bvm *vm, const be_const_member_t * definitions, size_t def_len); +extern bbool be_const_class_member(bvm *vm, const be_const_member_t * definitions, size_t def_len); +extern intptr_t be_convert_single_elt(bvm *vm, int idx, const char * arg_type, int *len); +extern int be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_type, intptr_t p[8]); +extern int be_call_c_func(bvm *vm, const void * func, const char * return_type, const char * arg_type); +extern int be_call_ctype_func(bvm *vm, const void *definition); /* handler for Berry vm */ + +#ifdef __cplusplus +} +#endif +#endif // __BE_MAPPING__ diff --git a/lib/libesp32/berry_mapping/src/be_mapping_utils.c b/lib/libesp32/berry_mapping/src/be_mapping_utils.c new file mode 100644 index 000000000..e3a2cc6e2 --- /dev/null +++ b/lib/libesp32/berry_mapping/src/be_mapping_utils.c @@ -0,0 +1,97 @@ +#include "be_mapping.h" +#include +#include + +/*********************************************************************************************\ + * Helper functions to create a map with single line calls +\*********************************************************************************************/ +/* Insert an int to a key */ +void be_map_insert_int(bvm *vm, const char *key, bint value) +{ + be_pushstring(vm, key); + be_pushint(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); +} +/* Insert an bbool to a key */ +void be_map_insert_bool(bvm *vm, const char *key, bbool value) +{ + be_pushstring(vm, key); + be_pushbool(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); +} +/* Insert an real to a key */ +/* if value == NAN, ignore */ +void be_map_insert_real(bvm *vm, const char *key, breal value) +{ + if (!isnan(value)) { + be_pushstring(vm, key); + be_pushreal(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); + } +} +/* Insert an C string to a key */ +void be_map_insert_str(bvm *vm, const char *key, const char *value) +{ + be_pushstring(vm, key); + be_pushstring(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); +} +/* Insert list of bytes as individual integers to a key */ +void be_map_insert_list_uint8(bvm *vm, const char *key, const uint8_t *value, size_t size) +{ + be_pushstring(vm, key); + + be_newobject(vm, "list"); + for (uint32_t i=0; i < size; i++) { + be_pushint(vm, value[i]); + be_data_push(vm, -2); + be_pop(vm, 1); + } + be_pop(vm, 1); // now list is on top + + be_data_insert(vm, -3); // insert into map, key/value + be_pop(vm, 2); // pop both key and value +} + +/*********************************************************************************************\ + * Binary search for dynamic attributes + * + * Names need to be sorted +\*********************************************************************************************/ +// binary search within an array of sorted strings +// the first 4 bytes are a pointer to a string +// returns 0..total_elements-1 or -1 if not found +// +// This version skips the first character of the string if it's not a letter, +// the first character is used to indicate the type of the value associated to the key +int be_map_bin_search(const char * needle, const void * table, size_t elt_size, size_t total_elements) { + int low = 0; + int high = total_elements - 1; + int mid = (low + high) / 2; + // start a dissect + while (low <= high) { + const char * elt = *(const char **) ( ((uint8_t*)table) + mid * elt_size ); + char first_char = elt[0]; + if ( !(first_char >= 'a' && first_char <='z') && !(first_char >= 'A' && first_char <='Z') ) { + elt++; // skip first char + } + int comp = strcmp(needle, elt); + if (comp < 0) { + high = mid - 1; + } else if (comp > 0) { + low = mid + 1; + } else { + break; + } + mid = (low + high) / 2; + } + if (low <= high) { + return mid; + } else { + return -1; + } +} \ No newline at end of file diff --git a/lib/libesp32/berry_mapping/src/be_raisef.c b/lib/libesp32/berry_mapping/src/be_raisef.c new file mode 100644 index 000000000..6d8451bab --- /dev/null +++ b/lib/libesp32/berry_mapping/src/be_raisef.c @@ -0,0 +1,22 @@ +/*********************************************************************************************\ + * Extended version of be_raise() +\*********************************************************************************************/ + +#include "be_mapping.h" +#include "be_exec.h" +#include +#include +#include + +// variant of be_raise with string format +void be_raisef(bvm *vm, const char *except, const char *msg, ...) { + // To save stack space support logging for max text length of 128 characters + char log_data[128]; + + va_list arg; + va_start(arg, msg); + uint32_t len = vsnprintf(log_data, sizeof(log_data)-3, msg, arg); + va_end(arg); + if (len+3 > sizeof(log_data)) { strcat(log_data, "..."); } // Actual data is more + be_raise(vm, except, log_data); +} diff --git a/lib/libesp32/Berry/include/be_ctypes.h b/lib/libesp32/berry_tasmota/include/be_ctypes.h similarity index 100% rename from lib/libesp32/Berry/include/be_ctypes.h rename to lib/libesp32/berry_tasmota/include/be_ctypes.h diff --git a/lib/libesp32/berry_tasmota/library.json b/lib/libesp32/berry_tasmota/library.json new file mode 100644 index 000000000..e506ce7b6 --- /dev/null +++ b/lib/libesp32/berry_tasmota/library.json @@ -0,0 +1,17 @@ +{ + "name": "Berry Tasmota mapping", + "version": "1.0", + "description": "Mapping of Tasmota features to Berry", + "license": "MIT", + "homepage": "https://github.com/arendst/Tasmota", + "frameworks": "arduino", + "platforms": "espressif32", + "authors": + { + "name": "Stephan Hadinger", + "maintainer": true + }, + "build": { + "flags": [ "-I$PROJECT_DIR/include", "-includetasmota_options.h" ] + } + } \ No newline at end of file diff --git a/lib/libesp32/berry_tasmota/src/be_MI32_lib.c b/lib/libesp32/berry_tasmota/src/be_MI32_lib.c new file mode 100644 index 000000000..4714f21a9 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_MI32_lib.c @@ -0,0 +1,72 @@ +/******************************************************************** + * Tasmota lib + * + * To use: `import MI32` + *******************************************************************/ +#include "be_constobj.h" + +#ifdef USE_MI_ESP32 +extern int be_MI32_devices(bvm *vm); +extern int be_MI32_set_bat(bvm *vm); +extern int be_MI32_get_name(bvm *vm); +extern int be_MI32_get_MAC(bvm *vm); +extern int be_MI32_set_hum(bvm *vm); +extern int be_MI32_set_temp(bvm *vm); + +/******************************************************************** +** Solidified class: MI32 +********************************************************************/ +be_local_class(MI32, + 0, + NULL, + be_nested_map(6, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("devices", -1593144448, 7, -1), be_const_func(be_MI32_devices) }, + { be_nested_key("set_bat", -1558299945, 7, -1), be_const_func(be_MI32_set_bat) }, + { be_nested_key("set_hum", 964296026, 7, 4), be_const_func(be_MI32_set_hum) }, + { be_nested_key("get_MAC", 2091521771, 7, -1), be_const_func(be_MI32_get_MAC) }, + { be_nested_key("set_temp", 1952131250, 8, -1), be_const_func(be_MI32_set_temp) }, + { be_nested_key("get_name", 1616902907, 8, 3), be_const_func(be_MI32_get_name) }, + })), + (be_nested_const_str("MI32", -220693882, 4)) +); +/*******************************************************************/ + +void be_load_MI32_class(bvm *vm) { + be_pushntvclass(vm, &be_class_MI32); + be_setglobal(vm, "MI32"); + be_pop(vm, 1); +} + +extern int be_BLE_reg_conn_cb(bvm *vm); +extern int be_BLE_reg_adv_cb(bvm *vm); +extern int be_BLE_set_MAC(bvm *vm); +extern int be_BLE_set_characteristic(bvm *vm); +extern int be_BLE_run(bvm *vm); +extern int be_BLE_set_service(bvm *vm); +/******************************************************************** +** Solidified class: BLE +********************************************************************/ +be_local_class(BLE, + 0, + NULL, + be_nested_map(6, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("conn_cb", 1381122945, 7, -1), be_const_func(be_BLE_reg_conn_cb) }, + { be_nested_key("set_svc", 752734654, 7, -1), be_const_func(be_BLE_set_service) }, + { be_nested_key("run", 718098122, 3, -1), be_const_func(be_BLE_run) }, + { be_nested_key("set_chr", 102133743, 7, 0), be_const_func(be_BLE_set_characteristic) }, + { be_nested_key("adv_cb", 1957890034, 6, 1), be_const_func(be_BLE_reg_adv_cb) }, + { be_nested_key("set_MAC", 1617581015, 7, -1), be_const_func(be_BLE_set_MAC) }, + })), + (be_nested_const_str("BLE", -361123990, 3)) +); +/*******************************************************************/ + +void be_load_BLE_class(bvm *vm) { + be_pushntvclass(vm, &be_class_BLE); + be_setglobal(vm, "BLE"); + be_pop(vm, 1); +} + +#endif //USE_MI_ESP32 diff --git a/lib/libesp32/Berry/default/be_animate_lib.c b/lib/libesp32/berry_tasmota/src/be_animate_lib.c similarity index 98% rename from lib/libesp32/Berry/default/be_animate_lib.c rename to lib/libesp32/berry_tasmota/src/be_animate_lib.c index 398f87b66..d5a44a6a7 100644 --- a/lib/libesp32/Berry/default/be_animate_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_animate_lib.c @@ -13,7 +13,7 @@ be_local_closure(Animate_rotate_init, /* name */ be_nested_proto( 12, /* nstack */ 5, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -84,7 +84,7 @@ be_local_closure(Animate_from_to_init, /* name */ be_nested_proto( 12, /* nstack */ 5, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -144,7 +144,7 @@ be_local_closure(Animate_back_forth_init, /* name */ be_nested_proto( 12, /* nstack */ 5, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -225,7 +225,7 @@ be_local_closure(Animate_ins_goto_init, /* name */ be_nested_proto( 4, /* nstack */ 4, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -272,7 +272,7 @@ be_local_closure(Animate_ins_ramp_init, /* name */ be_nested_proto( 4, /* nstack */ 4, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -319,7 +319,7 @@ be_local_closure(Animate_engine_run, /* name */ be_nested_proto( 6, /* nstack */ 3, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -368,7 +368,7 @@ be_local_closure(Animate_engine_init, /* name */ be_nested_proto( 2, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -405,7 +405,7 @@ be_local_closure(Animate_engine_autorun, /* name */ be_nested_proto( 7, /* nstack */ 3, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -441,7 +441,7 @@ be_local_closure(Animate_engine_stop, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -475,7 +475,7 @@ be_local_closure(Animate_engine_is_running, /* name */ be_nested_proto( 2, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -502,7 +502,7 @@ be_local_closure(Animate_engine_every_50ms, /* name */ be_nested_proto( 3, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -530,7 +530,7 @@ be_local_closure(Animate_engine_animate, /* name */ be_nested_proto( 12, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ diff --git a/lib/libesp32/berry_tasmota/src/be_audio_opus_lib.c b/lib/libesp32/berry_tasmota/src/be_audio_opus_lib.c new file mode 100644 index 000000000..19253b0d3 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_audio_opus_lib.c @@ -0,0 +1,88 @@ +/******************************************************************** + * Tasmota I2S audio classes + * + * + *******************************************************************/ +#include "be_constobj.h" + +#ifdef USE_I2S +#ifdef USE_I2S_AUDIO_BERRY + +#include "libopus/opus.h" +#include "be_mapping.h" + +// Tasmota Logging +extern void tasmota_log_C(uint32_t loglevel, const char * berry_buf, ...); +enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE}; + +// init(freq:int, channels:int) +void *be_audio_opus_decoder_init_ntv(int freq, int channels) { + if (freq <= 0) { freq = 16000; } + if (channels <= 0) { channels = 1; } + int opus_size = opus_decoder_get_size(channels); // get size for n channel + tasmota_log_C(LOG_LEVEL_DEBUG, "AUD: allocated %i bytes for Opus decoder", opus_size); + void * buf = BE_EXPLICIT_MALLOC(opus_size); + if (!buf) { berry_log_C("OPUS: out of memory"); } + + int err = opus_decoder_init((OpusDecoder*)buf, freq, channels); + if (err) { berry_log_C("OPUS: opus_encoder_init error=%i", err); } + + return buf; +} +int32_t be_audio_opus_decoder_init(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_audio_opus_decoder_init_ntv, "+.p", "i[i]"); +} + +// deinit() +void *be_audio_opus_decoder_deinit_ntv(OpusDecoder* buf) { + if (buf) BE_EXPLICIT_FREE(buf); + return NULL; +} +int32_t be_audio_opus_decoder_deinit(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_audio_opus_decoder_deinit_ntv, "", "."); +} + + +// decode(payload:bytes) -> pcm:bytes() +int32_t be_audio_opus_decoder_decode(struct bvm *vm) { + int32_t argc = be_top(vm); + be_call_c_func(vm, NULL, NULL, ".(bytes)"); + + OpusDecoder* st = (OpusDecoder*) be_convert_single_elt(vm, 1, NULL, NULL); // get value of '.p' + size_t frames_len; + const uint8_t * opus_frame = be_tobytes(vm, 2, &frames_len); + + int samples = opus_decoder_get_nb_samples(st, opus_frame, frames_len); + // tasmota_log_C(LOG_LEVEL_DEBUG, "AUD: frame contains %i samples", samples); + + // allocate a buffer for the content + void * pcm = be_pushbytes(vm, NULL, samples * 2); + + int ret = opus_decode(st, opus_frame, frames_len, pcm, samples, 0); + if (ret != samples) { be_raisef(vm, "internal_error", "wrong number of frames %i (supposed to be %i", ret, samples); } + + be_return(vm); +} + +#include "be_fixed_be_class_audio_opus_decoder.h" + +void be_load_driver_audio_opus_decoder(bvm *vm) { + be_pushntvclass(vm, &be_class_audio_opus_decoder); + be_setglobal(vm, "OpusDecoder"); + be_pop(vm, 1); +} + +/* @const_object_info_begin + +class be_class_audio_opus_decoder (scope: global, name: OpusDecoder) { + .p, var + init, func(be_audio_opus_decoder_init) + deinit, func(be_audio_opus_decoder_deinit) + + decode, func(be_audio_opus_decoder_decode) +} + +@const_object_info_end */ + +#endif // USE_I2S_AUDIO_BERRY +#endif // USE_I2S \ No newline at end of file diff --git a/lib/libesp32/Berry/default/be_autoconf_lib.c b/lib/libesp32/berry_tasmota/src/be_autoconf_lib.c similarity index 98% rename from lib/libesp32/Berry/default/be_autoconf_lib.c rename to lib/libesp32/berry_tasmota/src/be_autoconf_lib.c index da41707c7..6eafcc3a7 100644 --- a/lib/libesp32/Berry/default/be_autoconf_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_autoconf_lib.c @@ -14,7 +14,7 @@ be_local_closure(Autoconf_page_autoconf_ctl, /* name */ be_nested_proto( 13, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -196,7 +196,7 @@ be_local_closure(Autoconf_autoexec, /* name */ be_nested_proto( 9, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -359,7 +359,7 @@ be_local_closure(Autoconf_run_bat, /* name */ be_nested_proto( 13, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -447,7 +447,7 @@ be_local_closure(Autoconf_page_autoconf_mgr, /* name */ be_nested_proto( 19, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -634,7 +634,7 @@ be_local_closure(Autoconf_get_current_module_name, /* name */ be_nested_proto( 3, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -665,7 +665,7 @@ be_local_closure(Autoconf_delete_all_configs, /* name */ be_nested_proto( 10, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -723,7 +723,7 @@ be_local_closure(Autoconf_set_first_time, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -757,7 +757,7 @@ be_local_closure(Autoconf_load_templates, /* name */ be_nested_proto( 15, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -888,7 +888,7 @@ be_local_closure(Autoconf_web_add_config_button, /* name */ be_nested_proto( 5, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -920,7 +920,7 @@ be_local_closure(Autoconf_is_first_time, /* name */ be_nested_proto( 5, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -955,7 +955,7 @@ be_local_closure(Autoconf_init, /* name */ be_nested_proto( 12, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -976,8 +976,8 @@ be_local_closure(Autoconf_init, /* name */ /* K11 */ be_nested_str(_error), /* K12 */ be_const_int(1), /* K13 */ be_nested_str(log), - /* K14 */ be_nested_str(CFG_X3A_X20no_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found), - /* K15 */ be_const_int(2), + /* K14 */ be_nested_str(CFG_X3A_X20No_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found), + /* K15 */ be_const_int(3), /* K16 */ be_nested_str(_archive), }), &be_const_str_init, @@ -1047,7 +1047,7 @@ be_local_closure(Autoconf_preinit, /* name */ be_nested_proto( 7, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1107,7 +1107,7 @@ be_local_closure(Autoconf_reset, /* name */ be_nested_proto( 12, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1179,7 +1179,7 @@ be_local_closure(Autoconf_web_add_handler, /* name */ be_nested_proto( 7, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 1, /* has sup protos */ @@ -1268,7 +1268,7 @@ be_local_closure(Autoconf_clear_first_time, /* name */ be_nested_proto( 5, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1300,7 +1300,7 @@ be_local_closure(Autoconf_get_current_module_path, /* name */ be_nested_proto( 2, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ diff --git a/lib/libesp32/Berry/default/be_crypto_lib.c b/lib/libesp32/berry_tasmota/src/be_crypto_lib.c similarity index 92% rename from lib/libesp32/Berry/default/be_crypto_lib.c rename to lib/libesp32/berry_tasmota/src/be_crypto_lib.c index 04a10b28e..03173ec0c 100644 --- a/lib/libesp32/Berry/default/be_crypto_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_crypto_lib.c @@ -17,8 +17,8 @@ extern int m_aes_gcm_tag(bvm *vm); extern int m_ec_c25519_pubkey(bvm *vm); extern int m_ec_c25519_sharedkey(bvm *vm); -#include "../generate/be_fixed_be_class_aes_gcm.h" -#include "../generate/be_fixed_be_class_ec_c25519.h" +#include "be_fixed_be_class_aes_gcm.h" +#include "be_fixed_be_class_ec_c25519.h" void be_load_crypto_lib(bvm *vm) { // insert the class GCM in module AES diff --git a/lib/libesp32/Berry/default/be_ctypes.c b/lib/libesp32/berry_tasmota/src/be_ctypes.c similarity index 99% rename from lib/libesp32/Berry/default/be_ctypes.c rename to lib/libesp32/berry_tasmota/src/be_ctypes.c index 18e655d8b..5bd8f309d 100644 --- a/lib/libesp32/Berry/default/be_ctypes.c +++ b/lib/libesp32/berry_tasmota/src/be_ctypes.c @@ -462,8 +462,8 @@ int be_ctypes_dyn_init(bvm *vm) { BE_EXPORT_VARIABLE extern const bclass be_class_bytes; -#include "../generate/be_fixed_be_class_ctypes.h" -#include "../generate/be_fixed_be_class_ctypes_dyn.h" +#include "be_fixed_be_class_ctypes.h" +#include "be_fixed_be_class_ctypes_dyn.h" void be_load_ctypes_lib(bvm *vm) { be_pushntvclass(vm, &be_class_ctypes); diff --git a/lib/libesp32/Berry/default/be_display_lib.c b/lib/libesp32/berry_tasmota/src/be_display_lib.c similarity index 100% rename from lib/libesp32/Berry/default/be_display_lib.c rename to lib/libesp32/berry_tasmota/src/be_display_lib.c diff --git a/lib/libesp32/Berry/default/be_driverlib.c b/lib/libesp32/berry_tasmota/src/be_driverlib.c similarity index 54% rename from lib/libesp32/Berry/default/be_driverlib.c rename to lib/libesp32/berry_tasmota/src/be_driverlib.c index 45a611382..7944b4a67 100644 --- a/lib/libesp32/Berry/default/be_driverlib.c +++ b/lib/libesp32/berry_tasmota/src/be_driverlib.c @@ -6,57 +6,6 @@ *******************************************************************/ #include "be_constobj.h" -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Driver_init, /* name */ - be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - &be_const_str_init, - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_tasmota -********************************************************************/ -be_local_closure(Driver_get_tasmota, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str(tasmota), - }), - &be_const_str_get_tasmota, - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: add_cmd ********************************************************************/ @@ -64,7 +13,7 @@ be_local_closure(Driver_add_cmd, /* name */ be_nested_proto( 7, /* nstack */ 3, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 1, /* has sup protos */ @@ -123,24 +72,22 @@ be_local_closure(Driver_add_cmd, /* name */ be_local_class(Driver, 13, NULL, - be_nested_map(16, + be_nested_map(14, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key(web_add_main_button, 14), be_const_var(4) }, - { be_const_key(web_add_console_button, -1), be_const_var(7) }, - { be_const_key(web_add_management_button, 8), be_const_var(5) }, - { be_const_key(init, -1), be_const_closure(Driver_init_closure) }, - { be_const_key(json_append, -1), be_const_var(10) }, - { be_const_key(web_add_config_button, 7), be_const_var(6) }, - { be_const_key(every_100ms, -1), be_const_var(1) }, - { be_const_key(display, -1), be_const_var(12) }, - { be_const_key(web_add_button, 13), be_const_var(3) }, - { be_const_key(every_second, -1), be_const_var(0) }, - { be_const_key(save_before_restart, -1), be_const_var(8) }, - { be_const_key(get_tasmota, -1), be_const_closure(Driver_get_tasmota_closure) }, - { be_const_key(web_sensor, 6), be_const_var(9) }, - { be_const_key(web_add_handler, -1), be_const_var(2) }, - { be_const_key(button_pressed, 1), be_const_var(11) }, + { be_const_key(web_add_console_button, 6), be_const_var(7) }, + { be_const_key(web_add_config_button, -1), be_const_var(6) }, + { be_const_key(button_pressed, 9), be_const_var(11) }, + { be_const_key(every_second, 1), be_const_var(0) }, + { be_const_key(web_add_handler, 11), be_const_var(2) }, { be_const_key(add_cmd, -1), be_const_closure(Driver_add_cmd_closure) }, + { be_const_key(web_sensor, -1), be_const_var(9) }, + { be_const_key(display, -1), be_const_var(12) }, + { be_const_key(web_add_main_button, 2), be_const_var(4) }, + { be_const_key(save_before_restart, -1), be_const_var(8) }, + { be_const_key(web_add_management_button, 0), be_const_var(5) }, + { be_const_key(every_100ms, 13), be_const_var(1) }, + { be_const_key(json_append, -1), be_const_var(10) }, + { be_const_key(web_add_button, -1), be_const_var(3) }, })), be_str_literal("Driver") ); diff --git a/lib/libesp32/Berry/default/be_energy_ctypes_definitions.c b/lib/libesp32/berry_tasmota/src/be_energy_ctypes_definitions.c similarity index 100% rename from lib/libesp32/Berry/default/be_energy_ctypes_definitions.c rename to lib/libesp32/berry_tasmota/src/be_energy_ctypes_definitions.c diff --git a/lib/libesp32/Berry/default/be_energylib.c b/lib/libesp32/berry_tasmota/src/be_energylib.c similarity index 100% rename from lib/libesp32/Berry/default/be_energylib.c rename to lib/libesp32/berry_tasmota/src/be_energylib.c diff --git a/lib/libesp32/Berry/default/be_flash_lib.c b/lib/libesp32/berry_tasmota/src/be_flash_lib.c similarity index 93% rename from lib/libesp32/Berry/default/be_flash_lib.c rename to lib/libesp32/berry_tasmota/src/be_flash_lib.c index 539805d5d..cbce3ce47 100644 --- a/lib/libesp32/Berry/default/be_flash_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_flash_lib.c @@ -18,4 +18,4 @@ module flash (scope: global) { erase, func(p_flash_erase) } @const_object_info_end */ -#include "../generate/be_fixed_flash.h" +#include "be_fixed_flash.h" diff --git a/lib/libesp32/Berry/default/be_gpio_lib.c b/lib/libesp32/berry_tasmota/src/be_gpio_lib.c similarity index 71% rename from lib/libesp32/Berry/default/be_gpio_lib.c rename to lib/libesp32/berry_tasmota/src/be_gpio_lib.c index 3f0b2b3ed..592861b9c 100644 --- a/lib/libesp32/Berry/default/be_gpio_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_gpio_lib.c @@ -6,6 +6,7 @@ * read power values *******************************************************************/ #include "be_constobj.h" +#include "be_mapping.h" // Tasmota specific @@ -18,6 +19,10 @@ extern int gp_dac_voltage(bvm *vm); extern int gp_pin_used(bvm *vm); extern int gp_pin(bvm *vm); +// esp_err_tledc_set_duty_and_update(ledc_mode_tspeed_mode, ledc_channel_tchannel, uint32_t duty, uint32_t hpoint) +extern void gp_set_duty(int32_t pin, int32_t duty, int32_t hpoint); BE_FUNC_CTYPE_DECLARE(gp_set_duty, "", "ii[i]"); + + /* @const_object_info_begin module gpio (scope: global) { member, func(gp_member) @@ -29,6 +34,8 @@ module gpio (scope: global) { pin_used, func(gp_pin_used) pin, func(gp_pin) + + set_pwm, ctype_func(gp_set_duty) } @const_object_info_end */ -#include "../generate/be_fixed_gpio.h" +#include "be_fixed_gpio.h" diff --git a/lib/libesp32/Berry/default/be_i2c_axp192_lib.c b/lib/libesp32/berry_tasmota/src/be_i2c_axp192_lib.c similarity index 99% rename from lib/libesp32/Berry/default/be_i2c_axp192_lib.c rename to lib/libesp32/berry_tasmota/src/be_i2c_axp192_lib.c index 4f9f02307..298e7b3a2 100644 --- a/lib/libesp32/Berry/default/be_i2c_axp192_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_i2c_axp192_lib.c @@ -712,7 +712,7 @@ be_local_closure(AXP192_web_sensor, /* name */ /* K4 */ be_nested_str(_X7Bs_X7DVBus_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D), /* K5 */ be_nested_str(_X7Bs_X7DBatt_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D), /* K6 */ be_nested_str(_X7Bs_X7DBatt_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D), - /* K7 */ be_nested_str(_X7Bs_X7DTemp_X20AXP_X7Bm_X7D_X25_X2E1f_X20_XB0C_X7Be_X7D), + /* K7 */ be_nested_str(_X7Bs_X7DTemp_X20AXP_X7Bm_X7D_X25_X2E1f_X20_X26deg_X3BC_X7Be_X7D), /* K8 */ be_nested_str(get_vbus_voltage), /* K9 */ be_nested_str(get_bat_voltage), /* K10 */ be_nested_str(get_bat_current), diff --git a/lib/libesp32/Berry/default/be_i2c_driverlib.c b/lib/libesp32/berry_tasmota/src/be_i2c_driverlib.c similarity index 89% rename from lib/libesp32/Berry/default/be_i2c_driverlib.c rename to lib/libesp32/berry_tasmota/src/be_i2c_driverlib.c index 45f829e19..a61321c12 100644 --- a/lib/libesp32/Berry/default/be_i2c_driverlib.c +++ b/lib/libesp32/berry_tasmota/src/be_i2c_driverlib.c @@ -279,7 +279,7 @@ be_local_closure(I2C_Driver_read8, /* name */ ********************************************************************/ be_local_closure(I2C_Driver_init, /* name */ be_nested_proto( - 10, /* nstack */ + 9, /* nstack */ 4, /* argc */ 0, /* varg */ 0, /* has upvals */ @@ -288,7 +288,7 @@ be_local_closure(I2C_Driver_init, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[10]) { /* constants */ - /* K0 */ be_nested_str(get_tasmota), + /* K0 */ be_nested_str(tasmota), /* K1 */ be_nested_str(i2c_enabled), /* K2 */ be_nested_str(addr), /* K3 */ be_nested_str(wire), @@ -302,49 +302,49 @@ be_local_closure(I2C_Driver_init, /* name */ &be_const_str_init, &be_const_str_solidified, ( &(const binstruction[44]) { /* code */ - 0x8C100100, // 0000 GETMET R4 R0 K0 - 0x7C100200, // 0001 CALL R4 1 - 0x4C140000, // 0002 LDNIL R5 - 0x20140605, // 0003 NE R5 R3 R5 - 0x78160004, // 0004 JMPF R5 #000A - 0x8C140901, // 0005 GETMET R5 R4 K1 - 0x5C1C0600, // 0006 MOVE R7 R3 - 0x7C140400, // 0007 CALL R5 2 - 0x74160000, // 0008 JMPT R5 #000A - 0x80000A00, // 0009 RET 0 - 0x90020402, // 000A SETMBR R0 K2 R2 - 0x8C140904, // 000B GETMET R5 R4 K4 - 0x881C0102, // 000C GETMBR R7 R0 K2 - 0x7C140400, // 000D CALL R5 2 - 0x90020605, // 000E SETMBR R0 K3 R5 - 0x88140103, // 000F GETMBR R5 R0 K3 - 0x78160019, // 0010 JMPF R5 #002B - 0x60140004, // 0011 GETGBL R5 G4 - 0x5C180200, // 0012 MOVE R6 R1 - 0x7C140200, // 0013 CALL R5 1 - 0x1C140B05, // 0014 EQ R5 R5 K5 - 0x78160004, // 0015 JMPF R5 #001B - 0x5C140200, // 0016 MOVE R5 R1 - 0x5C180000, // 0017 MOVE R6 R0 - 0x7C140200, // 0018 CALL R5 1 - 0x90020C05, // 0019 SETMBR R0 K6 R5 + 0x4C100000, // 0000 LDNIL R4 + 0x20100604, // 0001 NE R4 R3 R4 + 0x78120005, // 0002 JMPF R4 #0009 + 0xB8120000, // 0003 GETNGBL R4 K0 + 0x8C100901, // 0004 GETMET R4 R4 K1 + 0x5C180600, // 0005 MOVE R6 R3 + 0x7C100400, // 0006 CALL R4 2 + 0x74120000, // 0007 JMPT R4 #0009 + 0x80000800, // 0008 RET 0 + 0x90020402, // 0009 SETMBR R0 K2 R2 + 0xB8120000, // 000A GETNGBL R4 K0 + 0x8C100904, // 000B GETMET R4 R4 K4 + 0x88180102, // 000C GETMBR R6 R0 K2 + 0x7C100400, // 000D CALL R4 2 + 0x90020604, // 000E SETMBR R0 K3 R4 + 0x88100103, // 000F GETMBR R4 R0 K3 + 0x78120019, // 0010 JMPF R4 #002B + 0x60100004, // 0011 GETGBL R4 G4 + 0x5C140200, // 0012 MOVE R5 R1 + 0x7C100200, // 0013 CALL R4 1 + 0x1C100905, // 0014 EQ R4 R4 K5 + 0x78120004, // 0015 JMPF R4 #001B + 0x5C100200, // 0016 MOVE R4 R1 + 0x5C140000, // 0017 MOVE R5 R0 + 0x7C100200, // 0018 CALL R4 1 + 0x90020C04, // 0019 SETMBR R0 K6 R4 0x70020000, // 001A JMP #001C 0x90020C01, // 001B SETMBR R0 K6 R1 - 0x88140106, // 001C GETMBR R5 R0 K6 - 0x4C180000, // 001D LDNIL R6 - 0x1C140A06, // 001E EQ R5 R5 R6 - 0x78160001, // 001F JMPF R5 #0022 - 0x4C140000, // 0020 LDNIL R5 - 0x90020605, // 0021 SETMBR R0 K3 R5 - 0x88140103, // 0022 GETMBR R5 R0 K3 - 0x78160006, // 0023 JMPF R5 #002B - 0x60140001, // 0024 GETGBL R5 G1 - 0x58180007, // 0025 LDCONST R6 K7 - 0x881C0106, // 0026 GETMBR R7 R0 K6 - 0x58200008, // 0027 LDCONST R8 K8 - 0x88240103, // 0028 GETMBR R9 R0 K3 - 0x88241309, // 0029 GETMBR R9 R9 K9 - 0x7C140800, // 002A CALL R5 4 + 0x88100106, // 001C GETMBR R4 R0 K6 + 0x4C140000, // 001D LDNIL R5 + 0x1C100805, // 001E EQ R4 R4 R5 + 0x78120001, // 001F JMPF R4 #0022 + 0x4C100000, // 0020 LDNIL R4 + 0x90020604, // 0021 SETMBR R0 K3 R4 + 0x88100103, // 0022 GETMBR R4 R0 K3 + 0x78120006, // 0023 JMPF R4 #002B + 0x60100001, // 0024 GETGBL R4 G1 + 0x58140007, // 0025 LDCONST R5 K7 + 0x88180106, // 0026 GETMBR R6 R0 K6 + 0x581C0008, // 0027 LDCONST R7 K8 + 0x88200103, // 0028 GETMBR R8 R0 K3 + 0x88201109, // 0029 GETMBR R8 R8 K9 + 0x7C100800, // 002A CALL R4 4 0x80000000, // 002B RET 0 }) ) diff --git a/lib/libesp32/berry_tasmota/src/be_i2s_audio_lib.cpp b/lib/libesp32/berry_tasmota/src/be_i2s_audio_lib.cpp new file mode 100644 index 000000000..0b0d08919 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_i2s_audio_lib.cpp @@ -0,0 +1,245 @@ +/******************************************************************** + * Tasmota I2S audio classes + * + * + *******************************************************************/ +#include "be_constobj.h" + +#ifdef USE_I2S +#ifdef USE_I2S_AUDIO_BERRY + +#include "be_mapping.h" +#include "AudioOutput.h" + +extern "C" void berry_log_C(const char * berry_buf, ...); + +extern "C" { + extern int i2s_output_i2s_init(bvm *vm); + extern int i2s_output_i2s_deinit(bvm *vm); + extern int i2s_output_i2s_stop(bvm *vm); + + extern int i2s_generator_wav_init(bvm *vm); + extern int i2s_generator_wav_deinit(bvm *vm); + extern int i2s_generator_wav_begin(bvm *vm); + extern int i2s_generator_wav_loop(bvm *vm); + extern int i2s_generator_wav_stop(bvm *vm); + extern int i2s_generator_wav_isrunning(bvm *vm); + + extern int i2s_generator_mp3_init(bvm *vm); + extern int i2s_generator_mp3_deinit(bvm *vm); + extern int i2s_generator_mp3_begin(bvm *vm); + extern int i2s_generator_mp3_loop(bvm *vm); + extern int i2s_generator_mp3_stop(bvm *vm); + extern int i2s_generator_mp3_isrunning(bvm *vm); + +#ifdef USE_UFILESYS + extern int i2s_file_source_fs_init(bvm *vm); + extern int i2s_file_source_fs_deinit(bvm *vm); +#endif // USE_UFILESYS +} + +// AudioOutput.set_rate(rate_hz:int) -> bool +AudioOutput* be_audio_output_init_ntv(void) { + return new AudioOutput(); +} +int32_t be_audio_output_init(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_audio_output_init_ntv, "+.p", ""); +} + +// AudioOutput.set_rate(rate_hz:int) -> bool +int be_audio_output_set_rate_ntv(AudioOutput* out, int hz) { + return out->SetRate(hz); +} +int32_t be_audio_output_set_rate(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_audio_output_set_rate_ntv, "b", ".i"); +} + +// AudioOutput.set_bits_per_sample(bits_per_sample:int) -> bool +int be_audio_output_set_bits_per_sample_ntv(AudioOutput* out, int bps) { + return out->SetBitsPerSample(bps); +} +int32_t be_audio_output_set_bits_per_sample(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_audio_output_set_bits_per_sample_ntv, "b", ".i"); +} + +// AudioOutput.set_channels(channels:int) -> bool +int be_audio_output_set_channels_ntv(AudioOutput* out, int channels) { + return out->SetChannels(channels); +} +int32_t be_audio_output_set_channels(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_audio_output_set_channels_ntv, "b", ".i"); +} + +// AudioOutput.set_gain(gain:real) -> bool +int be_audio_output_set_gain_ntv(AudioOutput* out, float gain) { + return out->SetGain(gain); +} +int32_t be_audio_output_set_gain(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_audio_output_set_gain_ntv, "b", ".f"); +} + +// AudioOutput.begin() -> bool +int be_audio_output_begin_ntv(AudioOutput* out) { + return out->begin(); +} +int32_t be_audio_output_begin(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_audio_output_begin_ntv, "b", "."); +} +// AudioOutput.stop() -> bool +int be_audio_output_stop_ntv(AudioOutput* out) { + return out->stop(); +} +int32_t be_audio_output_stop(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_audio_output_stop_ntv, "b", "."); +} +// AudioOutput.flush() -> bool +void be_audio_output_flush_ntv(AudioOutput* out) { + out->flush(); +} +int32_t be_audio_output_flush(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_audio_output_flush_ntv, "", "."); +} + +// AudioOutput.consume_mono(bytes) -> int +int be_audio_output_consume_mono_ntv(AudioOutput* out, uint16_t *pcm, int bytes_len, int index) { + int pcm_len = bytes_len / 2; + int n; + // berry_log_C("be_audio_output_consume_mono_ntv out=%p pcm=%p bytes_len=%i index=%i", out, pcm, bytes_len, index); + for (n = 0; index + n < pcm_len; n++) { + int16_t ms[2]; + ms[AudioOutput::LEFTCHANNEL] = ms[AudioOutput::RIGHTCHANNEL] = pcm[index + n]; + if (!out->ConsumeSample(ms)) { break; } + } + return n; +} +int32_t be_audio_output_consume_mono(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_audio_output_consume_mono_ntv, "i", ".(bytes)~i"); +} + +// AudioOutput.consume_stereo(bytes) -> int +int be_audio_output_consume_stereo_ntv(AudioOutput* out, uint16_t *pcm, int bytes_len, int index) { + int pcm_len = bytes_len / 4; // 2 samples LEFT+RIGHT of 2 bytes each + int n; + // berry_log_C("be_audio_output_consume_stereo_ntv out=%p pcm=%p bytes_len=%i index=%i", out, pcm, bytes_len, index); + for (n = 0; index + n < pcm_len; n++) { + int16_t ms[2]; + ms[AudioOutput::LEFTCHANNEL] = pcm[index + n + n]; + ms[AudioOutput::RIGHTCHANNEL] = pcm[index + n + n + 1]; + if (!out->ConsumeSample(ms)) { break; } + } + return n; +} +int32_t be_audio_output_consume_stereo(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_audio_output_consume_stereo_ntv, "i", ".(bytes)~i"); +} + +// AudioOutput.consume_silence() -> int, push silence frames +int be_audio_output_consume_silence_ntv(AudioOutput* out) { + int n = 0; + int16_t ms[2] = {0, 0}; + while (true) { + if (!out->ConsumeSample(ms)) { break; } + n++; + } + return n; +} +int32_t be_audio_output_consume_silence(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_audio_output_consume_silence_ntv, "i", "."); +} + +extern "C" { + +#include "be_fixed_be_class_audio_output.h" +#include "be_fixed_be_class_audio_output_i2s.h" +#include "be_fixed_be_class_audio_generator.h" +#include "be_fixed_be_class_audio_generator_wav.h" +#include "be_fixed_be_class_audio_generator_mp3.h" +#include "be_fixed_be_class_audio_file_source.h" +#include "be_fixed_be_class_audio_file_source_fs.h" + + void be_load_driver_audio_lib(bvm *vm) { + be_pushntvclass(vm, &be_class_audio_output); + be_setglobal(vm, "AudioOutput"); + be_pop(vm, 1); + + be_pushntvclass(vm, &be_class_audio_output_i2s); + be_setglobal(vm, "AudioOutputI2S"); + be_pop(vm, 1); + + be_pushntvclass(vm, &be_class_audio_generator_wav); + be_setglobal(vm, "AudioGeneratorWAV"); + be_pop(vm, 1); + + be_pushntvclass(vm, &be_class_audio_generator_mp3); + be_setglobal(vm, "AudioGeneratorMP3"); + be_pop(vm, 1); + + #ifdef USE_UFILESYS + be_pushntvclass(vm, &be_class_audio_file_source_fs); + be_setglobal(vm, "AudioFileSourceFS"); + be_pop(vm, 1); + #endif // USE_UFILESYS + } +} + +/* @const_object_info_begin + +class be_class_audio_output (scope: global, name: AudioOutput) { + .p, var + init, func(be_audio_output_init) + + begin, func(be_audio_output_begin) + stop, func(be_audio_output_stop) + flush, func(be_audio_output_flush) + + consume_mono, func(be_audio_output_consume_mono) + consume_stereo, func(be_audio_output_consume_stereo) + consume_silence, func(be_audio_output_consume_silence) + + set_rate, func(be_audio_output_set_rate) + set_bits_per_sample, func(be_audio_output_set_bits_per_sample) + set_channels, func(be_audio_output_set_channels) + set_gain, func(be_audio_output_set_gain) +} + +class be_class_audio_generator (scope: global, name: AudioGenerator) { + .p, var +} + +class be_class_audio_file_source (scope: global, name: AudioFileSource) { + .p, var +} + +class be_class_audio_output_i2s (scope: global, name: AudioOutputI2S, super: be_class_audio_output) { + init, func(i2s_output_i2s_init) + deinit, func(i2s_output_i2s_deinit) + stop, func(i2s_output_i2s_stop) +} + +class be_class_audio_generator_wav (scope: global, name: AudioGeneratorWAV, super: be_class_audio_generator) { + init, func(i2s_generator_wav_init) + deinit, func(i2s_generator_wav_deinit) + begin, func(i2s_generator_wav_begin) + loop, func(i2s_generator_wav_loop) + stop, func(i2s_generator_wav_stop) + isrunning, func(i2s_generator_wav_isrunning) +} + +class be_class_audio_generator_mp3 (scope: global, name: AudioGeneratorMP3, super: be_class_audio_generator) { + init, func(i2s_generator_mp3_init) + deinit, func(i2s_generator_mp3_deinit) + begin, func(i2s_generator_mp3_begin) + loop, func(i2s_generator_mp3_loop) + stop, func(i2s_generator_mp3_stop) + isrunning, func(i2s_generator_mp3_isrunning) +} + +class be_class_audio_file_source_fs (scope: global, name: AudioFileSourceFS, super: be_class_audio_file_source) { + init, func(i2s_file_source_fs_init) + deinit, func(i2s_file_source_fs_deinit) +} + +@const_object_info_end */ + +#endif // USE_I2S_AUDIO_BERRY +#endif // USE_I2S \ No newline at end of file diff --git a/lib/libesp32/Berry/default/be_leds_animator_lib.c b/lib/libesp32/berry_tasmota/src/be_leds_animator_lib.c similarity index 100% rename from lib/libesp32/Berry/default/be_leds_animator_lib.c rename to lib/libesp32/berry_tasmota/src/be_leds_animator_lib.c diff --git a/lib/libesp32/Berry/default/be_leds_lib.c b/lib/libesp32/berry_tasmota/src/be_leds_lib.c similarity index 100% rename from lib/libesp32/Berry/default/be_leds_lib.c rename to lib/libesp32/berry_tasmota/src/be_leds_lib.c diff --git a/lib/libesp32/Berry/default/be_leds_ntv_lib.c b/lib/libesp32/berry_tasmota/src/be_leds_ntv_lib.c similarity index 100% rename from lib/libesp32/Berry/default/be_leds_ntv_lib.c rename to lib/libesp32/berry_tasmota/src/be_leds_ntv_lib.c diff --git a/lib/libesp32/Berry/default/be_light_lib.c b/lib/libesp32/berry_tasmota/src/be_light_lib.c similarity index 94% rename from lib/libesp32/Berry/default/be_light_lib.c rename to lib/libesp32/berry_tasmota/src/be_light_lib.c index 6d020eca8..cb0393411 100644 --- a/lib/libesp32/Berry/default/be_light_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_light_lib.c @@ -23,6 +23,6 @@ module light (scope: global) { reverse_gamma10, func(l_rev_gamma10) } @const_object_info_end */ -#include "../generate/be_fixed_light.h" +#include "be_fixed_light.h" #endif // USE_LIGHT \ No newline at end of file diff --git a/lib/libesp32/berry_tasmota/src/be_lv_tasmota_lib.c b/lib/libesp32/berry_tasmota/src/be_lv_tasmota_lib.c new file mode 100644 index 000000000..6da172c6a --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_lv_tasmota_lib.c @@ -0,0 +1,116 @@ +/******************************************************************** + * Tasmota LVGL lv_signal_bars widget + *******************************************************************/ +#include "be_constobj.h" + +#ifdef USE_LVGL + +extern int lv0_start(bvm *vm); + +extern int lv0_register_button_encoder(bvm *vm); // add buttons with encoder logic + +extern int lv0_load_montserrat_font(bvm *vm); +extern int lv0_load_seg7_font(bvm *vm); +extern int lv0_load_robotocondensed_latin1_font(bvm *vm); + +extern int lv0_screenshot(bvm *vm); +extern int lv0_load_freetype_font(bvm *vm); + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(lv_tasmota_init, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[23]) { /* constants */ + /* K0 */ be_nested_str(lv), + /* K1 */ be_nested_str(start), + /* K2 */ be_nested_str(font_montserrat), + /* K3 */ be_nested_str(montserrat_font), + /* K4 */ be_nested_str(font_seg7), + /* K5 */ be_nested_str(seg7_font), + /* K6 */ be_nested_str(load_freetype_font), + /* K7 */ be_nested_str(register_button_encoder), + /* K8 */ be_nested_str(screenshot), + /* K9 */ be_nested_str(clock_icon), + /* K10 */ be_nested_str(lv_clock_icon), + /* K11 */ be_nested_str(signal_arcs), + /* K12 */ be_nested_str(lv_signal_arcs), + /* K13 */ be_nested_str(signal_bars), + /* K14 */ be_nested_str(lv_signal_bars), + /* K15 */ be_nested_str(wifi_arcs_icon), + /* K16 */ be_nested_str(lv_wifi_arcs_icon), + /* K17 */ be_nested_str(wifi_arcs), + /* K18 */ be_nested_str(lv_wifi_arcs), + /* K19 */ be_nested_str(wifi_bars_icon), + /* K20 */ be_nested_str(lv_wifi_bars_icon), + /* K21 */ be_nested_str(wifi_bars), + /* K22 */ be_nested_str(lv_wifi_bars), + }), + &be_const_str_init, + &be_const_str_solidified, + ( &(const binstruction[33]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x88080101, // 0001 GETMBR R2 R0 K1 + 0x90060202, // 0002 SETMBR R1 K1 R2 + 0x88080102, // 0003 GETMBR R2 R0 K2 + 0x90060402, // 0004 SETMBR R1 K2 R2 + 0x88080102, // 0005 GETMBR R2 R0 K2 + 0x90060602, // 0006 SETMBR R1 K3 R2 + 0x88080104, // 0007 GETMBR R2 R0 K4 + 0x90060802, // 0008 SETMBR R1 K4 R2 + 0x88080104, // 0009 GETMBR R2 R0 K4 + 0x90060A02, // 000A SETMBR R1 K5 R2 + 0x88080106, // 000B GETMBR R2 R0 K6 + 0x90060C02, // 000C SETMBR R1 K6 R2 + 0x88080107, // 000D GETMBR R2 R0 K7 + 0x90060E02, // 000E SETMBR R1 K7 R2 + 0x88080108, // 000F GETMBR R2 R0 K8 + 0x90061002, // 0010 SETMBR R1 K8 R2 + 0xB80A1400, // 0011 GETNGBL R2 K10 + 0x90061202, // 0012 SETMBR R1 K9 R2 + 0xB80A1800, // 0013 GETNGBL R2 K12 + 0x90061602, // 0014 SETMBR R1 K11 R2 + 0xB80A1C00, // 0015 GETNGBL R2 K14 + 0x90061A02, // 0016 SETMBR R1 K13 R2 + 0xB80A2000, // 0017 GETNGBL R2 K16 + 0x90061E02, // 0018 SETMBR R1 K15 R2 + 0xB80A2400, // 0019 GETNGBL R2 K18 + 0x90062202, // 001A SETMBR R1 K17 R2 + 0xB80A2800, // 001B GETNGBL R2 K20 + 0x90062602, // 001C SETMBR R1 K19 R2 + 0xB80A2C00, // 001D GETNGBL R2 K22 + 0x90062A02, // 001E SETMBR R1 K21 R2 + 0x4C080000, // 001F LDNIL R2 + 0x80040400, // 0020 RET 1 R2 + }) + ) +); +/*******************************************************************/ + +/* @const_object_info_begin +module lv_tasmota (scope: global) { + init, closure(lv_tasmota_init_closure) + + start, func(lv0_start) + + font_montserrat, func(lv0_load_montserrat_font) + montserrat_font, func(lv0_load_montserrat_font) + font_seg7, func(lv0_load_seg7_font) + seg7_font, func(lv0_load_seg7_font) + register_button_encoder, func(lv0_register_button_encoder) + screenshot, func(lv0_screenshot) + + load_freetype_font, func(lv0_load_freetype_font) +} +@const_object_info_end */ +#include "be_fixed_lv_tasmota.h" + +#endif // USE_LVGL \ No newline at end of file diff --git a/lib/libesp32/Berry/default/be_lvgl_clock_icon_lib.c b/lib/libesp32/berry_tasmota/src/be_lvgl_clock_icon_lib.c similarity index 79% rename from lib/libesp32/Berry/default/be_lvgl_clock_icon_lib.c rename to lib/libesp32/berry_tasmota/src/be_lvgl_clock_icon_lib.c index c9cf7f207..5d15e661d 100644 --- a/lib/libesp32/Berry/default/be_lvgl_clock_icon_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_lvgl_clock_icon_lib.c @@ -14,7 +14,7 @@ be_local_closure(lv_clock_icon_set_time, /* name */ be_nested_proto( 11, /* nstack */ 4, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -75,7 +75,7 @@ be_local_closure(lv_clock_icon_every_second, /* name */ be_nested_proto( 7, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -125,13 +125,37 @@ be_local_closure(lv_clock_icon_init, /* name */ be_nested_proto( 11, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 1]) { + be_nested_proto( + 2, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(before_del), + }), + &be_const_str__X3Clambda_X3E, + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x7C000200, // 0002 CALL R0 1 + 0x80040000, // 0003 RET 1 R0 + }) + ), + }), 1, /* has constants */ - ( &(const bvalue[22]) { /* constants */ + ( &(const bvalue[25]) { /* constants */ /* K0 */ be_nested_str(init), /* K1 */ be_nested_str(lv), /* K2 */ be_nested_str(seg7_font), @@ -152,12 +176,15 @@ be_local_closure(lv_clock_icon_init, /* name */ /* K17 */ be_nested_str(set_style_bg_color), /* K18 */ be_nested_str(color), /* K19 */ be_nested_str(COLOR_BLACK), - /* K20 */ be_nested_str(tasmota), - /* K21 */ be_nested_str(add_driver), + /* K20 */ be_nested_str(add_event_cb), + /* K21 */ be_nested_str(EVENT_DELETE), + /* K22 */ be_const_int(0), + /* K23 */ be_nested_str(tasmota), + /* K24 */ be_nested_str(add_driver), }), &be_const_str_init, &be_const_str_solidified, - ( &(const binstruction[82]) { /* code */ + ( &(const binstruction[89]) { /* code */ 0x60080003, // 0000 GETGBL R2 G3 0x5C0C0000, // 0001 MOVE R3 R0 0x7C080200, // 0002 CALL R2 1 @@ -235,11 +262,18 @@ be_local_closure(lv_clock_icon_init, /* name */ 0x88281505, // 004A GETMBR R10 R10 K5 0x3024120A, // 004B OR R9 R9 R10 0x7C180600, // 004C CALL R6 3 - 0xB80E2800, // 004D GETNGBL R3 K20 - 0x8C0C0715, // 004E GETMET R3 R3 K21 - 0x5C140000, // 004F MOVE R5 R0 - 0x7C0C0400, // 0050 CALL R3 2 - 0x80000000, // 0051 RET 0 + 0x8C0C0114, // 004D GETMET R3 R0 K20 + 0x84140000, // 004E CLOSURE R5 P0 + 0xB81A0200, // 004F GETNGBL R6 K1 + 0x88180D15, // 0050 GETMBR R6 R6 K21 + 0x581C0016, // 0051 LDCONST R7 K22 + 0x7C0C0800, // 0052 CALL R3 4 + 0xB80E2E00, // 0053 GETNGBL R3 K23 + 0x8C0C0718, // 0054 GETMET R3 R3 K24 + 0x5C140000, // 0055 MOVE R5 R0 + 0x7C0C0400, // 0056 CALL R3 2 + 0xA0000000, // 0057 CLOSE R0 + 0x80000000, // 0058 RET 0 }) ) ); @@ -247,36 +281,30 @@ be_local_closure(lv_clock_icon_init, /* name */ /******************************************************************** -** Solidified function: del +** Solidified function: before_del ********************************************************************/ -be_local_closure(lv_clock_icon_del, /* name */ +be_local_closure(lv_clock_icon_before_del, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str(del), - /* K1 */ be_nested_str(tasmota), - /* K2 */ be_nested_str(remove_driver), + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str(tasmota), + /* K1 */ be_nested_str(remove_driver), }), - &be_const_str_del, + &be_const_str_before_del, &be_const_str_solidified, - ( &(const binstruction[10]) { /* code */ - 0x60040003, // 0000 GETGBL R1 G3 - 0x5C080000, // 0001 MOVE R2 R0 - 0x7C040200, // 0002 CALL R1 1 - 0x8C040300, // 0003 GETMET R1 R1 K0 - 0x7C040200, // 0004 CALL R1 1 - 0xB8060200, // 0005 GETNGBL R1 K1 - 0x8C040302, // 0006 GETMET R1 R1 K2 - 0x5C0C0000, // 0007 MOVE R3 R0 - 0x7C040400, // 0008 CALL R1 2 - 0x80000000, // 0009 RET 0 + ( &(const binstruction[ 5]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C040400, // 0003 CALL R1 2 + 0x80000000, // 0004 RET 0 }) ) ); @@ -294,11 +322,11 @@ be_local_class(lv_clock_icon, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key(sec, -1), be_const_var(2) }, { be_const_key(hour, -1), be_const_var(0) }, - { be_const_key(set_time, 6), be_const_closure(lv_clock_icon_set_time_closure) }, + { be_const_key(before_del, 6), be_const_closure(lv_clock_icon_before_del_closure) }, { be_const_key(every_second, -1), be_const_closure(lv_clock_icon_every_second_closure) }, { be_const_key(minute, -1), be_const_var(1) }, - { be_const_key(init, 2), be_const_closure(lv_clock_icon_init_closure) }, - { be_const_key(del, -1), be_const_closure(lv_clock_icon_del_closure) }, + { be_const_key(set_time, 2), be_const_closure(lv_clock_icon_set_time_closure) }, + { be_const_key(init, -1), be_const_closure(lv_clock_icon_init_closure) }, })), be_str_literal("lv_clock_icon") ); diff --git a/lib/libesp32/Berry/default/be_lvgl_signal_arcs_lib.c b/lib/libesp32/berry_tasmota/src/be_lvgl_signal_arcs_lib.c similarity index 100% rename from lib/libesp32/Berry/default/be_lvgl_signal_arcs_lib.c rename to lib/libesp32/berry_tasmota/src/be_lvgl_signal_arcs_lib.c diff --git a/lib/libesp32/Berry/default/be_lvgl_signal_bars_lib.c b/lib/libesp32/berry_tasmota/src/be_lvgl_signal_bars_lib.c similarity index 100% rename from lib/libesp32/Berry/default/be_lvgl_signal_bars_lib.c rename to lib/libesp32/berry_tasmota/src/be_lvgl_signal_bars_lib.c diff --git a/lib/libesp32/Berry/default/be_lvgl_wifi_arcs_icon_lib.c b/lib/libesp32/berry_tasmota/src/be_lvgl_wifi_arcs_icon_lib.c similarity index 100% rename from lib/libesp32/Berry/default/be_lvgl_wifi_arcs_icon_lib.c rename to lib/libesp32/berry_tasmota/src/be_lvgl_wifi_arcs_icon_lib.c diff --git a/lib/libesp32/Berry/default/be_lvgl_wifi_arcs_lib.c b/lib/libesp32/berry_tasmota/src/be_lvgl_wifi_arcs_lib.c similarity index 84% rename from lib/libesp32/Berry/default/be_lvgl_wifi_arcs_lib.c rename to lib/libesp32/berry_tasmota/src/be_lvgl_wifi_arcs_lib.c index 57cbf18a9..dcbefb619 100644 --- a/lib/libesp32/Berry/default/be_lvgl_wifi_arcs_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_lvgl_wifi_arcs_lib.c @@ -7,6 +7,80 @@ #include "lvgl.h" +/******************************************************************** +** Solidified function: before_del +********************************************************************/ +be_local_closure(lv_wifi_arcs_before_del, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str(tasmota), + /* K1 */ be_nested_str(remove_driver), + }), + &be_const_str_before_del, + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C040400, // 0003 CALL R1 2 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(lv_wifi_arcs_init, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str(init), + /* K1 */ be_nested_str(tasmota), + /* K2 */ be_nested_str(add_driver), + /* K3 */ be_nested_str(set_percentage), + /* K4 */ be_const_int(0), + }), + &be_const_str_init, + &be_const_str_solidified, + ( &(const binstruction[14]) { /* code */ + 0x60080003, // 0000 GETGBL R2 G3 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x8C080500, // 0003 GETMET R2 R2 K0 + 0x5C100200, // 0004 MOVE R4 R1 + 0x7C080400, // 0005 CALL R2 2 + 0xB80A0200, // 0006 GETNGBL R2 K1 + 0x8C080502, // 0007 GETMET R2 R2 K2 + 0x5C100000, // 0008 MOVE R4 R0 + 0x7C080400, // 0009 CALL R2 2 + 0x8C080103, // 000A GETMET R2 R0 K3 + 0x58100004, // 000B LDCONST R4 K4 + 0x7C080400, // 000C CALL R2 2 + 0x80000000, // 000D RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: every_second ********************************************************************/ @@ -14,7 +88,7 @@ be_local_closure(lv_wifi_arcs_every_second, /* name */ be_nested_proto( 7, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -61,86 +135,6 @@ be_local_closure(lv_wifi_arcs_every_second, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(lv_wifi_arcs_init, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str(init), - /* K1 */ be_nested_str(tasmota), - /* K2 */ be_nested_str(add_driver), - /* K3 */ be_nested_str(set_percentage), - /* K4 */ be_const_int(0), - }), - &be_const_str_init, - &be_const_str_solidified, - ( &(const binstruction[14]) { /* code */ - 0x60080003, // 0000 GETGBL R2 G3 - 0x5C0C0000, // 0001 MOVE R3 R0 - 0x7C080200, // 0002 CALL R2 1 - 0x8C080500, // 0003 GETMET R2 R2 K0 - 0x5C100200, // 0004 MOVE R4 R1 - 0x7C080400, // 0005 CALL R2 2 - 0xB80A0200, // 0006 GETNGBL R2 K1 - 0x8C080502, // 0007 GETMET R2 R2 K2 - 0x5C100000, // 0008 MOVE R4 R0 - 0x7C080400, // 0009 CALL R2 2 - 0x8C080103, // 000A GETMET R2 R0 K3 - 0x58100004, // 000B LDCONST R4 K4 - 0x7C080400, // 000C CALL R2 2 - 0x80000000, // 000D RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: del -********************************************************************/ -be_local_closure(lv_wifi_arcs_del, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str(del), - /* K1 */ be_nested_str(tasmota), - /* K2 */ be_nested_str(remove_driver), - }), - &be_const_str_del, - &be_const_str_solidified, - ( &(const binstruction[10]) { /* code */ - 0x60040003, // 0000 GETGBL R1 G3 - 0x5C080000, // 0001 MOVE R2 R0 - 0x7C040200, // 0002 CALL R1 1 - 0x8C040300, // 0003 GETMET R1 R1 K0 - 0x7C040200, // 0004 CALL R1 1 - 0xB8060200, // 0005 GETNGBL R1 K1 - 0x8C040302, // 0006 GETMET R1 R1 K2 - 0x5C0C0000, // 0007 MOVE R3 R0 - 0x7C040400, // 0008 CALL R1 2 - 0x80000000, // 0009 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified class: lv_wifi_arcs ********************************************************************/ @@ -150,9 +144,9 @@ be_local_class(lv_wifi_arcs, &be_class_lv_signal_arcs, be_nested_map(3, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key(every_second, 1), be_const_closure(lv_wifi_arcs_every_second_closure) }, + { be_const_key(before_del, 1), be_const_closure(lv_wifi_arcs_before_del_closure) }, + { be_const_key(every_second, 2), be_const_closure(lv_wifi_arcs_every_second_closure) }, { be_const_key(init, -1), be_const_closure(lv_wifi_arcs_init_closure) }, - { be_const_key(del, -1), be_const_closure(lv_wifi_arcs_del_closure) }, })), be_str_literal("lv_wifi_arcs") ); diff --git a/lib/libesp32/Berry/default/be_lvgl_wifi_bars_icon_lib.c b/lib/libesp32/berry_tasmota/src/be_lvgl_wifi_bars_icon_lib.c similarity index 100% rename from lib/libesp32/Berry/default/be_lvgl_wifi_bars_icon_lib.c rename to lib/libesp32/berry_tasmota/src/be_lvgl_wifi_bars_icon_lib.c diff --git a/lib/libesp32/Berry/default/be_lvgl_wifi_bars_lib.c b/lib/libesp32/berry_tasmota/src/be_lvgl_wifi_bars_lib.c similarity index 84% rename from lib/libesp32/Berry/default/be_lvgl_wifi_bars_lib.c rename to lib/libesp32/berry_tasmota/src/be_lvgl_wifi_bars_lib.c index c61cb2bb3..e9facadf6 100644 --- a/lib/libesp32/Berry/default/be_lvgl_wifi_bars_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_lvgl_wifi_bars_lib.c @@ -7,6 +7,80 @@ #include "lvgl.h" +/******************************************************************** +** Solidified function: before_del +********************************************************************/ +be_local_closure(lv_wifi_bars_before_del, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str(tasmota), + /* K1 */ be_nested_str(remove_driver), + }), + &be_const_str_before_del, + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C040400, // 0003 CALL R1 2 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(lv_wifi_bars_init, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str(init), + /* K1 */ be_nested_str(tasmota), + /* K2 */ be_nested_str(add_driver), + /* K3 */ be_nested_str(set_percentage), + /* K4 */ be_const_int(0), + }), + &be_const_str_init, + &be_const_str_solidified, + ( &(const binstruction[14]) { /* code */ + 0x60080003, // 0000 GETGBL R2 G3 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x8C080500, // 0003 GETMET R2 R2 K0 + 0x5C100200, // 0004 MOVE R4 R1 + 0x7C080400, // 0005 CALL R2 2 + 0xB80A0200, // 0006 GETNGBL R2 K1 + 0x8C080502, // 0007 GETMET R2 R2 K2 + 0x5C100000, // 0008 MOVE R4 R0 + 0x7C080400, // 0009 CALL R2 2 + 0x8C080103, // 000A GETMET R2 R0 K3 + 0x58100004, // 000B LDCONST R4 K4 + 0x7C080400, // 000C CALL R2 2 + 0x80000000, // 000D RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: every_second ********************************************************************/ @@ -14,7 +88,7 @@ be_local_closure(lv_wifi_bars_every_second, /* name */ be_nested_proto( 7, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -61,86 +135,6 @@ be_local_closure(lv_wifi_bars_every_second, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(lv_wifi_bars_init, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str(init), - /* K1 */ be_nested_str(tasmota), - /* K2 */ be_nested_str(add_driver), - /* K3 */ be_nested_str(set_percentage), - /* K4 */ be_const_int(0), - }), - &be_const_str_init, - &be_const_str_solidified, - ( &(const binstruction[14]) { /* code */ - 0x60080003, // 0000 GETGBL R2 G3 - 0x5C0C0000, // 0001 MOVE R3 R0 - 0x7C080200, // 0002 CALL R2 1 - 0x8C080500, // 0003 GETMET R2 R2 K0 - 0x5C100200, // 0004 MOVE R4 R1 - 0x7C080400, // 0005 CALL R2 2 - 0xB80A0200, // 0006 GETNGBL R2 K1 - 0x8C080502, // 0007 GETMET R2 R2 K2 - 0x5C100000, // 0008 MOVE R4 R0 - 0x7C080400, // 0009 CALL R2 2 - 0x8C080103, // 000A GETMET R2 R0 K3 - 0x58100004, // 000B LDCONST R4 K4 - 0x7C080400, // 000C CALL R2 2 - 0x80000000, // 000D RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: del -********************************************************************/ -be_local_closure(lv_wifi_bars_del, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str(del), - /* K1 */ be_nested_str(tasmota), - /* K2 */ be_nested_str(remove_driver), - }), - &be_const_str_del, - &be_const_str_solidified, - ( &(const binstruction[10]) { /* code */ - 0x60040003, // 0000 GETGBL R1 G3 - 0x5C080000, // 0001 MOVE R2 R0 - 0x7C040200, // 0002 CALL R1 1 - 0x8C040300, // 0003 GETMET R1 R1 K0 - 0x7C040200, // 0004 CALL R1 1 - 0xB8060200, // 0005 GETNGBL R1 K1 - 0x8C040302, // 0006 GETMET R1 R1 K2 - 0x5C0C0000, // 0007 MOVE R3 R0 - 0x7C040400, // 0008 CALL R1 2 - 0x80000000, // 0009 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified class: lv_wifi_bars ********************************************************************/ @@ -150,9 +144,9 @@ be_local_class(lv_wifi_bars, &be_class_lv_signal_bars, be_nested_map(3, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key(every_second, 1), be_const_closure(lv_wifi_bars_every_second_closure) }, + { be_const_key(before_del, 1), be_const_closure(lv_wifi_bars_before_del_closure) }, + { be_const_key(every_second, 2), be_const_closure(lv_wifi_bars_every_second_closure) }, { be_const_key(init, -1), be_const_closure(lv_wifi_bars_init_closure) }, - { be_const_key(del, -1), be_const_closure(lv_wifi_bars_del_closure) }, })), be_str_literal("lv_wifi_bars") ); diff --git a/lib/libesp32/berry_tasmota/src/be_md5_lib.c b/lib/libesp32/berry_tasmota/src/be_md5_lib.c new file mode 100644 index 000000000..baa200747 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_md5_lib.c @@ -0,0 +1,100 @@ +/******************************************************************** + * Berry module `webserver` + * + * To use: `import webserver` + * + * Allows to respond to HTTP request + *******************************************************************/ +#include "be_constobj.h" +#include "be_mem.h" +#include "be_exec.h" +#include "esp_rom_md5.h" + +int free_ctx(bvm* vm) { + int argc = be_top(vm); + if (argc > 0) { + be_getmember(vm, 1, ".p"); + md5_context_t * ctx = (md5_context_t *) be_tocomptr(vm, -1); + if (ctx != NULL) { + be_os_free(ctx); + } + } + be_return_nil(vm); +} + +// `Md5.init() -> ` +int32_t m_md5_init(struct bvm *vm); +int32_t m_md5_init(struct bvm *vm) { + + md5_context_t * ctx = (md5_context_t *) be_os_malloc(sizeof(md5_context_t)); + if (!ctx) { + be_throw(vm, BE_MALLOC_FAIL); + } + esp_rom_md5_init(ctx); + + be_newcomobj(vm, ctx, &free_ctx); + be_setmember(vm, 1, ".p"); + be_return_nil(vm); +} + +// `Md5.update(content:bytes()) -> nil` +// +// Add raw bytes to the MD5 calculation +int32_t m_md5_update(struct bvm *vm); +int32_t m_md5_update(struct bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 2 && be_isinstance(vm, 2)) { + do { + be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */ + if (!be_isderived(vm, 2)) break; + size_t length = 0; + const void * bytes = be_tobytes(vm, 2, &length); + if (!bytes) break; + + be_getmember(vm, 1, ".p"); + md5_context_t * ctx; + ctx = (md5_context_t *) be_tocomptr(vm, -1); + if (!ctx) break; + + if (length > 0) { + esp_rom_md5_update(ctx, (const uint8_t*) bytes, length); + } + be_return_nil(vm); + // success + } while (0); + } + be_raise(vm, "value_error", NULL); +} + +// `Md5.update(content:bytes()) -> nil` +// +// Add raw bytes to the MD5 calculation +int32_t m_md5_finish(struct bvm *vm); +int32_t m_md5_finish(struct bvm *vm) { + be_getmember(vm, 1, ".p"); + md5_context_t * ctx; + ctx = (md5_context_t *) be_tocomptr(vm, -1); + + uint8_t output[16]; + esp_rom_md5_final(output, ctx); + be_pushbytes(vm, output, sizeof(output)); + be_return(vm); +} + +#include "be_fixed_be_class_md5.h" + +void be_load_md5_lib(bvm *vm) { + be_pushntvclass(vm, &be_class_md5); + be_setglobal(vm, "MD5"); + be_pop(vm, 1); +} +/* @const_object_info_begin + +class be_class_md5 (scope: global, name: MD5) { + .p, var + + init, func(m_md5_init) + update, func(m_md5_update) + finish, func(m_md5_finish) +} +@const_object_info_end */ diff --git a/lib/libesp32/berry_tasmota/src/be_modtab_tasmota.c b/lib/libesp32/berry_tasmota/src/be_modtab_tasmota.c new file mode 100644 index 000000000..b2a6be29e --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_modtab_tasmota.c @@ -0,0 +1,2 @@ +// TODO + diff --git a/lib/libesp32/Berry/default/be_onewire_lib.c b/lib/libesp32/berry_tasmota/src/be_onewire_lib.c similarity index 96% rename from lib/libesp32/Berry/default/be_onewire_lib.c rename to lib/libesp32/berry_tasmota/src/be_onewire_lib.c index 838e6ccf9..e43fcf7c1 100644 --- a/lib/libesp32/Berry/default/be_onewire_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_onewire_lib.c @@ -24,7 +24,7 @@ extern int b_onewire_reset_search(bvm *vm); extern int b_onewire_target_search(bvm *vm); extern int b_onewire_search(bvm *vm); -#include "../generate/be_fixed_be_class_tasmota_onewire.h" +#include "be_fixed_be_class_tasmota_onewire.h" void be_load_onewirelib(bvm *vm) { be_pushntvclass(vm, &be_class_tasmota_onewire); diff --git a/lib/libesp32/Berry/default/be_path_tasmota_lib.c b/lib/libesp32/berry_tasmota/src/be_path_tasmota_lib.c similarity index 97% rename from lib/libesp32/Berry/default/be_path_tasmota_lib.c rename to lib/libesp32/berry_tasmota/src/be_path_tasmota_lib.c index 81711a053..0350edf12 100644 --- a/lib/libesp32/Berry/default/be_path_tasmota_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_path_tasmota_lib.c @@ -67,4 +67,4 @@ module path (scope: global, file: tasmota_path) { remove, func(m_path_remove) } @const_object_info_end */ -#include "../generate/be_fixed_tasmota_path.h" +#include "be_fixed_tasmota_path.h" diff --git a/lib/libesp32/Berry/default/be_persist_lib.c b/lib/libesp32/berry_tasmota/src/be_persist_lib.c similarity index 100% rename from lib/libesp32/Berry/default/be_persist_lib.c rename to lib/libesp32/berry_tasmota/src/be_persist_lib.c diff --git a/lib/libesp32/Berry/default/be_port.cpp b/lib/libesp32/berry_tasmota/src/be_port.cpp similarity index 99% rename from lib/libesp32/Berry/default/be_port.cpp rename to lib/libesp32/berry_tasmota/src/be_port.cpp index 5da10f47e..4204c2171 100644 --- a/lib/libesp32/Berry/default/be_port.cpp +++ b/lib/libesp32/berry_tasmota/src/be_port.cpp @@ -101,6 +101,7 @@ BERRY_API void be_writebuffer(const char *buffer, size_t length) extern "C" { int m_path_listdir(bvm *vm) { +#ifdef USE_UFILESYS if (be_top(vm) >= 1 && be_isstring(vm, 1)) { const char *path = be_tostring(vm, 1); be_newobject(vm, "list"); @@ -126,6 +127,7 @@ extern "C" { be_return(vm); } +#endif // USE_UFILESYS be_return_nil(vm); } } @@ -136,10 +138,9 @@ BERRY_API char* be_readstring(char *buffer, size_t size) } /* use the standard library implementation file API. */ - +#ifdef USE_UFILESYS void* be_fopen(const char *filename, const char *modes) { -#ifdef USE_UFILESYS if (filename != nullptr && modes != nullptr) { char fname2[strlen(filename) + 2]; if (filename[0] == '/') { @@ -156,23 +157,24 @@ void* be_fopen(const char *filename, const char *modes) return f_ptr; } } -#endif // USE_UFILESYS return nullptr; // return fopen(filename, modes); } +#endif // USE_UFILESYS + +#ifdef USE_UFILESYS // Tasmota specific, get the underlying Arduino File File * be_get_arduino_file(void *hfile) { -#ifdef USE_UFILESYS if (hfile != nullptr) { File * f_ptr = (File*) hfile; return f_ptr; } -#endif // USE_UFILESYS return nullptr; // return fopen(filename, modes); } +#endif int be_fclose(void *hfile) { diff --git a/lib/libesp32/Berry/default/be_python_compat.c b/lib/libesp32/berry_tasmota/src/be_python_compat.c similarity index 100% rename from lib/libesp32/Berry/default/be_python_compat.c rename to lib/libesp32/berry_tasmota/src/be_python_compat.c diff --git a/lib/libesp32/Berry/default/be_re_lib.c b/lib/libesp32/berry_tasmota/src/be_re_lib.c similarity index 100% rename from lib/libesp32/Berry/default/be_re_lib.c rename to lib/libesp32/berry_tasmota/src/be_re_lib.c diff --git a/lib/libesp32/Berry/default/be_serial_lib.c b/lib/libesp32/berry_tasmota/src/be_serial_lib.c similarity index 96% rename from lib/libesp32/Berry/default/be_serial_lib.c rename to lib/libesp32/berry_tasmota/src/be_serial_lib.c index 4f1c4b577..1a5f6fd96 100644 --- a/lib/libesp32/Berry/default/be_serial_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_serial_lib.c @@ -17,7 +17,7 @@ extern int b_serial_read(bvm *vm); extern int b_serial_available(bvm *vm); extern int b_serial_flush(bvm *vm); -#include "../generate/be_fixed_be_class_tasmota_serial.h" +#include "be_fixed_be_class_tasmota_serial.h" void be_load_serial_lib(bvm *vm) { be_pushntvclass(vm, &be_class_tasmota_serial); diff --git a/lib/libesp32/Berry/default/be_tapp_lib.c b/lib/libesp32/berry_tasmota/src/be_tapp_lib.c similarity index 98% rename from lib/libesp32/Berry/default/be_tapp_lib.c rename to lib/libesp32/berry_tasmota/src/be_tapp_lib.c index 1a312d110..d47d9c2d0 100644 --- a/lib/libesp32/Berry/default/be_tapp_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_tapp_lib.c @@ -61,7 +61,7 @@ be_local_closure(Tapp_autoexec, /* name */ /* K7 */ be_nested_str(tasmota), /* K8 */ be_nested_str(log), /* K9 */ be_nested_str(format), - /* K10 */ be_nested_str(TAP_X3A_X20found_X20Tasmota_X20App_X20_X27_X25s_X27), + /* K10 */ be_nested_str(TAP_X3A_X20Loaded_X20Tasmota_X20App_X20_X27_X25s_X27), /* K11 */ be_const_int(2), /* K12 */ be_nested_str(load), /* K13 */ be_nested_str(_X23autoexec_X2Ebe), diff --git a/lib/libesp32/Berry/default/be_tasmotalib.c b/lib/libesp32/berry_tasmota/src/be_tasmotalib.c similarity index 87% rename from lib/libesp32/Berry/default/be_tasmotalib.c rename to lib/libesp32/berry_tasmota/src/be_tasmotalib.c index e117bae70..9d1ac2fd6 100644 --- a/lib/libesp32/Berry/default/be_tasmotalib.c +++ b/lib/libesp32/berry_tasmota/src/be_tasmotalib.c @@ -4,19 +4,18 @@ * To use: `import tasmota` *******************************************************************/ #include "be_constobj.h" +#include "be_ctypes.h" -struct dummy_struct {}; // we need a struct name but don't need any meaningful content, we just take the address extern struct TasmotaGlobal_t TasmotaGlobal; extern struct TSettings * Settings; -extern struct dummy_struct be_tasmota_global_struct; -extern struct dummy_struct be_tasmota_settings_struct; +extern const be_ctypes_structure_t be_tasmota_global_struct; +extern const be_ctypes_structure_t be_tasmota_settings_struct; extern int l_getFreeHeap(bvm *vm); extern int l_arch(bvm *vm); extern int l_publish(bvm *vm); extern int l_publish_result(bvm *vm); extern int l_cmd(bvm *vm); -extern int l_get_cb(bvm *vm); extern int l_getoption(bvm *vm); extern int l_millis(bvm *vm); extern int l_timereached(bvm *vm); @@ -32,6 +31,7 @@ extern int l_delay(bvm *vm); extern int l_scaleuint(bvm *vm); extern int l_logInfo(bvm *vm); extern int l_save(bvm *vm); +extern int t_random_byte(bvm *vm); extern int l_read_sensors(bvm *vm); @@ -62,31 +62,40 @@ be_local_closure(Tasmota_add_driver, /* name */ be_nested_proto( 5, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str(_drivers), - /* K1 */ be_nested_str(push), + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str(instance), + /* K1 */ be_nested_str(value_error), + /* K2 */ be_nested_str(instance_X20required), + /* K3 */ be_nested_str(_drivers), + /* K4 */ be_nested_str(push), }), &be_const_str_add_driver, &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x780A0004, // 0001 JMPF R2 #0007 - 0x88080100, // 0002 GETMBR R2 R0 K0 - 0x8C080501, // 0003 GETMET R2 R2 K1 - 0x5C100200, // 0004 MOVE R4 R1 - 0x7C080400, // 0005 CALL R2 2 - 0x70020003, // 0006 JMP #000B - 0x60080012, // 0007 GETGBL R2 G18 - 0x7C080000, // 0008 CALL R2 0 - 0x400C0401, // 0009 CONNECT R3 R2 R1 - 0x90020002, // 000A SETMBR R0 K0 R2 - 0x80000000, // 000B RET 0 + ( &(const binstruction[18]) { /* code */ + 0x60080004, // 0000 GETGBL R2 G4 + 0x5C0C0200, // 0001 MOVE R3 R1 + 0x7C080200, // 0002 CALL R2 1 + 0x20080500, // 0003 NE R2 R2 K0 + 0x780A0000, // 0004 JMPF R2 #0006 + 0xB0060302, // 0005 RAISE 1 K1 K2 + 0x88080103, // 0006 GETMBR R2 R0 K3 + 0x780A0004, // 0007 JMPF R2 #000D + 0x88080103, // 0008 GETMBR R2 R0 K3 + 0x8C080504, // 0009 GETMET R2 R2 K4 + 0x5C100200, // 000A MOVE R4 R1 + 0x7C080400, // 000B CALL R2 2 + 0x70020003, // 000C JMP #0011 + 0x60080012, // 000D GETGBL R2 G18 + 0x7C080000, // 000E CALL R2 0 + 0x400C0401, // 000F CONNECT R3 R2 R1 + 0x90020602, // 0010 SETMBR R0 K3 R2 + 0x80000000, // 0011 RET 0 }) ) ); @@ -100,7 +109,7 @@ be_local_closure(Tasmota_gc, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -133,7 +142,7 @@ be_local_closure(Tasmota_find_op, /* name */ be_nested_proto( 13, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -205,7 +214,7 @@ be_local_closure(Tasmota_try_rule, /* name */ be_nested_proto( 15, /* nstack */ 4, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -384,60 +393,26 @@ be_local_closure(Tasmota_try_rule, /* name */ ********************************************************************/ be_local_closure(Tasmota_gen_cb, /* name */ be_nested_proto( - 7, /* nstack */ + 6, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_nested_str(_cb), - /* K1 */ be_const_int(0), - /* K2 */ be_nested_str(find), - /* K3 */ be_nested_str(_get_cb), - /* K4 */ be_nested_str(stop_iteration), - /* K5 */ be_nested_str(internal_error), - /* K6 */ be_nested_str(No_X20callback_X20available), + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str(cb), + /* K1 */ be_nested_str(gen_cb), }), &be_const_str_gen_cb, &be_const_str_solidified, - ( &(const binstruction[34]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x1C080403, // 0002 EQ R2 R2 R3 - 0x780A0002, // 0003 JMPF R2 #0007 - 0x60080013, // 0004 GETGBL R2 G19 - 0x7C080000, // 0005 CALL R2 0 - 0x90020002, // 0006 SETMBR R0 K0 R2 - 0x60080010, // 0007 GETGBL R2 G16 - 0x540E0012, // 0008 LDINT R3 19 - 0x400E0203, // 0009 CONNECT R3 K1 R3 - 0x7C080200, // 000A CALL R2 1 - 0xA8020010, // 000B EXBLK 0 #001D - 0x5C0C0400, // 000C MOVE R3 R2 - 0x7C0C0000, // 000D CALL R3 0 - 0x88100100, // 000E GETMBR R4 R0 K0 - 0x8C100902, // 000F GETMET R4 R4 K2 - 0x5C180600, // 0010 MOVE R6 R3 - 0x7C100400, // 0011 CALL R4 2 - 0x4C140000, // 0012 LDNIL R5 - 0x1C100805, // 0013 EQ R4 R4 R5 - 0x78120006, // 0014 JMPF R4 #001C - 0x88100100, // 0015 GETMBR R4 R0 K0 - 0x98100601, // 0016 SETIDX R4 R3 R1 - 0x8C100103, // 0017 GETMET R4 R0 K3 - 0x5C180600, // 0018 MOVE R6 R3 - 0x7C100400, // 0019 CALL R4 2 - 0xA8040001, // 001A EXBLK 1 1 - 0x80040800, // 001B RET 1 R4 - 0x7001FFEE, // 001C JMP #000C - 0x58080004, // 001D LDCONST R2 K4 - 0xAC080200, // 001E CATCH R2 1 0 - 0xB0080000, // 001F RAISE 2 R0 R0 - 0xB0060B06, // 0020 RAISE 1 K5 K6 - 0x80000000, // 0021 RET 0 + ( &(const binstruction[ 5]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0x8C0C0501, // 0001 GETMET R3 R2 K1 + 0x5C140200, // 0002 MOVE R5 R1 + 0x7C0C0400, // 0003 CALL R3 2 + 0x80040600, // 0004 RET 1 R3 }) ) ); @@ -451,7 +426,7 @@ be_local_closure(Tasmota_set_light, /* name */ be_nested_proto( 8, /* nstack */ 3, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -496,7 +471,7 @@ be_local_closure(Tasmota_exec_tele, /* name */ be_nested_proto( 12, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -573,7 +548,7 @@ be_local_closure(Tasmota_run_deferred, /* name */ be_nested_proto( 6, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -632,7 +607,7 @@ be_local_closure(Tasmota_remove_driver, /* name */ be_nested_proto( 6, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -665,6 +640,101 @@ be_local_closure(Tasmota_remove_driver, /* name */ ); /*******************************************************************/ +/******************************************************************** +** Solidified function: fast_loop +********************************************************************/ +be_local_closure(Tasmota_fast_loop, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str(_fl), + /* K1 */ be_const_int(0), + /* K2 */ be_const_int(1), + }), + &be_const_str_fast_loop, + &be_const_str_solidified, + ( &(const binstruction[15]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x5C080200, // 0001 MOVE R2 R1 + 0x740A0000, // 0002 JMPT R2 #0004 + 0x80000400, // 0003 RET 0 + 0x58080001, // 0004 LDCONST R2 K1 + 0x600C000C, // 0005 GETGBL R3 G12 + 0x5C100200, // 0006 MOVE R4 R1 + 0x7C0C0200, // 0007 CALL R3 1 + 0x140C0403, // 0008 LT R3 R2 R3 + 0x780E0003, // 0009 JMPF R3 #000E + 0x940C0202, // 000A GETIDX R3 R1 R2 + 0x7C0C0000, // 000B CALL R3 0 + 0x00080502, // 000C ADD R2 R2 K2 + 0x7001FFF6, // 000D JMP #0005 + 0x80000000, // 000E RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_fast_loop +********************************************************************/ +be_local_closure(Tasmota_add_fast_loop, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str(check_not_method), + /* K1 */ be_nested_str(_fl), + /* K2 */ be_nested_str(function), + /* K3 */ be_nested_str(value_error), + /* K4 */ be_nested_str(argument_X20must_X20be_X20a_X20function), + /* K5 */ be_nested_str(global), + /* K6 */ be_nested_str(fast_loop_enabled), + /* K7 */ be_const_int(1), + /* K8 */ be_nested_str(push), + }), + &be_const_str_add_fast_loop, + &be_const_str_solidified, + ( &(const binstruction[21]) { /* code */ + 0x8C080100, // 0000 GETMET R2 R0 K0 + 0x5C100200, // 0001 MOVE R4 R1 + 0x7C080400, // 0002 CALL R2 2 + 0x88080101, // 0003 GETMBR R2 R0 K1 + 0x740A0002, // 0004 JMPT R2 #0008 + 0x60080012, // 0005 GETGBL R2 G18 + 0x7C080000, // 0006 CALL R2 0 + 0x90020202, // 0007 SETMBR R0 K1 R2 + 0x60080004, // 0008 GETGBL R2 G4 + 0x5C0C0200, // 0009 MOVE R3 R1 + 0x7C080200, // 000A CALL R2 1 + 0x20080502, // 000B NE R2 R2 K2 + 0x780A0000, // 000C JMPF R2 #000E + 0xB0060704, // 000D RAISE 1 K3 K4 + 0x88080105, // 000E GETMBR R2 R0 K5 + 0x900A0D07, // 000F SETMBR R2 K6 K7 + 0x88080101, // 0010 GETMBR R2 R0 K1 + 0x8C080508, // 0011 GETMET R2 R2 K8 + 0x5C100200, // 0012 MOVE R4 R1 + 0x7C080400, // 0013 CALL R2 2 + 0x80000000, // 0014 RET 0 + }) + ) +); +/*******************************************************************/ + /******************************************************************** ** Solidified function: event @@ -673,7 +743,7 @@ be_local_closure(Tasmota_event, /* name */ be_nested_proto( 20, /* nstack */ 6, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -811,7 +881,7 @@ be_local_closure(Tasmota_find_key_i, /* name */ be_nested_proto( 10, /* nstack */ 3, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -870,7 +940,7 @@ be_local_closure(Tasmota_wire_scan, /* name */ be_nested_proto( 6, /* nstack */ 3, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -932,7 +1002,7 @@ be_local_closure(Tasmota_init, /* name */ be_nested_proto( 7, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1007,7 +1077,7 @@ be_local_closure(Tasmota_time_str, /* name */ be_nested_proto( 13, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1055,7 +1125,7 @@ be_local_closure(Tasmota_remove_rule, /* name */ be_nested_proto( 6, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1105,7 +1175,7 @@ be_local_closure(Tasmota_load, /* name */ be_nested_proto( 21, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 1, /* has sup protos */ @@ -1113,7 +1183,7 @@ be_local_closure(Tasmota_load, /* name */ be_nested_proto( 6, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1146,7 +1216,7 @@ be_local_closure(Tasmota_load, /* name */ be_nested_proto( 7, /* nstack */ 1, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1338,7 +1408,7 @@ be_local_closure(Tasmota_chars_in_string, /* name */ be_nested_proto( 10, /* nstack */ 4, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1395,7 +1465,7 @@ be_local_closure(Tasmota_cmd, /* name */ be_nested_proto( 5, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1433,38 +1503,42 @@ be_local_closure(Tasmota_cmd, /* name */ ********************************************************************/ be_local_closure(Tasmota_add_cmd, /* name */ be_nested_proto( - 5, /* nstack */ + 6, /* nstack */ 3, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str(_ccmd), - /* K1 */ be_nested_str(function), - /* K2 */ be_nested_str(value_error), - /* K3 */ be_nested_str(the_X20second_X20argument_X20is_X20not_X20a_X20function), + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str(check_not_method), + /* K1 */ be_nested_str(_ccmd), + /* K2 */ be_nested_str(function), + /* K3 */ be_nested_str(value_error), + /* K4 */ be_nested_str(the_X20second_X20argument_X20is_X20not_X20a_X20function), }), &be_const_str_add_cmd, &be_const_str_solidified, - ( &(const binstruction[15]) { /* code */ - 0x880C0100, // 0000 GETMBR R3 R0 K0 - 0x740E0002, // 0001 JMPT R3 #0005 - 0x600C0013, // 0002 GETGBL R3 G19 - 0x7C0C0000, // 0003 CALL R3 0 - 0x90020003, // 0004 SETMBR R0 K0 R3 - 0x600C0004, // 0005 GETGBL R3 G4 - 0x5C100400, // 0006 MOVE R4 R2 - 0x7C0C0200, // 0007 CALL R3 1 - 0x1C0C0701, // 0008 EQ R3 R3 K1 - 0x780E0002, // 0009 JMPF R3 #000D - 0x880C0100, // 000A GETMBR R3 R0 K0 - 0x980C0202, // 000B SETIDX R3 R1 R2 - 0x70020000, // 000C JMP #000E - 0xB0060503, // 000D RAISE 1 K2 K3 - 0x80000000, // 000E RET 0 + ( &(const binstruction[18]) { /* code */ + 0x8C0C0100, // 0000 GETMET R3 R0 K0 + 0x5C140400, // 0001 MOVE R5 R2 + 0x7C0C0400, // 0002 CALL R3 2 + 0x880C0101, // 0003 GETMBR R3 R0 K1 + 0x740E0002, // 0004 JMPT R3 #0008 + 0x600C0013, // 0005 GETGBL R3 G19 + 0x7C0C0000, // 0006 CALL R3 0 + 0x90020203, // 0007 SETMBR R0 K1 R3 + 0x600C0004, // 0008 GETGBL R3 G4 + 0x5C100400, // 0009 MOVE R4 R2 + 0x7C0C0200, // 000A CALL R3 1 + 0x1C0C0702, // 000B EQ R3 R3 K2 + 0x780E0002, // 000C JMPF R3 #0010 + 0x880C0101, // 000D GETMBR R3 R0 K1 + 0x980C0202, // 000E SETIDX R3 R1 R2 + 0x70020000, // 000F JMP #0011 + 0xB0060704, // 0010 RAISE 1 K3 K4 + 0x80000000, // 0011 RET 0 }) ) ); @@ -1478,43 +1552,47 @@ be_local_closure(Tasmota_add_rule, /* name */ be_nested_proto( 9, /* nstack */ 3, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str(_rules), - /* K1 */ be_nested_str(function), - /* K2 */ be_nested_str(push), - /* K3 */ be_nested_str(kv), - /* K4 */ be_nested_str(value_error), - /* K5 */ be_nested_str(the_X20second_X20argument_X20is_X20not_X20a_X20function), + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str(check_not_method), + /* K1 */ be_nested_str(_rules), + /* K2 */ be_nested_str(function), + /* K3 */ be_nested_str(push), + /* K4 */ be_nested_str(kv), + /* K5 */ be_nested_str(value_error), + /* K6 */ be_nested_str(the_X20second_X20argument_X20is_X20not_X20a_X20function), }), &be_const_str_add_rule, &be_const_str_solidified, - ( &(const binstruction[20]) { /* code */ - 0x880C0100, // 0000 GETMBR R3 R0 K0 - 0x740E0002, // 0001 JMPT R3 #0005 - 0x600C0012, // 0002 GETGBL R3 G18 - 0x7C0C0000, // 0003 CALL R3 0 - 0x90020003, // 0004 SETMBR R0 K0 R3 - 0x600C0004, // 0005 GETGBL R3 G4 - 0x5C100400, // 0006 MOVE R4 R2 - 0x7C0C0200, // 0007 CALL R3 1 - 0x1C0C0701, // 0008 EQ R3 R3 K1 - 0x780E0007, // 0009 JMPF R3 #0012 - 0x880C0100, // 000A GETMBR R3 R0 K0 - 0x8C0C0702, // 000B GETMET R3 R3 K2 - 0x8C140103, // 000C GETMET R5 R0 K3 - 0x5C1C0200, // 000D MOVE R7 R1 - 0x5C200400, // 000E MOVE R8 R2 - 0x7C140600, // 000F CALL R5 3 - 0x7C0C0400, // 0010 CALL R3 2 - 0x70020000, // 0011 JMP #0013 - 0xB0060905, // 0012 RAISE 1 K4 K5 - 0x80000000, // 0013 RET 0 + ( &(const binstruction[23]) { /* code */ + 0x8C0C0100, // 0000 GETMET R3 R0 K0 + 0x5C140400, // 0001 MOVE R5 R2 + 0x7C0C0400, // 0002 CALL R3 2 + 0x880C0101, // 0003 GETMBR R3 R0 K1 + 0x740E0002, // 0004 JMPT R3 #0008 + 0x600C0012, // 0005 GETGBL R3 G18 + 0x7C0C0000, // 0006 CALL R3 0 + 0x90020203, // 0007 SETMBR R0 K1 R3 + 0x600C0004, // 0008 GETGBL R3 G4 + 0x5C100400, // 0009 MOVE R4 R2 + 0x7C0C0200, // 000A CALL R3 1 + 0x1C0C0702, // 000B EQ R3 R3 K2 + 0x780E0007, // 000C JMPF R3 #0015 + 0x880C0101, // 000D GETMBR R3 R0 K1 + 0x8C0C0703, // 000E GETMET R3 R3 K3 + 0x8C140104, // 000F GETMET R5 R0 K4 + 0x5C1C0200, // 0010 MOVE R7 R1 + 0x5C200400, // 0011 MOVE R8 R2 + 0x7C140600, // 0012 CALL R5 3 + 0x7C0C0400, // 0013 CALL R3 2 + 0x70020000, // 0014 JMP #0016 + 0xB0060B06, // 0015 RAISE 1 K5 K6 + 0x80000000, // 0016 RET 0 }) ) ); @@ -1528,7 +1606,7 @@ be_local_closure(Tasmota_exec_rules, /* name */ be_nested_proto( 12, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1605,53 +1683,6 @@ be_local_closure(Tasmota_exec_rules, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: cb_dispatch -********************************************************************/ -be_local_closure(Tasmota_cb_dispatch, /* name */ - be_nested_proto( - 12, /* nstack */ - 6, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str(_cb), - /* K1 */ be_const_int(0), - /* K2 */ be_nested_str(find), - }), - &be_const_str_cb_dispatch, - &be_const_str_solidified, - ( &(const binstruction[20]) { /* code */ - 0x88180100, // 0000 GETMBR R6 R0 K0 - 0x4C1C0000, // 0001 LDNIL R7 - 0x1C180C07, // 0002 EQ R6 R6 R7 - 0x781A0000, // 0003 JMPF R6 #0005 - 0x80060200, // 0004 RET 1 K1 - 0x88180100, // 0005 GETMBR R6 R0 K0 - 0x8C180D02, // 0006 GETMET R6 R6 K2 - 0x5C200200, // 0007 MOVE R8 R1 - 0x7C180400, // 0008 CALL R6 2 - 0x4C1C0000, // 0009 LDNIL R7 - 0x201C0C07, // 000A NE R7 R6 R7 - 0x781E0006, // 000B JMPF R7 #0013 - 0x5C1C0C00, // 000C MOVE R7 R6 - 0x5C200400, // 000D MOVE R8 R2 - 0x5C240600, // 000E MOVE R9 R3 - 0x5C280800, // 000F MOVE R10 R4 - 0x5C2C0A00, // 0010 MOVE R11 R5 - 0x7C1C0800, // 0011 CALL R7 4 - 0x80040E00, // 0012 RET 1 R7 - 0x80060200, // 0013 RET 1 K1 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: hs2rgb ********************************************************************/ @@ -1659,7 +1690,7 @@ be_local_closure(Tasmota_hs2rgb, /* name */ be_nested_proto( 17, /* nstack */ 3, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1757,7 +1788,7 @@ be_local_closure(KV_init, /* name */ be_nested_proto( 3, /* nstack */ 3, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1801,7 +1832,7 @@ be_local_closure(Tasmota_kv, /* name */ be_nested_proto( 7, /* nstack */ 3, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1833,7 +1864,7 @@ be_local_closure(Tasmota_remove_cmd, /* name */ be_nested_proto( 5, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1866,37 +1897,41 @@ be_local_closure(Tasmota_set_timer, /* name */ be_nested_proto( 10, /* nstack */ 4, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str(_timers), - /* K1 */ be_nested_str(push), - /* K2 */ be_nested_str(Timer), - /* K3 */ be_nested_str(millis), + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str(check_not_method), + /* K1 */ be_nested_str(_timers), + /* K2 */ be_nested_str(push), + /* K3 */ be_nested_str(Timer), + /* K4 */ be_nested_str(millis), }), &be_const_str_set_timer, &be_const_str_solidified, - ( &(const binstruction[16]) { /* code */ - 0x88100100, // 0000 GETMBR R4 R0 K0 - 0x74120002, // 0001 JMPT R4 #0005 - 0x60100012, // 0002 GETGBL R4 G18 - 0x7C100000, // 0003 CALL R4 0 - 0x90020004, // 0004 SETMBR R0 K0 R4 - 0x88100100, // 0005 GETMBR R4 R0 K0 - 0x8C100901, // 0006 GETMET R4 R4 K1 - 0xB81A0400, // 0007 GETNGBL R6 K2 - 0x8C1C0103, // 0008 GETMET R7 R0 K3 - 0x5C240200, // 0009 MOVE R9 R1 - 0x7C1C0400, // 000A CALL R7 2 - 0x5C200400, // 000B MOVE R8 R2 - 0x5C240600, // 000C MOVE R9 R3 - 0x7C180600, // 000D CALL R6 3 - 0x7C100400, // 000E CALL R4 2 - 0x80000000, // 000F RET 0 + ( &(const binstruction[19]) { /* code */ + 0x8C100100, // 0000 GETMET R4 R0 K0 + 0x5C180400, // 0001 MOVE R6 R2 + 0x7C100400, // 0002 CALL R4 2 + 0x88100101, // 0003 GETMBR R4 R0 K1 + 0x74120002, // 0004 JMPT R4 #0008 + 0x60100012, // 0005 GETGBL R4 G18 + 0x7C100000, // 0006 CALL R4 0 + 0x90020204, // 0007 SETMBR R0 K1 R4 + 0x88100101, // 0008 GETMBR R4 R0 K1 + 0x8C100902, // 0009 GETMET R4 R4 K2 + 0xB81A0600, // 000A GETNGBL R6 K3 + 0x8C1C0104, // 000B GETMET R7 R0 K4 + 0x5C240200, // 000C MOVE R9 R1 + 0x7C1C0400, // 000D CALL R7 2 + 0x5C200400, // 000E MOVE R8 R2 + 0x5C240600, // 000F MOVE R9 R3 + 0x7C180600, // 0010 CALL R6 3 + 0x7C100400, // 0011 CALL R4 2 + 0x80000000, // 0012 RET 0 }) ) ); @@ -1910,7 +1945,7 @@ be_local_closure(Tasmota_remove_timer, /* name */ be_nested_proto( 6, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -1964,7 +1999,7 @@ be_local_closure(Tasmota_exec_cmd, /* name */ be_nested_proto( 12, /* nstack */ 4, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -2020,7 +2055,7 @@ be_local_closure(Tasmota_get_light, /* name */ be_nested_proto( 6, /* nstack */ 2, /* argc */ - 0, /* varg */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ @@ -2055,7 +2090,43 @@ be_local_closure(Tasmota_get_light, /* name */ ); /*******************************************************************/ -#include "../generate/be_fixed_be_class_tasmota.h" +/******************************************************************** +** Solidified function: check_not_method +********************************************************************/ +be_local_closure(Tasmota_check_not_method, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str(introspect), + /* K1 */ be_nested_str(ismethod), + /* K2 */ be_nested_str(type_error), + /* K3 */ be_nested_str(BRY_X3A_X20method_X20not_X20allowed_X2C_X20use_X20a_X20closure_X20like_X20_X27_X2F_X20args_X20_X2D_X3E_X20obj_X2Efunc_X28args_X29_X27), + }), + &be_const_str_check_not_method, + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0x8C0C0501, // 0001 GETMET R3 R2 K1 + 0x5C140200, // 0002 MOVE R5 R1 + 0x7C0C0400, // 0003 CALL R3 2 + 0x50100200, // 0004 LDBOOL R4 1 0 + 0x1C0C0604, // 0005 EQ R3 R3 R4 + 0x780E0000, // 0006 JMPF R3 #0008 + 0xB0060503, // 0007 RAISE 1 K2 K3 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + +#include "be_fixed_be_class_tasmota.h" // Class definition @@ -2068,11 +2139,11 @@ void be_load_tasmota_ntvlib(bvm *vm) /* @const_object_info_begin class be_class_tasmota (scope: global, name: Tasmota) { + _fl, var _rules, var _timers, var _ccmd, var _drivers, var - _cb, var wire1, var wire2, var global, var @@ -2094,7 +2165,6 @@ class be_class_tasmota (scope: global, name: Tasmota) { publish, func(l_publish) publish_result, func(l_publish_result) _cmd, func(l_cmd) - _get_cb, func(l_get_cb) get_option, func(l_getoption) millis, func(l_millis) time_reached, func(l_timereached) @@ -2130,6 +2200,8 @@ class be_class_tasmota (scope: global, name: Tasmota) { i2c_enabled, func(l_i2cenabled) + fast_loop, closure(Tasmota_fast_loop_closure) + add_fast_loop, closure(Tasmota_add_fast_loop_closure) cmd, closure(Tasmota_cmd_closure) chars_in_string, closure(Tasmota_chars_in_string_closure) find_key_i, closure(Tasmota_find_key_i_closure) @@ -2153,9 +2225,10 @@ class be_class_tasmota (scope: global, name: Tasmota) { wire_scan, closure(Tasmota_wire_scan_closure) time_str, closure(Tasmota_time_str_closure) + check_not_method, closure(Tasmota_check_not_method_closure) + hs2rgb, closure(Tasmota_hs2rgb_closure) - cb_dispatch, closure(Tasmota_cb_dispatch_closure) gen_cb, closure(Tasmota_gen_cb_closure) get_light, closure(Tasmota_get_light_closure) diff --git a/lib/libesp32/Berry/default/be_tcpclient_lib.c b/lib/libesp32/berry_tasmota/src/be_tcpclient_lib.c similarity index 95% rename from lib/libesp32/Berry/default/be_tcpclient_lib.c rename to lib/libesp32/berry_tasmota/src/be_tcpclient_lib.c index b39db458e..246436058 100644 --- a/lib/libesp32/Berry/default/be_tcpclient_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_tcpclient_lib.c @@ -20,7 +20,7 @@ extern int wc_tcp_write(bvm *vm); extern int wc_tcp_read(bvm *vm); extern int wc_tcp_readbytes(bvm *vm); -#include "../generate/be_fixed_be_class_tcpclient.h" +#include "be_fixed_be_class_tcpclient.h" void be_load_tcpclient_lib(bvm *vm) { be_pushntvclass(vm, &be_class_tcpclient); diff --git a/lib/libesp32/Berry/default/be_timer_class.c b/lib/libesp32/berry_tasmota/src/be_timer_class.c similarity index 100% rename from lib/libesp32/Berry/default/be_timer_class.c rename to lib/libesp32/berry_tasmota/src/be_timer_class.c diff --git a/lib/libesp32/berry_tasmota/src/be_udp_lib.cpp b/lib/libesp32/berry_tasmota/src/be_udp_lib.cpp new file mode 100644 index 000000000..042962952 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_udp_lib.cpp @@ -0,0 +1,145 @@ +/******************************************************************** + * UDP lib + * + * To use: `d = udp()` + * + *******************************************************************/ +#include "be_constobj.h" + +#ifdef USE_WEBCLIENT + +// extern int be_udp_init(bvm *vm); +// extern int be_udp_deinit(bvm *vm); +// extern int be_udp_begin(bvm *vm); +// extern int be_udp_begin_mcast(bvm *vm); + +#include +#include +#include +#include "be_mapping.h" + +extern "C" { + + // init() + WiFiUDP *be_udp_init_ntv(void) { + return new WiFiUDP(); + } + int32_t be_udp_init(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_udp_init_ntv, "+.p", ""); + } + + // deinit() + void *be_udp_deinit_ntv(WiFiUDP *udp) { + if (udp != nullptr) { delete udp; } + return nullptr; + } + int32_t be_udp_deinit(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_udp_deinit_ntv, "=.p", ""); + } + + // udp.begin(address:string, port:int) -> nil + int32_t be_udp_begin_ntv(WiFiUDP *udp, const char *host, int32_t port) { + IPAddress addr(INADDR_ANY); + // if no host or host is "" then we defult to INADDR_ANY (0.0.0.0) + if(host && (*host != 0) && !WiFiGenericClass::hostByName(host, addr)){ + return 0; + } + return udp->begin(addr, port); + } + int32_t be_udp_begin(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_udp_begin_ntv, "b", ".si"); + } + + // udp.begin_multicast(address:string, port:int) -> nil + int32_t be_udp_begin_mcast_ntv(WiFiUDP *udp, const char *host, int32_t port) { + IPAddress addr((uint32_t)0); + if(!WiFiGenericClass::hostByName(host, addr)){ + return 0; + } + return udp->WiFiUDP::beginMulticast(addr, port); + } + int32_t be_udp_begin_mcast(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_udp_begin_mcast_ntv, "b", ".si"); + } + + // udp.send(address:string, port:int, payload:bytes) -> bool + int32_t be_udp_send_ntv(WiFiUDP *udp, const char *host, int32_t port, const uint8_t* buf, int32_t len) { + IPAddress addr((uint32_t)0); + if (!WiFiGenericClass::hostByName(host, addr)){ + return 0; + } + if (!udp->beginPacket(addr, port)) { return 0; } + int bw = udp->write(buf, len); + if (!bw) { return 0; } + if (!udp->endPacket()) { return 0; } + return btrue; + } + int32_t be_udp_send(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_udp_send_ntv, "b", ".si(bytes)~"); + } + + // udp.send_multicast(payload:bytes) -> bool + int32_t be_udp_send_mcast_ntv(WiFiUDP *udp, const uint8_t* buf, int32_t len) { + if (!udp->beginMulticastPacket()) { return 0; } + int bw = udp->write(buf, len); + if (!bw) { return 0; } + if (!udp->endPacket()) { return 0; } + return btrue; + } + int32_t be_udp_send_mcast(struct bvm *vm) { + return be_call_c_func(vm, (void*) &be_udp_send_mcast_ntv, "b", ".(bytes)~"); + } + + // udp.read() -> bytes or nil + int32_t be_udp_read(struct bvm *vm) { + WiFiUDP *udp = (WiFiUDP*) be_convert_single_elt(vm, 1, NULL, NULL); + if (udp->parsePacket()) { + int btr = udp->available(); + uint8_t * buf = (uint8_t*) be_pushbuffer(vm, btr); + int32_t btr2 = udp->read(buf, btr); + be_pushbytes(vm, buf, btr2); + + // set remotet ip + IPAddress remote_ip = udp->remoteIP(); + be_pushstring(vm, remote_ip.toString().c_str()); + be_setmember(vm, 1, "remote_ip"); + be_pop(vm, 1); + + // set remote port + be_pushint(vm, udp->remotePort()); + be_setmember(vm, 1, "remote_port"); + be_pop(vm, 1); + + be_return(vm); /* return code */ + } else { + be_return_nil(vm); + } + } + + #include "be_fixed_be_class_udp.h" + + void be_load_udp_lib(bvm *vm) { + be_pushntvclass(vm, &be_class_udp); + be_setglobal(vm, "udp"); + be_pop(vm, 1); + } +} +/* @const_object_info_begin + +class be_class_udp (scope: global, name: udp) { + .p, var + remote_ip, var + remote_port, var + init, func(be_udp_init) + deinit, func(be_udp_deinit) + + send, func(be_udp_send) + send_multicast, func(be_udp_send_mcast) + + begin, func(be_udp_begin) + begin_multicast, func(be_udp_begin_mcast) + read, func(be_udp_read) +} +@const_object_info_end */ + +#endif // USE_WEBCLIENT diff --git a/lib/libesp32/berry_tasmota/src/be_unishox_lib.cpp b/lib/libesp32/berry_tasmota/src/be_unishox_lib.cpp new file mode 100644 index 000000000..af4317987 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_unishox_lib.cpp @@ -0,0 +1,83 @@ +/******************************************************************** + * Berry module `unishox` + * + * To use: `import unishox` + * + * Allows to respond to HTTP request + *******************************************************************/ + +#ifdef USE_UNISHOX_COMPRESSION + +#include "be_constobj.h" +#include "be_mapping.h" +#include +#include "unishox.h" + +extern Unishox compressor; + +/*********************************************************************************************\ + * Native functions mapped to Berry functions + * + * import unishox + * + * +\*********************************************************************************************/ +static int be_ntv_unishox_compress(bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc == 1 && be_isstring(vm, 1)) { + const char * s = be_tostring(vm, 1); + // do a dry-run to know the compressed size + int32_t compressed_size = compressor.unishox_compress(s, strlen(s), (char*) nullptr, 0); + if (compressed_size < 0) { + be_raise(vm, "internal_error", nullptr); + } + void * buf = be_pushbytes(vm, NULL, compressed_size); + if (compressed_size > 0) { + int32_t ret = compressor.unishox_compress(s, strlen(s), (char*) buf, compressed_size+5); // We expand by 4 the buffer size to avoid an error, but we are sure it will not overflow (see unishox implementation) + if (ret < 0 || ret != compressed_size) { + be_raisef(vm, "internal_error", "unishox size=%i ret=%i", compressed_size, ret); + } + } + be_return(vm); + } + be_raise(vm, "type_error", nullptr); +} + +static int be_ntv_unishox_decompress(bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc == 1 && be_isbytes(vm, 1)) { + size_t len; + const void * buf = be_tobytes(vm, 1, &len); + if (len == 0) { + be_pushstring(vm, ""); + } else { + int32_t decomp_size = compressor.unishox_decompress((const char*)buf, len, (char*) nullptr, 0); + if (decomp_size < 0) { + be_raise(vm, "internal_error", nullptr); + } + if (decomp_size == 0) { + be_pushstring(vm, ""); + } else { + void * buf_out = be_pushbuffer(vm, decomp_size); + int32_t ret = compressor.unishox_decompress((const char*)buf, len, (char*) buf_out, decomp_size); + if (ret < 0 || ret != decomp_size) { + be_raisef(vm, "internal_error", "unishox size=%i ret=%i", decomp_size, ret); + } + be_pushnstring(vm, (const char*) buf_out, decomp_size); + } + } + be_return(vm); + } + be_raise(vm, "type_error", nullptr); +} + + +/* @const_object_info_begin +module unishox (scope: global) { + decompress, func(be_ntv_unishox_decompress) + compress, func(be_ntv_unishox_compress) +} +@const_object_info_end */ +#include "be_fixed_unishox.h" + +#endif // USE_UNISHOX_COMPRESSION diff --git a/lib/libesp32/Berry/default/be_webclient_lib.c b/lib/libesp32/berry_tasmota/src/be_webclient_lib.c similarity index 96% rename from lib/libesp32/Berry/default/be_webclient_lib.c rename to lib/libesp32/berry_tasmota/src/be_webclient_lib.c index 0e4b66e90..b95740f76 100644 --- a/lib/libesp32/Berry/default/be_webclient_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_webclient_lib.c @@ -24,7 +24,7 @@ extern int wc_getstring(bvm *vm); extern int wc_writefile(bvm *vm); extern int wc_getsize(bvm *vm); -#include "../generate/be_fixed_be_class_webclient.h" +#include "be_fixed_be_class_webclient.h" void be_load_webclient_lib(bvm *vm) { be_pushntvclass(vm, &be_class_webclient); diff --git a/lib/libesp32/Berry/default/be_webserver_lib.c b/lib/libesp32/berry_tasmota/src/be_webserver_lib.c similarity index 97% rename from lib/libesp32/Berry/default/be_webserver_lib.c rename to lib/libesp32/berry_tasmota/src/be_webserver_lib.c index 0f3e45d05..c14e9efd3 100644 --- a/lib/libesp32/Berry/default/be_webserver_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_webserver_lib.c @@ -50,6 +50,6 @@ module webserver (scope: global) { has_arg, func(w_webserver_has_arg) } @const_object_info_end */ -#include "../generate/be_fixed_webserver.h" +#include "be_fixed_webserver.h" #endif // USE_WEBSERVER diff --git a/lib/libesp32/Berry/default/be_wirelib.c b/lib/libesp32/berry_tasmota/src/be_wirelib.c similarity index 98% rename from lib/libesp32/Berry/default/be_wirelib.c rename to lib/libesp32/berry_tasmota/src/be_wirelib.c index 38f345553..6dd1fd6a8 100644 --- a/lib/libesp32/Berry/default/be_wirelib.c +++ b/lib/libesp32/berry_tasmota/src/be_wirelib.c @@ -118,7 +118,7 @@ be_local_closure(read_bytes, /* name */ /*******************************************************************/ -#include "../generate/be_fixed_be_class_tasmota_wire.h" +#include "be_fixed_be_class_tasmota_wire.h" void be_load_wirelib(bvm *vm) { be_pushntvclass(vm, &be_class_tasmota_wire); diff --git a/lib/libesp32/berry_tasmota/src/berry_tasmota.h b/lib/libesp32/berry_tasmota/src/berry_tasmota.h new file mode 100644 index 000000000..372a32b1e --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/berry_tasmota.h @@ -0,0 +1,8 @@ +// force include of module by including this file + +#ifndef __BERRY_TASMOTA__ +#define __BERRY_TASMOTA__ + + + +#endif // __BERRY_TASMOTA__ diff --git a/lib/libesp32/Berry/default/embedded/Animate.be b/lib/libesp32/berry_tasmota/src/embedded/Animate.be similarity index 100% rename from lib/libesp32/Berry/default/embedded/Animate.be rename to lib/libesp32/berry_tasmota/src/embedded/Animate.be diff --git a/lib/libesp32/Berry/default/embedded/Driver.be b/lib/libesp32/berry_tasmota/src/embedded/Driver.be similarity index 88% rename from lib/libesp32/Berry/default/embedded/Driver.be rename to lib/libesp32/berry_tasmota/src/embedded/Driver.be index d0782f024..bb365aa29 100644 --- a/lib/libesp32/Berry/default/embedded/Driver.be +++ b/lib/libesp32/berry_tasmota/src/embedded/Driver.be @@ -16,13 +16,6 @@ class Driver var button_pressed var display - def init() - end - - def get_tasmota() - return tasmota - end - def add_cmd(c, f) tasmota.add_cmd(c, / cmd, idx, payload, payload_json -> f(self, cmd, idx, payload, payload_json)) end diff --git a/lib/libesp32/Berry/default/embedded/Tasmota.be b/lib/libesp32/berry_tasmota/src/embedded/Tasmota.be similarity index 91% rename from lib/libesp32/Berry/default/embedded/Tasmota.be rename to lib/libesp32/berry_tasmota/src/embedded/Tasmota.be index 3305d57ff..1eb1f1d34 100644 --- a/lib/libesp32/Berry/default/embedded/Tasmota.be +++ b/lib/libesp32/berry_tasmota/src/embedded/Tasmota.be @@ -17,11 +17,11 @@ end tasmota = nil class Tasmota + var _fl # list of fast_loop registered closures var _rules var _timers var _ccmd var _drivers - var _cb var wire1 var wire2 var cmd_res # store the command result, nil if disables, true if capture enabled, contains return value @@ -47,6 +47,14 @@ class Tasmota end end + # check that the parameter is not a method, it would require a closure instead + def check_not_method(f) + import introspect + if introspect.ismethod(f) == true + raise "type_error", "BRY: method not allowed, use a closure like '/ args -> obj.func(args)'" + end + end + # create a specific sub-class for rules: pattern(string) -> closure # Classs KV has two members k and v def kv(k, v) @@ -120,6 +128,7 @@ class Tasmota # Rules def add_rule(pat,f) + self.check_not_method(f) if !self._rules self._rules=[] end @@ -237,6 +246,7 @@ class Tasmota end def set_timer(delay,f,id) + self.check_not_method(f) if !self._timers self._timers=[] end self._timers.push(Timer(self.millis(delay),f,id)) end @@ -273,6 +283,7 @@ class Tasmota # Add command to list def add_cmd(c,f) + self.check_not_method(f) if !self._ccmd self._ccmd={} end @@ -427,6 +438,30 @@ class Tasmota return true end + # fast_loop() is a trimmed down version of event() called at every Tasmota loop iteration + # it is optimized to be as fast as possible and reduce overhead + # there is no introspect, closures must be registered directly + def fast_loop() + var fl = self._fl + if !fl return end # fast exit if no closure is registered (most common case) + + # iterate and call each closure + var i = 0 + while i < size(fl) + # note: this is not guarded in try/except for performance reasons. The inner function must not raise exceptions + fl[i]() + i += 1 + end + end + + def add_fast_loop(cl) + self.check_not_method(cl) + if !self._fl self._fl = [] end + if type(cl) != 'function' raise "value_error", "argument must be a function" end + self.global.fast_loop_enabled = 1 # enable fast_loop at global level: `TasmotaGlobal.fast_loop_enabled = true` + self._fl.push(cl) + end + def event(event_type, cmd, idx, payload, raw) import introspect import string @@ -469,6 +504,9 @@ class Tasmota end def add_driver(d) + if type(d) != 'instance' + raise "value_error", "instance required" + end if self._drivers self._drivers.push(d) else @@ -520,28 +558,11 @@ class Tasmota end end - - #- dispatch callback number n, with parameters v0,v1,v2,v3 -# - def cb_dispatch(n,v0,v1,v2,v3) - if self._cb == nil return 0 end - var f = self._cb.find(n) - if f != nil - return f(v0,v1,v2,v3) - end - return 0 - end - #- generate a new C callback and record the associated Berry closure -# def gen_cb(f) - if self._cb == nil self._cb = {} end # create map if not already initialized - for i:0..19 - if self._cb.find(i) == nil - #- free slot -# - self._cb[i] = f - return self._get_cb(i) - end - end - raise "internal_error", "No callback available" + # DEPRECATED + import cb + return cb.gen_cb(f) end #- convert hue/sat to rgb -# diff --git a/lib/libesp32/Berry/default/embedded/Wire.be b/lib/libesp32/berry_tasmota/src/embedded/Wire.be similarity index 100% rename from lib/libesp32/Berry/default/embedded/Wire.be rename to lib/libesp32/berry_tasmota/src/embedded/Wire.be diff --git a/lib/libesp32/Berry/default/embedded/autoconf.be b/lib/libesp32/berry_tasmota/src/embedded/autoconf.be similarity index 99% rename from lib/libesp32/Berry/default/embedded/autoconf.be rename to lib/libesp32/berry_tasmota/src/embedded/autoconf.be index 8489c7447..f76fde271 100644 --- a/lib/libesp32/Berry/default/embedded/autoconf.be +++ b/lib/libesp32/berry_tasmota/src/embedded/autoconf.be @@ -49,7 +49,7 @@ autoconf_module.init = def (m) end if entry == nil - tasmota.log("CFG: no '*.autoconf' file found", 2) + tasmota.log("CFG: No '*.autoconf' file found", 3) return nil end diff --git a/lib/libesp32/Berry/default/embedded/i2c_axp192.be b/lib/libesp32/berry_tasmota/src/embedded/i2c_axp192.be similarity index 99% rename from lib/libesp32/Berry/default/embedded/i2c_axp192.be rename to lib/libesp32/berry_tasmota/src/embedded/i2c_axp192.be index 3d958334f..d762b0363 100644 --- a/lib/libesp32/Berry/default/embedded/i2c_axp192.be +++ b/lib/libesp32/berry_tasmota/src/embedded/i2c_axp192.be @@ -153,7 +153,7 @@ class AXP192 : I2C_Driver "{s}Batt Voltage{m}%.3f V{e}".. "{s}Batt Current{m}%.1f mA{e}".. #"{s}Batt Power{m}%.3f{e}".. - "{s}Temp AXP{m}%.1f °C{e}", + "{s}Temp AXP{m}%.1f °C{e}", self.get_vbus_voltage(), self.get_vbus_voltage(), self.get_bat_voltage(), self.get_bat_current(), #self.get_bat_power(), diff --git a/lib/libesp32/Berry/default/embedded/i2c_driver.be b/lib/libesp32/berry_tasmota/src/embedded/i2c_driver.be similarity index 97% rename from lib/libesp32/Berry/default/embedded/i2c_driver.be rename to lib/libesp32/berry_tasmota/src/embedded/i2c_driver.be index a66afa5ad..816a4d9be 100644 --- a/lib/libesp32/Berry/default/embedded/i2c_driver.be +++ b/lib/libesp32/berry_tasmota/src/embedded/i2c_driver.be @@ -29,8 +29,6 @@ class I2C_Driver - i2c_index : Tasmota I2C index, see `I2CDEVICES.md` (int) --# def init(name_or_detect, addr, i2c_index) - var tasmota = self.get_tasmota() #- retrieve the 'tasmota' singleton -# - #- check if the i2c index is disabled by Tasmota configuration -# if i2c_index != nil && !tasmota.i2c_enabled(i2c_index) return end diff --git a/lib/libesp32/Berry/default/embedded/leds.be b/lib/libesp32/berry_tasmota/src/embedded/leds.be similarity index 100% rename from lib/libesp32/Berry/default/embedded/leds.be rename to lib/libesp32/berry_tasmota/src/embedded/leds.be diff --git a/lib/libesp32/Berry/default/embedded/leds_animator.be b/lib/libesp32/berry_tasmota/src/embedded/leds_animator.be similarity index 100% rename from lib/libesp32/Berry/default/embedded/leds_animator.be rename to lib/libesp32/berry_tasmota/src/embedded/leds_animator.be diff --git a/lib/libesp32/Berry/default/embedded/lv_clock_icon.be b/lib/libesp32/berry_tasmota/src/embedded/lv_clock_icon.be similarity index 91% rename from lib/libesp32/Berry/default/embedded/lv_clock_icon.be rename to lib/libesp32/berry_tasmota/src/embedded/lv_clock_icon.be index f5d19ca11..497c0b805 100644 --- a/lib/libesp32/Berry/default/embedded/lv_clock_icon.be +++ b/lib/libesp32/berry_tasmota/src/embedded/lv_clock_icon.be @@ -25,6 +25,8 @@ class lv_clock_icon: lv.label self.set_style_bg_color(lv.color(lv.COLOR_BLACK), lv.PART_MAIN | lv.STATE_DEFAULT) end + self.add_event_cb(/->self.before_del(), lv.EVENT_DELETE, 0) # register `before_del` to be called when object is deleted + tasmota.add_driver(self) end @@ -47,8 +49,7 @@ class lv_clock_icon: lv.label end end - def del() - super(self).del() + def before_del() tasmota.remove_driver(self) end end \ No newline at end of file diff --git a/lib/libesp32/Berry/default/embedded/lv_signal_arcs.be b/lib/libesp32/berry_tasmota/src/embedded/lv_signal_arcs.be similarity index 98% rename from lib/libesp32/Berry/default/embedded/lv_signal_arcs.be rename to lib/libesp32/berry_tasmota/src/embedded/lv_signal_arcs.be index 7dd924e90..614c5ec65 100644 --- a/lib/libesp32/Berry/default/embedded/lv_signal_arcs.be +++ b/lib/libesp32/berry_tasmota/src/embedded/lv_signal_arcs.be @@ -109,8 +109,7 @@ class lv_wifi_arcs: lv_signal_arcs end end - def del() - super(self).del() + def before_del() # called when the widget is being deleted tasmota.remove_driver(self) end end diff --git a/lib/libesp32/Berry/default/embedded/lv_signal_bars.be b/lib/libesp32/berry_tasmota/src/embedded/lv_signal_bars.be similarity index 98% rename from lib/libesp32/Berry/default/embedded/lv_signal_bars.be rename to lib/libesp32/berry_tasmota/src/embedded/lv_signal_bars.be index f548457b9..7e0c24a89 100644 --- a/lib/libesp32/Berry/default/embedded/lv_signal_bars.be +++ b/lib/libesp32/berry_tasmota/src/embedded/lv_signal_bars.be @@ -95,8 +95,7 @@ class lv_wifi_bars: lv_signal_bars end end - def del() - super(self).del() + def before_del() # called when the widget is being deleted tasmota.remove_driver(self) end end diff --git a/lib/libesp32/berry_tasmota/src/embedded/lv_tasmota.be b/lib/libesp32/berry_tasmota/src/embedded/lv_tasmota.be new file mode 100644 index 000000000..5be5733d3 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/embedded/lv_tasmota.be @@ -0,0 +1,36 @@ +#- ------------------------------------------------------------ -# +# Module `lv_tasmota` - piggybacks on `lv` to extend it +#- ------------------------------------------------------------ -# +lv_tasmota = module("lv_tasmota") + +# rename `lv` to `lv_ntv` and replace `lv` with `lv_tasmota` +def init(lv_tasmota) + import lv + lv.start = lv_tasmota.start + + lv.font_montserrat = lv_tasmota.font_montserrat + lv.montserrat_font = lv_tasmota.font_montserrat + + lv.font_seg7 = lv_tasmota.font_seg7 + lv.seg7_font = lv_tasmota.font_seg7 + + lv.load_freetype_font = lv_tasmota.load_freetype_font + + lv.register_button_encoder = lv_tasmota.register_button_encoder + lv.screenshot = lv_tasmota.screenshot + + # add widgets + lv.clock_icon = lv_clock_icon + lv.signal_arcs = lv_signal_arcs + lv.signal_bars = lv_signal_bars + lv.wifi_arcs_icon = lv_wifi_arcs_icon + lv.wifi_arcs = lv_wifi_arcs + lv.wifi_bars_icon = lv_wifi_bars_icon + lv.wifi_bars = lv_wifi_bars + + return nil +end + +lv_tasmota.init = init + +return lv_tasmota diff --git a/lib/libesp32/Berry/default/embedded/openhasp.be b/lib/libesp32/berry_tasmota/src/embedded/openhasp.be similarity index 100% rename from lib/libesp32/Berry/default/embedded/openhasp.be rename to lib/libesp32/berry_tasmota/src/embedded/openhasp.be diff --git a/lib/libesp32/Berry/default/embedded/openhasp/demo-all.jsonl b/lib/libesp32/berry_tasmota/src/embedded/openhasp/demo-all.jsonl similarity index 100% rename from lib/libesp32/Berry/default/embedded/openhasp/demo-all.jsonl rename to lib/libesp32/berry_tasmota/src/embedded/openhasp/demo-all.jsonl diff --git a/lib/libesp32/Berry/default/embedded/openhasp/demo1.jsonl b/lib/libesp32/berry_tasmota/src/embedded/openhasp/demo1.jsonl similarity index 100% rename from lib/libesp32/Berry/default/embedded/openhasp/demo1.jsonl rename to lib/libesp32/berry_tasmota/src/embedded/openhasp/demo1.jsonl diff --git a/lib/libesp32/Berry/default/embedded/openhasp/demo2.jsonl b/lib/libesp32/berry_tasmota/src/embedded/openhasp/demo2.jsonl similarity index 100% rename from lib/libesp32/Berry/default/embedded/openhasp/demo2.jsonl rename to lib/libesp32/berry_tasmota/src/embedded/openhasp/demo2.jsonl diff --git a/lib/libesp32/Berry/default/embedded/openhasp/demo3.jsonl b/lib/libesp32/berry_tasmota/src/embedded/openhasp/demo3.jsonl similarity index 100% rename from lib/libesp32/Berry/default/embedded/openhasp/demo3.jsonl rename to lib/libesp32/berry_tasmota/src/embedded/openhasp/demo3.jsonl diff --git a/lib/libesp32/Berry/default/embedded/persist.be b/lib/libesp32/berry_tasmota/src/embedded/persist.be similarity index 100% rename from lib/libesp32/Berry/default/embedded/persist.be rename to lib/libesp32/berry_tasmota/src/embedded/persist.be diff --git a/lib/libesp32/Berry/default/embedded/tapp.be b/lib/libesp32/berry_tasmota/src/embedded/tapp.be similarity index 89% rename from lib/libesp32/Berry/default/embedded/tapp.be rename to lib/libesp32/berry_tasmota/src/embedded/tapp.be index 30aa1f740..d1638bb64 100644 --- a/lib/libesp32/Berry/default/embedded/tapp.be +++ b/lib/libesp32/berry_tasmota/src/embedded/tapp.be @@ -19,7 +19,7 @@ tapp_module.init = def (m) for d: dir if string.find(d, ".tapp") > 0 - tasmota.log(string.format("TAP: found Tasmota App '%s'", d), 2) + tasmota.log(string.format("TAP: Loaded Tasmota App '%s'", d), 2) tasmota.load(d + "#autoexec.be") end end diff --git a/lib/libesp32/Berry/default/embedded/test_crypto.be b/lib/libesp32/berry_tasmota/src/embedded/test_crypto.be similarity index 100% rename from lib/libesp32/Berry/default/embedded/test_crypto.be rename to lib/libesp32/berry_tasmota/src/embedded/test_crypto.be diff --git a/lib/libesp32/Berry/default/static_block.hpp b/lib/libesp32/berry_tasmota/src/static_block.hpp similarity index 100% rename from lib/libesp32/Berry/default/static_block.hpp rename to lib/libesp32/berry_tasmota/src/static_block.hpp diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/LICENSE b/lib/libesp32/esp32-camera/LICENSE similarity index 93% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/LICENSE rename to lib/libesp32/esp32-camera/LICENSE index 08b9b218a..d64569567 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/LICENSE +++ b/lib/libesp32/esp32-camera/LICENSE @@ -1,3 +1,4 @@ + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -178,7 +179,7 @@ APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -186,7 +187,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -199,19 +200,3 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - -This product bundles queue.h 8.5, which is available under the "3-clause BSD" -license. For details, see porting/nimble/include/os/queue.h - -This product partly derives from FreeBSD, which is available under the -"3-clause BSD" license. For details, see: - * porting/nimble/src/os_mbuf.c - -This product bundles Gary S. Brown's CRC32 implementation, which is available -under the following license: - COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or - code or tables extracted from it, as desired without restriction. - -This product bundles tinycrypt, which is available under the "3-clause BSD" -license. For details, and bundled files see: - * ext/tinycrypt/LICENSE diff --git a/lib/libesp32/esp32-camera/README.md b/lib/libesp32/esp32-camera/README.md new file mode 100644 index 000000000..e93d5cdba --- /dev/null +++ b/lib/libesp32/esp32-camera/README.md @@ -0,0 +1,368 @@ +# ESP32 Camera Driver + +[![Build examples](https://github.com/espressif/esp32-camera/actions/workflows/build.yml/badge.svg)](https://github.com/espressif/esp32-camera/actions/workflows/build.yml) +## General Information + +This repository hosts ESP32 series Soc compatible driver for image sensors. Additionally it provides a few tools, which allow converting the captured frame data to the more common BMP and JPEG formats. + +### Supported Soc + +- ESP32 +- ESP32-S2 +- ESP32-S3 + +### Supported Sensor + +| model | max resolution | color type | output format | Len Size | +| ------- | -------------- | ---------- | ------------------------------------------------------------ | -------- | +| OV2640 | 1600 x 1200 | color | YUV(422/420)/YCbCr422
RGB565/555
8-bit compressed data
8/10-bit Raw RGB data | 1/4" | +| OV3660 | 2048 x 1536 | color | raw RGB data
RGB565/555/444
CCIR656
YCbCr422
compression | 1/5" | +| OV5640 | 2592 x 1944 | color | RAW RGB
RGB565/555/444
CCIR656
YUV422/420
YCbCr422
compression | 1/4" | +| OV7670 | 640 x 480 | color | Raw Bayer RGB
Processed Bayer RGB
YUV/YCbCr422
GRB422
RGB565/555 | 1/6" | +| OV7725 | 640 x 480 | color | Raw RGB
GRB 422
RGB565/555/444
YCbCr 422 | 1/4" | +| NT99141 | 1280 x 720 | color | YCbCr 422
RGB565/555/444
Raw
CCIR656
JPEG compression | 1/4" | +| GC032A | 640 x 480 | color | YUV/YCbCr422
RAW Bayer
RGB565 | 1/10" | +| GC0308 | 640 x 480 | color | YUV/YCbCr422
RAW Bayer
RGB565 | 1/6.5" | +| GC2145 | 1600 x 1200 | color | YUV/YCbCr422
RAW Bayer
RGB565 | 1/5" | + +## Important to Remember + +- Except when using CIF or lower resolution with JPEG, the driver requires PSRAM to be installed and activated. +- Using YUV or RGB puts a lot of strain on the chip because writing to PSRAM is not particularly fast. The result is that image data might be missing. This is particularly true if WiFi is enabled. If you need RGB data, it is recommended that JPEG is captured and then turned into RGB using `fmt2rgb888` or `fmt2bmp`/`frame2bmp`. +- When 1 frame buffer is used, the driver will wait for the current frame to finish (VSYNC) and start I2S DMA. After the frame is acquired, I2S will be stopped and the frame buffer returned to the application. This approach gives more control over the system, but results in longer time to get the frame. +- When 2 or more frame bufers are used, I2S is running in continuous mode and each frame is pushed to a queue that the application can access. This approach puts more strain on the CPU/Memory, but allows for double the frame rate. Please use only with JPEG. + +## Installation Instructions + + +### Using esp-idf + +- Clone or download and extract the repository to the components folder of your ESP-IDF project +- Enable PSRAM in `menuconfig` (also set Flash and PSRAM frequiencies to 80MHz) +- Include `esp_camera.h` in your code + +### Using PlatformIO + +The easy way -- on the `env` section of `platformio.ini`, add the following: + +```ini +[env] +lib_deps = + esp32-camera +``` + +Now the `esp_camera.h` is available to be included: + +```c +#include "esp_camera.h" +``` + +Enable PSRAM on `menuconfig` or type it direclty on `sdkconfig`. Check the [official doc](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-esp32-spiram-support) for more info. + +``` +CONFIG_ESP32_SPIRAM_SUPPORT=y +``` + +***Arduino*** The easy-way (content above) only seems to work if you're using `framework=arduino` which seems to take a bunch of the guesswork out (thanks Arduino!) but also suck up a lot more memory and flash, almost crippling the performance. If you plan to use the `framework=espidf` then read the sections below carefully!! + +## Platform.io lib/submodule (for framework=espidf) + +It's probably easier to just skip the platform.io library registry version and link the git repo as a submodule. (i.e. using code outside the platform.io library management). In this example we will install this as a submodule inside the platform.io $project/lib folder: +``` +cd $project\lib +git submodule add -b master https://github.com/espressif/esp32-camera.git +``` + +Then in `platformio.ini` file +``` +build_flags = + -I../lib/esp32-camera +``` +After that `#include "esp_camera.h"` statement will be available. Now the module is included, and you're hopefully back to the same place as the easy-Arduino way. + +**Warning about platform.io/espidf and fresh (not initialized) git repos** +There is a sharp-edge on you'll discover in the platform.io build process (in espidf v3.3 & 4.0.1) where a project which has only had `git init` but nothing committed will crash platform.io build process with highly non-useful output. The cause is due to lack of a version (making you think you did something wrong, when you didn't at all) - the output is horribly non-descript. Solution: the devs want you to create a file called version.txt with a number in it, or simply commit any file to the projects git repo and use git. This happens because platform.io build process tries to be too clever and determine the build version number from the git repo - it's a sharp edge you'll only encounter if you're experimenting on a new project with no commits .. like wtf is my camera not working let's try a 'clean project'?! + +## Platform.io Kconfig +Kconfig is used by the platform.io menuconfig (accessed by running: `pio run -t menuconfig`) to interactively manage the various #ifdef statements throughout the espidf and supporting libraries (i.e. this repo: esp32-camera and arduino-esp32.git). The menuconfig process generates the `sdkconfig` file which is ultimately used behind the scenes by espidf compile+build process. + +**Make sure to append or symlink** [this `Kconfig`](./Kconfig) content into the `Kconfig` of your project. + +You symlink (or copy) the included Kconfig into your platform.io projects src directory. The file should be named `Kconfig.projbuild` in your projects src\ directory or you could also add the library path to a CMakefile.txt and hope the `Kconfig` (or `Kconfig.projbuild`) gets discovered by the menuconfig process, though this unpredictable for me. + +The unpredictable wonky behavior in platform.io build process around Kconfig naming (Kconfig vs. Kconfig.projbuild) occurs between espidf versions 3.3 and 4.0 - but if you don't see "Camera configuration" in your `pio run -t menuconfig` then there is no point trying to test camera code (it may compile, but it probably won't work!) and it seems the platform.io devs (when they built their wrapper around the espidf menuconfig) didn't implement it properly. You've probably already figured out you can't use the espidf build tools since the files are in totally different locations and also different versions with sometimes different syntax. This is one of those times you might consider changing the `platformio.ini` from `platform=espressif32` to `platform=https://github.com/platformio/platform-espressif32.git#develop` to get a more recent version of the espidf 4.0 tools. + +However with a bit of patience and experimenting you'll figure the Kconfig out. Once Kconfig (or Kconfig.projbuild) is working then you will be able to choose the configurations according to your setup or the camera libraries will be compiled. Although you might also need to delete your .pio/build directory before the options appear .. again, the `pio run -t menuconfig` doens't always notice the new Kconfig files! + +If you miss-skip-ignore this critical step the camera module will compile but camera logic inside the library will be 'empty' because the Kconfig sets the proper #ifdef statements during the build process to initialize the selected cameras. It's very not optional! + + +## Examples + +### Initialization + +```c +#include "esp_camera.h" + +//WROVER-KIT PIN Map +#define CAM_PIN_PWDN -1 //power down is not used +#define CAM_PIN_RESET -1 //software reset will be performed +#define CAM_PIN_XCLK 21 +#define CAM_PIN_SIOD 26 +#define CAM_PIN_SIOC 27 + +#define CAM_PIN_D7 35 +#define CAM_PIN_D6 34 +#define CAM_PIN_D5 39 +#define CAM_PIN_D4 36 +#define CAM_PIN_D3 19 +#define CAM_PIN_D2 18 +#define CAM_PIN_D1 5 +#define CAM_PIN_D0 4 +#define CAM_PIN_VSYNC 25 +#define CAM_PIN_HREF 23 +#define CAM_PIN_PCLK 22 + +static camera_config_t camera_config = { + .pin_pwdn = CAM_PIN_PWDN, + .pin_reset = CAM_PIN_RESET, + .pin_xclk = CAM_PIN_XCLK, + .pin_sscb_sda = CAM_PIN_SIOD, + .pin_sscb_scl = CAM_PIN_SIOC, + + .pin_d7 = CAM_PIN_D7, + .pin_d6 = CAM_PIN_D6, + .pin_d5 = CAM_PIN_D5, + .pin_d4 = CAM_PIN_D4, + .pin_d3 = CAM_PIN_D3, + .pin_d2 = CAM_PIN_D2, + .pin_d1 = CAM_PIN_D1, + .pin_d0 = CAM_PIN_D0, + .pin_vsync = CAM_PIN_VSYNC, + .pin_href = CAM_PIN_HREF, + .pin_pclk = CAM_PIN_PCLK, + + .xclk_freq_hz = 20000000,//EXPERIMENTAL: Set to 16MHz on ESP32-S2 or ESP32-S3 to enable EDMA mode + .ledc_timer = LEDC_TIMER_0, + .ledc_channel = LEDC_CHANNEL_0, + + .pixel_format = PIXFORMAT_JPEG,//YUV422,GRAYSCALE,RGB565,JPEG + .frame_size = FRAMESIZE_UXGA,//QQVGA-QXGA Do not use sizes above QVGA when not JPEG + + .jpeg_quality = 12, //0-63 lower number means higher quality + .fb_count = 1, //if more than one, i2s runs in continuous mode. Use only with JPEG + .grab_mode = CAMERA_GRAB_WHEN_EMPTY//CAMERA_GRAB_LATEST. Sets when buffers should be filled +}; + +esp_err_t camera_init(){ + //power up the camera if PWDN pin is defined + if(CAM_PIN_PWDN != -1){ + pinMode(CAM_PIN_PWDN, OUTPUT); + digitalWrite(CAM_PIN_PWDN, LOW); + } + + //initialize the camera + esp_err_t err = esp_camera_init(&camera_config); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Camera Init Failed"); + return err; + } + + return ESP_OK; +} + +esp_err_t camera_capture(){ + //acquire a frame + camera_fb_t * fb = esp_camera_fb_get(); + if (!fb) { + ESP_LOGE(TAG, "Camera Capture Failed"); + return ESP_FAIL; + } + //replace this with your own function + process_image(fb->width, fb->height, fb->format, fb->buf, fb->len); + + //return the frame buffer back to the driver for reuse + esp_camera_fb_return(fb); + return ESP_OK; +} +``` + +### JPEG HTTP Capture + +```c +#include "esp_camera.h" +#include "esp_http_server.h" +#include "esp_timer.h" + +typedef struct { + httpd_req_t *req; + size_t len; +} jpg_chunking_t; + +static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len){ + jpg_chunking_t *j = (jpg_chunking_t *)arg; + if(!index){ + j->len = 0; + } + if(httpd_resp_send_chunk(j->req, (const char *)data, len) != ESP_OK){ + return 0; + } + j->len += len; + return len; +} + +esp_err_t jpg_httpd_handler(httpd_req_t *req){ + camera_fb_t * fb = NULL; + esp_err_t res = ESP_OK; + size_t fb_len = 0; + int64_t fr_start = esp_timer_get_time(); + + fb = esp_camera_fb_get(); + if (!fb) { + ESP_LOGE(TAG, "Camera capture failed"); + httpd_resp_send_500(req); + return ESP_FAIL; + } + res = httpd_resp_set_type(req, "image/jpeg"); + if(res == ESP_OK){ + res = httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg"); + } + + if(res == ESP_OK){ + if(fb->format == PIXFORMAT_JPEG){ + fb_len = fb->len; + res = httpd_resp_send(req, (const char *)fb->buf, fb->len); + } else { + jpg_chunking_t jchunk = {req, 0}; + res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk)?ESP_OK:ESP_FAIL; + httpd_resp_send_chunk(req, NULL, 0); + fb_len = jchunk.len; + } + } + esp_camera_fb_return(fb); + int64_t fr_end = esp_timer_get_time(); + ESP_LOGI(TAG, "JPG: %uKB %ums", (uint32_t)(fb_len/1024), (uint32_t)((fr_end - fr_start)/1000)); + return res; +} +``` + +### JPEG HTTP Stream + +```c +#include "esp_camera.h" +#include "esp_http_server.h" +#include "esp_timer.h" + +#define PART_BOUNDARY "123456789000000000000987654321" +static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY; +static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n"; +static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n"; + +esp_err_t jpg_stream_httpd_handler(httpd_req_t *req){ + camera_fb_t * fb = NULL; + esp_err_t res = ESP_OK; + size_t _jpg_buf_len; + uint8_t * _jpg_buf; + char * part_buf[64]; + static int64_t last_frame = 0; + if(!last_frame) { + last_frame = esp_timer_get_time(); + } + + res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE); + if(res != ESP_OK){ + return res; + } + + while(true){ + fb = esp_camera_fb_get(); + if (!fb) { + ESP_LOGE(TAG, "Camera capture failed"); + res = ESP_FAIL; + break; + } + if(fb->format != PIXFORMAT_JPEG){ + bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len); + if(!jpeg_converted){ + ESP_LOGE(TAG, "JPEG compression failed"); + esp_camera_fb_return(fb); + res = ESP_FAIL; + } + } else { + _jpg_buf_len = fb->len; + _jpg_buf = fb->buf; + } + + if(res == ESP_OK){ + res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY)); + } + if(res == ESP_OK){ + size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len); + + res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen); + } + if(res == ESP_OK){ + res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len); + } + if(fb->format != PIXFORMAT_JPEG){ + free(_jpg_buf); + } + esp_camera_fb_return(fb); + if(res != ESP_OK){ + break; + } + int64_t fr_end = esp_timer_get_time(); + int64_t frame_time = fr_end - last_frame; + last_frame = fr_end; + frame_time /= 1000; + ESP_LOGI(TAG, "MJPG: %uKB %ums (%.1ffps)", + (uint32_t)(_jpg_buf_len/1024), + (uint32_t)frame_time, 1000.0 / (uint32_t)frame_time); + } + + last_frame = 0; + return res; +} +``` + +### BMP HTTP Capture + +```c +#include "esp_camera.h" +#include "esp_http_server.h" +#include "esp_timer.h" + +esp_err_t bmp_httpd_handler(httpd_req_t *req){ + camera_fb_t * fb = NULL; + esp_err_t res = ESP_OK; + int64_t fr_start = esp_timer_get_time(); + + fb = esp_camera_fb_get(); + if (!fb) { + ESP_LOGE(TAG, "Camera capture failed"); + httpd_resp_send_500(req); + return ESP_FAIL; + } + + uint8_t * buf = NULL; + size_t buf_len = 0; + bool converted = frame2bmp(fb, &buf, &buf_len); + esp_camera_fb_return(fb); + if(!converted){ + ESP_LOGE(TAG, "BMP conversion failed"); + httpd_resp_send_500(req); + return ESP_FAIL; + } + + res = httpd_resp_set_type(req, "image/x-windows-bmp") + || httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.bmp") + || httpd_resp_send(req, (const char *)buf, buf_len); + free(buf); + int64_t fr_end = esp_timer_get_time(); + ESP_LOGI(TAG, "BMP: %uKB %ums", (uint32_t)(buf_len/1024), (uint32_t)((fr_end - fr_start)/1000)); + return res; +} +``` + + + diff --git a/lib/libesp32/esp32-camera/driver/include/cam_hal.h b/lib/libesp32/esp32-camera/driver/include/cam_hal.h new file mode 100644 index 000000000..c8e38ed47 --- /dev/null +++ b/lib/libesp32/esp32-camera/driver/include/cam_hal.h @@ -0,0 +1,60 @@ +// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "esp_camera.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Uninitialize the lcd_cam module + * + * @param handle Provide handle pointer to release resources + * + * @return + * - ESP_OK Success + * - ESP_FAIL Uninitialize fail + */ +esp_err_t cam_deinit(void); + +/** + * @brief Initialize the lcd_cam module + * + * @param config Configurations - see lcd_cam_config_t struct + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM No memory to initialize lcd_cam + * - ESP_FAIL Initialize fail + */ +esp_err_t cam_init(const camera_config_t *config); + +esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint16_t sensor_pid); + +void cam_stop(void); + +void cam_start(void); + +camera_fb_t *cam_take(TickType_t timeout); + +void cam_give(camera_fb_t *dma_buffer); + +#ifdef __cplusplus +} +#endif diff --git a/lib/libesp32/esp32-camera/driver/include/esp_camera.h b/lib/libesp32/esp32-camera/driver/include/esp_camera.h new file mode 100644 index 000000000..e9981671f --- /dev/null +++ b/lib/libesp32/esp32-camera/driver/include/esp_camera.h @@ -0,0 +1,214 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +/* + * Example Use + * + static camera_config_t camera_example_config = { + .pin_pwdn = PIN_PWDN, + .pin_reset = PIN_RESET, + .pin_xclk = PIN_XCLK, + .pin_sscb_sda = PIN_SIOD, + .pin_sscb_scl = PIN_SIOC, + .pin_d7 = PIN_D7, + .pin_d6 = PIN_D6, + .pin_d5 = PIN_D5, + .pin_d4 = PIN_D4, + .pin_d3 = PIN_D3, + .pin_d2 = PIN_D2, + .pin_d1 = PIN_D1, + .pin_d0 = PIN_D0, + .pin_vsync = PIN_VSYNC, + .pin_href = PIN_HREF, + .pin_pclk = PIN_PCLK, + + .xclk_freq_hz = 20000000, + .ledc_timer = LEDC_TIMER_0, + .ledc_channel = LEDC_CHANNEL_0, + .pixel_format = PIXFORMAT_JPEG, + .frame_size = FRAMESIZE_SVGA, + .jpeg_quality = 10, + .fb_count = 2, + .grab_mode = CAMERA_GRAB_WHEN_EMPTY + }; + + esp_err_t camera_example_init(){ + return esp_camera_init(&camera_example_config); + } + + esp_err_t camera_example_capture(){ + //capture a frame + camera_fb_t * fb = esp_camera_fb_get(); + if (!fb) { + ESP_LOGE(TAG, "Frame buffer could not be acquired"); + return ESP_FAIL; + } + + //replace this with your own function + display_image(fb->width, fb->height, fb->pixformat, fb->buf, fb->len); + + //return the frame buffer back to be reused + esp_camera_fb_return(fb); + + return ESP_OK; + } +*/ + +#pragma once + +#include "esp_err.h" +#include "driver/ledc.h" +#include "sensor.h" +#include "sys/time.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Configuration structure for camera initialization + */ +typedef enum { + CAMERA_GRAB_WHEN_EMPTY, /*!< Fills buffers when they are empty. Less resources but first 'fb_count' frames might be old */ + CAMERA_GRAB_LATEST /*!< Except when 1 frame buffer is used, queue will always contain the last 'fb_count' frames */ +} camera_grab_mode_t; + +/** + * @brief Camera frame buffer location + */ +typedef enum { + CAMERA_FB_IN_PSRAM, /*!< Frame buffer is placed in external PSRAM */ + CAMERA_FB_IN_DRAM /*!< Frame buffer is placed in internal DRAM */ +} camera_fb_location_t; + +/** + * @brief Configuration structure for camera initialization + */ +typedef struct { + int pin_pwdn; /*!< GPIO pin for camera power down line */ + int pin_reset; /*!< GPIO pin for camera reset line */ + int pin_xclk; /*!< GPIO pin for camera XCLK line */ + int pin_sscb_sda; /*!< GPIO pin for camera SDA line */ + int pin_sscb_scl; /*!< GPIO pin for camera SCL line */ + int pin_d7; /*!< GPIO pin for camera D7 line */ + int pin_d6; /*!< GPIO pin for camera D6 line */ + int pin_d5; /*!< GPIO pin for camera D5 line */ + int pin_d4; /*!< GPIO pin for camera D4 line */ + int pin_d3; /*!< GPIO pin for camera D3 line */ + int pin_d2; /*!< GPIO pin for camera D2 line */ + int pin_d1; /*!< GPIO pin for camera D1 line */ + int pin_d0; /*!< GPIO pin for camera D0 line */ + int pin_vsync; /*!< GPIO pin for camera VSYNC line */ + int pin_href; /*!< GPIO pin for camera HREF line */ + int pin_pclk; /*!< GPIO pin for camera PCLK line */ + + int xclk_freq_hz; /*!< Frequency of XCLK signal, in Hz. EXPERIMENTAL: Set to 16MHz on ESP32-S2 or ESP32-S3 to enable EDMA mode */ + + ledc_timer_t ledc_timer; /*!< LEDC timer to be used for generating XCLK */ + ledc_channel_t ledc_channel; /*!< LEDC channel to be used for generating XCLK */ + + pixformat_t pixel_format; /*!< Format of the pixel data: PIXFORMAT_ + YUV422|GRAYSCALE|RGB565|JPEG */ + framesize_t frame_size; /*!< Size of the output image: FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA */ + + int jpeg_quality; /*!< Quality of JPEG output. 0-63 lower means higher quality */ + size_t fb_count; /*!< Number of frame buffers to be allocated. If more than one, then each frame will be acquired (double speed) */ + camera_fb_location_t fb_location; /*!< The location where the frame buffer will be allocated */ + camera_grab_mode_t grab_mode; /*!< When buffers should be filled */ +} camera_config_t; + +/** + * @brief Data structure of camera frame buffer + */ +typedef struct { + uint8_t * buf; /*!< Pointer to the pixel data */ + size_t len; /*!< Length of the buffer in bytes */ + size_t width; /*!< Width of the buffer in pixels */ + size_t height; /*!< Height of the buffer in pixels */ + pixformat_t format; /*!< Format of the pixel data */ + struct timeval timestamp; /*!< Timestamp since boot of the first DMA buffer of the frame */ +} camera_fb_t; + +#define ESP_ERR_CAMERA_BASE 0x20000 +#define ESP_ERR_CAMERA_NOT_DETECTED (ESP_ERR_CAMERA_BASE + 1) +#define ESP_ERR_CAMERA_FAILED_TO_SET_FRAME_SIZE (ESP_ERR_CAMERA_BASE + 2) +#define ESP_ERR_CAMERA_FAILED_TO_SET_OUT_FORMAT (ESP_ERR_CAMERA_BASE + 3) +#define ESP_ERR_CAMERA_NOT_SUPPORTED (ESP_ERR_CAMERA_BASE + 4) + +/** + * @brief Initialize the camera driver + * + * @note call camera_probe before calling this function + * + * This function detects and configures camera over I2C interface, + * allocates framebuffer and DMA buffers, + * initializes parallel I2S input, and sets up DMA descriptors. + * + * Currently this function can only be called once and there is + * no way to de-initialize this module. + * + * @param config Camera configuration parameters + * + * @return ESP_OK on success + */ +esp_err_t esp_camera_init(const camera_config_t* config); + +/** + * @brief Deinitialize the camera driver + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if the driver hasn't been initialized yet + */ +esp_err_t esp_camera_deinit(); + +/** + * @brief Obtain pointer to a frame buffer. + * + * @return pointer to the frame buffer + */ +camera_fb_t* esp_camera_fb_get(); + +/** + * @brief Return the frame buffer to be reused again. + * + * @param fb Pointer to the frame buffer + */ +void esp_camera_fb_return(camera_fb_t * fb); + +/** + * @brief Get a pointer to the image sensor control structure + * + * @return pointer to the sensor + */ +sensor_t * esp_camera_sensor_get(); + +/** + * @brief Save camera settings to non-volatile-storage (NVS) + * + * @param key A unique nvs key name for the camera settings + */ +esp_err_t esp_camera_save_to_nvs(const char *key); + +/** + * @brief Load camera settings from non-volatile-storage (NVS) + * + * @param key A unique nvs key name for the camera settings + */ +esp_err_t esp_camera_load_from_nvs(const char *key); + +#ifdef __cplusplus +} +#endif + +#include "img_converters.h" + diff --git a/lib/libesp32/esp32-camera/driver/include/sensor.h b/lib/libesp32/esp32-camera/driver/include/sensor.h new file mode 100644 index 000000000..1f99c1541 --- /dev/null +++ b/lib/libesp32/esp32-camera/driver/include/sensor.h @@ -0,0 +1,245 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * Sensor abstraction layer. + * + */ +#ifndef __SENSOR_H__ +#define __SENSOR_H__ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + OV9650_PID = 0x96, + OV7725_PID = 0x77, + OV2640_PID = 0x26, + OV3660_PID = 0x3660, + OV5640_PID = 0x5640, + OV7670_PID = 0x76, + NT99141_PID = 0x1410, + GC2145_PID = 0x2145, + GC032A_PID = 0x232a, + GC0308_PID = 0x9b, +} camera_pid_t; + +typedef enum { + CAMERA_OV7725, + CAMERA_OV2640, + CAMERA_OV3660, + CAMERA_OV5640, + CAMERA_OV7670, + CAMERA_NT99141, + CAMERA_GC2145, + CAMERA_GC032A, + CAMERA_GC0308, + CAMERA_MODEL_MAX, + CAMERA_NONE, +} camera_model_t; + +typedef enum { + OV2640_SCCB_ADDR = 0x30,// 0x60 >> 1 + OV5640_SCCB_ADDR = 0x3C,// 0x78 >> 1 + OV3660_SCCB_ADDR = 0x3C,// 0x78 >> 1 + OV7725_SCCB_ADDR = 0x21,// 0x42 >> 1 + OV7670_SCCB_ADDR = 0x21,// 0x42 >> 1 + NT99141_SCCB_ADDR = 0x2A,// 0x54 >> 1 + GC2145_SCCB_ADDR = 0x3C,// 0x78 >> 1 + GC032A_SCCB_ADDR = 0x21,// 0x42 >> 1 + GC0308_SCCB_ADDR = 0x21,// 0x42 >> 1 +} camera_sccb_addr_t; + +typedef enum { + PIXFORMAT_RGB565, // 2BPP/RGB565 + PIXFORMAT_YUV422, // 2BPP/YUV422 + PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE + PIXFORMAT_JPEG, // JPEG/COMPRESSED + PIXFORMAT_RGB888, // 3BPP/RGB888 + PIXFORMAT_RAW, // RAW + PIXFORMAT_RGB444, // 3BP2P/RGB444 + PIXFORMAT_RGB555, // 3BP2P/RGB555 +} pixformat_t; + +typedef enum { + FRAMESIZE_96X96, // 96x96 + FRAMESIZE_QQVGA, // 160x120 + FRAMESIZE_QCIF, // 176x144 + FRAMESIZE_HQVGA, // 240x176 + FRAMESIZE_240X240, // 240x240 + FRAMESIZE_QVGA, // 320x240 + FRAMESIZE_CIF, // 400x296 + FRAMESIZE_HVGA, // 480x320 + FRAMESIZE_VGA, // 640x480 + FRAMESIZE_SVGA, // 800x600 + FRAMESIZE_XGA, // 1024x768 + FRAMESIZE_HD, // 1280x720 + FRAMESIZE_SXGA, // 1280x1024 + FRAMESIZE_UXGA, // 1600x1200 + // 3MP Sensors + FRAMESIZE_FHD, // 1920x1080 + FRAMESIZE_P_HD, // 720x1280 + FRAMESIZE_P_3MP, // 864x1536 + FRAMESIZE_QXGA, // 2048x1536 + // 5MP Sensors + FRAMESIZE_QHD, // 2560x1440 + FRAMESIZE_WQXGA, // 2560x1600 + FRAMESIZE_P_FHD, // 1080x1920 + FRAMESIZE_QSXGA, // 2560x1920 + FRAMESIZE_INVALID +} framesize_t; + +typedef struct { + const camera_model_t model; + const char *name; + const camera_sccb_addr_t sccb_addr; + const camera_pid_t pid; + const framesize_t max_size; + const bool support_jpeg; +} camera_sensor_info_t; + +typedef enum { + ASPECT_RATIO_4X3, + ASPECT_RATIO_3X2, + ASPECT_RATIO_16X10, + ASPECT_RATIO_5X3, + ASPECT_RATIO_16X9, + ASPECT_RATIO_21X9, + ASPECT_RATIO_5X4, + ASPECT_RATIO_1X1, + ASPECT_RATIO_9X16 +} aspect_ratio_t; + +typedef enum { + GAINCEILING_2X, + GAINCEILING_4X, + GAINCEILING_8X, + GAINCEILING_16X, + GAINCEILING_32X, + GAINCEILING_64X, + GAINCEILING_128X, +} gainceiling_t; + +typedef struct { + uint16_t max_width; + uint16_t max_height; + uint16_t start_x; + uint16_t start_y; + uint16_t end_x; + uint16_t end_y; + uint16_t offset_x; + uint16_t offset_y; + uint16_t total_x; + uint16_t total_y; +} ratio_settings_t; + +typedef struct { + const uint16_t width; + const uint16_t height; + const aspect_ratio_t aspect_ratio; +} resolution_info_t; + +// Resolution table (in sensor.c) +extern const resolution_info_t resolution[]; +// camera sensor table (in sensor.c) +extern const camera_sensor_info_t camera_sensor[]; + +typedef struct { + uint8_t MIDH; + uint8_t MIDL; + uint16_t PID; + uint8_t VER; +} sensor_id_t; + +typedef struct { + framesize_t framesize;//0 - 10 + bool scale; + bool binning; + uint8_t quality;//0 - 63 + int8_t brightness;//-2 - 2 + int8_t contrast;//-2 - 2 + int8_t saturation;//-2 - 2 + int8_t sharpness;//-2 - 2 + uint8_t denoise; + uint8_t special_effect;//0 - 6 + uint8_t wb_mode;//0 - 4 + uint8_t awb; + uint8_t awb_gain; + uint8_t aec; + uint8_t aec2; + int8_t ae_level;//-2 - 2 + uint16_t aec_value;//0 - 1200 + uint8_t agc; + uint8_t agc_gain;//0 - 30 + uint8_t gainceiling;//0 - 6 + uint8_t bpc; + uint8_t wpc; + uint8_t raw_gma; + uint8_t lenc; + uint8_t hmirror; + uint8_t vflip; + uint8_t dcw; + uint8_t colorbar; +} camera_status_t; + +typedef struct _sensor sensor_t; +typedef struct _sensor { + sensor_id_t id; // Sensor ID. + uint8_t slv_addr; // Sensor I2C slave address. + pixformat_t pixformat; + camera_status_t status; + int xclk_freq_hz; + + // Sensor function pointers + int (*init_status) (sensor_t *sensor); + int (*reset) (sensor_t *sensor); + int (*set_pixformat) (sensor_t *sensor, pixformat_t pixformat); + int (*set_framesize) (sensor_t *sensor, framesize_t framesize); + int (*set_contrast) (sensor_t *sensor, int level); + int (*set_brightness) (sensor_t *sensor, int level); + int (*set_saturation) (sensor_t *sensor, int level); + int (*set_sharpness) (sensor_t *sensor, int level); + int (*set_denoise) (sensor_t *sensor, int level); + int (*set_gainceiling) (sensor_t *sensor, gainceiling_t gainceiling); + int (*set_quality) (sensor_t *sensor, int quality); + int (*set_colorbar) (sensor_t *sensor, int enable); + int (*set_whitebal) (sensor_t *sensor, int enable); + int (*set_gain_ctrl) (sensor_t *sensor, int enable); + int (*set_exposure_ctrl) (sensor_t *sensor, int enable); + int (*set_hmirror) (sensor_t *sensor, int enable); + int (*set_vflip) (sensor_t *sensor, int enable); + + int (*set_aec2) (sensor_t *sensor, int enable); + int (*set_awb_gain) (sensor_t *sensor, int enable); + int (*set_agc_gain) (sensor_t *sensor, int gain); + int (*set_aec_value) (sensor_t *sensor, int gain); + + int (*set_special_effect) (sensor_t *sensor, int effect); + int (*set_wb_mode) (sensor_t *sensor, int mode); + int (*set_ae_level) (sensor_t *sensor, int level); + + int (*set_dcw) (sensor_t *sensor, int enable); + int (*set_bpc) (sensor_t *sensor, int enable); + int (*set_wpc) (sensor_t *sensor, int enable); + + int (*set_raw_gma) (sensor_t *sensor, int enable); + int (*set_lenc) (sensor_t *sensor, int enable); + + int (*get_reg) (sensor_t *sensor, int reg, int mask); + int (*set_reg) (sensor_t *sensor, int reg, int mask, int value); + int (*set_res_raw) (sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning); + int (*set_pll) (sensor_t *sensor, int bypass, int mul, int sys, int root, int pre, int seld5, int pclken, int pclk); + int (*set_xclk) (sensor_t *sensor, int timer, int xclk); +} sensor_t; + +camera_sensor_info_t *esp_camera_sensor_get_info(sensor_id_t *id); + +#ifdef __cplusplus +} +#endif + +#endif /* __SENSOR_H__ */ diff --git a/lib/libesp32/esp32-camera/driver/include/xclk.h b/lib/libesp32/esp32-camera/driver/include/xclk.h new file mode 100644 index 000000000..3d721a613 --- /dev/null +++ b/lib/libesp32/esp32-camera/driver/include/xclk.h @@ -0,0 +1,9 @@ +#pragma once + +#include "esp_system.h" + +esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz); + +esp_err_t camera_enable_out_clock(); + +void camera_disable_out_clock(); diff --git a/lib/libesp32/esp32-camera/library.json b/lib/libesp32/esp32-camera/library.json new file mode 100644 index 000000000..bb542c0bf --- /dev/null +++ b/lib/libesp32/esp32-camera/library.json @@ -0,0 +1,20 @@ +{ + "name": "esp32-camera-header", + "version": "1.0.0", + "keywords": "esp32, camera, espressif, esp32-cam", + "description": "ESP32 camera header files", + "repository": { + "type": "git", + "url": "https://github.com/espressif/esp32-camera" + }, + "frameworks": "arduino", + "platforms": "espressif32", + "build": { + "flags": [ + "-Idriver/include" + ], + "includeDir": ".", + "srcDir": ".", + "srcFilter": ["-<*>", "+"] + } +} diff --git a/lib/libesp32/re1.5/library.json b/lib/libesp32/re1.5/library.json index 8233b2142..7584bee24 100644 --- a/lib/libesp32/re1.5/library.json +++ b/lib/libesp32/re1.5/library.json @@ -8,6 +8,6 @@ "type": "git", "url": "https://github.com/pfalcon/re1.5" }, - "frameworks": "*", - "platforms": "*" + "frameworks": "arduino", + "platforms": "espressif32" } \ No newline at end of file diff --git a/lib/libesp32/re1.5/main.c b/lib/libesp32/re1.5/main.c deleted file mode 100644 index 7d688adf1..000000000 --- a/lib/libesp32/re1.5/main.c +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2007-2009 Russ Cox. All Rights Reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "re1.5.h" - -struct { - char *name; - int (*fn)(ByteProg*, Subject*, const char**, int, int); -} tab[] = { - {"recursive", re1_5_recursiveprog}, - {"recursiveloop", re1_5_recursiveloopprog}, - {"backtrack", re1_5_backtrack}, - {"thompson", re1_5_thompsonvm}, - {"pike", re1_5_pikevm}, -}; - -#ifdef DEBUG -int debug; -#endif -const char *re_engine; - -void -usage(void) -{ - fprintf(stderr, "Usage: re [-hmd] [-e ENGINE] ...\n" - "-h: Print help message and exit\n" - "-m: String is anchored\n" - "-e ENGINE: Specify one of: recursive recursiveloop backtrack thompson pike\n"); -#ifdef DEBUG - fprintf(stderr, - "-d: Print debug messages\n"); -#endif - exit(2); -} - -int -main(int argc, char **argv) -{ - int i, j, k, l; - int is_anchored = 0; - - argv++; - argc--; - while (argc > 0 && argv[0][0] == '-') { - char *arg; - for (arg = &argv[0][1]; *arg; arg++) { - switch (*arg) { - case 'h': - usage(); - break; - case 'm': - is_anchored = 1; - break; -#ifdef DEBUG - case 'd': - debug = 1; - break; -#endif - case 'e': - if (argv[1] == NULL) - re1_5_fatal("-e: Missing Regex engine argument"); - if (re_engine) - re1_5_fatal("-e: Regex engine already specified"); - re_engine = argv[1]; - argv++; - argc--; - break; - default: - re1_5_fatal("Unknown flag"); - } - } - argv++; - argc--; - } - - if(argc < 2) - usage(); - -#ifdef ODEBUG - // Old and unmaintained code - Regexp *re = parse(argv[0]); - printre(re); - printf("\n"); - - Prog *prog = compile(re); - printprog(prog); - printf("=============\n"); -#endif - int sz = re1_5_sizecode(argv[0]); -#ifdef DEBUG - if (debug) printf("Precalculated size: %d\n", sz); -#endif - if (sz == -1) { - re1_5_fatal("Error in regexp"); - } - - ByteProg *code = malloc(sizeof(ByteProg) + sz); - int ret = re1_5_compilecode(code, argv[0]); - if (ret != 0) { - re1_5_fatal("Error in regexp"); - } - - int sub_els = (code->sub + 1) * 2; -#ifdef DEBUG - if (debug) re1_5_dumpcode(code); -#endif - const char *sub[sub_els]; - int engine_found = 0; - for(i=1; i0; k--) - if(sub[k-1]) - break; - for(l=0; l #include #include <_esp_hap_config.h> +#include +#include static QueueHandle_t xQueue; ESP_EVENT_DEFINE_BASE(HAP_EVENT); +// static TaskHandle_t hap_loop_handle; const char * hap_get_version(void) { @@ -354,7 +357,11 @@ int hap_start(void) int hap_stop(void) { int ret = HAP_SUCCESS; - //todo + hap_mdns_deannounce(); + hap_mdns_deinit(); + httpd_handle_t _handle = hap_platform_httpd_get_handle(); + if(_handle != NULL) hap_platform_httpd_stop(_handle); + ret = hap_loop_stop(); return ret; } diff --git a/lib/libesp32_div/ESP32-HomeKit/src/port/bignum_impl.h b/lib/libesp32_div/ESP32-HomeKit/src/port/bignum_impl.h index 20943499b..28219e682 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/port/bignum_impl.h +++ b/lib/libesp32_div/ESP32-HomeKit/src/port/bignum_impl.h @@ -91,6 +91,12 @@ void esp_mpi_exp_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const #if CONFIG_IDF_TARGET_ESP32C3 void esp_mpi_exp_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t num_words); +extern int esp_mpi_exp_mod( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, mbedtls_mpi *_Rinv ); +extern size_t esp_mpi_hardware_words(size_t words); +extern void esp_mpi_enable_hardware_hw_op( void ); +extern void esp_mpi_disable_hardware_hw_op( void ); +extern void esp_mpi_read_result_hw_op(mbedtls_mpi *Z, size_t z_words); +extern void esp_mpi_mult_mpi_failover_mod_mult_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words); #endif //CONFIG_IDF_TARGET_ESP32C3 #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md b/lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md index b833a03dc..b80c3c93b 100644 --- a/lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md +++ b/lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md @@ -1,6 +1,20 @@ # Changelog -All notable changes to this project will be documented in this file. +All notable changes to this project will be documented in this file. + +## [1.3.5] - 2022-01-14 + +### Added +- CONFIG_NIMBLE_CPP_DEBUG_LEVEL macro in nimconfig.h to allow setting the log level separately from the Arduino core log level. + +### Fixed +- Memory leak when initializing/deinitializing the BLE stack caused by new FreeRTOS timers be created on each initialization. + +## [1.3.4] - 2022-01-09 + +### Fixed +- Workaround for latest Arduino-esp32 core that causes tasks not to block when required, which caused functions to return prematurely resulting in exceptions/crashing. +- The wrong length value was being used to set the values read from peer attributes. This has been corrected to use the proper value size. ## [1.3.3] - 2021-11-24 diff --git a/lib/libesp32_div/NimBLE-Arduino/library.json b/lib/libesp32_div/NimBLE-Arduino/library.json index fd9dd44cf..e501aed59 100644 --- a/lib/libesp32_div/NimBLE-Arduino/library.json +++ b/lib/libesp32_div/NimBLE-Arduino/library.json @@ -2,7 +2,7 @@ "name": "NimBLE-Arduino", "keywords": "esp32, bluetooth", "description": "Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE", - "version": "1.3.3", + "version": "1.3.5", "frameworks": "arduino", "platforms": "espressif32" } diff --git a/lib/libesp32_div/NimBLE-Arduino/library.properties b/lib/libesp32_div/NimBLE-Arduino/library.properties index 11abace65..cbea51f6a 100644 --- a/lib/libesp32_div/NimBLE-Arduino/library.properties +++ b/lib/libesp32_div/NimBLE-Arduino/library.properties @@ -1,5 +1,5 @@ name=NimBLE-Arduino -version=1.3.3 +version=1.3.5 author=h2zero maintainer=h2zero sentence=Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE. diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/CODING_STANDARDS.md b/lib/libesp32_div/NimBLE-Arduino/src/CODING_STANDARDS.md similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/CODING_STANDARDS.md rename to lib/libesp32_div/NimBLE-Arduino/src/CODING_STANDARDS.md diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/NOTICE b/lib/libesp32_div/NimBLE-Arduino/src/NOTICE similarity index 61% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/NOTICE rename to lib/libesp32_div/NimBLE-Arduino/src/NOTICE index 02fe5929d..fc24c6abc 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/NOTICE +++ b/lib/libesp32_div/NimBLE-Arduino/src/NOTICE @@ -1,6 +1,5 @@ Apache Mynewt NimBLE -Copyright 2015-2020 The Apache Software Foundation -Modifications Copyright 2017-2020 Espressif Systems (Shanghai) CO., LTD. +Copyright 2015-2018 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.cpp index 282eff55f..80318b5b8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.cpp @@ -16,8 +16,11 @@ * See also: * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml */ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) + #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLE2904.h" @@ -83,4 +86,5 @@ void NimBLE2904::setUnit(uint16_t unit) { setValue((uint8_t*) &m_data, sizeof(m_data)); } // setUnit -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.h index 29dde51e8..d8800dd2f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.h @@ -14,8 +14,11 @@ #ifndef MAIN_NIMBLE2904_H_ #define MAIN_NIMBLE2904_H_ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) + #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLEDescriptor.h" @@ -79,5 +82,6 @@ private: BLE2904_Data m_data; }; // BLE2904 -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif /* CONFIG_BT_ENABLED */ #endif /* MAIN_NIMBLE2904_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.cpp index b8df5ac83..e1d3e548b 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.cpp @@ -11,7 +11,7 @@ * Created on: Jul 2, 2017 * Author: kolban */ -#include "nimconfig.h" +#include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.h index a6e10a09c..50f9231fe 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.h @@ -14,15 +14,10 @@ #ifndef COMPONENTS_NIMBLEADDRESS_H_ #define COMPONENTS_NIMBLEADDRESS_H_ -#include "nimconfig.h" +#include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) -#if defined(CONFIG_NIMBLE_CPP_IDF) #include "nimble/ble.h" -#else -#include "nimble/nimble/include/nimble/ble.h" -#endif - /**** FIX COMPILATION ****/ #undef min #undef max diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp index 01dd75d41..ecfd49814 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp @@ -11,9 +11,11 @@ * Created on: Jul 3, 2017 * Author: kolban */ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #include "NimBLEDevice.h" #include "NimBLEAdvertisedDevice.h" @@ -781,5 +783,7 @@ size_t NimBLEAdvertisedDevice::getPayloadLength() { return m_payload.size(); } // getPayloadLength -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ + +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#endif /* CONFIG_BT_ENABLED */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h index 39410e665..7d378ed0f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h @@ -14,22 +14,20 @@ #ifndef COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ #define COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) + #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #include "NimBLEAddress.h" #include "NimBLEScan.h" #include "NimBLEUUID.h" -#if defined(CONFIG_NIMBLE_CPP_IDF) #include "host/ble_hs_adv.h" -#else -#include "nimble/nimble/host/include/host/ble_hs_adv.h" -#endif #include #include -#include class NimBLEScan; @@ -173,5 +171,6 @@ public: virtual void onResult(NimBLEAdvertisedDevice* advertisedDevice) = 0; }; -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_OBSERVER */ +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.cpp index a804130f8..3112efff0 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.cpp @@ -13,14 +13,13 @@ * Author: kolban * */ -#include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) + +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) -#if defined(CONFIG_NIMBLE_CPP_IDF) #include "services/gap/ble_svc_gap.h" -#else -#include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h" -#endif #include "NimBLEAdvertising.h" #include "NimBLEDevice.h" #include "NimBLEServer.h" @@ -69,7 +68,6 @@ void NimBLEAdvertising::reset() { m_advDataSet = false; // Set this to non-zero to prevent auto start if host reset before started by app. m_duration = BLE_HS_FOREVER; - m_advCompCB = nullptr; } // reset @@ -655,8 +653,12 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv break; } + if(rc != 0) { + return false; + } + NIMBLE_LOGD(LOG_TAG, "<< Advertising start"); - return (rc == 0); + return true; } // start @@ -1026,4 +1028,5 @@ std::string NimBLEAdvertisementData::getPayload() { return m_payload; } // getPayload -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER */ +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif /* CONFIG_BT_ENABLED */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.h index 63a21d846..17a866561 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.h @@ -14,15 +14,13 @@ #ifndef MAIN_BLEADVERTISING_H_ #define MAIN_BLEADVERTISING_H_ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) + #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) +#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) -#if defined(CONFIG_NIMBLE_CPP_IDF) #include "host/ble_gap.h" -#else -#include "nimble/nimble/host/include/host/ble_gap.h" -#endif - /**** FIX COMPILATION ****/ #undef min #undef max @@ -134,5 +132,6 @@ private: std::vector m_uri; }; -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER */ +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif /* CONFIG_BT_ENABLED */ #endif /* MAIN_BLEADVERTISING_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.cpp index 996893ab1..8c4574bc2 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.cpp @@ -11,7 +11,7 @@ * Created on: Jan 4, 2018 * Author: kolban */ -#include "nimconfig.h" +#include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.cpp index cc87483b7..e81fdbcda 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.cpp @@ -9,9 +9,11 @@ * Created on: Jun 22, 2017 * Author: kolban */ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLECharacteristic.h" #include "NimBLE2904.h" @@ -49,6 +51,7 @@ NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t prop m_pCallbacks = &defaultCallback; m_pService = pService; m_value = ""; + m_valMux = portMUX_INITIALIZER_UNLOCKED; m_timestamp = 0; m_removed = 0; } // NimBLECharacteristic @@ -234,12 +237,12 @@ NimBLEUUID NimBLECharacteristic::getUUID() { * @return A std::string containing the current characteristic value. */ std::string NimBLECharacteristic::getValue(time_t *timestamp) { - ble_npl_hw_enter_critical(); + portENTER_CRITICAL(&m_valMux); std::string retVal = m_value; if(timestamp != nullptr) { *timestamp = m_timestamp; } - ble_npl_hw_exit_critical(0); + portEXIT_CRITICAL(&m_valMux); return retVal; } // getValue @@ -250,9 +253,10 @@ std::string NimBLECharacteristic::getValue(time_t *timestamp) { * @return The length of the current characteristic data. */ size_t NimBLECharacteristic::getDataLength() { - ble_npl_hw_enter_critical(); + portENTER_CRITICAL(&m_valMux); size_t len = m_value.length(); - ble_npl_hw_exit_critical(0); + portEXIT_CRITICAL(&m_valMux); + return len; } @@ -285,10 +289,11 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han pCharacteristic->m_pCallbacks->onRead(pCharacteristic, &desc); } - ble_npl_hw_enter_critical(); + portENTER_CRITICAL(&pCharacteristic->m_valMux); rc = os_mbuf_append(ctxt->om, (uint8_t*)pCharacteristic->m_value.data(), pCharacteristic->m_value.length()); - ble_npl_hw_exit_critical(0); + portEXIT_CRITICAL(&pCharacteristic->m_valMux); + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; } @@ -427,7 +432,7 @@ void NimBLECharacteristic::notify(bool is_notification) { int rc = 0; for (auto &it : m_subscribedVec) { - uint16_t _mtu = getService()->getServer()->getPeerMTU(it.first) - 3; + uint16_t _mtu = getService()->getServer()->getPeerMTU(it.first); // check if connected and subscribed if(_mtu == 0 || it.second == 0) { @@ -443,8 +448,8 @@ void NimBLECharacteristic::notify(bool is_notification) { } } - if (length > _mtu) { - NIMBLE_LOGW(LOG_TAG, "- Truncating to %d bytes (maximum notify size)", _mtu); + if (length > _mtu - 3) { + NIMBLE_LOGW(LOG_TAG, "- Truncating to %d bytes (maximum notify size)", _mtu - 3); } if(is_notification && (!(it.second & NIMBLE_SUB_NOTIFY))) { @@ -511,7 +516,7 @@ NimBLECharacteristicCallbacks* NimBLECharacteristic::getCallbacks() { * @param [in] length The length of the data in bytes. */ void NimBLECharacteristic::setValue(const uint8_t* data, size_t length) { -#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && CORE_DEBUG_LEVEL >= 4) +#if CONFIG_NIMBLE_CPP_DEBUG_LEVEL >= 4 char* pHex = NimBLEUtils::buildHexData(nullptr, data, length); NIMBLE_LOGD(LOG_TAG, ">> setValue: length=%d, data=%s, characteristic UUID=%s", length, pHex, getUUID().toString().c_str()); free(pHex); @@ -523,10 +528,10 @@ void NimBLECharacteristic::setValue(const uint8_t* data, size_t length) { } time_t t = time(nullptr); - ble_npl_hw_enter_critical(); + portENTER_CRITICAL(&m_valMux); m_value = std::string((char*)data, length); m_timestamp = t; - ble_npl_hw_exit_critical(0); + portEXIT_CRITICAL(&m_valMux); NIMBLE_LOGD(LOG_TAG, "<< setValue"); } // setValue @@ -636,4 +641,6 @@ void NimBLECharacteristicCallbacks::onSubscribe(NimBLECharacteristic* pCharacter NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onSubscribe: default"); } -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ + +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif /* CONFIG_BT_ENABLED */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.h index 9edfb54b3..6008d127f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.h @@ -13,15 +13,13 @@ #ifndef MAIN_NIMBLECHARACTERISTIC_H_ #define MAIN_NIMBLECHARACTERISTIC_H_ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) + #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) -#if defined(CONFIG_NIMBLE_CPP_IDF) #include "host/ble_hs.h" -#else -#include "nimble/nimble/host/include/host/ble_hs.h" -#endif - /**** FIX COMPILATION ****/ #undef min #undef max @@ -153,6 +151,7 @@ private: NimBLEService* m_pService; std::string m_value; std::vector m_dscVec; + portMUX_TYPE m_valMux; time_t m_timestamp; uint8_t m_removed; @@ -196,5 +195,6 @@ public: virtual void onSubscribe(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc, uint16_t subValue); }; -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif /* CONFIG_BT_ENABLED */ #endif /*MAIN_NIMBLECHARACTERISTIC_H_*/ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.cpp index 9f4e08fdb..49cda6649 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.cpp @@ -11,8 +11,11 @@ * Author: kolban */ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) + #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLEClient.h" #include "NimBLEDevice.h" @@ -21,11 +24,8 @@ #include #include -#if defined(CONFIG_NIMBLE_CPP_IDF) #include "nimble/nimble_port.h" -#else -#include "nimble/porting/nimble/include/nimble/nimble_port.h" -#endif + static const char* LOG_TAG = "NimBLEClient"; static NimBLEClientCallbacks defaultCallbacks; @@ -74,7 +74,6 @@ NimBLEClient::NimBLEClient(const NimBLEAddress &peerAddress) : m_peerAddress(pee m_pConnParams.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN; // Minimum length of connection event in 0.625ms units m_pConnParams.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN; // Maximum length of connection event in 0.625ms units - memset(&m_dcTimer, 0, sizeof(m_dcTimer)); ble_npl_callout_init(&m_dcTimer, nimble_port_get_dflt_eventq(), NimBLEClient::dcTimerCb, this); } // NimBLEClient @@ -207,7 +206,8 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) { m_peerAddress = address; } - ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr}; + TaskHandle_t cur_task = xTaskGetCurrentTaskHandle(); + ble_task_data_t taskData = {this, cur_task, 0, nullptr}; m_pTaskData = &taskData; int rc = 0; @@ -260,6 +260,10 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) { return false; } +#ifdef ulTaskNotifyValueClear + // Clear the task notification value to ensure we block + ulTaskNotifyValueClear(cur_task, ULONG_MAX); +#endif // Wait for the connect timeout time +1 second for the connection to complete if(ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(m_connectTimeout + 1000)) == pdFALSE) { m_pTaskData = nullptr; @@ -310,7 +314,8 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) { * @return True on success. */ bool NimBLEClient::secureConnection() { - ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr}; + TaskHandle_t cur_task = xTaskGetCurrentTaskHandle(); + ble_task_data_t taskData = {this, cur_task, 0, nullptr}; int retryCount = 1; @@ -324,6 +329,10 @@ bool NimBLEClient::secureConnection() { return false; } +#ifdef ulTaskNotifyValueClear + // Clear the task notification value to ensure we block + ulTaskNotifyValueClear(cur_task, ULONG_MAX); +#endif ulTaskNotifyTake(pdTRUE, portMAX_DELAY); } while (taskData.rc == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING) && retryCount--); @@ -444,28 +453,6 @@ void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval, } // updateConnParams -/** - * @brief Request an update of the data packet length. - * * Can only be used after a connection has been established. - * @details Sends a data length update request to the server the client is connected to. - * The Data Length Extension (DLE) allows to increase the Data Channel Payload from 27 bytes to up to 251 bytes. - * The server needs to support the Bluetooth 4.2 specifications, to be capable of DLE. - * @param [in] tx_octets The preferred number of payload octets to use (Range 0x001B-0x00FB). - */ -void NimBLEClient::setDataLen(uint16_t tx_octets) { -#ifdef CONFIG_NIMBLE_CPP_IDF // not yet available in IDF, Sept 9 2021 - return; -#else - uint16_t tx_time = (tx_octets + 14) * 8; - - int rc = ble_gap_set_data_len(m_conn_id, tx_octets, tx_time); - if(rc != 0) { - NIMBLE_LOGE(LOG_TAG, "Set data length error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc)); - } -#endif -} // setDataLen - - /** * @brief Get detailed information about the current peer connection. */ @@ -670,7 +657,8 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID *uuid_filter) { } int rc = 0; - ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr}; + TaskHandle_t cur_task = xTaskGetCurrentTaskHandle(); + ble_task_data_t taskData = {this, cur_task, 0, nullptr}; if(uuid_filter == nullptr) { rc = ble_gattc_disc_all_svcs(m_conn_id, NimBLEClient::serviceDiscoveredCB, &taskData); @@ -685,6 +673,11 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID *uuid_filter) { return false; } +#ifdef ulTaskNotifyValueClear + // Clear the task notification value to ensure we block + ulTaskNotifyValueClear(cur_task, ULONG_MAX); +#endif + // wait until we have all the services ulTaskNotifyTake(pdTRUE, portMAX_DELAY); m_lastErr = taskData.rc; @@ -958,11 +951,11 @@ uint16_t NimBLEClient::getMTU() { (*characteristic)->toString().c_str()); time_t t = time(nullptr); - ble_npl_hw_enter_critical(); + portENTER_CRITICAL(&(*characteristic)->m_valMux); (*characteristic)->m_value = std::string((char *)event->notify_rx.om->om_data, event->notify_rx.om->om_len); (*characteristic)->m_timestamp = t; - ble_npl_hw_exit_critical(0); + portEXIT_CRITICAL(&(*characteristic)->m_valMux); if ((*characteristic)->m_notifyCallback != nullptr) { NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s", @@ -1212,4 +1205,5 @@ bool NimBLEClientCallbacks::onConfirmPIN(uint32_t pin){ return true; } -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#endif // CONFIG_BT_ENABLED diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.h index 37700b7c4..8bb3119dc 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.h @@ -14,8 +14,11 @@ #ifndef MAIN_NIMBLECLIENT_H_ #define MAIN_NIMBLECLIENT_H_ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) + #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLEAddress.h" #include "NimBLEUUID.h" @@ -68,7 +71,6 @@ public: uint16_t scanInterval=16, uint16_t scanWindow=16); void updateConnParams(uint16_t minInterval, uint16_t maxInterval, uint16_t latency, uint16_t timeout); - void setDataLen(uint16_t tx_octets); void discoverAttributes(); NimBLEConnInfo getConnInfo(); int getLastError(); @@ -158,5 +160,6 @@ public: virtual bool onConfirmPIN(uint32_t pin); }; -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#endif // CONFIG_BT_ENABLED #endif /* MAIN_NIMBLECLIENT_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.cpp index 5b0db1a64..f94676607 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.cpp @@ -11,9 +11,11 @@ * Created on: Jun 22, 2017 * Author: kolban */ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLEService.h" #include "NimBLEDescriptor.h" @@ -49,6 +51,7 @@ NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_ m_pCharacteristic = pCharacteristic; m_pCallbacks = &defaultCallbacks; // No initial callback. m_value.attr_value = (uint8_t*) calloc(max_len,1); // Allocate storage for the value. + m_valMux = portMUX_INITIALIZER_UNLOCKED; m_properties = 0; m_removed = 0; @@ -142,9 +145,6 @@ NimBLECharacteristic* NimBLEDescriptor::getCharacteristic() { int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { - (void)conn_handle; - (void)attr_handle; - const ble_uuid_t *uuid; int rc; NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg; @@ -161,10 +161,9 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle, if(ctxt->om->om_pkthdr_len > 8) { pDescriptor->m_pCallbacks->onRead(pDescriptor); } - - ble_npl_hw_enter_critical(); + portENTER_CRITICAL(&pDescriptor->m_valMux); rc = os_mbuf_append(ctxt->om, pDescriptor->getValue(), pDescriptor->getLength()); - ble_npl_hw_exit_critical(0); + portEXIT_CRITICAL(&pDescriptor->m_valMux); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; } @@ -235,12 +234,10 @@ void NimBLEDescriptor::setValue(const uint8_t* data, size_t length) { NIMBLE_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, m_value.attr_max_len); return; } - - ble_npl_hw_enter_critical(); + portENTER_CRITICAL(&m_valMux); m_value.attr_len = length; memcpy(m_value.attr_value, data, length); - ble_npl_hw_exit_critical(0); - + portEXIT_CRITICAL(&m_valMux); } // setValue @@ -280,7 +277,6 @@ NimBLEDescriptorCallbacks::~NimBLEDescriptorCallbacks() {} * @param [in] pDescriptor The descriptor that is the source of the event. */ void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor) { - (void)pDescriptor; NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onRead: default"); } // onRead @@ -290,8 +286,8 @@ void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor) { * @param [in] pDescriptor The descriptor that is the source of the event. */ void NimBLEDescriptorCallbacks::onWrite(NimBLEDescriptor* pDescriptor) { - (void)pDescriptor; NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onWrite: default"); } // onWrite -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif /* CONFIG_BT_ENABLED */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.h index fe6c73303..5dc0ce89b 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.h @@ -14,9 +14,11 @@ #ifndef MAIN_NIMBLEDESCRIPTOR_H_ #define MAIN_NIMBLEDESCRIPTOR_H_ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLECharacteristic.h" #include "NimBLEUUID.h" @@ -90,6 +92,7 @@ private: NimBLECharacteristic* m_pCharacteristic; uint8_t m_properties; attr_value_t m_value; + portMUX_TYPE m_valMux; uint8_t m_removed; }; // NimBLEDescriptor @@ -110,5 +113,6 @@ public: #include "NimBLE2904.h" -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif /* CONFIG_BT_ENABLED */ #endif /* MAIN_NIMBLEDESCRIPTOR_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.cpp index 0302cb8a8..bc253659a 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.cpp @@ -11,45 +11,27 @@ * Created on: Mar 16, 2017 * Author: kolban */ - -#include "nimconfig.h" +#include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" #include "NimBLEDevice.h" #include "NimBLEUtils.h" -#ifdef ESP_PLATFORM -# include "esp_err.h" -# include "esp_bt.h" -# include "nvs_flash.h" -# if defined(CONFIG_NIMBLE_CPP_IDF) -# include "esp_nimble_hci.h" -# include "nimble/nimble_port.h" -# include "nimble/nimble_port_freertos.h" -# include "host/ble_hs.h" -# include "host/ble_hs_pvcy.h" -# include "host/util/util.h" -# include "services/gap/ble_svc_gap.h" -# include "services/gatt/ble_svc_gatt.h" -# else -# include "nimble/esp_port/esp-hci/include/esp_nimble_hci.h" -# endif -#else -# include "nimble/nimble/controller/include/controller/ble_phy.h" -#endif +#include "esp_err.h" +#include "esp_bt.h" +#include "nvs_flash.h" +#include "esp_nimble_hci.h" +#include "nimble/nimble_port.h" +#include "nimble/nimble_port_freertos.h" +#include "host/ble_hs.h" +#include "host/ble_hs_pvcy.h" +#include "host/util/util.h" +#include "services/gap/ble_svc_gap.h" +#include "services/gatt/ble_svc_gatt.h" -#ifndef CONFIG_NIMBLE_CPP_IDF -# include "nimble/porting/nimble/include/nimble/nimble_port.h" -# include "nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h" -# include "nimble/nimble/host/include/host/ble_hs.h" -# include "nimble/nimble/host/include/host/ble_hs_pvcy.h" -# include "nimble/nimble/host/util/include/host/util/util.h" -# include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h" -# include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" -#endif - -#if defined(ESP_PLATFORM) && defined(CONFIG_ENABLE_ARDUINO_DEPENDS) -# include "esp32-hal-bt.h" +#ifdef CONFIG_ENABLE_ARDUINO_DEPENDS +#include "esp32-hal-bt.h" #endif #include "NimBLELog.h" @@ -81,10 +63,9 @@ std::list NimBLEDevice::m_ignoreList; std::vector NimBLEDevice::m_whiteList; NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr; uint8_t NimBLEDevice::m_own_addr_type = BLE_OWN_ADDR_PUBLIC; -#ifdef ESP_PLATFORM uint16_t NimBLEDevice::m_scanDuplicateSize = CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE; uint8_t NimBLEDevice::m_scanFilterMode = CONFIG_BTDM_SCAN_DUPL_TYPE; -#endif + /** * @brief Create a new instance of a server. @@ -149,8 +130,7 @@ void NimBLEDevice::stopAdvertising() { * try and release/delete it. */ #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) -/* STATIC */ -NimBLEScan* NimBLEDevice::getScan() { +/* STATIC */ NimBLEScan* NimBLEDevice::getScan() { if (m_pScan == nullptr) { m_pScan = new NimBLEScan(); } @@ -167,8 +147,7 @@ NimBLEScan* NimBLEDevice::getScan() { * @return A reference to the new client object. */ #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) -/* STATIC */ -NimBLEClient* NimBLEDevice::createClient(NimBLEAddress peerAddress) { +/* STATIC */ NimBLEClient* NimBLEDevice::createClient(NimBLEAddress peerAddress) { if(m_cList.size() >= NIMBLE_MAX_CONNECTIONS) { NIMBLE_LOGW(LOG_TAG,"Number of clients exceeds Max connections. Cur=%d Max=%d", m_cList.size(), NIMBLE_MAX_CONNECTIONS); @@ -186,8 +165,7 @@ NimBLEClient* NimBLEDevice::createClient(NimBLEAddress peerAddress) { * Checks if it is connected or trying to connect and disconnects/stops it first. * @param [in] pClient A pointer to the client object. */ -/* STATIC */ -bool NimBLEDevice::deleteClient(NimBLEClient* pClient) { +/* STATIC */ bool NimBLEDevice::deleteClient(NimBLEClient* pClient) { if(pClient == nullptr) { return false; } @@ -231,8 +209,7 @@ bool NimBLEDevice::deleteClient(NimBLEClient* pClient) { * @brief Get the list of created client objects. * @return A pointer to the list of clients. */ -/* STATIC */ -std::list* NimBLEDevice::getClientList() { +/* STATIC */std::list* NimBLEDevice::getClientList() { return &m_cList; } // getClientList @@ -241,8 +218,7 @@ std::list* NimBLEDevice::getClientList() { * @brief Get the number of created client objects. * @return Number of client objects created. */ -/* STATIC */ -size_t NimBLEDevice::getClientListSize() { +/* STATIC */size_t NimBLEDevice::getClientListSize() { return m_cList.size(); } // getClientList @@ -252,8 +228,7 @@ size_t NimBLEDevice::getClientListSize() { * @param [in] conn_id The client connection ID to search for. * @return A pointer to the client object with the spcified connection ID. */ -/* STATIC */ -NimBLEClient* NimBLEDevice::getClientByID(uint16_t conn_id) { +/* STATIC */NimBLEClient* NimBLEDevice::getClientByID(uint16_t conn_id) { for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) { if((*it)->getConnId() == conn_id) { return (*it); @@ -269,8 +244,7 @@ NimBLEClient* NimBLEDevice::getClientByID(uint16_t conn_id) { * @param [in] peer_addr The address of the peer to search for. * @return A pointer to the client object with the peer address. */ -/* STATIC */ -NimBLEClient* NimBLEDevice::getClientByPeerAddress(const NimBLEAddress &peer_addr) { +/* STATIC */NimBLEClient* NimBLEDevice::getClientByPeerAddress(const NimBLEAddress &peer_addr) { for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) { if((*it)->getPeerAddress().equals(peer_addr)) { return (*it); @@ -284,8 +258,7 @@ NimBLEClient* NimBLEDevice::getClientByPeerAddress(const NimBLEAddress &peer_add * @brief Finds the first disconnected client in the list. * @return A pointer to the first client object that is not connected to a peer. */ -/* STATIC */ -NimBLEClient* NimBLEDevice::getDisconnectedClient() { +/* STATIC */NimBLEClient* NimBLEDevice::getDisconnectedClient() { for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) { if(!(*it)->isConnected()) { return (*it); @@ -296,7 +269,7 @@ NimBLEClient* NimBLEDevice::getDisconnectedClient() { #endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) -#ifdef ESP_PLATFORM + /** * @brief Set the transmission power. * @param [in] powerLevel The power level to set, can be one of: @@ -322,15 +295,12 @@ NimBLEClient* NimBLEDevice::getDisconnectedClient() { * * ESP_BLE_PWR_TYPE_SCAN = 10, For scan * * ESP_BLE_PWR_TYPE_DEFAULT = 11, For default, if not set other, it will use default value */ -/* STATIC */ -void NimBLEDevice::setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType) { +/* STATIC */ void NimBLEDevice::setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType) { NIMBLE_LOGD(LOG_TAG, ">> setPower: %d (type: %d)", powerLevel, powerType); - esp_err_t errRc = esp_ble_tx_power_set(powerType, powerLevel); if (errRc != ESP_OK) { NIMBLE_LOGE(LOG_TAG, "esp_ble_tx_power_set: rc=%d", errRc); } - NIMBLE_LOGD(LOG_TAG, "<< setPower"); } // setPower @@ -352,8 +322,9 @@ void NimBLEDevice::setPower(esp_power_level_t powerLevel, esp_ble_power_type_t p * * ESP_BLE_PWR_TYPE_DEFAULT = 11, For default, if not set other, it will use default value * @return the power level currently used by the type specified. */ -/* STATIC */ -int NimBLEDevice::getPower(esp_ble_power_type_t powerType) { + +/* STATIC */ int NimBLEDevice::getPower(esp_ble_power_type_t powerType) { + switch(esp_ble_tx_power_get(powerType)) { case ESP_PWR_LVL_N12: return -12; @@ -376,25 +347,13 @@ int NimBLEDevice::getPower(esp_ble_power_type_t powerType) { } } // getPower -#else - -void NimBLEDevice::setPower(int dbm) { - ble_phy_txpwr_set(dbm); -} - - -int NimBLEDevice::getPower() { - return ble_phy_txpwr_get(); -} -#endif /** * @brief Get our device address. * @return A NimBLEAddress object of our public address if we have one, * if not then our current random address. */ -/* STATIC*/ -NimBLEAddress NimBLEDevice::getAddress() { +/* STATIC*/ NimBLEAddress NimBLEDevice::getAddress() { ble_addr_t addr = {BLE_ADDR_PUBLIC, 0}; if(BLE_HS_ENOADDR == ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL)) { @@ -411,8 +370,7 @@ NimBLEAddress NimBLEDevice::getAddress() { * @brief Return a string representation of the address of this device. * @return A string representation of this device address. */ -/* STATIC */ -std::string NimBLEDevice::toString() { +/* STATIC */ std::string NimBLEDevice::toString() { return getAddress().toString(); } // toString @@ -422,8 +380,7 @@ std::string NimBLEDevice::toString() { * @param [in] mtu Value to set local mtu: * * This should be larger than 23 and lower or equal to BLE_ATT_MTU_MAX = 527. */ -/* STATIC */ -int NimBLEDevice::setMTU(uint16_t mtu) { +/* STATIC */int NimBLEDevice::setMTU(uint16_t mtu) { NIMBLE_LOGD(LOG_TAG, ">> setLocalMTU: %d", mtu); int rc = ble_att_set_preferred_mtu(mtu); @@ -441,13 +398,11 @@ int NimBLEDevice::setMTU(uint16_t mtu) { * @brief Get local MTU value set. * @return The current preferred MTU setting. */ -/* STATIC */ -uint16_t NimBLEDevice::getMTU() { +/* STATIC */uint16_t NimBLEDevice::getMTU() { return ble_att_preferred_mtu(); } -#ifdef ESP_PLATFORM /** * @brief Set the duplicate filter cache size for filtering scanned devices. * @param [in] cacheSize The number of advertisements filtered before the cache is reset.\n @@ -493,7 +448,6 @@ void NimBLEDevice::setScanFilterMode(uint8_t mode) { m_scanFilterMode = mode; } -#endif #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) /** @@ -516,7 +470,7 @@ int NimBLEDevice::getNumBonds() { /** * @brief Deletes all bonding information. */ -/*STATIC*/ + /*STATIC*/ void NimBLEDevice::deleteAllBonds() { ble_store_clear(); } @@ -596,7 +550,6 @@ NimBLEAddress NimBLEDevice::getBondedAddress(int index) { * @param [in] address The address to check for in the whitelist. * @returns true if the address is in the whitelist. */ -/*STATIC*/ bool NimBLEDevice::onWhiteList(const NimBLEAddress & address) { for (auto &it : m_whiteList) { if (it == address) { @@ -613,7 +566,6 @@ bool NimBLEDevice::onWhiteList(const NimBLEAddress & address) { * @param [in] address The address to add to the whitelist. * @returns true if successful. */ -/*STATIC*/ bool NimBLEDevice::whiteListAdd(const NimBLEAddress & address) { if (NimBLEDevice::onWhiteList(address)) { return true; @@ -645,7 +597,6 @@ bool NimBLEDevice::whiteListAdd(const NimBLEAddress & address) { * @param [in] address The address to remove from the whitelist. * @returns true if successful. */ -/*STATIC*/ bool NimBLEDevice::whiteListRemove(const NimBLEAddress & address) { if (!NimBLEDevice::onWhiteList(address)) { return true; @@ -685,7 +636,6 @@ bool NimBLEDevice::whiteListRemove(const NimBLEAddress & address) { * @brief Gets the count of addresses in the whitelist. * @returns The number of addresses in the whitelist. */ -/*STATIC*/ size_t NimBLEDevice::getWhiteListCount() { return m_whiteList.size(); } @@ -696,7 +646,6 @@ size_t NimBLEDevice::getWhiteListCount() { * @param [in] index The vector index to retrieve the address from. * @returns the NimBLEAddress at the whitelist index or nullptr if not found. */ -/*STATIC*/ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) { if (index > m_whiteList.size()) { NIMBLE_LOGE(LOG_TAG, "Invalid index; %u", index); @@ -710,8 +659,7 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) { * @brief Host reset, we pass the message so we don't make calls until resynced. * @param [in] reason The reason code for the reset. */ -/* STATIC */ -void NimBLEDevice::onReset(int reason) +/* STATIC */ void NimBLEDevice::onReset(int reason) { if(!m_synced) { return; @@ -735,8 +683,7 @@ void NimBLEDevice::onReset(int reason) /** * @brief Host resynced with controller, all clear to make calls to the stack. */ -/* STATIC */ -void NimBLEDevice::onSync(void) +/* STATIC */ void NimBLEDevice::onSync(void) { NIMBLE_LOGI(LOG_TAG, "NimBle host synced."); // This check is needed due to potentially being called multiple times in succession @@ -749,14 +696,6 @@ void NimBLEDevice::onSync(void) int rc = ble_hs_util_ensure_addr(0); assert(rc == 0); -#ifndef ESP_PLATFORM - rc = ble_hs_id_infer_auto(m_own_addr_type, &m_own_addr_type); - if (rc != 0) { - NIMBLE_LOGE(LOG_TAG, "error determining address type; rc=%d", rc); - return; - } -#endif - // Yield for houskeeping before returning to operations. // Occasionally triggers exception without. taskYIELD(); @@ -782,11 +721,9 @@ void NimBLEDevice::onSync(void) /** * @brief The main host task. */ -/* STATIC */ -void NimBLEDevice::host_task(void *param) +/* STATIC */ void NimBLEDevice::host_task(void *param) { NIMBLE_LOGI(LOG_TAG, "BLE Host Task Started"); - /* This function will return only when nimble_port_stop() is executed */ nimble_port_run(); @@ -798,11 +735,9 @@ void NimBLEDevice::host_task(void *param) * @brief Initialize the %BLE environment. * @param [in] deviceName The device name of the device. */ -/* STATIC */ -void NimBLEDevice::init(const std::string &deviceName) { +/* STATIC */ void NimBLEDevice::init(const std::string &deviceName) { if(!initialized){ int rc=0; -#ifdef ESP_PLATFORM esp_err_t errRc = ESP_OK; #ifdef CONFIG_ENABLE_ARDUINO_DEPENDS @@ -834,7 +769,6 @@ void NimBLEDevice::init(const std::string &deviceName) { ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg)); ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE)); ESP_ERROR_CHECK(esp_nimble_hci_init()); -#endif nimble_port_init(); // Setup callbacks for host events @@ -859,10 +793,9 @@ void NimBLEDevice::init(const std::string &deviceName) { nimble_port_freertos_init(NimBLEDevice::host_task); } - // Wait for host and controller to sync before returning and accepting new tasks while(!m_synced){ - taskYIELD(); + vTaskDelay(1 / portTICK_PERIOD_MS); } initialized = true; // Set the initialization flag to ensure we are only initialized once. @@ -874,17 +807,16 @@ void NimBLEDevice::init(const std::string &deviceName) { * @param [in] clearAll If true, deletes all server/advertising/scan/client objects after deinitializing. * @note If clearAll is true when called, any references to the created objects become invalid. */ -/* STATIC */ -void NimBLEDevice::deinit(bool clearAll) { +/* STATIC */ void NimBLEDevice::deinit(bool clearAll) { int ret = nimble_port_stop(); if (ret == 0) { nimble_port_deinit(); -#ifdef ESP_PLATFORM + ret = esp_nimble_hci_and_controller_deinit(); if (ret != ESP_OK) { NIMBLE_LOGE(LOG_TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret); } -#endif + initialized = false; m_synced = false; @@ -931,7 +863,6 @@ void NimBLEDevice::deinit(bool clearAll) { * @brief Check if the initialization is complete. * @return true if initialized. */ -/*STATIC*/ bool NimBLEDevice::getInitialized() { return initialized; } // getInitialized @@ -943,8 +874,7 @@ bool NimBLEDevice::getInitialized() { * @param mitm If true we are capable of man in the middle protection, false if not. * @param sc If true we will perform secure connection pairing, false we will use legacy pairing. */ -/*STATIC*/ -void NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc) { +/*STATIC*/ void NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc) { NIMBLE_LOGD(LOG_TAG, "Setting bonding: %d, mitm: %d, sc: %d",bonding,mitm,sc); ble_hs_cfg.sm_bonding = bonding; ble_hs_cfg.sm_mitm = mitm; @@ -961,8 +891,7 @@ void NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc) { * * 0x08 BLE_SM_PAIR_AUTHREQ_SC * * 0x10 BLE_SM_PAIR_AUTHREQ_KEYPRESS - not yet supported. */ -/*STATIC*/ -void NimBLEDevice::setSecurityAuth(uint8_t auth_req) { +/*STATIC*/void NimBLEDevice::setSecurityAuth(uint8_t auth_req) { NimBLEDevice::setSecurityAuth((auth_req & BLE_SM_PAIR_AUTHREQ_BOND)>0, (auth_req & BLE_SM_PAIR_AUTHREQ_MITM)>0, (auth_req & BLE_SM_PAIR_AUTHREQ_SC)>0); @@ -978,8 +907,7 @@ void NimBLEDevice::setSecurityAuth(uint8_t auth_req) { * * 0x03 BLE_HS_IO_NO_INPUT_OUTPUT NoInputNoOutput IO capability * * 0x04 BLE_HS_IO_KEYBOARD_DISPLAY KeyboardDisplay Only IO capability */ -/*STATIC*/ -void NimBLEDevice::setSecurityIOCap(uint8_t iocap) { +/*STATIC*/ void NimBLEDevice::setSecurityIOCap(uint8_t iocap) { ble_hs_cfg.sm_io_cap = iocap; } // setSecurityIOCap @@ -993,8 +921,7 @@ void NimBLEDevice::setSecurityIOCap(uint8_t iocap) { * * 0x04: BLE_SM_PAIR_KEY_DIST_SIGN * * 0x08: BLE_SM_PAIR_KEY_DIST_LINK */ -/*STATIC*/ -void NimBLEDevice::setSecurityInitKey(uint8_t init_key) { +/*STATIC*/void NimBLEDevice::setSecurityInitKey(uint8_t init_key) { ble_hs_cfg.sm_our_key_dist = init_key; } // setsSecurityInitKey @@ -1008,8 +935,7 @@ void NimBLEDevice::setSecurityInitKey(uint8_t init_key) { * * 0x04: BLE_SM_PAIR_KEY_DIST_SIGN * * 0x08: BLE_SM_PAIR_KEY_DIST_LINK */ -/*STATIC*/ -void NimBLEDevice::setSecurityRespKey(uint8_t resp_key) { +/*STATIC*/void NimBLEDevice::setSecurityRespKey(uint8_t resp_key) { ble_hs_cfg.sm_their_key_dist = resp_key; } // setsSecurityRespKey @@ -1018,8 +944,7 @@ void NimBLEDevice::setSecurityRespKey(uint8_t resp_key) { * @brief Set the passkey the server will ask for when pairing. * @param [in] pin The passkey to use. */ -/*STATIC*/ -void NimBLEDevice::setSecurityPasskey(uint32_t pin) { +/*STATIC*/void NimBLEDevice::setSecurityPasskey(uint32_t pin) { m_passkey = pin; } // setSecurityPasskey @@ -1028,8 +953,7 @@ void NimBLEDevice::setSecurityPasskey(uint32_t pin) { * @brief Get the current passkey used for pairing. * @return The current passkey. */ -/*STATIC*/ -uint32_t NimBLEDevice::getSecurityPasskey() { +/*STATIC*/uint32_t NimBLEDevice::getSecurityPasskey() { return m_passkey; } // getSecurityPasskey @@ -1039,13 +963,11 @@ uint32_t NimBLEDevice::getSecurityPasskey() { * @param [in] callbacks Pointer to NimBLESecurityCallbacks class * @deprecated For backward compatibility, New code should use client/server callback methods. */ -/*STATIC*/ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) { NimBLEDevice::m_securityCallbacks = callbacks; } // setSecurityCallbacks -#ifdef ESP_PLATFORM /** * @brief Set the own address type. * @param [in] own_addr_type Own Bluetooth Device address type.\n @@ -1056,7 +978,6 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) { * * 0x03: BLE_OWN_ADDR_RPA_RANDOM_DEFAULT * @param [in] useNRPA If true, and address type is random, uses a non-resolvable random address. */ -/*STATIC*/ void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) { m_own_addr_type = own_addr_type; switch (own_addr_type) { @@ -1080,15 +1001,18 @@ void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) { break; } } // setOwnAddrType -#endif + /** * @brief Start the connection securing and authorization for this connection. * @param conn_id The connection id of the peer device. * @returns NimBLE stack return code, 0 = success. */ -/* STATIC */ -int NimBLEDevice::startSecurity(uint16_t conn_id) { +/* STATIC */int NimBLEDevice::startSecurity(uint16_t conn_id) { + /* if(m_securityCallbacks != nullptr) { + m_securityCallbacks->onSecurityRequest(); + } + */ int rc = ble_gap_security_initiate(conn_id); if(rc != 0){ NIMBLE_LOGE(LOG_TAG, "ble_gap_security_initiate: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); @@ -1103,8 +1027,7 @@ int NimBLEDevice::startSecurity(uint16_t conn_id) { * @param [in] address The address to look for. * @return True if ignoring. */ -/*STATIC*/ -bool NimBLEDevice::isIgnored(const NimBLEAddress &address) { +/*STATIC*/ bool NimBLEDevice::isIgnored(const NimBLEAddress &address) { for(auto &it : m_ignoreList) { if(it.equals(address)){ return true; @@ -1119,8 +1042,7 @@ bool NimBLEDevice::isIgnored(const NimBLEAddress &address) { * @brief Add a device to the ignore list. * @param [in] address The address of the device we want to ignore. */ -/*STATIC*/ -void NimBLEDevice::addIgnored(const NimBLEAddress &address) { +/*STATIC*/ void NimBLEDevice::addIgnored(const NimBLEAddress &address) { m_ignoreList.push_back(address); } @@ -1129,8 +1051,7 @@ void NimBLEDevice::addIgnored(const NimBLEAddress &address) { * @brief Remove a device from the ignore list. * @param [in] address The address of the device we want to remove from the list. */ -/*STATIC*/ -void NimBLEDevice::removeIgnored(const NimBLEAddress &address) { +/*STATIC*/void NimBLEDevice::removeIgnored(const NimBLEAddress &address) { for(auto it = m_ignoreList.begin(); it != m_ignoreList.end(); ++it) { if((*it).equals(address)){ m_ignoreList.erase(it); @@ -1144,7 +1065,6 @@ void NimBLEDevice::removeIgnored(const NimBLEAddress &address) { * @brief Set a custom callback for gap events. * @param [in] handler The function to call when gap events occur. */ -/*STATIC*/ void NimBLEDevice::setCustomGapHandler(gap_event_handler handler) { m_customGapHandler = handler; int rc = ble_gap_event_listener_register(&m_listener, m_customGapHandler, NULL); @@ -1156,4 +1076,5 @@ void NimBLEDevice::setCustomGapHandler(gap_event_handler handler) { } } // setCustomGapHandler + #endif // CONFIG_BT_ENABLED diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.h index 94ad29478..08a042fc2 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.h @@ -14,9 +14,10 @@ #ifndef MAIN_NIMBLEDEVICE_H_ #define MAIN_NIMBLEDEVICE_H_ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #include "NimBLEScan.h" @@ -38,9 +39,7 @@ #include "NimBLESecurity.h" #include "NimBLEAddress.h" -#ifdef ESP_PLATFORM -# include "esp_bt.h" -#endif +#include "esp_bt.h" #include #include @@ -111,17 +110,8 @@ public: static NimBLEServer* getServer(); #endif -#ifdef ESP_PLATFORM static void setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT); static int getPower(esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT); - static void setOwnAddrType(uint8_t own_addr_type, bool useNRPA=false); - static void setScanDuplicateCacheSize(uint16_t cacheSize); - static void setScanFilterMode(uint8_t type); -#else - static void setPower(int dbm); - static int getPower(); -#endif - static void setCustomGapHandler(gap_event_handler handler); static void setSecurityAuth(bool bonding, bool mitm, bool sc); static void setSecurityAuth(uint8_t auth_req); @@ -131,12 +121,15 @@ public: static void setSecurityPasskey(uint32_t pin); static uint32_t getSecurityPasskey(); static void setSecurityCallbacks(NimBLESecurityCallbacks* pCallbacks); + static void setOwnAddrType(uint8_t own_addr_type, bool useNRPA=false); static int startSecurity(uint16_t conn_id); static int setMTU(uint16_t mtu); static uint16_t getMTU(); static bool isIgnored(const NimBLEAddress &address); static void addIgnored(const NimBLEAddress &address); static void removeIgnored(const NimBLEAddress &address); + static void setScanDuplicateCacheSize(uint16_t cacheSize); + static void setScanFilterMode(uint8_t type); #if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) static NimBLEAdvertising* getAdvertising(); @@ -206,10 +199,8 @@ private: static ble_gap_event_listener m_listener; static gap_event_handler m_customGapHandler; static uint8_t m_own_addr_type; -#ifdef ESP_PLATFORM static uint16_t m_scanDuplicateSize; static uint8_t m_scanFilterMode; -#endif static std::vector m_whiteList; }; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp index 255131c02..a07294265 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp @@ -11,14 +11,12 @@ * Created on: Mar 12, 2018 * Author: pcbreflux */ - -#include "nimconfig.h" +#include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) #include "NimBLEEddystoneTLM.h" #include "NimBLELog.h" -#include #include #define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00)>>8) + (((x)&0xFF)<<8)) @@ -126,30 +124,30 @@ std::string NimBLEEddystoneTLM::toString() { out += " C\n"; out += "Adv. Count "; - snprintf(val, sizeof(val), "%" PRIu32, ENDIAN_CHANGE_U32(m_eddystoneData.advCount)); + snprintf(val, sizeof(val), "%d", ENDIAN_CHANGE_U32(m_eddystoneData.advCount)); out += val; out += "\n"; out += "Time in seconds "; - snprintf(val, sizeof(val), "%" PRIu32, rawsec/10); + snprintf(val, sizeof(val), "%d", rawsec/10); out += val; out += "\n"; out += "Time "; - snprintf(val, sizeof(val), "%04" PRIu32, rawsec / 864000); + snprintf(val, sizeof(val), "%04d", rawsec / 864000); out += val; out += "."; - snprintf(val, sizeof(val), "%02" PRIu32, (rawsec / 36000) % 24); + snprintf(val, sizeof(val), "%02d", (rawsec / 36000) % 24); out += val; out += ":"; - snprintf(val, sizeof(val), "%02" PRIu32, (rawsec / 600) % 60); + snprintf(val, sizeof(val), "%02d", (rawsec / 600) % 60); out += val; out += ":"; - snprintf(val, sizeof(val), "%02" PRIu32, (rawsec / 10) % 60); + snprintf(val, sizeof(val), "%02d", (rawsec / 10) % 60); out += val; out += "\n"; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.h index 265c81b45..eb1cb0721 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.h @@ -14,7 +14,6 @@ #ifndef _NimBLEEddystoneTLM_H_ #define _NimBLEEddystoneTLM_H_ - #include "NimBLEUUID.h" #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp index 424df958e..7c3194c28 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp @@ -11,7 +11,7 @@ * Created on: Mar 12, 2018 * Author: pcbreflux */ -#include "nimconfig.h" +#include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) #include "NimBLEEddystoneURL.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.cpp index 78c8fea3c..37d0f52f5 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.cpp @@ -11,9 +11,11 @@ * Created on: Jan 03, 2018 * Author: chegewara */ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLEHIDDevice.h" #include "NimBLE2904.h" @@ -27,7 +29,7 @@ NimBLEHIDDevice::NimBLEHIDDevice(NimBLEServer* server) { * Here we create mandatory services described in bluetooth specification */ m_deviceInfoService = server->createService(NimBLEUUID((uint16_t) 0x180a)); - m_hidService = server->createService(NimBLEUUID((uint16_t) 0x1812)); + m_hidService = server->createService(NimBLEUUID((uint16_t) 0x1812), 40); m_batteryService = server->createService(NimBLEUUID((uint16_t) 0x180f)); /* @@ -245,4 +247,5 @@ NimBLEService* NimBLEHIDDevice::batteryService() { return m_batteryService; } -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif // #if defined(CONFIG_BT_ENABLED) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.h index ef2ed7395..6ed7c2bde 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.h @@ -15,8 +15,11 @@ #ifndef _BLEHIDDEVICE_H_ #define _BLEHIDDEVICE_H_ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) + #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) +#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) #include "NimBLECharacteristic.h" #include "NimBLEService.h" @@ -81,6 +84,6 @@ private: NimBLECharacteristic* m_protocolModeCharacteristic; //0x2a4e NimBLECharacteristic* m_batteryLevelCharacteristic; //0x2a19 }; - -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER */ +#endif // CONFIG_BT_NIMBLE_ROLE_BROADCASTER +#endif // CONFIG_BT_ENABLED #endif /* _BLEHIDDEVICE_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLELog.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLELog.h index 0cedca940..b76f1dc2d 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLELog.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLELog.h @@ -12,7 +12,49 @@ #if defined(CONFIG_BT_ENABLED) -#if defined(CONFIG_NIMBLE_CPP_IDF) // using esp-idf +#ifdef ARDUINO_ARCH_ESP32 +#include "syscfg/syscfg.h" +#include "modlog/modlog.h" + +// If Arduino is being used, strip out the colors and ignore log printing below ui setting. +// Note: because CONFIG_LOG_DEFAULT_LEVEL is set at ERROR in Arduino we must use MODLOG_DFLT(ERROR +// otherwise no messages will be printed above that level. + +#ifndef CONFIG_NIMBLE_CPP_DEBUG_LEVEL + #ifdef CORE_DEBUG_LEVEL + #define CONFIG_NIMBLE_CPP_DEBUG_LEVEL CORE_DEBUG_LEVEL + #else + #define CONFIG_NIMBLE_CPP_DEBUG_LEVEL 0 + #endif +#endif + +#if CONFIG_NIMBLE_CPP_DEBUG_LEVEL >= 4 +#define NIMBLE_LOGD( tag, format, ... ) MODLOG_DFLT(ERROR, "D %s: "#format"\n",tag,##__VA_ARGS__) +#else +#define NIMBLE_LOGD( tag, format, ... ) (void)tag +#endif + +#if CONFIG_NIMBLE_CPP_DEBUG_LEVEL >= 3 +#define NIMBLE_LOGI( tag, format, ... ) MODLOG_DFLT(ERROR, "I %s: "#format"\n",tag,##__VA_ARGS__) +#else +#define NIMBLE_LOGI( tag, format, ... ) (void)tag +#endif + +#if CONFIG_NIMBLE_CPP_DEBUG_LEVEL >= 2 +#define NIMBLE_LOGW( tag, format, ... ) MODLOG_DFLT(ERROR, "W %s: "#format"\n",tag,##__VA_ARGS__) +#else +#define NIMBLE_LOGW( tag, format, ... ) (void)tag +#endif + +#if CONFIG_NIMBLE_CPP_DEBUG_LEVEL >= 1 +#define NIMBLE_LOGE( tag, format, ... ) MODLOG_DFLT(ERROR, "E %s: "#format"\n",tag,##__VA_ARGS__) +#else +#define NIMBLE_LOGE( tag, format, ... ) (void)tag +#endif + +#define NIMBLE_LOGC( tag, format, ... ) MODLOG_DFLT(CRITICAL, "CRIT %s: "#format"\n",tag,##__VA_ARGS__) + +#else #include "esp_log.h" @@ -22,51 +64,7 @@ #define NIMBLE_LOGD(tag, format, ...) ESP_LOGD(tag, format, ##__VA_ARGS__) #define NIMBLE_LOGC(tag, format, ...) ESP_LOGE(tag, format, ##__VA_ARGS__) -#else // using Arduino +#endif /*ARDUINO_ARCH_ESP32*/ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/console/console.h" - -// If Arduino is being used, strip out the colors and ignore log printing below ui setting. -// Note: because CONFIG_LOG_DEFAULT_LEVEL is set at ERROR in Arduino we must use MODLOG_DFLT(ERROR -// otherwise no messages will be printed above that level. - -#ifndef NIMBLE_CPP_DEBUG_LEVEL - #if defined(ARDUINO_ARCH_ESP32) && defined(CORE_DEBUG_LEVEL) - #define NIMBLE_CPP_DEBUG_LEVEL CORE_DEBUG_LEVEL - #else - #define NIMBLE_CPP_DEBUG_LEVEL 0 - #endif -#endif - -#if NIMBLE_CPP_DEBUG_LEVEL >= 4 -#define NIMBLE_LOGD( tag, format, ... ) console_printf("D %s: "#format"\n",tag,##__VA_ARGS__) -#else -#define NIMBLE_LOGD( tag, format, ... ) (void)tag -#endif - -#if NIMBLE_CPP_DEBUG_LEVEL >= 3 -#define NIMBLE_LOGI( tag, format, ... ) console_printf("I %s: "#format"\n",tag,##__VA_ARGS__) -#else -#define NIMBLE_LOGI( tag, format, ... ) (void)tag -#endif - -#if NIMBLE_CPP_DEBUG_LEVEL >= 2 -#define NIMBLE_LOGW( tag, format, ... ) console_printf("W %s: "#format"\n",tag,##__VA_ARGS__) -#else -#define NIMBLE_LOGW( tag, format, ... ) (void)tag -#endif - -#if NIMBLE_CPP_DEBUG_LEVEL >= 1 -#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 -#define NIMBLE_LOGE( tag, format, ... ) (void)tag -#define NIMBLE_LOGC( tag, format, ... ) (void)tag -#endif - - - -#endif /* CONFIG_NIMBLE_CPP_IDF */ -#endif /* CONFIG_BT_ENABLED */ -#endif /* MAIN_NIMBLELOG_H_ */ +#endif /*CONFIG_BT_ENABLED*/ +#endif /*MAIN_NIMBLELOG_H_*/ \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp index de5040672..3b7e1ccfc 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp @@ -12,8 +12,11 @@ * Author: kolban */ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) + #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLERemoteCharacteristic.h" #include "NimBLEUtils.h" @@ -57,6 +60,7 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic"; m_pRemoteService = pRemoteService; m_notifyCallback = nullptr; m_timestamp = 0; + m_valMux = portMUX_INITIALIZER_UNLOCKED; NIMBLE_LOGD(LOG_TAG, "<< NimBLERemoteCharacteristic(): %s", m_uuid.toString().c_str()); } // NimBLERemoteCharacteristic @@ -237,7 +241,8 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filt } int rc = 0; - ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr}; + TaskHandle_t cur_task = xTaskGetCurrentTaskHandle(); + ble_task_data_t taskData = {this, cur_task, 0, nullptr}; // If we don't know the end handle of this characteristic retrieve the next one in the service // The end handle is the next characteristic definition handle -1. @@ -252,6 +257,10 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filt return false; } +#ifdef ulTaskNotifyValueClear + // Clear the task notification value to ensure we block + ulTaskNotifyValueClear(cur_task, ULONG_MAX); +#endif ulTaskNotifyTake(pdTRUE, portMAX_DELAY); if (taskData.rc != 0) { @@ -273,6 +282,10 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filt return false; } +#ifdef ulTaskNotifyValueClear + // Clear the task notification value to ensure we block + ulTaskNotifyValueClear(cur_task, ULONG_MAX); +#endif ulTaskNotifyTake(pdTRUE, portMAX_DELAY); if (taskData.rc != 0) { @@ -404,12 +417,12 @@ NimBLEUUID NimBLERemoteCharacteristic::getUUID() { * @return The value of the remote characteristic. */ std::string NimBLERemoteCharacteristic::getValue(time_t *timestamp) { - ble_npl_hw_enter_critical(); + portENTER_CRITICAL(&m_valMux); std::string value = m_value; if(timestamp != nullptr) { *timestamp = m_timestamp; } - ble_npl_hw_exit_critical(0); + portEXIT_CRITICAL(&m_valMux); return value; } @@ -473,7 +486,8 @@ std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) { int rc = 0; int retryCount = 1; - ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(),0, &value}; + TaskHandle_t cur_task = xTaskGetCurrentTaskHandle(); + ble_task_data_t taskData = {this, cur_task, 0, &value}; do { rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0, @@ -485,6 +499,10 @@ std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) { return value; } +#ifdef ulTaskNotifyValueClear + // Clear the task notification value to ensure we block + ulTaskNotifyValueClear(cur_task, ULONG_MAX); +#endif ulTaskNotifyTake(pdTRUE, portMAX_DELAY); rc = taskData.rc; @@ -511,13 +529,13 @@ std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) { } while(rc != 0 && retryCount--); time_t t = time(nullptr); - ble_npl_hw_enter_critical(); + portENTER_CRITICAL(&m_valMux); m_value = value; m_timestamp = t; if(timestamp != nullptr) { *timestamp = m_timestamp; } - ble_npl_hw_exit_critical(0); + portEXIT_CRITICAL(&m_valMux); NIMBLE_LOGD(LOG_TAG, "<< readValue length: %d rc=%d", value.length(), rc); return value; @@ -547,11 +565,12 @@ int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle, if(rc == 0) { if(attr) { - if(((*strBuf).length() + attr->om->om_len) > BLE_ATT_ATTR_MAX_LEN) { + uint32_t data_len = OS_MBUF_PKTLEN(attr->om); + if(((*strBuf).length() + data_len) > BLE_ATT_ATTR_MAX_LEN) { rc = BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } else { - NIMBLE_LOGD(LOG_TAG, "Got %d bytes", attr->om->om_len); - (*strBuf) += std::string((char*) attr->om->om_data, attr->om->om_len); + NIMBLE_LOGD(LOG_TAG, "Got %d bytes", data_len); + (*strBuf) += std::string((char*) attr->om->om_data, data_len); return 0; } } @@ -741,7 +760,8 @@ bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length, return (rc==0); } - ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr}; + TaskHandle_t cur_task = xTaskGetCurrentTaskHandle(); + ble_task_data_t taskData = {this, cur_task, 0, nullptr}; do { if(length > mtu) { @@ -761,6 +781,10 @@ bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length, return false; } +#ifdef ulTaskNotifyValueClear + // Clear the task notification value to ensure we block + ulTaskNotifyValueClear(cur_task, ULONG_MAX); +#endif ulTaskNotifyTake(pdTRUE, portMAX_DELAY); rc = taskData.rc; @@ -815,4 +839,6 @@ int NimBLERemoteCharacteristic::onWriteCB(uint16_t conn_handle, return 0; } -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ + +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#endif /* CONFIG_BT_ENABLED */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h index 41ae816d4..39e6d40fa 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h @@ -14,9 +14,11 @@ #ifndef COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ #define COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLERemoteService.h" #include "NimBLERemoteDescriptor.h" @@ -159,10 +161,12 @@ private: std::string m_value; notify_callback m_notifyCallback; time_t m_timestamp; + portMUX_TYPE m_valMux; // We maintain a vector of descriptors owned by this characteristic. std::vector m_descriptorVector; }; // NimBLERemoteCharacteristic -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp index 44b559000..887dab667 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp @@ -11,9 +11,11 @@ * Created on: Jul 8, 2017 * Author: kolban */ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLERemoteDescriptor.h" #include "NimBLEUtils.h" @@ -137,7 +139,8 @@ std::string NimBLERemoteDescriptor::readValue() { int rc = 0; int retryCount = 1; - ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(),0, &value}; + TaskHandle_t cur_task = xTaskGetCurrentTaskHandle(); + ble_task_data_t taskData = {this, cur_task, 0, &value}; do { rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0, @@ -149,6 +152,10 @@ std::string NimBLERemoteDescriptor::readValue() { return value; } +#ifdef ulTaskNotifyValueClear + // Clear the task notification value to ensure we block + ulTaskNotifyValueClear(cur_task, ULONG_MAX); +#endif ulTaskNotifyTake(pdTRUE, portMAX_DELAY); rc = taskData.rc; @@ -186,7 +193,6 @@ int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg) { - (void)attr; ble_task_data_t *pTaskData = (ble_task_data_t*)arg; NimBLERemoteDescriptor* desc = (NimBLERemoteDescriptor*)pTaskData->pATT; uint16_t conn_id = desc->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId(); @@ -202,11 +208,12 @@ int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle, if(rc == 0) { if(attr) { - if(((*strBuf).length() + attr->om->om_len) > BLE_ATT_ATTR_MAX_LEN) { + uint32_t data_len = OS_MBUF_PKTLEN(attr->om); + if(((*strBuf).length() + data_len) > BLE_ATT_ATTR_MAX_LEN) { rc = BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } else { - NIMBLE_LOGD(LOG_TAG, "Got %d bytes", attr->om->om_len); - (*strBuf) += std::string((char*) attr->om->om_data, attr->om->om_len); + NIMBLE_LOGD(LOG_TAG, "Got %d bytes", data_len); + (*strBuf) += std::string((char*) attr->om->om_data, data_len); return 0; } } @@ -288,7 +295,8 @@ bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool return (rc == 0); } - ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr}; + TaskHandle_t cur_task = xTaskGetCurrentTaskHandle(); + ble_task_data_t taskData = {this, cur_task, 0, nullptr}; do { if(length > mtu) { @@ -309,6 +317,10 @@ bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool return false; } +#ifdef ulTaskNotifyValueClear + // Clear the task notification value to ensure we block + ulTaskNotifyValueClear(cur_task, ULONG_MAX); +#endif ulTaskNotifyTake(pdTRUE, portMAX_DELAY); rc = taskData.rc; @@ -349,4 +361,5 @@ bool NimBLERemoteDescriptor::writeValue(const std::string &newValue, bool respon return writeValue((uint8_t*) newValue.data(), newValue.length(), response); } // writeValue -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#endif /* CONFIG_BT_ENABLED */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.h index 13e83516d..b52738ef7 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.h @@ -14,9 +14,11 @@ #ifndef COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ #define COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLERemoteCharacteristic.h" @@ -79,5 +81,6 @@ private: NimBLERemoteCharacteristic* m_pRemoteCharacteristic; }; -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.cpp index b8ae4fce5..6557369df 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.cpp @@ -11,9 +11,11 @@ * Created on: Jul 8, 2017 * Author: kolban */ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLERemoteService.h" #include "NimBLEUtils.h" @@ -196,7 +198,8 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter) NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics() for service: %s", getUUID().toString().c_str()); int rc = 0; - ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr}; + TaskHandle_t cur_task = xTaskGetCurrentTaskHandle(); + ble_task_data_t taskData = {this, cur_task, 0, nullptr}; if(uuid_filter == nullptr) { rc = ble_gattc_disc_all_chrs(m_pClient->getConnId(), @@ -218,6 +221,10 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter) return false; } +#ifdef ulTaskNotifyValueClear + // Clear the task notification value to ensure we block + ulTaskNotifyValueClear(cur_task, ULONG_MAX); +#endif ulTaskNotifyTake(pdTRUE, portMAX_DELAY); if(taskData.rc == 0){ @@ -384,4 +391,6 @@ std::string NimBLERemoteService::toString() { return res; } // toString -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ + +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#endif /* CONFIG_BT_ENABLED */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.h index 0443cfd99..751c9effb 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.h @@ -14,9 +14,11 @@ #ifndef COMPONENTS_NIMBLEREMOTESERVICE_H_ #define COMPONENTS_NIMBLEREMOTESERVICE_H_ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLEClient.h" #include "NimBLEUUID.h" @@ -81,5 +83,6 @@ private: uint16_t m_endHandle; }; // NimBLERemoteService -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_NIMBLEREMOTESERVICE_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.cpp index d9dcb7de4..10c946a7e 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.cpp @@ -11,9 +11,11 @@ * Created on: Jul 1, 2017 * Author: kolban */ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #include "NimBLEScan.h" #include "NimBLEDevice.h" @@ -356,10 +358,15 @@ NimBLEScanResults NimBLEScan::start(uint32_t duration, bool is_continue) { NIMBLE_LOGW(LOG_TAG, "Blocking scan called with duration = forever"); } - ble_task_data_t taskData = {nullptr, xTaskGetCurrentTaskHandle(),0, nullptr}; + TaskHandle_t cur_task = xTaskGetCurrentTaskHandle(); + ble_task_data_t taskData = {nullptr, cur_task, 0, nullptr}; m_pTaskData = &taskData; if(start(duration, nullptr, is_continue)) { +#ifdef ulTaskNotifyValueClear + // Clear the task notification value to ensure we block + ulTaskNotifyValueClear(cur_task, ULONG_MAX); +#endif ulTaskNotifyTake(pdTRUE, portMAX_DELAY); } @@ -532,4 +539,5 @@ NimBLEAdvertisedDevice *NimBLEScanResults::getDevice(const NimBLEAddress &addres return nullptr; } -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_OBSERVER */ +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) +#endif /* CONFIG_BT_ENABLED */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.h index 76a114276..49d67c8ec 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.h @@ -13,18 +13,16 @@ */ #ifndef COMPONENTS_NIMBLE_SCAN_H_ #define COMPONENTS_NIMBLE_SCAN_H_ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #include "NimBLEAdvertisedDevice.h" #include "NimBLEUtils.h" -#if defined(CONFIG_NIMBLE_CPP_IDF) #include "host/ble_gap.h" -#else -#include "nimble/nimble/host/include/host/ble_gap.h" -#endif #include @@ -99,5 +97,6 @@ private: uint8_t m_maxResults; }; -#endif /* CONFIG_BT_ENABLED CONFIG_BT_NIMBLE_ROLE_OBSERVER */ +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) +#endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_NIMBLE_SCAN_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.cpp index df6d192b4..aa0629698 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.cpp @@ -12,7 +12,7 @@ * Author: chegewara */ -#include "nimconfig.h" +#include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) #include "NimBLESecurity.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.h index 157577d7b..5a7619f45 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.h @@ -14,16 +14,10 @@ #ifndef COMPONENTS_NIMBLESECURITY_H_ #define COMPONENTS_NIMBLESECURITY_H_ - -#include "nimconfig.h" +#include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) -#if defined(CONFIG_NIMBLE_CPP_IDF) #include "host/ble_gap.h" -#else -#include "nimble/nimble/host/include/host/ble_gap.h" -#endif - /**** FIX COMPILATION ****/ #undef min #undef max diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.cpp index e31c81b45..7206a1508 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.cpp @@ -12,20 +12,19 @@ * Author: kolban */ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) + #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLEServer.h" #include "NimBLEDevice.h" #include "NimBLELog.h" -#if defined(CONFIG_NIMBLE_CPP_IDF) #include "services/gap/ble_svc_gap.h" #include "services/gatt/ble_svc_gatt.h" -#else -#include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h" -#include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" -#endif + static const char* LOG_TAG = "NimBLEServer"; static NimBLEServerCallbacks defaultCallbacks; @@ -80,17 +79,18 @@ NimBLEService* NimBLEServer::createService(const char* uuid) { * to provide inst_id value different for each service. * @return A reference to the new service object. */ -NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid) { +NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numHandles, uint8_t inst_id) { NIMBLE_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str()); - + // TODO: add functionality to use inst_id for multiple services with same uuid + (void)inst_id; // Check that a service with the supplied UUID does not already exist. if(getServiceByUUID(uuid) != nullptr) { NIMBLE_LOGW(LOG_TAG, "Warning creating a duplicate service UUID: %s", std::string(uuid).c_str()); } - NimBLEService* pService = new NimBLEService(uuid); - m_svcVec.push_back(pService); + NimBLEService* pService = new NimBLEService(uuid, numHandles, this); + m_svcVec.push_back(pService); // Save a reference to this service being on this server. serviceChanged(); NIMBLE_LOGD(LOG_TAG, "<< createService"); @@ -181,7 +181,7 @@ void NimBLEServer::start() { abort(); } -#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && CORE_DEBUG_LEVEL >= 4) +#if CONFIG_NIMBLE_CPP_DEBUG_LEVEL >= 4 ble_gatts_show_local(); #endif /*** Future use *** @@ -734,7 +734,7 @@ void NimBLEServer::startAdvertising() { */ void NimBLEServer::stopAdvertising() { NimBLEDevice::stopAdvertising(); -} // stopAdvertising +} // startAdvertising /** @@ -772,30 +772,7 @@ void NimBLEServer::updateConnParams(uint16_t conn_handle, if(rc != 0) { NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc)); } -} // updateConnParams - - -/** - * @brief Request an update of the data packet length. - * * Can only be used after a connection has been established. - * @details Sends a data length update request to the peer. - * The Data Length Extension (DLE) allows to increase the Data Channel Payload from 27 bytes to up to 251 bytes. - * The peer needs to support the Bluetooth 4.2 specifications, to be capable of DLE. - * @param [in] conn_handle The connection handle of the peer to send the request to. - * @param [in] tx_octets The preferred number of payload octets to use (Range 0x001B-0x00FB). - */ -void NimBLEServer::setDataLen(uint16_t conn_handle, uint16_t tx_octets) { -#ifdef CONFIG_NIMBLE_CPP_IDF // not yet available in IDF, Sept 9 2021 - return; -#else - uint16_t tx_time = (tx_octets + 14) * 8; - - int rc = ble_gap_set_data_len(conn_handle, tx_octets, tx_time); - if(rc != 0) { - NIMBLE_LOGE(LOG_TAG, "Set data length error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc)); - } -#endif -} // setDataLen +}// updateConnParams bool NimBLEServer::setIndicateWait(uint16_t conn_handle) { @@ -865,4 +842,6 @@ bool NimBLEServerCallbacks::onConfirmPIN(uint32_t pin){ return true; } -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ + +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif // CONFIG_BT_ENABLED diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.h index 5054b844e..ebcf39f23 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.h @@ -14,9 +14,11 @@ #ifndef MAIN_NIMBLESERVER_H_ #define MAIN_NIMBLESERVER_H_ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #define NIMBLE_ATT_REMOVE_HIDE 1 #define NIMBLE_ATT_REMOVE_DELETE 2 @@ -41,7 +43,8 @@ class NimBLEServer { public: size_t getConnectedCount(); NimBLEService* createService(const char* uuid); - NimBLEService* createService(const NimBLEUUID &uuid); + NimBLEService* createService(const NimBLEUUID &uuid, uint32_t numHandles=15, + uint8_t inst_id=0); void removeService(NimBLEService* service, bool deleteSvc = false); void addService(NimBLEService* service); NimBLEAdvertising* getAdvertising(); @@ -58,7 +61,6 @@ public: void updateConnParams(uint16_t conn_handle, uint16_t minInterval, uint16_t maxInterval, uint16_t latency, uint16_t timeout); - void setDataLen(uint16_t conn_handle, uint16_t tx_octets); uint16_t getPeerMTU(uint16_t conn_id); std::vector getPeerDevices(); NimBLEConnInfo getPeerInfo(size_t index); @@ -166,5 +168,7 @@ public: virtual bool onConfirmPIN(uint32_t pin); }; // NimBLEServerCallbacks -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ + +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif /* CONFIG_BT_ENABLED */ #endif /* MAIN_NIMBLESERVER_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.cpp index 18e15bcbd..9c43e900c 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.cpp @@ -14,10 +14,12 @@ // A service is identified by a UUID. A service is also the container for one or more characteristics. -#include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) + +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) -#include "NimBLEDevice.h" #include "NimBLEService.h" #include "NimBLEUtils.h" #include "NimBLELog.h" @@ -32,19 +34,25 @@ static const char* LOG_TAG = "NimBLEService"; // Tag for logging. /** * @brief Construct an instance of the NimBLEService * @param [in] uuid The UUID of the service. + * @param [in] numHandles The maximum number of handles associated with the service. + * @param [in] pServer A pointer to the server instance that this service belongs to. */ -NimBLEService::NimBLEService(const char* uuid) -: NimBLEService(NimBLEUUID(uuid)) { +NimBLEService::NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer) +: NimBLEService(NimBLEUUID(uuid), numHandles, pServer) { } /** * @brief Construct an instance of the BLEService * @param [in] uuid The UUID of the service. + * @param [in] numHandles The maximum number of handles associated with the service. + * @param [in] pServer A pointer to the server instance that this service belongs to. */ -NimBLEService::NimBLEService(const NimBLEUUID &uuid) { +NimBLEService::NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer) { m_uuid = uuid; m_handle = NULL_HANDLE; + m_pServer = pServer; + m_numHandles = numHandles; m_pSvcDef = nullptr; m_removed = 0; @@ -421,7 +429,8 @@ std::string NimBLEService::toString() { * @return The BLEServer associated with this service. */ NimBLEServer* NimBLEService::getServer() { - return NimBLEDevice::getServer(); + return m_pServer; }// getServer -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif // CONFIG_BT_ENABLED diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.h index fbdd2e1bd..ebf913d32 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.h @@ -14,9 +14,11 @@ #ifndef MAIN_NIMBLESERVICE_H_ #define MAIN_NIMBLESERVICE_H_ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLEServer.h" #include "NimBLECharacteristic.h" @@ -34,8 +36,8 @@ class NimBLECharacteristic; class NimBLEService { public: - NimBLEService(const char* uuid); - NimBLEService(const NimBLEUUID &uuid); + NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer); + NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer); ~NimBLEService(); NimBLEServer* getServer(); @@ -74,12 +76,16 @@ private: friend class NimBLEDevice; uint16_t m_handle; + NimBLEServer* m_pServer; NimBLEUUID m_uuid; + uint16_t m_numHandles; ble_gatt_svc_def* m_pSvcDef; uint8_t m_removed; std::vector m_chrVec; }; // NimBLEService -#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ + +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif // CONFIG_BT_ENABLED #endif /* MAIN_NIMBLESERVICE_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.cpp index 4234650d8..9338d7d00 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.cpp @@ -11,8 +11,7 @@ * Created on: Jun 21, 2017 * Author: kolban */ - -#include "nimconfig.h" +#include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) #include "NimBLEUtils.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.h index 724db19fd..982f9c36d 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.h @@ -14,16 +14,10 @@ #ifndef COMPONENTS_NIMBLEUUID_H_ #define COMPONENTS_NIMBLEUUID_H_ - -#include "nimconfig.h" +#include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) -#if defined(CONFIG_NIMBLE_CPP_IDF) #include "host/ble_uuid.h" -#else -#include "nimble/nimble/host/include/host/ble_uuid.h" -#endif - /**** FIX COMPILATION ****/ #undef min #undef max diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.cpp index c6bd823ff..7a1f55b41 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.cpp @@ -6,13 +6,12 @@ * */ -#include "nimconfig.h" +#include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) #include "NimBLEUtils.h" #include "NimBLELog.h" - -#include +#include "nimconfig.h" static const char* LOG_TAG = "NimBLEUtils"; @@ -343,7 +342,6 @@ const char* NimBLEUtils::returnCodeToString(int rc) { return "Unknown"; } #else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT) - (void)rc; return ""; #endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT) } @@ -371,7 +369,6 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) { return "Unknown flag"; } #else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT) - (void)advType; return ""; #endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT) } // adFlagsToString @@ -419,11 +416,8 @@ char* NimBLEUtils::buildHexData(uint8_t* target, const uint8_t* source, uint8_t * @param [in] arg Unused. */ void NimBLEUtils::dumpGapEvent(ble_gap_event *event, void *arg){ - (void)arg; #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT) NIMBLE_LOGD(LOG_TAG, "Received a GAP event: %s", gapEventToString(event->type)); -#else - (void)event; #endif } @@ -510,7 +504,6 @@ const char* NimBLEUtils::gapEventToString(uint8_t eventType) { return "Unknown event type"; } #else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT) - (void)eventType; return ""; #endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT) } // gapEventToString diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.h index 2fe4b3c41..acbc93e72 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.h @@ -8,15 +8,10 @@ #ifndef COMPONENTS_NIMBLEUTILS_H_ #define COMPONENTS_NIMBLEUTILS_H_ - -#include "nimconfig.h" +#include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) -#if defined(CONFIG_NIMBLE_CPP_IDF) #include "host/ble_gap.h" -#else -#include "nimble/nimble/host/include/host/ble_gap.h" -#endif /**** FIX COMPILATION ****/ #undef min diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/README.md b/lib/libesp32_div/NimBLE-Arduino/src/README.md similarity index 90% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/README.md rename to lib/libesp32_div/NimBLE-Arduino/src/README.md index 37103be08..bbd17fc85 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/README.md +++ b/lib/libesp32_div/NimBLE-Arduino/src/README.md @@ -23,7 +23,7 @@ ## Overview -Apache NimBLE is an open-source Bluetooth 5.1 stack (both Host & Controller) +Apache NimBLE is an open-source Bluetooth 5.0 stack (both Host & Controller) that completely replaces the proprietary SoftDevice on Nordic chipsets. It is part of [Apache Mynewt project](https://github.com/apache/mynewt-core). @@ -33,6 +33,7 @@ Features highlight: - Support for up to 32 simultaneous connections. - Legacy and SC (secure connections) SMP support (pairing and bonding). - Advertising Extensions. + - Periodic Advertising. - Coded (aka Long Range) and 2M PHYs. - Bluetooth Mesh. @@ -83,24 +84,27 @@ There are also some sample applications that show how to Apache Mynewt NimBLE stack. These sample applications are located in the `apps/` directory of Apache Mynewt [repo](https://github.com/apache/mynewt-core). Some examples: -* [blecent](https://github.com/apache/mynewt-nimble/tree/master/apps/blecent): +* [blecent](https://github.com/apache/mynewt-core/tree/master/apps/blecent): A basic central device with no user interface. This application scans for a peripheral that supports the alert notification service (ANS). Upon discovering such a peripheral, blecent connects and performs a characteristic read, characteristic write, and notification subscription. -* [blehci](https://github.com/apache/mynewt-nimble/tree/master/apps/blehci): +* [blehci](https://github.com/apache/mynewt-core/tree/master/apps/blehci): Implements a BLE controller-only application. A separate host-only implementation, such as Linux's BlueZ, can interface with this application via HCI over UART. -* [bleprph](https://github.com/apache/mynewt-nimble/tree/master/apps/bleprph): An +* [bleprph](https://github.com/apache/mynewt-core/tree/master/apps/bleprph): An implementation of a minimal BLE peripheral. -* [btshell](https://github.com/apache/mynewt-nimble/tree/master/apps/btshell): A +* [btshell](https://github.com/apache/mynewt-core/tree/master/apps/btshell): A shell-like application allowing to configure and use most of NimBLE functionality from command line. * [bleuart](https://github.com/apache/mynewt-core/tree/master/apps/bleuart): Implements a simple BLE peripheral that supports the Nordic UART / Serial Port Emulation service (https://developer.nordicsemi.com/nRF5_SDK/nRF51_SDK_v8.x.x/doc/8.0.0/s110/html/a00072.html). +* [test](https://github.com/apache/mynewt-core/tree/master/apps/test): Test + project which can be compiled either with the simulator, or on a per-architecture basis. + Test will run all the package's unit tests. # Getting Help @@ -109,7 +113,7 @@ want to talk to a human about what you're working on, you can contact us via the [developers mailing list](mailto:dev@mynewt.apache.org). Although not a formal channel, you can also find a number of core developers -on the #mynewt channel on Freenode IRC or #general channel on [Mynewt Slack](https://mynewt.slack.com/join/shared_invite/enQtNjA1MTg0NzgyNzg3LTcyMmZiOGQzOGMxM2U4ODFmMTIwNjNmYTE5Y2UwYjQwZWIxNTE0MTUzY2JmMTEzOWFjYWZkNGM0YmM4MzAxNWQ) +on the #mynewt channel on Freenode IRC or #general channel on [Mynewt Slack](https://join.slack.com/mynewt/shared_invite/MTkwMTg1ODM1NTg5LTE0OTYxNzQ4NzQtZTU1YmNhYjhkMg) Also, be sure to checkout the [Frequently Asked Questions](https://mynewt.apache.org/faq/answers) for some help troubleshooting first. diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/RELEASE_NOTES.md b/lib/libesp32_div/NimBLE-Arduino/src/RELEASE_NOTES.md similarity index 56% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/RELEASE_NOTES.md rename to lib/libesp32_div/NimBLE-Arduino/src/RELEASE_NOTES.md index 3bdd31ad0..cda8fe2e4 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/RELEASE_NOTES.md +++ b/lib/libesp32_div/NimBLE-Arduino/src/RELEASE_NOTES.md @@ -1,32 +1,26 @@ # RELEASE NOTES -18 March 2020 - Apache NimBLE v1.3.0 +16 July 2019 - Apache NimBLE v1.2.0 For full release notes, please visit the [Apache Mynewt Wiki](https://cwiki.apache.org/confluence/display/MYNEWT/Release+Notes). -Apache NimBLE is an open-source Bluetooth 5.1 stack (both Host & Controller) that completely +Apache NimBLE is an open-source Bluetooth 5.0 stack (both Host & Controller) that completely replaces the proprietary SoftDevice on Nordic chipsets. New features in this version of NimBLE include: -* Support for Bluetooth Core Specification 5.1 -* New blestress test application -* Dialog DA1469x CMAC driver -* Support for LE Secure Connections out-of-band (OOB) association model -* Support for automated generation of syscfg for ports +* Perdiodic Advertising support with up to 1650 bytes of data (scanner and advertiser) +* Support for scan request notification in GAP API +* Updated host qualification ID * Qualification related bugfixes +* GAP API doxygen documentation update * BLE Mesh improvements - fixes and resync with latest Zephyr code * RIOT OS port fixes and improvements * btshell sample application improvements * improvements for bttester application * Controller duplicates filtering improvements -* Multi PHY support improvements -* Memory and CPU usage optimizations -* Use of packed structs for HCI (code size reduction) -* Linux sample improvements -* PTS test instructions updates -* Clock managements improvements in controller +* Memory and CPU usage optimizations in controller If working on next-generation RTOS and Bluetooth protocol stack sounds exciting to you, get in touch, by sending a mail to the Apache Mynewt diff --git a/lib/libesp32_div/NimBLE-Arduino/src/console/console.h b/lib/libesp32_div/NimBLE-Arduino/src/console/console.h new file mode 100644 index 000000000..96f965159 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/console/console.h @@ -0,0 +1,21 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +#ifndef _CONSOLE_H +#define _CONSOLE_H + +#include + +#define console_printf printf + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/src/esp_nimble_hci.c b/lib/libesp32_div/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/src/esp_nimble_hci.c rename to lib/libesp32_div/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c index f4df29a65..2963e15b3 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/src/esp_nimble_hci.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c @@ -19,19 +19,17 @@ * under the License. */ -#ifdef ESP_PLATFORM - #include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "nimble/porting/nimble/include/nimble/nimble_port.h" -#include "nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h" -#include "../include/esp_nimble_hci.h" -#include "../../port/include/esp_nimble_mem.h" -#include -#include -#include "../include/esp_compiler.h" +#include "sysinit/sysinit.h" +#include "nimble/hci_common.h" +#include "host/ble_hs.h" +#include "nimble/nimble_port.h" +#include "nimble/nimble_port_freertos.h" +#include "esp_nimble_hci.h" +#include "esp_nimble_mem.h" +#include "esp_bt.h" +#include "freertos/semphr.h" +#include "esp_compiler.h" /* IPC is used to improve performance when calls come from a processor not running the NimBLE stack */ /* but does not exist for solo */ #ifndef CONFIG_FREERTOS_UNICORE @@ -312,6 +310,7 @@ static struct os_mbuf *ble_hci_trans_acl_buf_alloc(void) static void ble_hci_rx_acl(uint8_t *data, uint16_t len) { struct os_mbuf *m; + int rc; int sr; if (len < BLE_HCI_DATA_HDR_SZ || len > MYNEWT_VAL(BLE_ACL_BUF_SIZE)) { return; @@ -320,9 +319,11 @@ static void ble_hci_rx_acl(uint8_t *data, uint16_t len) m = ble_hci_trans_acl_buf_alloc(); if (!m) { + ESP_LOGE(TAG, "%s failed to allocate ACL buffers; increase ACL_BUF_COUNT", __func__); return; } - if (os_mbuf_append(m, data, len)) { + if ((rc = os_mbuf_append(m, data, len)) != 0) { + ESP_LOGE(TAG, "%s failed to os_mbuf_append; rc = %d", __func__, rc); os_mbuf_free_chain(m); return; } @@ -530,6 +531,7 @@ esp_err_t esp_nimble_hci_and_controller_init(void) if ((ret = esp_bt_controller_enable(ESP_BT_MODE_BLE)) != ESP_OK) { return ret; } + return esp_nimble_hci_init(); } @@ -591,5 +593,3 @@ esp_err_t esp_nimble_hci_and_controller_deinit(void) return ESP_OK; } - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/esp_compiler.h b/lib/libesp32_div/NimBLE-Arduino/src/esp_compiler.h new file mode 100644 index 000000000..94ec29c23 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/esp_compiler.h @@ -0,0 +1,33 @@ +// Copyright 2016-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef __ESP_COMPILER_H +#define __ESP_COMPILER_H + +/* + * The likely and unlikely macro pairs: + * These macros are useful to place when application + * knows the majority ocurrence of a decision paths, + * placing one of these macros can hint the compiler + * to reorder instructions producing more optimized + * code. + */ +#if (CONFIG_COMPILER_OPTIMIZATION_PERF) +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif + +#endif \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/include/esp_nimble_cfg.h b/lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_cfg.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/include/esp_nimble_cfg.h rename to lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_cfg.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/include/esp_nimble_hci.h b/lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_hci.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/include/esp_nimble_hci.h rename to lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_hci.h index dda03216e..e10436f3c 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/include/esp_nimble_hci.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_hci.h @@ -19,11 +19,10 @@ * under the License. */ -#ifdef ESP_PLATFORM #ifndef __ESP_NIMBLE_HCI_H__ #define __ESP_NIMBLE_HCI_H__ -#include "nimble/nimble/include/nimble/ble_hci_trans.h" +#include "nimble/ble_hci_trans.h" #ifdef __cplusplus extern "C" { @@ -137,4 +136,3 @@ esp_err_t esp_nimble_hci_and_controller_deinit(void); #endif #endif /* __ESP_NIMBLE_HCI_H__ */ -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/include/esp_nimble_mem.h b/lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_mem.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/include/esp_nimble_mem.h rename to lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_mem.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/AUTHORS b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/AUTHORS similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/AUTHORS rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/AUTHORS diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/LICENSE b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/LICENSE similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/LICENSE rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/LICENSE diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/README b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/README similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/README rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/README diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/VERSION b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/VERSION similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/VERSION rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/VERSION diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/documentation/tinycrypt.rst b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/documentation/tinycrypt.rst similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/documentation/tinycrypt.rst rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/documentation/tinycrypt.rst diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_decrypt.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_decrypt.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_decrypt.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_decrypt.c index 0bab6e280..993a6180c 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_decrypt.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_decrypt.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/aes.h" -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include static const uint8_t inv_sbox[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_encrypt.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_encrypt.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_encrypt.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_encrypt.c index bdc434bce..8991aee52 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_encrypt.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_encrypt.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/aes.h" -#include "../include/tinycrypt/utils.h" -#include "../include/tinycrypt/constants.h" +#include +#include +#include static const uint8_t sbox[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cbc_mode.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cbc_mode.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cbc_mode.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cbc_mode.c index b743878a9..62d7879eb 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cbc_mode.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cbc_mode.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/cbc_mode.h" -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, unsigned int inlen, const uint8_t *iv, diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ccm_mode.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ccm_mode.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ccm_mode.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ccm_mode.c index 598531252..929adac63 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ccm_mode.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ccm_mode.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/ccm_mode.h" -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cmac_mode.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cmac_mode.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cmac_mode.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cmac_mode.c index dff28cf03..96d147e80 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cmac_mode.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cmac_mode.c @@ -30,10 +30,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/aes.h" -#include "../include/tinycrypt/cmac_mode.h" -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include +#include /* max number of calls until change the key (2^48).*/ const static uint64_t MAX_CALLS = ((uint64_t)1 << 48); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_mode.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_mode.c similarity index 95% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_mode.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_mode.c index 6653afc52..1dfb92dfe 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_mode.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_mode.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/ctr_mode.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_prng.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_prng.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_prng.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_prng.c index f908932e2..cac2cc41d 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_prng.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_prng.c @@ -27,9 +27,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/ctr_prng.h" -#include "../include/tinycrypt/utils.h" -#include "../include/tinycrypt/constants.h" +#include +#include +#include #include /* diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc.c index e7fce278d..46080bf61 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc.c @@ -52,8 +52,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/ecc.h" -#include "../include/tinycrypt/ecc_platform_specific.h" +#include +#include #include /* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dh.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dh.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dh.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dh.c index 5cd6a2e2f..e5257d2d4 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dh.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dh.c @@ -54,9 +54,9 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/ecc.h" -#include "../include/tinycrypt/ecc_dh.h" +#include +#include +#include #include #if default_RNG_defined diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dsa.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dsa.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dsa.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dsa.c index 31046c860..064dfe5ae 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dsa.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dsa.c @@ -53,9 +53,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/ecc.h" -#include "../include/tinycrypt/ecc_dsa.h" +#include +#include +#include #if default_RNG_defined static uECC_RNG_Function g_rng_function = &default_CSPRNG; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_platform_specific.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_platform_specific.c similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_platform_specific.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_platform_specific.c diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac.c index c86fd35a7..89878cec7 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/hmac.h" -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size) { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac_prng.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac_prng.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac_prng.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac_prng.c index a41ea43d5..68b5b1faf 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac_prng.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac_prng.c @@ -30,10 +30,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/hmac_prng.h" -#include "../include/tinycrypt/hmac.h" -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include +#include /* * min bytes in the seed string. diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/sha256.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/sha256.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/sha256.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/sha256.c index b7e0bba55..b4efd2044 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/sha256.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/sha256.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/sha256.h" -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include static void compress(unsigned int *iv, const uint8_t *data); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/utils.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/utils.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/utils.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/utils.c index 792a78178..13cc49512 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/utils.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/utils.c @@ -30,8 +30,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/utils.h" -#include "../include/tinycrypt/constants.h" +#include +#include #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/hal/hal_timer.h b/lib/libesp32_div/NimBLE-Arduino/src/hal/hal_timer.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/hal/hal_timer.h rename to lib/libesp32_div/NimBLE-Arduino/src/hal/hal_timer.h index 936545d8c..be41c6095 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/hal/hal_timer.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/hal/hal_timer.h @@ -29,7 +29,7 @@ #define H_HAL_TIMER_ #include -#include "../os/queue.h" +#include "os/queue.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_att.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_att.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_att.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_att.h index ceca35179..391a992ae 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_att.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_att.h @@ -27,7 +27,7 @@ * @{ */ -#include "nimble/porting/nimble/include/os/queue.h" +#include "os/queue.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_eddystone.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_eddystone.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_eddystone.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_eddystone.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gap.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_gap.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gap.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_gap.h index edaf3bc4d..ed7fbb128 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gap.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_gap.h @@ -28,9 +28,9 @@ */ #include -#include "ble_hs.h" -#include "ble_hs_adv.h" -#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "host/ble_hs.h" +#include "host/ble_hs_adv.h" +#include "syscfg/syscfg.h" #ifdef __cplusplus extern "C" { @@ -1821,22 +1821,6 @@ int ble_gap_wl_tx_rmv(const ble_addr_t *addrs); int ble_gap_update_params(uint16_t conn_handle, const struct ble_gap_upd_params *params); -/** - * Configure LE Data Length in controller (OGF = 0x08, OCF = 0x0022). - * - * @param conn_handle Connection handle. - * @param tx_octets The preferred value of payload octets that the Controller - * should use for a new connection (Range - * 0x001B-0x00FB). - * @param tx_time The preferred maximum number of microseconds that the local Controller - * should use to transmit a single link layer packet - * (Range 0x0148-0x4290). - * - * @return 0 on success, - * other error code on failure. - */ -int ble_gap_set_data_len(uint16_t conn_handle, uint16_t tx_octets, uint16_t tx_time); - /** * Initiates the GAP security procedure. * diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gatt.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_gatt.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gatt.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_gatt.h index ee8f177f8..d5c3269f0 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gatt.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_gatt.h @@ -28,8 +28,8 @@ */ #include -#include "ble_att.h" -#include "ble_uuid.h" +#include "host/ble_att.h" +#include "host/ble_uuid.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs.h similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs.h index f24b8a9e0..43979ba57 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs.h @@ -27,23 +27,23 @@ */ #include -#include "nimble/nimble/include/nimble/hci_common.h" -#include "ble_att.h" -#include "ble_eddystone.h" -#include "ble_gap.h" -#include "ble_gatt.h" -#include "ble_hs_adv.h" -#include "ble_hs_id.h" -#include "ble_hs_hci.h" -#include "ble_hs_log.h" -#include "ble_hs_mbuf.h" -#include "ble_hs_stop.h" -#include "ble_ibeacon.h" -#include "ble_l2cap.h" -#include "ble_sm.h" -#include "ble_store.h" -#include "ble_uuid.h" -#include "nimble/nimble/include/nimble/nimble_npl.h" +#include "nimble/hci_common.h" +#include "host/ble_att.h" +#include "host/ble_eddystone.h" +#include "host/ble_gap.h" +#include "host/ble_gatt.h" +#include "host/ble_hs_adv.h" +#include "host/ble_hs_id.h" +#include "host/ble_hs_hci.h" +#include "host/ble_hs_log.h" +#include "host/ble_hs_mbuf.h" +#include "host/ble_hs_stop.h" +#include "host/ble_ibeacon.h" +#include "host/ble_l2cap.h" +#include "host/ble_sm.h" +#include "host/ble_store.h" +#include "host/ble_uuid.h" +#include "nimble/nimble_npl.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_adv.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_adv.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_adv.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_adv.h index ae2965328..e3b6ea709 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_adv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_adv.h @@ -21,7 +21,7 @@ #define H_BLE_HS_ADV_ #include -#include "ble_uuid.h" +#include "host/ble_uuid.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_hci.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_hci.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_hci.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_hci.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_id.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_id.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_id.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_id.h index 568303412..c96bd20f5 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_id.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_id.h @@ -28,7 +28,7 @@ */ #include -#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/ble.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_log.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_log.h similarity index 92% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_log.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_log.h index 303b53c6e..8d0a4596e 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_log.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_log.h @@ -20,11 +20,11 @@ #ifndef H_BLE_HS_LOG_ #define H_BLE_HS_LOG_ -#include "nimble/porting/nimble/include/modlog/modlog.h" +#include "modlog/modlog.h" /* Only include the logcfg header if this version of newt can generate it. */ #if MYNEWT_VAL(NEWT_FEATURE_LOGCFG) -#include "nimble/porting/nimble/include/logcfg/logcfg.h" +#include "logcfg/logcfg.h" #endif #ifdef __cplusplus diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_mbuf.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_mbuf.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_mbuf.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_mbuf.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_pvcy.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_pvcy.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_pvcy.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_pvcy.h index 26450f4f8..19087f220 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_pvcy.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_pvcy.h @@ -22,7 +22,7 @@ #ifndef H_BLE_HS_PVCY_ #define H_BLE_HS_PVCY_ -#include "ble_hs.h" +#include "host/ble_hs.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_stop.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_stop.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_stop.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_stop.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_ibeacon.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_ibeacon.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_ibeacon.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_ibeacon.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_l2cap.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_l2cap.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_l2cap.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_l2cap.h index 9d92c08f1..aef9682cc 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_l2cap.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_l2cap.h @@ -20,7 +20,7 @@ #ifndef H_BLE_L2CAP_ #define H_BLE_L2CAP_ -#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble_opt.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_monitor.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_monitor.h similarity index 95% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_monitor.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_monitor.h index 418d4e379..61722f7db 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_monitor.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_monitor.h @@ -20,7 +20,7 @@ #ifndef H_BLE_MONITOR_ #define H_BLE_MONITOR_ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include #undef BLE_MONITOR #define BLE_MONITOR (MYNEWT_VAL(BLE_MONITOR_UART) || MYNEWT_VAL(BLE_MONITOR_RTT)) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_sm.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_sm.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_sm.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_sm.h index 42414d584..ceebb8564 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_sm.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_sm.h @@ -21,7 +21,7 @@ #define H_BLE_SM_ #include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "syscfg/syscfg.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_store.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_store.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_store.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_store.h index 8e6721bf3..a3eca5d23 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_store.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_store.h @@ -21,7 +21,7 @@ #define H_BLE_STORE_ #include -#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/ble.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_uuid.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_uuid.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_uuid.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_uuid.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/include/host/util/util.h b/lib/libesp32_div/NimBLE-Arduino/src/host/util/util.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/include/host/util/util.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/util/util.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log/log.h b/lib/libesp32_div/NimBLE-Arduino/src/log/log.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log/log.h rename to lib/libesp32_div/NimBLE-Arduino/src/log/log.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log_common/ignore.h b/lib/libesp32_div/NimBLE-Arduino/src/log_common/ignore.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log_common/ignore.h rename to lib/libesp32_div/NimBLE-Arduino/src/log_common/ignore.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log_common/log_common.h b/lib/libesp32_div/NimBLE-Arduino/src/log_common/log_common.h similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log_common/log_common.h rename to lib/libesp32_div/NimBLE-Arduino/src/log_common/log_common.h index f6c9e57e0..f13a61ad9 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log_common/log_common.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/log_common/log_common.h @@ -20,7 +20,7 @@ #ifndef H_LOG_COMMON_ #define H_LOG_COMMON_ -#include "ignore.h" +#include "log_common/ignore.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/logcfg/logcfg.h b/lib/libesp32_div/NimBLE-Arduino/src/logcfg/logcfg.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/logcfg/logcfg.h rename to lib/libesp32_div/NimBLE-Arduino/src/logcfg/logcfg.h index d7422cc8f..764f87f27 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/logcfg/logcfg.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/logcfg/logcfg.h @@ -5,8 +5,8 @@ #ifndef H_MYNEWT_LOGCFG_ #define H_MYNEWT_LOGCFG_ -#include "../modlog/modlog.h" -#include "../log_common/log_common.h" +#include "modlog/modlog.h" +#include "log_common/log_common.h" #if (MYNEWT_VAL(BLE_HS_LOG_LVL) == LOG_LEVEL_DEBUG) #define BLE_HS_LOG_DEBUG(...) MODLOG_DEBUG(4, __VA_ARGS__) @@ -130,7 +130,6 @@ #define BLE_MESH_TRANS_LOG_ERROR(...) MODLOG_ERROR(21, __VA_ARGS__) #define BLE_MESH_TRANS_LOG_CRITICAL(...) MODLOG_CRITICAL(21, __VA_ARGS__) #define BLE_MESH_TRANS_LOG_DISABLED(...) MODLOG_DISABLED(21, __VA_ARGS__) - #define DFLT_LOG_DEBUG(...) IGNORE(__VA_ARGS__) #define DFLT_LOG_INFO(...) MODLOG_INFO(0, __VA_ARGS__) #define DFLT_LOG_WARN(...) MODLOG_WARN(0, __VA_ARGS__) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/mem/mem.h b/lib/libesp32_div/NimBLE-Arduino/src/mem/mem.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/mem/mem.h rename to lib/libesp32_div/NimBLE-Arduino/src/mem/mem.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/access.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/access.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/access.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/access.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_cli.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/cfg_cli.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_cli.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/cfg_cli.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_srv.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/cfg_srv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_srv.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/cfg_srv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/glue.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/glue.h similarity index 95% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/glue.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/glue.h index f50b6ece8..388ecba39 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/glue.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/mesh/glue.h @@ -23,19 +23,19 @@ #include #include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/logcfg/logcfg.h" -#include "nimble/porting/nimble/include/modlog/modlog.h" -#include "nimble/nimble/include/nimble/nimble_npl.h" +#include "syscfg/syscfg.h" +#include "logcfg/logcfg.h" +#include "modlog/modlog.h" +#include "nimble/nimble_npl.h" -#include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "nimble/porting/nimble/include/os/queue.h" +#include "os/os_mbuf.h" +#include "os/queue.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "nimble/nimble/host/include/host/ble_uuid.h" -#include "nimble/nimble/host/src/ble_sm_priv.h" -#include "nimble/nimble/host/src/ble_hs_hci_priv.h" +#include "nimble/ble.h" +#include "host/ble_hs.h" +#include "host/ble_uuid.h" +#include "../src/ble_sm_priv.h" +#include "../src/ble_hs_hci_priv.h" #if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS) #include "mbedtls/aes.h" @@ -47,11 +47,11 @@ #include "mbedtls/ecp.h" #else -#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h" +#include "tinycrypt/aes.h" +#include "tinycrypt/constants.h" +#include "tinycrypt/utils.h" +#include "tinycrypt/cmac_mode.h" +#include "tinycrypt/ecc_dh.h" #endif #if MYNEWT_VAL(BLE_MESH_SETTINGS) @@ -359,6 +359,8 @@ static inline void net_buf_simple_restore(struct os_mbuf *buf, static inline void sys_memcpy_swap(void *dst, const void *src, size_t length) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpointer-arith" __ASSERT(((src < dst && (src + length) <= dst) || (src > dst && (dst + length) <= src)), "Source and destination buffers must not overlap"); @@ -368,6 +370,7 @@ static inline void sys_memcpy_swap(void *dst, const void *src, size_t length) for (; length > 0; length--) { *((u8_t *)dst++) = *((u8_t *)src--); } +#pragma GCC diagnostic pop } #define popcount(x) __builtin_popcount(x) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_cli.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/health_cli.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_cli.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/health_cli.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_srv.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/health_srv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_srv.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/health_srv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/main.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/main.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/main.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/main.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/mesh.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/mesh.h similarity index 78% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/mesh.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/mesh.h index 77b2871fc..9ba63ef0e 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/mesh.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/mesh/mesh.h @@ -11,8 +11,8 @@ #define __BT_MESH_H #include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include "syscfg/syscfg.h" +#include "os/os_mbuf.h" #include "glue.h" #include "access.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_cli.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/model_cli.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_cli.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/model_cli.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_srv.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/model_srv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_srv.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/model_srv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/porting.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/porting.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/porting.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/porting.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/proxy.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/proxy.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/proxy.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/proxy.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/slist.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/slist.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/slist.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/slist.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/testing.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/testing.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/testing.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/testing.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/modlog/modlog.h b/lib/libesp32_div/NimBLE-Arduino/src/modlog/modlog.h similarity index 79% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/modlog/modlog.h rename to lib/libesp32_div/NimBLE-Arduino/src/modlog/modlog.h index c12b13991..e81ea3812 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/modlog/modlog.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/modlog/modlog.h @@ -22,8 +22,7 @@ #include -#include "../log/log.h" -#include "../log_common/log_common.h" +#include "log/log.h" #ifdef ESP_PLATFORM #include "esp_log.h" @@ -33,11 +32,36 @@ #define MODLOG_MODULE_DFLT 255 -#if defined(ESP_PLATFORM) && !defined(ARDUINO_ARCH_ESP32) +#if (MYNEWT_VAL(LOG_LEVEL) > 0) +static inline void +modlog_dummy(const char *msg, ...) +{ + (void)msg; +} +#endif + +#ifdef ESP_PLATFORM #define MODLOG_ESP_LOCAL(level, ml_msg_, ...) do { \ - if (MYNEWT_VAL(BLE_HS_LOG_LVL) <= LOG_LOCAL_LEVEL) ESP_LOG_LEVEL_LOCAL(level, "NimBLE", ml_msg_, ##__VA_ARGS__); \ + if (LOG_LOCAL_LEVEL >= level) esp_log_write(level, "NimBLE", ml_msg_, ##__VA_ARGS__); \ } while(0) +#ifdef ARDUINO_ARCH_ESP32 +#include "nimconfig.h" +#endif + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_BT_NIMBLE_DEBUG) + +#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \ + MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__) + +#define MODLOG_INFO(ml_mod_, ml_msg_, ...) \ + MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__) + +#define MODLOG_WARN(ml_mod_, ml_msg_, ...) \ + MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__) + +#else + #define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \ MODLOG_ESP_LOCAL(ESP_LOG_DEBUG, ml_msg_, ##__VA_ARGS__) @@ -47,6 +71,8 @@ #define MODLOG_WARN(ml_mod_, ml_msg_, ...) \ MODLOG_ESP_LOCAL(ESP_LOG_WARN, ml_msg_, ##__VA_ARGS__) +#endif + #define MODLOG_ERROR(ml_mod_, ml_msg_, ...) \ MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__) @@ -55,30 +81,12 @@ #else -#if (MYNEWT_VAL(LOG_LEVEL) > 0) -static inline void -modlog_dummy(const char *msg, ...) -{ - (void)msg; -} -#endif - -#include "nimble/console/console.h" - -#if (MYNEWT_VAL(LOG_LEVEL) > 0) -#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \ - modlog_dummy((ml_msg_), ##__VA_ARGS__) -#else -#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \ - console_printf((ml_msg_), ##__VA_ARGS__); -#endif - #if (MYNEWT_VAL(LOG_LEVEL) > 1) #define MODLOG_INFO(ml_mod_, ml_msg_, ...) \ modlog_dummy((ml_msg_), ##__VA_ARGS__) #else #define MODLOG_INFO(ml_mod_, ml_msg_, ...) \ - console_printf((ml_msg_), ##__VA_ARGS__); + printf((ml_msg_), ##__VA_ARGS__); #endif #if (MYNEWT_VAL(LOG_LEVEL) > 2) @@ -86,7 +94,7 @@ modlog_dummy(const char *msg, ...) modlog_dummy((ml_msg_), ##__VA_ARGS__) #else #define MODLOG_WARN(ml_mod_, ml_msg_, ...) \ - console_printf((ml_msg_), ##__VA_ARGS__); + printf((ml_msg_), ##__VA_ARGS__); #endif #if (MYNEWT_VAL(LOG_LEVEL) > 3) @@ -94,7 +102,7 @@ modlog_dummy(const char *msg, ...) modlog_dummy((ml_msg_), ##__VA_ARGS__) #else #define MODLOG_ERROR(ml_mod_, ml_msg_, ...) \ - console_printf((ml_msg_), ##__VA_ARGS__); + printf((ml_msg_), ##__VA_ARGS__); #endif #if (MYNEWT_VAL(LOG_LEVEL) > 4) @@ -102,7 +110,7 @@ modlog_dummy(const char *msg, ...) modlog_dummy((ml_msg_), ##__VA_ARGS__) #else #define MODLOG_CRITICAL(ml_mod_, ml_msg_, ...) \ - console_printf((ml_msg_), ##__VA_ARGS__); + printf((ml_msg_), ##__VA_ARGS__); #endif #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ble.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ble.h index f6847728c..3fc2902ec 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ble.h @@ -22,8 +22,8 @@ #include #include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" +#include "syscfg/syscfg.h" +#include "os/os.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble_hci_trans.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ble_hci_trans.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble_hci_trans.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ble_hci_trans.h index d4c353f1f..e8d3ec031 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble_hci_trans.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ble_hci_trans.h @@ -21,7 +21,7 @@ #define H_HCI_TRANSPORT_ #include -#include "nimble/porting/nimble/include/os/os_mempool.h" +#include "os/os_mempool.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/console/console.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/console/console.h deleted file mode 100644 index b1052e62e..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/console/console.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __CONSOLE_H__ -#define __CONSOLE_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define console_printf printf - -#ifdef __cplusplus -} -#endif - -#endif /* __CONSOLE_H__ */ \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/include/esp_compiler.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/include/esp_compiler.h deleted file mode 100644 index 7ab8cb9af..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/include/esp_compiler.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2016-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef __ESP_COMPILER_H -#define __ESP_COMPILER_H - -/* - * The likely and unlikely macro pairs: - * These macros are useful to place when application - * knows the majority ocurrence of a decision paths, - * placing one of these macros can hint the compiler - * to reorder instructions producing more optimized - * code. - */ -#if (CONFIG_COMPILER_OPTIMIZATION_PERF) -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) -#else -#define likely(x) (x) -#define unlikely(x) (x) -#endif - -/* - * Utility macros used for designated initializers, which work differently - * in C99 and C++ standards mainly for aggregate types. - * The member separator, comma, is already part of the macro, please omit the trailing comma. - * Usage example: - * struct config_t { char* pchr; char arr[SIZE]; } config = { - * ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(pchr) - * ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(arr, "Value") - * }; - */ -#ifdef __cplusplus -#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(member, value) { .member = value }, -#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(member) .member = { }, -#else -#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(member, value) .member = value, -#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(member) -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/hci_common.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/hci_common.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/hci_common.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/hci_common.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.c index 37580b400..ff8e99997 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.c @@ -6,15 +6,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_ACCESS_LOG #include -#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include -#include "../include/mesh/mesh.h" +#include "mesh/mesh.h" #include "mesh_priv.h" #include "adv.h" @@ -24,7 +22,7 @@ #include "access.h" #include "foundation.h" #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS) -#include "../include/mesh/model_cli.h" +#include "mesh/model_cli.h" #endif static const struct bt_mesh_comp *dev_comp; @@ -856,4 +854,3 @@ int bt_mesh_model_extend(struct bt_mesh_model *mod, return 0; } #endif -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.h index 03081b9ad..48514983f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.h @@ -9,7 +9,7 @@ #ifndef __ACCESS_H__ #define __ACCESS_H__ -#include "../include/mesh/mesh.h" +#include "mesh/mesh.h" /* bt_mesh_model.flags */ enum { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.c similarity index 94% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.c index b9d290176..b8fb1c7de 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.c @@ -7,17 +7,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_ADV_LOG -#include "../include/mesh/mesh.h" -#include "nimble/nimble/host/include/host/ble_hs_adv.h" -#include "nimble/nimble/host/include/host/ble_gap.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "../include/mesh/porting.h" -#include "nimble/porting/nimble/include/nimble/nimble_port.h" +#include "mesh/mesh.h" +#include "host/ble_hs_adv.h" +#include "host/ble_gap.h" +#include "nimble/hci_common.h" +#include "mesh/porting.h" +#include "nimble/nimble_port.h" + #include "adv.h" #include "net.h" #include "foundation.h" @@ -338,12 +337,9 @@ void bt_mesh_adv_init(void) os_task_init(&adv_task, "mesh_adv", mesh_adv_thread, NULL, MYNEWT_VAL(BLE_MESH_ADV_TASK_PRIO), OS_WAIT_FOREVER, g_blemesh_stack, ADV_STACK_SIZE); -#elif ESP_PLATFORM +#else xTaskCreatePinnedToCore(mesh_adv_thread, "mesh_adv", 2768, NULL, (configMAX_PRIORITIES - 5), &adv_task_h, NIMBLE_CORE); -#else - xTaskCreate(mesh_adv_thread, "mesh_adv", MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE), - NULL, MYNEWT_VAL(BLE_MESH_ADV_TASK_PRIO), &adv_task_h); #endif /* For BT5 controllers we can have fast advertising interval */ @@ -447,4 +443,3 @@ int bt_mesh_scan_disable(void) return 0; } -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.h index 40e65e5f4..4d0f7d8ba 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.h @@ -10,7 +10,7 @@ #define __ADV_H__ /* Maximum advertising data payload for a single data type */ -#include "../include/mesh/mesh.h" +#include "mesh/mesh.h" #define BT_MESH_ADV(om) (*(struct bt_mesh_adv **) OS_MBUF_USRHDR(om)) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/atomic.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/atomic.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/atomic.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/atomic.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.c index 89ee1a086..cd540aa8c 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.c @@ -6,15 +6,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_BEACON_LOG #include #include -#include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "../include/mesh/mesh.h" +#include "os/os_mbuf.h" +#include "mesh/mesh.h" #include "adv.h" #include "mesh_priv.h" @@ -441,4 +439,3 @@ void bt_mesh_beacon_disable(void) k_delayed_work_cancel(&beacon_timer); } } -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.h similarity index 89% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.h index 08fd88d96..ac4bfed8a 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.h @@ -9,7 +9,7 @@ #ifndef __BEACON_H__ #define __BEACON_H__ -#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include "os/os_mbuf.h" void bt_mesh_beacon_enable(void); void bt_mesh_beacon_disable(void); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h new file mode 100644 index 000000000..2201d4ddb --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h @@ -0,0 +1,307 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_ATT_PRIV_ +#define H_BLE_ATT_PRIV_ + +#include +#include "stats/stats.h" +#include "host/ble_att.h" +#include "host/ble_uuid.h" +#include "nimble/nimble_npl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct os_mbuf; +struct ble_hs_conn; +struct ble_l2cap_chan; +struct ble_att_find_info_req; +struct ble_att_error_rsp; +struct ble_att_mtu_cmd; +struct ble_att_read_req; +struct ble_att_read_blob_req; +struct ble_att_read_type_req; +struct ble_att_read_group_type_req; +struct ble_att_read_group_type_rsp; +struct ble_att_find_type_value_req; +struct ble_att_write_req; +struct ble_att_prep_write_cmd; +struct ble_att_exec_write_req; +struct ble_att_notify_req; +struct ble_att_indicate_req; + +STATS_SECT_START(ble_att_stats) + STATS_SECT_ENTRY(error_rsp_rx) + STATS_SECT_ENTRY(error_rsp_tx) + STATS_SECT_ENTRY(mtu_req_rx) + STATS_SECT_ENTRY(mtu_req_tx) + STATS_SECT_ENTRY(mtu_rsp_rx) + STATS_SECT_ENTRY(mtu_rsp_tx) + STATS_SECT_ENTRY(find_info_req_rx) + STATS_SECT_ENTRY(find_info_req_tx) + STATS_SECT_ENTRY(find_info_rsp_rx) + STATS_SECT_ENTRY(find_info_rsp_tx) + STATS_SECT_ENTRY(find_type_value_req_rx) + STATS_SECT_ENTRY(find_type_value_req_tx) + STATS_SECT_ENTRY(find_type_value_rsp_rx) + STATS_SECT_ENTRY(find_type_value_rsp_tx) + STATS_SECT_ENTRY(read_type_req_rx) + STATS_SECT_ENTRY(read_type_req_tx) + STATS_SECT_ENTRY(read_type_rsp_rx) + STATS_SECT_ENTRY(read_type_rsp_tx) + STATS_SECT_ENTRY(read_req_rx) + STATS_SECT_ENTRY(read_req_tx) + STATS_SECT_ENTRY(read_rsp_rx) + STATS_SECT_ENTRY(read_rsp_tx) + STATS_SECT_ENTRY(read_blob_req_rx) + STATS_SECT_ENTRY(read_blob_req_tx) + STATS_SECT_ENTRY(read_blob_rsp_rx) + STATS_SECT_ENTRY(read_blob_rsp_tx) + STATS_SECT_ENTRY(read_mult_req_rx) + STATS_SECT_ENTRY(read_mult_req_tx) + STATS_SECT_ENTRY(read_mult_rsp_rx) + STATS_SECT_ENTRY(read_mult_rsp_tx) + STATS_SECT_ENTRY(read_group_type_req_rx) + STATS_SECT_ENTRY(read_group_type_req_tx) + STATS_SECT_ENTRY(read_group_type_rsp_rx) + STATS_SECT_ENTRY(read_group_type_rsp_tx) + STATS_SECT_ENTRY(write_req_rx) + STATS_SECT_ENTRY(write_req_tx) + STATS_SECT_ENTRY(write_rsp_rx) + STATS_SECT_ENTRY(write_rsp_tx) + STATS_SECT_ENTRY(prep_write_req_rx) + STATS_SECT_ENTRY(prep_write_req_tx) + STATS_SECT_ENTRY(prep_write_rsp_rx) + STATS_SECT_ENTRY(prep_write_rsp_tx) + STATS_SECT_ENTRY(exec_write_req_rx) + STATS_SECT_ENTRY(exec_write_req_tx) + STATS_SECT_ENTRY(exec_write_rsp_rx) + STATS_SECT_ENTRY(exec_write_rsp_tx) + STATS_SECT_ENTRY(notify_req_rx) + STATS_SECT_ENTRY(notify_req_tx) + STATS_SECT_ENTRY(indicate_req_rx) + STATS_SECT_ENTRY(indicate_req_tx) + STATS_SECT_ENTRY(indicate_rsp_rx) + STATS_SECT_ENTRY(indicate_rsp_tx) + STATS_SECT_ENTRY(write_cmd_rx) + STATS_SECT_ENTRY(write_cmd_tx) +STATS_SECT_END +extern STATS_SECT_DECL(ble_att_stats) ble_att_stats; + +struct ble_att_prep_entry { + SLIST_ENTRY(ble_att_prep_entry) bape_next; + uint16_t bape_handle; + uint16_t bape_offset; + + /* XXX: This is wasteful; we should use one mbuf chain for the entire + * prepared write, and compress the data into as few mbufs as possible. + */ + struct os_mbuf *bape_value; +}; + +SLIST_HEAD(ble_att_prep_entry_list, ble_att_prep_entry); + +struct ble_att_svr_conn { + /** This list is sorted by attribute handle ID. */ + struct ble_att_prep_entry_list basc_prep_list; + ble_npl_time_t basc_prep_timeout_at; +}; + +/** + * Handles a host attribute request. + * + * @param entry The host attribute being requested. + * @param op The operation being performed on the attribute. + * @param arg The request data associated with that host + * attribute. + * + * @return 0 on success; + * One of the BLE_ATT_ERR_[...] codes on + * failure. + */ +typedef int ble_att_svr_access_fn(uint16_t conn_handle, uint16_t attr_handle, + uint8_t op, uint16_t offset, + struct os_mbuf **om, void *arg); + +int ble_att_svr_register(const ble_uuid_t *uuid, uint8_t flags, + uint8_t min_key_size, uint16_t *handle_id, + ble_att_svr_access_fn *cb, void *cb_arg); + +struct ble_att_svr_entry { + STAILQ_ENTRY(ble_att_svr_entry) ha_next; + + const ble_uuid_t *ha_uuid; + uint8_t ha_flags; + uint8_t ha_min_key_size; + uint16_t ha_handle_id; + ble_att_svr_access_fn *ha_cb; + void *ha_cb_arg; +}; + +SLIST_HEAD(ble_att_clt_entry_list, ble_att_clt_entry); + +/*** @gen */ + +struct ble_l2cap_chan *ble_att_create_chan(uint16_t conn_handle); +int ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn, + struct ble_l2cap_chan **out_chan); +void ble_att_inc_tx_stat(uint8_t att_op); +void ble_att_truncate_to_mtu(const struct ble_l2cap_chan *att_chan, + struct os_mbuf *txom); +void ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu); +uint16_t ble_att_chan_mtu(const struct ble_l2cap_chan *chan); +int ble_att_init(void); + +#define BLE_ATT_LOG_CMD(is_tx, cmd_name, conn_handle, log_cb, cmd) \ + BLE_HS_LOG_CMD((is_tx), "att", (cmd_name), (conn_handle), (log_cb), (cmd)) + +#define BLE_ATT_LOG_EMPTY_CMD(is_tx, cmd_name, conn_handle) \ + BLE_HS_LOG_EMPTY_CMD((is_tx), "att", (cmd_name), (conn_handle)) + +/*** @svr */ + +int ble_att_svr_start(void); +void ble_att_svr_stop(void); + +struct ble_att_svr_entry * +ble_att_svr_find_by_uuid(struct ble_att_svr_entry *start_at, + const ble_uuid_t *uuid, + uint16_t end_handle); +uint16_t ble_att_svr_prev_handle(void); +int ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom); +struct ble_att_svr_entry *ble_att_svr_find_by_handle(uint16_t handle_id); +int32_t ble_att_svr_ticks_until_tmo(const struct ble_att_svr_conn *svr, + ble_npl_time_t now); +int ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_svr_rx_find_type_value(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_read_type(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_read_group_type(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_read(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_read_blob(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_read_mult(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_write(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_svr_rx_prep_write(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_exec_write(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_notify(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_indicate(uint16_t conn_handle, + struct os_mbuf **rxom); +void ble_att_svr_prep_clear(struct ble_att_prep_entry_list *prep_list); +int ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle, + uint16_t offset, struct os_mbuf *om, + uint8_t *out_att_err); +void ble_att_svr_reset(void); +int ble_att_svr_init(void); + +void ble_att_svr_hide_range(uint16_t start_handle, uint16_t end_handle); +void ble_att_svr_restore_range(uint16_t start_handle, uint16_t end_handle); + +int ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, + uint8_t req_op, uint16_t handle, + uint8_t error_code); +/*** $clt */ + +/** An information-data entry in a find information response. */ +struct ble_att_find_info_idata { + uint16_t attr_handle; + ble_uuid_any_t uuid; +}; + +/** A handles-information entry in a find by type value response. */ +struct ble_att_find_type_value_hinfo { + uint16_t attr_handle; + uint16_t group_end_handle; +}; + +/** An attribute-data entry in a read by type response. */ +struct ble_att_read_type_adata { + uint16_t att_handle; + int value_len; + uint8_t *value; + +}; + +/** An attribute-data entry in a read by group type response. */ +struct ble_att_read_group_type_adata { + uint16_t att_handle; + uint16_t end_group_handle; + int value_len; + uint8_t *value; +}; + +int ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu); +int ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle); +int ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, + uint16_t offset); +int ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_read_mult(uint16_t conn_handle, + const uint16_t *handles, int num_handles); +int ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t start_handle, + uint16_t end_handle, const ble_uuid_t *uuid); +int ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_read_group_type(uint16_t conn_handle, + uint16_t start_handle, uint16_t end_handle, + const ble_uuid_t *uuid128); +int ble_att_clt_rx_read_group_type(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t start_handle, + uint16_t end_handle); +int ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t start_handle, + uint16_t end_handle, uint16_t attribute_type, + const void *attribute_value, int value_len); +int ble_att_clt_rx_find_type_value(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t handle, + struct os_mbuf *txom); +int ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t handle, + struct os_mbuf *txom); +int ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, + uint16_t offset, struct os_mbuf *txom); +int ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags); +int ble_att_clt_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_rx_write(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_notify(uint16_t conn_handle, uint16_t handle, + struct os_mbuf *txom); +int ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t handle, + struct os_mbuf *txom); +int ble_att_clt_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatt_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_gatt_priv.h similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatt_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_gatt_priv.h index 07616d011..4a59635b8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatt_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_gatt_priv.h @@ -20,9 +20,9 @@ #ifndef H_BLE_GATT_PRIV_ #define H_BLE_GATT_PRIV_ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/stats/stats.h" -#include "nimble/nimble/host/include/host/ble_gatt.h" +#include "syscfg/syscfg.h" +#include "stats/stats.h" +#include "host/ble_gatt.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h new file mode 100644 index 000000000..92aacd405 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_HS_CONN_ +#define H_BLE_HS_CONN_ + +#include +#include "ble_l2cap_priv.h" +#include "ble_gatt_priv.h" +#include "ble_att_priv.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct hci_le_conn_complete; +struct hci_create_conn; +struct ble_l2cap_chan; + +typedef uint8_t ble_hs_conn_flags_t; + +#define BLE_HS_CONN_F_MASTER 0x01 +#define BLE_HS_CONN_F_TERMINATING 0x02 +#define BLE_HS_CONN_F_TX_FRAG 0x04 /* Cur ACL packet partially txed. */ + +struct ble_hs_conn { + SLIST_ENTRY(ble_hs_conn) bhc_next; + uint16_t bhc_handle; + uint8_t bhc_our_addr_type; +#if MYNEWT_VAL(BLE_EXT_ADV) + uint8_t bhc_our_rnd_addr[6]; +#endif + ble_addr_t bhc_peer_addr; + ble_addr_t bhc_our_rpa_addr; + ble_addr_t bhc_peer_rpa_addr; + + uint16_t bhc_itvl; + uint16_t bhc_latency; + uint16_t bhc_supervision_timeout; + uint8_t bhc_master_clock_accuracy; + + uint32_t supported_feat; + + ble_hs_conn_flags_t bhc_flags; + + struct ble_l2cap_chan_list bhc_channels; + struct ble_l2cap_chan *bhc_rx_chan; /* Channel rxing current packet. */ + ble_npl_time_t bhc_rx_timeout; + + /** + * Count of packets sent over this connection that the controller has not + * transmitted or flushed yet. + */ + uint16_t bhc_outstanding_pkts; + +#if MYNEWT_VAL(BLE_HS_FLOW_CTRL) + /** + * Count of packets received over this connection that have been processed + * and freed. + */ + uint16_t bhc_completed_pkts; +#endif + + /** Queue of outgoing packets that could not be sent. */ + STAILQ_HEAD(, os_mbuf_pkthdr) bhc_tx_q; + + struct ble_att_svr_conn bhc_att_svr; + struct ble_gatts_conn bhc_gatt_svr; + + struct ble_gap_sec_state bhc_sec_state; + + ble_gap_event_fn *bhc_cb; + void *bhc_cb_arg; +}; + +struct ble_hs_conn_addrs { + ble_addr_t our_id_addr; + ble_addr_t peer_id_addr; + ble_addr_t our_ota_addr; + ble_addr_t peer_ota_addr; +}; + +int ble_hs_conn_can_alloc(void); +struct ble_hs_conn *ble_hs_conn_alloc(uint16_t conn_handle); +void ble_hs_conn_free(struct ble_hs_conn *conn); +void ble_hs_conn_insert(struct ble_hs_conn *conn); +void ble_hs_conn_remove(struct ble_hs_conn *conn); +struct ble_hs_conn *ble_hs_conn_find(uint16_t conn_handle); +struct ble_hs_conn *ble_hs_conn_find_assert(uint16_t conn_handle); +struct ble_hs_conn *ble_hs_conn_find_by_addr(const ble_addr_t *addr); +struct ble_hs_conn *ble_hs_conn_find_by_idx(int idx); +int ble_hs_conn_exists(uint16_t conn_handle); +struct ble_hs_conn *ble_hs_conn_first(void); +struct ble_l2cap_chan *ble_hs_conn_chan_find_by_scid(struct ble_hs_conn *conn, + uint16_t cid); +struct ble_l2cap_chan *ble_hs_conn_chan_find_by_dcid(struct ble_hs_conn *conn, + uint16_t cid); +int ble_hs_conn_chan_insert(struct ble_hs_conn *conn, + struct ble_l2cap_chan *chan); +void +ble_hs_conn_delete_chan(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan); + +void ble_hs_conn_addrs(const struct ble_hs_conn *conn, + struct ble_hs_conn_addrs *addrs); +int32_t ble_hs_conn_timer(void); + +int ble_hs_conn_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h new file mode 100644 index 000000000..0a1a97b77 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_L2CAP_COC_PRIV_ +#define H_L2CAP_COC_PRIV_ + +#include +#include "syscfg/syscfg.h" +#include "os/queue.h" +#include "os/os_mbuf.h" +#include "host/ble_l2cap.h" +#include "ble_l2cap_sig_priv.h" +#ifdef __cplusplus +extern "C" { +#endif + +#define BLE_L2CAP_COC_CID_START 0x0040 +#define BLE_L2CAP_COC_CID_END 0x007F + +struct ble_l2cap_chan; + +#define BLE_L2CAP_COC_FLAG_STALLED 0x01 + +struct ble_l2cap_coc_endpoint { + struct os_mbuf *sdu; + uint16_t mtu; + uint16_t credits; + uint16_t data_offset; + uint8_t flags; +}; + +struct ble_l2cap_coc_srv { + STAILQ_ENTRY(ble_l2cap_coc_srv) next; + uint16_t psm; + uint16_t mtu; + ble_l2cap_event_fn *cb; + void *cb_arg; +}; + +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 +int ble_l2cap_coc_init(void); +int ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu, + ble_l2cap_event_fn *cb, void *cb_arg); +int ble_l2cap_coc_create_srv_chan(uint16_t conn_handle, uint16_t psm, + struct ble_l2cap_chan **chan); +struct ble_l2cap_chan * ble_l2cap_coc_chan_alloc(uint16_t conn_handle, + uint16_t psm, uint16_t mtu, + struct os_mbuf *sdu_rx, + ble_l2cap_event_fn *cb, + void *cb_arg); +void ble_l2cap_coc_cleanup_chan(struct ble_l2cap_chan *chan); +void ble_l2cap_coc_le_credits_update(uint16_t conn_handle, uint16_t dcid, + uint16_t credits); +int ble_l2cap_coc_recv_ready(struct ble_l2cap_chan *chan, + struct os_mbuf *sdu_rx); +int ble_l2cap_coc_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx); +#else +#define ble_l2cap_coc_init() 0 +#define ble_l2cap_coc_create_server(psm, mtu, cb, cb_arg) BLE_HS_ENOTSUP +#define ble_l2cap_coc_recv_ready(chan, sdu_rx) BLE_HS_ENOTSUP +#define ble_l2cap_coc_cleanup_chan(chan) +#define ble_l2cap_coc_send(chan, sdu_tx) BLE_HS_ENOTSUP +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* H_L2CAP_COC_PRIV_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h new file mode 100644 index 000000000..640974d2a --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_L2CAP_PRIV_ +#define H_L2CAP_PRIV_ + +#include "ble_l2cap_coc_priv.h" +#include "host/ble_l2cap.h" +#include +#include "stats/stats.h" +#include "os/queue.h" +#include "os/os_mbuf.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_hs_conn; +struct hci_data_hdr; + +STATS_SECT_START(ble_l2cap_stats) + STATS_SECT_ENTRY(chan_create) + STATS_SECT_ENTRY(chan_delete) + STATS_SECT_ENTRY(update_init) + STATS_SECT_ENTRY(update_rx) + STATS_SECT_ENTRY(update_fail) + STATS_SECT_ENTRY(proc_timeout) + STATS_SECT_ENTRY(sig_tx) + STATS_SECT_ENTRY(sig_rx) + STATS_SECT_ENTRY(sm_tx) + STATS_SECT_ENTRY(sm_rx) +STATS_SECT_END +extern STATS_SECT_DECL(ble_l2cap_stats) ble_l2cap_stats; + +extern struct os_mempool ble_l2cap_chan_pool; + +/* This is nimble specific; packets sent to the black hole CID do not elicit + * an "invalid CID" response. + */ +#define BLE_L2CAP_CID_BLACK_HOLE 0xffff + +#define BLE_L2CAP_HDR_SZ 4 + +typedef uint8_t ble_l2cap_chan_flags; + +typedef int ble_l2cap_rx_fn(struct ble_l2cap_chan *chan); + +struct ble_l2cap_chan { + SLIST_ENTRY(ble_l2cap_chan) next; + uint16_t conn_handle; + uint16_t dcid; + uint16_t scid; + uint16_t my_mtu; + uint16_t peer_mtu; /* 0 if not exchanged. */ + ble_l2cap_chan_flags flags; + + struct os_mbuf *rx_buf; + uint16_t rx_len; /* Length of current reassembled rx packet. */ + + ble_l2cap_rx_fn *rx_fn; + +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 + uint16_t psm; + struct ble_l2cap_coc_endpoint coc_rx; + struct ble_l2cap_coc_endpoint coc_tx; + uint16_t initial_credits; + ble_l2cap_event_fn *cb; + void *cb_arg; +#endif +}; + +struct ble_l2cap_hdr { + uint16_t len; + uint16_t cid; +}; + +typedef int ble_l2cap_tx_fn(struct ble_hs_conn *conn, + struct ble_l2cap_chan *chan); + +#define BLE_L2CAP_CHAN_F_TXED_MTU 0x01 /* We have sent our MTU. */ + +SLIST_HEAD(ble_l2cap_chan_list, ble_l2cap_chan); + +int ble_l2cap_parse_hdr(struct os_mbuf *om, int off, + struct ble_l2cap_hdr *l2cap_hdr); +struct os_mbuf *ble_l2cap_prepend_hdr(struct os_mbuf *om, uint16_t cid, + uint16_t len); + +struct ble_l2cap_chan *ble_l2cap_chan_alloc(uint16_t conn_handle); +void ble_l2cap_chan_free(struct ble_l2cap_chan *chan); + +bool ble_l2cap_is_mtu_req_sent(const struct ble_l2cap_chan *chan); + +int ble_l2cap_rx(struct ble_hs_conn *conn, + struct hci_data_hdr *hci_hdr, + struct os_mbuf *om, + ble_l2cap_rx_fn **out_rx_cb, + int *out_reject_cid); +int ble_l2cap_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan, + struct os_mbuf *txom); + +void ble_l2cap_remove_rx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan); + +int ble_l2cap_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h new file mode 100644 index 000000000..1a6fb8293 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_L2CAP_SIG_ +#define H_BLE_L2CAP_SIG_ + +#include "syscfg/syscfg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLE_L2CAP_SIG_MTU 100 /* This is our own default. */ + +#define BLE_L2CAP_SIG_HDR_SZ 4 +struct ble_l2cap_sig_hdr { + uint8_t op; + uint8_t identifier; + uint16_t length; + uint8_t data[0]; +} __attribute__((packed)); + +#define BLE_L2CAP_SIG_REJECT_MIN_SZ 2 +struct ble_l2cap_sig_reject { + uint16_t reason; + uint8_t data[0]; +} __attribute__((packed)); + +#define BLE_L2CAP_SIG_UPDATE_REQ_SZ 8 +struct ble_l2cap_sig_update_req { + uint16_t itvl_min; + uint16_t itvl_max; + uint16_t slave_latency; + uint16_t timeout_multiplier; +} __attribute__((packed)); + +#define BLE_L2CAP_SIG_UPDATE_RSP_SZ 2 +struct ble_l2cap_sig_update_rsp { + uint16_t result; +} __attribute__((packed)); + +#define BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT 0x0000 +#define BLE_L2CAP_SIG_UPDATE_RSP_RESULT_REJECT 0x0001 + +struct ble_l2cap_sig_le_con_req { + uint16_t psm; + uint16_t scid; + uint16_t mtu; + uint16_t mps; + uint16_t credits; +} __attribute__((packed)); + +struct ble_l2cap_sig_le_con_rsp { + uint16_t dcid; + uint16_t mtu; + uint16_t mps; + uint16_t credits; + uint16_t result; +} __attribute__((packed)); + +struct ble_l2cap_sig_disc_req { + uint16_t dcid; + uint16_t scid; +} __attribute__((packed)); + +struct ble_l2cap_sig_disc_rsp { + uint16_t dcid; + uint16_t scid; +} __attribute__((packed)); + +struct ble_l2cap_sig_le_credits { + uint16_t scid; + uint16_t credits; +} __attribute__((packed)); + +void ble_l2cap_sig_hdr_parse(void *payload, uint16_t len, + struct ble_l2cap_sig_hdr *hdr); +int ble_l2cap_sig_reject_tx(uint16_t conn_handle, + uint8_t id, uint16_t reason, + void *data, int data_len); +int ble_l2cap_sig_reject_invalid_cid_tx(uint16_t conn_handle, uint8_t id, + uint16_t src_cid, uint16_t dst_cid); +int ble_l2cap_sig_tx(uint16_t conn_handle, struct os_mbuf *txom); +void *ble_l2cap_sig_cmd_get(uint8_t opcode, uint8_t id, uint16_t len, + struct os_mbuf **txom); +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 +int ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu, + struct os_mbuf *sdu_rx, + ble_l2cap_event_fn *cb, void *cb_arg); +int ble_l2cap_sig_disconnect(struct ble_l2cap_chan *chan); +int ble_l2cap_sig_le_credits(uint16_t conn_handle, uint16_t scid, + uint16_t credits); +#else +#define ble_l2cap_sig_coc_connect(conn_handle, psm, mtu, sdu_rx, cb, cb_arg) \ + BLE_HS_ENOTSUP +#define ble_l2cap_sig_disconnect(chan) BLE_HS_ENOTSUP +#endif + +void ble_l2cap_sig_conn_broken(uint16_t conn_handle, int reason); +int32_t ble_l2cap_sig_timer(void); +struct ble_l2cap_chan *ble_l2cap_sig_create_chan(uint16_t conn_handle); +int ble_l2cap_sig_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_cli.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_cli.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_cli.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_cli.c index d2596c434..2c2f6c3ff 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_cli.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_cli.c @@ -6,13 +6,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG #if MYNEWT_VAL(BLE_MESH_CFG_CLI) -#include "../include/mesh/mesh.h" +#include "mesh/mesh.h" #include #include @@ -1498,4 +1496,3 @@ void bt_mesh_cfg_cli_timeout_set(s32_t timeout) } #endif -#endif \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_srv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_srv.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_srv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_srv.c index f5de01cbf..57aac90a3 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_srv.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_srv.c @@ -6,16 +6,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG #include #include #include -#include "../include/mesh/mesh.h" +#include "mesh/mesh.h" #include "mesh_priv.h" #include "adv.h" @@ -3619,4 +3617,3 @@ void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store) memset(sub, 0, sizeof(*sub)); sub->net_idx = BT_MESH_KEY_UNUSED; } -#endif \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.c index 425897630..20b110378 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.c @@ -6,14 +6,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_CRYPTO_LOG #include #include #include +#include "syscfg/syscfg.h" #if (MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS)) #include "mbedtls/aes.h" @@ -25,11 +24,11 @@ #include "mbedtls/ecp.h" #else -#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h" +#include +#include +#include +#include +#include #endif #include "crypto.h" @@ -966,4 +965,3 @@ int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags, return err; } -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.h index 8af371c60..745cf324a 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.h @@ -8,7 +8,7 @@ #ifndef __CRYPTO_H__ #define __CRYPTO_H__ -#include "../include/mesh/mesh.h" +#include "mesh/mesh.h" struct bt_mesh_sg { const void *data; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/foundation.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/foundation.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/foundation.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/foundation.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.c index c10a93ec7..9056a8658 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.c @@ -6,9 +6,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_CRYPTO_LOG #if MYNEWT_VAL(BLE_MESH_FRIEND) @@ -17,9 +15,9 @@ #include #include -#include "../include/mesh/mesh.h" -#include "../include/mesh/slist.h" -#include "../include/mesh_priv.h" +#include "mesh/mesh.h" +#include "mesh/slist.h" +#include "mesh_priv.h" #include "crypto.h" #include "adv.h" #include "net.h" @@ -1651,4 +1649,3 @@ void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src, } #endif /* MYNEWT_VAL(BLE_MESH_FRIEND) */ -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.h similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.h index 361c1f097..10ffa8190 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.h @@ -9,7 +9,7 @@ #ifndef __FRIEND_H__ #define __FRIEND_H__ -#include "../include/mesh/mesh.h" +#include "mesh/mesh.h" enum bt_mesh_friend_pdu_type { BT_MESH_FRIEND_PDU_SINGLE, diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/glue.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/glue.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/glue.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/glue.c index 14e515b91..7da73d15b 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/glue.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/glue.c @@ -17,15 +17,13 @@ * under the License. */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_LOG -#include "../include/mesh/glue.h" +#include "mesh/glue.h" #include "adv.h" #ifndef MYNEWT -#include "nimble/porting/nimble/include/nimble/nimble_port.h" +#include "nimble/nimble_port.h" #endif #if MYNEWT_VAL(BLE_MESH_SETTINGS) @@ -892,4 +890,4 @@ char *settings_str_from_bytes(const void *vp, int vp_len, } #endif /* MYNEWT_VAL(BLE_MESH_SETTINGS) */ -#endif + diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_cli.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_cli.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_cli.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_cli.c index 3fc29e52f..193279c28 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_cli.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_cli.c @@ -6,22 +6,20 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG #include #include #include -#include "../include/mesh/mesh.h" +#include "mesh/mesh.h" #include "mesh_priv.h" #include "adv.h" #include "net.h" #include "transport.h" #include "foundation.h" -#include "../include/mesh/health_cli.h" +#include "mesh/health_cli.h" static s32_t msg_timeout = K_SECONDS(5); @@ -556,4 +554,3 @@ static int health_cli_init(struct bt_mesh_model *model) const struct bt_mesh_model_cb bt_mesh_health_cli_cb = { .init = health_cli_init, }; -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_srv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_srv.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_srv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_srv.c index 7063d9203..16de83a99 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_srv.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_srv.c @@ -6,16 +6,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG #include #include #include -#include "../include/mesh/mesh.h" +#include "mesh/mesh.h" #include "mesh_priv.h" #include "adv.h" #include "net.h" @@ -453,4 +451,3 @@ void bt_mesh_attention(struct bt_mesh_model *model, u8_t time) } } } -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.c similarity index 87% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.c index a390bf86b..b6d838188 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.c @@ -1,9 +1,8 @@ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) +#include "syscfg/syscfg.h" -#include "../include/mesh/mesh.h" -#include "nimble/console/console.h" +#include "mesh/mesh.h" +#include "console/console.h" #include "light_model.h" @@ -56,4 +55,4 @@ int light_model_light_lightness_set(struct bt_mesh_model *model, s16_t lightness { return light_model_gen_level_set(model, lightness); } -#endif + diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.h similarity index 87% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.h index f3b1f7cb7..95fcdb786 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.h @@ -6,8 +6,8 @@ #ifndef __BT_MESH_LIGHT_MODEL_H #define __BT_MESH_LIGHT_MODEL_H -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "../include/mesh/mesh.h" +#include "syscfg/syscfg.h" +#include "mesh/mesh.h" int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state); int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.c index 5bb64b97d..ec012a5f0 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.c @@ -6,16 +6,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_LOW_POWER_LOG #if MYNEWT_VAL(BLE_MESH_LOW_POWER) #include -#include "../include/mesh/mesh.h" +#include "mesh/mesh.h" #include "mesh_priv.h" #include "crypto.h" #include "adv.h" @@ -1056,4 +1054,3 @@ int bt_mesh_lpn_init(void) } #endif /* MYNEWT_VAL(BLE_MESH_LOW_POWER) */ -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.h similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.h index e53c81d3d..0ff6c9cfd 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.h @@ -8,7 +8,7 @@ #ifndef __LPN_H__ #define __LPN_H__ -#include "../include/mesh/mesh.h" +#include "mesh/mesh.h" int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, struct os_mbuf *buf); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/mesh.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/mesh.c index 7ad1264ae..52fbdbf66 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/mesh.c @@ -6,17 +6,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_LOG #include #include -#include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "../include/mesh/mesh.h" -#include "nimble/nimble/host/include/host/ble_uuid.h" +#include "os/os_mbuf.h" +#include "mesh/mesh.h" +#include "host/ble_uuid.h" #include "adv.h" #include "prov.h" @@ -361,4 +359,3 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov, return 0; } -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/mesh_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/mesh_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_cli.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_cli.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_cli.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_cli.c index c8b10df0c..b00cfa520 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_cli.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_cli.c @@ -4,13 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG -#include "../include/mesh/mesh.h" -#include "../include/mesh/model_cli.h" +#include "mesh/mesh.h" +#include "mesh/model_cli.h" #include "mesh_priv.h" static s32_t msg_timeout = K_SECONDS(5); @@ -300,4 +298,4 @@ done: os_mbuf_free_chain(msg); return err; } -#endif + diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_srv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_srv.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_srv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_srv.c index e7bbf38d0..5f5a8df42 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_srv.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_srv.c @@ -4,13 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG -#include "../include/mesh/mesh.h" -#include "../include/mesh/model_srv.h" +#include "mesh/mesh.h" +#include "mesh/model_srv.h" #include "mesh_priv.h" static struct bt_mesh_gen_onoff_srv *gen_onoff_srv; @@ -266,4 +264,3 @@ static int lightness_srv_init(struct bt_mesh_model *model) const struct bt_mesh_model_cb light_lightness_srv_cb = { .init = lightness_srv_init, }; -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.c index b8e48d6ed..cf11c2d4f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.c @@ -6,17 +6,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_NET_LOG #include #include #include -#include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "../include/mesh/mesh.h" +#include "os/os_mbuf.h" +#include "mesh/mesh.h" #include "crypto.h" #include "adv.h" @@ -256,7 +254,8 @@ int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16]) void friend_cred_refresh(u16_t net_idx) { int i; - +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtype-limits" for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { struct friend_cred *cred = &friend_cred[i]; @@ -266,6 +265,7 @@ void friend_cred_refresh(u16_t net_idx) sizeof(cred->cred[0])); } } +#pragma GCC diagnostic pop } int friend_cred_update(struct bt_mesh_subnet *sub) @@ -273,7 +273,8 @@ int friend_cred_update(struct bt_mesh_subnet *sub) int err, i; BT_DBG("net_idx 0x%04x", sub->net_idx); - +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtype-limits" for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { struct friend_cred *cred = &friend_cred[i]; @@ -287,7 +288,7 @@ int friend_cred_update(struct bt_mesh_subnet *sub) return err; } } - +#pragma GCC diagnostic pop return 0; } @@ -298,7 +299,8 @@ struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr, int i, err; BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr); - +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtype-limits" for (cred = NULL, i = 0; i < ARRAY_SIZE(friend_cred); i++) { if ((friend_cred[i].addr == BT_MESH_ADDR_UNASSIGNED) || (friend_cred[i].addr == addr && @@ -307,7 +309,7 @@ struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr, break; } } - +#pragma GCC diagnostic pop if (!cred) { BT_WARN("No free friend credential slots"); return NULL; @@ -347,7 +349,8 @@ void friend_cred_clear(struct friend_cred *cred) int friend_cred_del(u16_t net_idx, u16_t addr) { int i; - +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtype-limits" for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { struct friend_cred *cred = &friend_cred[i]; @@ -356,7 +359,7 @@ int friend_cred_del(u16_t net_idx, u16_t addr) return 0; } } - +#pragma GCC diagnostic pop return -ENOENT; } @@ -366,7 +369,8 @@ int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid, int i; BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr); - +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtype-limits" for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { struct friend_cred *cred = &friend_cred[i]; @@ -392,7 +396,7 @@ int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid, return 0; } - +#pragma GCC diagnostic pop return -ENOENT; } @@ -1026,7 +1030,8 @@ static int friend_decrypt(struct bt_mesh_subnet *sub, const u8_t *data, int i; BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx); - +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtype-limits" for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { struct friend_cred *cred = &friend_cred[i]; @@ -1051,7 +1056,7 @@ static int friend_decrypt(struct bt_mesh_subnet *sub, const u8_t *data, return 0; } } - +#pragma GCC diagnostic pop return -ENOENT; } @@ -1433,4 +1438,3 @@ void bt_mesh_net_init(void) k_work_init(&bt_mesh.local_work, bt_mesh_net_local); net_buf_slist_init(&bt_mesh.local_queue); } -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.h index 1a7e3aa7d..976da0053 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.h @@ -22,8 +22,8 @@ #include #include "atomic.h" -#include "../include/mesh/mesh.h" -#include "../include/mesh/glue.h" +#include "mesh/mesh.h" +#include "mesh/glue.h" /* How many hours in between updating IVU duration */ #define BT_MESH_IVU_MIN_HOURS 96 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/nodes.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/nodes.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/nodes.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/nodes.c index de41f40d0..127ef21e4 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/nodes.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/nodes.c @@ -4,14 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_PROV_LOG #if MYNEWT_VAL(BLE_MESH_PROVISIONER) -#include "../include/mesh/mesh.h" +#include "mesh/mesh.h" #include "mesh_priv.h" #include "net.h" @@ -161,4 +159,3 @@ void bt_mesh_node_del(struct bt_mesh_node *node, bool store) } #endif -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/nodes.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/nodes.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/nodes.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/nodes.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.c index f8f22fa7e..fe92c0e34 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.c @@ -6,16 +6,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_PROV_LOG #if MYNEWT_VAL(BLE_MESH_PROV) #include -#include "../include/mesh/mesh.h" +#include "mesh/mesh.h" #include "mesh_priv.h" #include "crypto.h" @@ -2008,4 +2006,3 @@ void bt_mesh_prov_reset(void) } #endif /* MYNEWT_VAL(BLE_MESH_PROV) */ -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.h similarity index 85% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.h index c6866c9e2..96e5a447c 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.h @@ -9,9 +9,9 @@ #ifndef __PROV_H__ #define __PROV_H__ -#include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "../include/mesh/mesh.h" -#include "nimble/nimble/host/src/ble_hs_conn_priv.h" +#include "os/os_mbuf.h" +#include "mesh/mesh.h" +#include "../src/ble_hs_conn_priv.h" int bt_mesh_pb_adv_open(const u8_t uuid[16], u16_t net_idx, u16_t addr, u8_t attention_duration); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.c index 6801791f1..134a36dd6 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.c @@ -6,17 +6,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_PROXY_LOG #if MYNEWT_VAL(BLE_MESH_PROXY) -#include "../include/mesh/mesh.h" -#include "nimble/nimble/host/include/host/ble_att.h" -#include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" -#include "nimble/nimble/host/src/ble_hs_priv.h" +#include "mesh/mesh.h" +#include "host/ble_att.h" +#include "services/gatt/ble_svc_gatt.h" +#include "../../host/src/ble_hs_priv.h" #include "mesh_priv.h" #include "adv.h" @@ -1499,4 +1497,3 @@ int bt_mesh_proxy_init(void) } #endif /* MYNEWT_VAL(BLE_MESH_PROXY) */ -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.h similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.h index e099947c9..64338a0a3 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.h @@ -14,7 +14,7 @@ #define BT_MESH_PROXY_CONFIG 0x02 #define BT_MESH_PROXY_PROV 0x03 -#include "../include/mesh/mesh.h" +#include "mesh/mesh.h" int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type, struct os_mbuf *msg); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/settings.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/settings.c index 2130e9e6c..88d9b302e 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/settings.c @@ -4,15 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_SETTINGS_LOG #if MYNEWT_VAL(BLE_MESH_SETTINGS) -#include "../include/mesh/mesh.h" -#include "../include/mesh/glue.h" +#include "mesh/mesh.h" +#include "mesh/glue.h" #include "net.h" #include "crypto.h" #include "transport.h" @@ -2083,4 +2081,3 @@ void bt_mesh_settings_init(void) } #endif /* MYNEWT_VAL(BLE_MESH_SETTINGS) */ -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/settings.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/settings.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/shell.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/shell.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/shell.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/shell.c index c19342764..91fbd9785 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/shell.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/shell.c @@ -9,8 +9,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) +#include "syscfg/syscfg.h" #if MYNEWT_VAL(BLE_MESH_SHELL) @@ -2818,4 +2817,3 @@ void ble_mesh_shell_init(void) #endif } -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/shell.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/shell.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/shell.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/shell.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_cmd_priv.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_cmd_priv.h index 18f473603..70f33260a 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_cmd_priv.h @@ -22,7 +22,7 @@ #include #include -#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include "os/os_mbuf.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h index ab59c4f01..73b6aeab0 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h @@ -21,10 +21,10 @@ #define H_BLE_ATT_PRIV_ #include -#include "nimble/porting/nimble/include/stats/stats.h" -#include "nimble/nimble/host/include/host/ble_att.h" -#include "nimble/nimble/host/include/host/ble_uuid.h" -#include "nimble/nimble/include/nimble/nimble_npl.h" +#include "stats/stats.h" +#include "host/ble_att.h" +#include "host/ble_uuid.h" +#include "nimble/nimble_npl.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h index 3767ddba8..2b6b40696 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h @@ -21,9 +21,9 @@ #define H_BLE_GAP_CONN_ #include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/stats/stats.h" -#include "nimble/nimble/host/include/host/ble_gap.h" +#include "syscfg/syscfg.h" +#include "stats/stats.h" +#include "host/ble_gap.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h new file mode 100644 index 000000000..4a59635b8 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h @@ -0,0 +1,199 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_GATT_PRIV_ +#define H_BLE_GATT_PRIV_ + +#include "syscfg/syscfg.h" +#include "stats/stats.h" +#include "host/ble_gatt.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_att_read_type_adata; +struct ble_att_find_type_value_hinfo; +struct ble_att_find_info_idata; +struct ble_att_read_group_type_adata; +struct ble_att_prep_write_cmd; + +STATS_SECT_START(ble_gattc_stats) + STATS_SECT_ENTRY(mtu) + STATS_SECT_ENTRY(mtu_fail) + STATS_SECT_ENTRY(disc_all_svcs) + STATS_SECT_ENTRY(disc_all_svcs_fail) + STATS_SECT_ENTRY(disc_svc_uuid) + STATS_SECT_ENTRY(disc_svc_uuid_fail) + STATS_SECT_ENTRY(find_inc_svcs) + STATS_SECT_ENTRY(find_inc_svcs_fail) + STATS_SECT_ENTRY(disc_all_chrs) + STATS_SECT_ENTRY(disc_all_chrs_fail) + STATS_SECT_ENTRY(disc_chrs_uuid) + STATS_SECT_ENTRY(disc_chrs_uuid_fail) + STATS_SECT_ENTRY(disc_all_dscs) + STATS_SECT_ENTRY(disc_all_dscs_fail) + STATS_SECT_ENTRY(read) + STATS_SECT_ENTRY(read_fail) + STATS_SECT_ENTRY(read_uuid) + STATS_SECT_ENTRY(read_uuid_fail) + STATS_SECT_ENTRY(read_long) + STATS_SECT_ENTRY(read_long_fail) + STATS_SECT_ENTRY(read_mult) + STATS_SECT_ENTRY(read_mult_fail) + STATS_SECT_ENTRY(write_no_rsp) + STATS_SECT_ENTRY(write_no_rsp_fail) + STATS_SECT_ENTRY(write) + STATS_SECT_ENTRY(write_fail) + STATS_SECT_ENTRY(write_long) + STATS_SECT_ENTRY(write_long_fail) + STATS_SECT_ENTRY(write_reliable) + STATS_SECT_ENTRY(write_reliable_fail) + STATS_SECT_ENTRY(notify) + STATS_SECT_ENTRY(notify_fail) + STATS_SECT_ENTRY(indicate) + STATS_SECT_ENTRY(indicate_fail) + STATS_SECT_ENTRY(proc_timeout) +STATS_SECT_END +extern STATS_SECT_DECL(ble_gattc_stats) ble_gattc_stats; + +STATS_SECT_START(ble_gatts_stats) + STATS_SECT_ENTRY(svcs) + STATS_SECT_ENTRY(chrs) + STATS_SECT_ENTRY(dscs) + STATS_SECT_ENTRY(svc_def_reads) + STATS_SECT_ENTRY(svc_inc_reads) + STATS_SECT_ENTRY(chr_def_reads) + STATS_SECT_ENTRY(chr_val_reads) + STATS_SECT_ENTRY(chr_val_writes) + STATS_SECT_ENTRY(dsc_reads) + STATS_SECT_ENTRY(dsc_writes) +STATS_SECT_END +extern STATS_SECT_DECL(ble_gatts_stats) ble_gatts_stats; + +#define BLE_GATT_CHR_DECL_SZ_16 5 +#define BLE_GATT_CHR_DECL_SZ_128 19 + +typedef uint8_t ble_gatts_conn_flags; + +struct ble_gatts_conn { + struct ble_gatts_clt_cfg *clt_cfgs; + int num_clt_cfgs; + + uint16_t indicate_val_handle; +}; + +/*** @client. */ + +int ble_gattc_locked_by_cur_task(void); +void ble_gatts_indicate_fail_notconn(uint16_t conn_handle); + +void ble_gattc_rx_err(uint16_t conn_handle, uint16_t handle, uint16_t status); +void ble_gattc_rx_mtu(uint16_t conn_handle, int status, uint16_t chan_mtu); +void ble_gattc_rx_read_type_adata(uint16_t conn_handle, + struct ble_att_read_type_adata *adata); +void ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status); +void ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, + struct os_mbuf **rxom); +void ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, + struct os_mbuf **rxom); +void ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, + struct os_mbuf **rxom); +void ble_gattc_rx_read_group_type_adata( + uint16_t conn_handle, struct ble_att_read_group_type_adata *adata); +void ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int rc); +void ble_gattc_rx_find_type_value_hinfo( + uint16_t conn_handle, struct ble_att_find_type_value_hinfo *hinfo); +void ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status); +void ble_gattc_rx_write_rsp(uint16_t conn_handle); +void ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, + uint16_t handle, uint16_t offset, + struct os_mbuf **rxom); +void ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status); +void ble_gattc_rx_indicate_rsp(uint16_t conn_handle); +void ble_gattc_rx_find_info_idata(uint16_t conn_handle, + struct ble_att_find_info_idata *idata); +void ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status); +void ble_gattc_connection_txable(uint16_t conn_handle); +void ble_gattc_connection_broken(uint16_t conn_handle); +int32_t ble_gattc_timer(void); + +int ble_gattc_any_jobs(void); +int ble_gattc_init(void); + +/*** @server. */ +#define BLE_GATTS_CLT_CFG_F_NOTIFY 0x0001 +#define BLE_GATTS_CLT_CFG_F_INDICATE 0x0002 +#define BLE_GATTS_CLT_CFG_F_MODIFIED 0x0080 /* Internal only. */ +#define BLE_GATTS_CLT_CFG_F_RESERVED 0xfffc + +#define BLE_GATTS_INC_SVC_LEN_NO_UUID 4 +#define BLE_GATTS_INC_SVC_LEN_UUID 6 + +/** + * Contains counts of resources required by the GATT server. The contents of + * this struct are generally used to populate a configuration struct before + * the host is initialized. + */ +struct ble_gatt_resources { + /** Number of services. */ + uint16_t svcs; + + /** Number of included services. */ + uint16_t incs; + + /** Number of characteristics. */ + uint16_t chrs; + + /** Number of descriptors. */ + uint16_t dscs; + + /** + * Number of client characteristic configuration descriptors. Each of + * these also contributes to the total descriptor count. + */ + uint16_t cccds; + + /** Total number of ATT attributes. */ + uint16_t attrs; +}; + +int ble_gatts_rx_indicate_ack(uint16_t conn_handle, uint16_t chr_val_handle); +int ble_gatts_send_next_indicate(uint16_t conn_handle); +void ble_gatts_tx_notifications(void); +void ble_gatts_bonding_established(uint16_t conn_handle); +void ble_gatts_bonding_restored(uint16_t conn_handle); +void ble_gatts_connection_broken(uint16_t conn_handle); +void ble_gatts_lcl_svc_foreach(ble_gatt_svc_foreach_fn cb, void *arg); +int ble_gatts_register_svcs(const struct ble_gatt_svc_def *svcs, + ble_gatt_register_fn *register_cb, + void *cb_arg); +int ble_gatts_clt_cfg_access(uint16_t conn_handle, uint16_t attr_handle, + uint8_t op, uint16_t offset, struct os_mbuf **om, + void *arg); + +/*** @misc. */ +int ble_gatts_conn_can_alloc(void); +int ble_gatts_conn_init(struct ble_gatts_conn *gatts_conn); +int ble_gatts_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_adv_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_adv_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_adv_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_adv_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_atomic_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_atomic_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_atomic_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_atomic_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_conn_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_conn_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_conn_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_conn_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_flow_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_flow_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_flow_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_flow_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h index d8a72cb29..362f12cbd 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h @@ -20,7 +20,7 @@ #ifndef H_BLE_HS_HCI_PRIV_ #define H_BLE_HS_HCI_PRIV_ -#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/hci_common.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_id_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_id_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mbuf_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_mbuf_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mbuf_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_mbuf_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_periodic_sync_priv.h similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_periodic_sync_priv.h index f16132f04..c82ea7904 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_periodic_sync_priv.h @@ -21,7 +21,7 @@ #define H_BLE_HS_PERIODIC_SYNC_ #include -#include "nimble/porting/nimble/include/os/queue.h" +#include "os/queue.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_priv.h similarity index 95% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_priv.h index 952690e71..538d07a97 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_priv.h @@ -42,10 +42,10 @@ #include "ble_hs_id_priv.h" #include "ble_hs_periodic_sync_priv.h" #include "ble_uuid_priv.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "nimble/nimble/host/include/host/ble_monitor.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/porting/nimble/include/stats/stats.h" +#include "host/ble_hs.h" +#include "host/ble_monitor.h" +#include "nimble/nimble_opt.h" +#include "stats/stats.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_pvcy_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_pvcy_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_resolv_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_resolv_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_startup_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_startup_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_startup_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_startup_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h similarity index 93% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h index 911946e05..5ebdaa050 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h @@ -21,10 +21,10 @@ #define H_L2CAP_COC_PRIV_ #include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/queue.h" -#include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "nimble/nimble/host/include/host/ble_l2cap.h" +#include "syscfg/syscfg.h" +#include "os/queue.h" +#include "os/os_mbuf.h" +#include "host/ble_l2cap.h" #include "ble_l2cap_sig_priv.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h similarity index 95% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h index 30af30427..e3409743b 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h @@ -21,11 +21,11 @@ #define H_L2CAP_PRIV_ #include "ble_l2cap_coc_priv.h" -#include "nimble/nimble/host/include/host/ble_l2cap.h" +#include "host/ble_l2cap.h" #include -#include "nimble/porting/nimble/include/stats/stats.h" -#include "nimble/porting/nimble/include/os/queue.h" -#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include "stats/stats.h" +#include "os/queue.h" +#include "os/os_mbuf.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h index a0e2e58cf..a698cd0d8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h @@ -20,7 +20,7 @@ #ifndef H_BLE_L2CAP_SIG_ #define H_BLE_L2CAP_SIG_ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "syscfg/syscfg.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_monitor_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_monitor_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_monitor_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_monitor_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h index 853b33f7a..def0a32f5 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h @@ -21,9 +21,9 @@ #define H_BLE_SM_PRIV_ #include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/queue.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "syscfg/syscfg.h" +#include "os/queue.h" +#include "nimble/nimble_opt.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_uuid_priv.h similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_uuid_priv.h index 39ce88d7a..3dbcc6b8e 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_uuid_priv.h @@ -20,7 +20,7 @@ #ifndef H_BLE_UUID_PRIV_ #define H_BLE_UUID_PRIV_ -#include "nimble/nimble/host/include/host/ble_uuid.h" +#include "host/ble_uuid.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c new file mode 100644 index 000000000..d0a053760 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "console/console.h" +#include "mesh/testing.h" +#include "mesh/slist.h" +#include "mesh/glue.h" +#include "mesh/access.h" + +#include "net.h" +#include "testing.h" +#include "access.h" +#include "foundation.h" +#include "lpn.h" +#include "transport.h" + +static sys_slist_t cb_slist; + +void bt_test_cb_register(struct bt_test_cb *cb) +{ + sys_slist_append(&cb_slist, &cb->node); +} + +void bt_test_cb_unregister(struct bt_test_cb *cb) +{ + sys_slist_find_and_remove(&cb_slist, &cb->node); +} + +void bt_test_mesh_net_recv(u8_t ttl, u8_t ctl, u16_t src, u16_t dst, + const void *payload, size_t payload_len) +{ + struct bt_test_cb *cb; + + SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) { + if (cb->mesh_net_recv) { + cb->mesh_net_recv(ttl, ctl, src, dst, payload, + payload_len); + } + } +} + +void bt_test_mesh_model_bound(u16_t addr, struct bt_mesh_model *model, + u16_t key_idx) +{ + struct bt_test_cb *cb; + + SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) { + if (cb->mesh_model_bound) { + cb->mesh_model_bound(addr, model, key_idx); + } + } +} + +void bt_test_mesh_model_unbound(u16_t addr, struct bt_mesh_model *model, + u16_t key_idx) +{ + struct bt_test_cb *cb; + + SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) { + if (cb->mesh_model_unbound) { + cb->mesh_model_unbound(addr, model, key_idx); + } + } +} + +void bt_test_mesh_prov_invalid_bearer(u8_t opcode) +{ + struct bt_test_cb *cb; + + SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) { + if (cb->mesh_prov_invalid_bearer) { + cb->mesh_prov_invalid_bearer(opcode); + } + } +} + +void bt_test_mesh_trans_incomp_timer_exp(void) +{ + struct bt_test_cb *cb; + + SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) { + if (cb->mesh_trans_incomp_timer_exp) { + cb->mesh_trans_incomp_timer_exp(); + } + } +} + +int bt_test_mesh_lpn_group_add(u16_t group) +{ + bt_mesh_lpn_group_add(group); + + return 0; +} + +int bt_test_mesh_lpn_group_remove(u16_t *groups, size_t groups_count) +{ + bt_mesh_lpn_group_del(groups, groups_count); + + return 0; +} + +int bt_test_mesh_rpl_clear(void) +{ + bt_mesh_rpl_clear(); + + return 0; +} + +void bt_test_print_credentials(void) +{ + int i; + u8_t nid; + const u8_t *enc; + const u8_t *priv; + struct bt_mesh_subnet *sub; + struct bt_mesh_app_key *app_key; + + console_printf("IV Index: %08lx\n", (long) bt_mesh.iv_index); + console_printf("Dev key: %s\n", bt_hex(bt_mesh.dev_key, 16)); + + for (i = 0; i < MYNEWT_VAL(BLE_MESH_SUBNET_COUNT); ++i) + { + if (bt_mesh.app_keys[i].net_idx == BT_MESH_KEY_UNUSED) { + continue; + } + + sub = &bt_mesh.sub[i]; + + console_printf("Subnet: %d\n", i); + console_printf("\tNetKeyIdx: %04x\n", + sub->net_idx); + console_printf("\tNetKey: %s\n", + bt_hex(sub->keys[sub->kr_flag].net, 16)); + } + + for (i = 0; i < MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT); ++i) + { + if (bt_mesh.app_keys[i].net_idx == BT_MESH_KEY_UNUSED) { + continue; + } + + sub = &bt_mesh.sub[i]; + app_key = &bt_mesh.app_keys[i]; + + console_printf("AppKey: %d\n", i); + console_printf("\tNetKeyIdx: %04x\n", + app_key->net_idx); + console_printf("\tAppKeyIdx: %04x\n", + app_key->app_idx); + console_printf("\tAppKey: %s\n", + bt_hex(app_key->keys[sub->kr_flag].val, 16)); + } + + for (i = 0; i < MYNEWT_VAL(BLE_MESH_SUBNET_COUNT); ++i) + { + if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) { + continue; + } + + if (friend_cred_get(&bt_mesh.sub[i], BT_MESH_ADDR_UNASSIGNED, + &nid, &enc, &priv)) { + return; + } + + console_printf("Friend cred: %d\n", i); + console_printf("\tNetKeyIdx: %04x\n", + bt_mesh.sub[i].net_idx); + console_printf("\tNID: %02x\n", nid); + console_printf("\tEncKey: %s\n", + bt_hex(enc, 16)); + console_printf("\tPrivKey: %s\n", + bt_hex(priv, 16)); + } +} + +int bt_test_shell_init(void) +{ +#if MYNEWT_VAL(BLE_MESH_SHELL) + return cmd_mesh_init(0, NULL); +#else + return -ENOTSUP; +#endif +} + +int bt_test_bind_app_key_to_model(struct bt_mesh_model *model, u16_t key_idx, u16_t id) +{ + struct bt_mesh_model *found_model; + + found_model = bt_mesh_model_find(bt_mesh_model_elem(model), id); + if (!found_model) { + return STATUS_INVALID_MODEL; + } + + return mod_bind(found_model, key_idx); +} diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h new file mode 100644 index 000000000..166a9eea6 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h @@ -0,0 +1,23 @@ +/** + * @file testing.h + * @brief Internal API for Bluetooth testing. + */ + +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mesh/glue.h" +#include "mesh/access.h" + +void bt_test_mesh_model_bound(u16_t addr, struct bt_mesh_model *model, + u16_t key_idx); +void bt_test_mesh_model_unbound(u16_t addr, struct bt_mesh_model *model, + u16_t key_idx); +void bt_test_mesh_prov_invalid_bearer(u8_t opcode); +void bt_test_mesh_net_recv(u8_t ttl, u8_t ctl, u16_t src, u16_t dst, + const void *payload, size_t payload_len); +void bt_test_mesh_trans_incomp_timer_exp(void); +void bt_test_print_credentials(void); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.c index c8e716a04..caf1b4f12 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.c @@ -6,15 +6,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - +#include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_TRANS_LOG #include #include -#include "../include/mesh/mesh.h" +#include "mesh/mesh.h" #include "mesh_priv.h" #include "crypto.h" @@ -1668,4 +1666,3 @@ int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, u16_t app_idx, return 0; } -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.h similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.h index 227ba5922..eff768e9f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.h @@ -6,8 +6,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "../include/mesh/mesh.h" +#include "syscfg/syscfg.h" +#include "mesh/mesh.h" #define TRANS_SEQ_AUTH_NVAL 0xffffffffffffffff diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/src/ble_svc_ans.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ans/src/ble_svc_ans.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/src/ble_svc_ans.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ans/src/ble_svc_ans.c index 2fc50c4be..5b64f18c4 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/src/ble_svc_ans.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ans/src/ble_svc_ans.c @@ -20,11 +20,11 @@ #include #include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "nimble/nimble/host/include/host/ble_gap.h" -#include "../include/services/ans/ble_svc_ans.h" +#include "sysinit/sysinit.h" +#include "syscfg/syscfg.h" +#include "host/ble_hs.h" +#include "host/ble_gap.h" +#include "services/ans/ble_svc_ans.h" /* Max length of new alert info string */ #define BLE_SVC_ANS_INFO_STR_MAX_LEN 18 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/src/ble_svc_bas.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/bas/src/ble_svc_bas.c similarity index 92% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/src/ble_svc_bas.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/bas/src/ble_svc_bas.c index 317b11627..631519cf9 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/src/ble_svc_bas.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/bas/src/ble_svc_bas.c @@ -20,11 +20,11 @@ #include #include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "nimble/nimble/host/include/host/ble_gap.h" -#include "../include/services/bas/ble_svc_bas.h" +#include "sysinit/sysinit.h" +#include "syscfg/syscfg.h" +#include "host/ble_hs.h" +#include "host/ble_gap.h" +#include "services/bas/ble_svc_bas.h" /* Characteristic value handles */ #if MYNEWT_VAL(BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE) > 0 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/src/ble_svc_gap.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gap/src/ble_svc_gap.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/src/ble_svc_gap.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gap/src/ble_svc_gap.c index f1cf2d9ba..e79b2b872 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/src/ble_svc_gap.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gap/src/ble_svc_gap.c @@ -20,10 +20,10 @@ #include #include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/services/gap/ble_svc_gap.h" -#include "nimble/porting/nimble/include/os/endian.h" +#include "sysinit/sysinit.h" +#include "host/ble_hs.h" +#include "services/gap/ble_svc_gap.h" +#include "os/endian.h" #define PPCP_ENABLED \ MYNEWT_VAL(BLE_ROLE_PERIPHERAL) && \ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gatt/src/ble_svc_gatt.c similarity index 95% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gatt/src/ble_svc_gatt.c index eef3c49ba..78b4a0683 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gatt/src/ble_svc_gatt.c @@ -19,9 +19,9 @@ #include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/services/gatt/ble_svc_gatt.h" +#include "sysinit/sysinit.h" +#include "host/ble_hs.h" +#include "services/gatt/ble_svc_gatt.h" static uint16_t ble_svc_gatt_changed_val_handle; static uint16_t ble_svc_gatt_start_handle; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/src/ble_svc_ias.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ias/src/ble_svc_ias.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/src/ble_svc_ias.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ias/src/ble_svc_ias.c index 98be867f1..9f5da1485 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/src/ble_svc_ias.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ias/src/ble_svc_ias.c @@ -19,9 +19,9 @@ #include #include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/services/ias/ble_svc_ias.h" +#include "sysinit/sysinit.h" +#include "host/ble_hs.h" +#include "services/ias/ble_svc_ias.h" /* Callback function */ static ble_svc_ias_event_fn *ble_svc_ias_cb_fn; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/src/ble_svc_ipss.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ipss/src/ble_svc_ipss.c similarity index 89% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/src/ble_svc_ipss.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ipss/src/ble_svc_ipss.c index dd9d4ee96..f42ca1e9e 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/src/ble_svc_ipss.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ipss/src/ble_svc_ipss.c @@ -19,9 +19,9 @@ #include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/services/ipss/ble_svc_ipss.h" +#include "sysinit/sysinit.h" +#include "host/ble_hs.h" +#include "services/ipss/ble_svc_ipss.h" static const struct ble_gatt_svc_def ble_svc_ipss_defs[] = { { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/src/ble_svc_lls.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/lls/src/ble_svc_lls.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/src/ble_svc_lls.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/lls/src/ble_svc_lls.c index 822f72ece..b5f7f9bd4 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/src/ble_svc_lls.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/lls/src/ble_svc_lls.c @@ -19,9 +19,9 @@ #include #include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/services/lls/ble_svc_lls.h" +#include "sysinit/sysinit.h" +#include "host/ble_hs.h" +#include "services/lls/ble_svc_lls.h" /* Callback function */ static ble_svc_lls_event_fn *ble_svc_lls_cb_fn; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_hs_hci_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_hs_hci_priv.h new file mode 100644 index 000000000..362f12cbd --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_hs_hci_priv.h @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_HS_HCI_PRIV_ +#define H_BLE_HS_HCI_PRIV_ + +#include "nimble/hci_common.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_hs_conn; +struct os_mbuf; + +#define BLE_HS_HCI_LE_FEAT_ENCRYPTION (0x00000001) +#define BLE_HS_HCI_LE_FEAT_CONN_PARAM_REQUEST (0x00000002) +#define BLE_HS_HCI_LE_FEAT_EXT_REJECT (0x00000004) +#define BLE_HS_HCI_LE_FEAT_SLAVE_FEAT_EXCHANGE (0x00000008) +#define BLE_HS_HCI_LE_FEAT_PING (0x00000010) +#define BLE_HS_HCI_LE_FEAT_DATA_PACKET_LENGTH_EXT (0x00000020) +#define BLE_HS_HCI_LE_FEAT_LL_PRIVACY (0x00000040) +#define BLE_HS_HCI_LE_FEAT_EXT_SCANNER_FILTER_POLICIES (0x00000080) +#define BLE_HS_HCI_LE_FEAT_2M_PHY (0x00000100) +#define BLE_HS_HCI_LE_FEAT_STABLE_MOD_INDEX_TX (0x00000200) +#define BLE_HS_HCI_LE_FEAT_STABLE_MOD_INDEX_RX (0x00000400) +#define BLE_HS_HCI_LE_FEAT_CODED_PHY (0x00000800) +#define BLE_HS_HCI_LE_FEAT_EXT_ADV (0x00001000) +#define BLE_HS_HCI_LE_FEAT_PERIODIC_ADV (0x00002000) +#define BLE_HS_HCI_LE_FEAT_CSA2 (0x00004000) +#define BLE_HS_HCI_LE_FEAT_POWER_CLASS_1 (0x00008000) +#define BLE_HS_HCI_LE_FEAT_MIN_NUM_USED_CHAN (0x00010000) + +struct ble_hs_hci_ack { + int bha_status; /* A BLE_HS_E<...> error; NOT a naked HCI code. */ + const uint8_t *bha_params; + int bha_params_len; + uint16_t bha_opcode; + uint8_t bha_hci_handle; +}; + +#if MYNEWT_VAL(BLE_EXT_ADV) +struct ble_hs_hci_ext_scan_param { + uint8_t scan_type; + uint16_t scan_itvl; + uint16_t scan_window; +}; + +struct ble_hs_hci_ext_conn_params { + uint16_t scan_itvl; + uint16_t scan_window; + uint16_t conn_itvl; + uint16_t conn_windows; +}; + +#if MYNEWT_VAL(BLE_PERIODIC_ADV) +/* Periodic Advertising Parameters */ +struct hci_periodic_adv_params +{ + uint16_t min_interval; + uint16_t max_interval; + uint16_t properties; +}; +#endif +#endif + +extern uint16_t ble_hs_hci_avail_pkts; + +int ble_hs_hci_cmd_tx(uint16_t opcode, const void *cmd, uint8_t cmd_len, + void *rsp, uint8_t rsp_len); +void ble_hs_hci_init(void); +void ble_hs_hci_deinit(void); + +void ble_hs_hci_set_le_supported_feat(uint32_t feat); +uint32_t ble_hs_hci_get_le_supported_feat(void); +void ble_hs_hci_set_hci_version(uint8_t hci_version); +uint8_t ble_hs_hci_get_hci_version(void); + +#if MYNEWT_VAL(BLE_HS_PHONY_HCI_ACKS) +typedef int ble_hs_hci_phony_ack_fn(uint8_t *ack, int ack_buf_len); +void ble_hs_hci_set_phony_ack_cb(ble_hs_hci_phony_ack_fn *cb); +#endif + +int ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_pwr); +int ble_hs_hci_util_rand(void *dst, int len); +int ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi); +int ble_hs_hci_util_set_random_addr(const uint8_t *addr); +int ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om, + struct hci_data_hdr *out_hdr); +int ble_hs_hci_evt_process(const struct ble_hci_ev *ev); + +int ble_hs_hci_cmd_send_buf(uint16_t opcode, const void *buf, uint8_t buf_len); +int ble_hs_hci_set_buf_sz(uint16_t pktlen, uint16_t max_pkts); +void ble_hs_hci_add_avail_pkts(uint16_t delta); + +uint16_t ble_hs_hci_util_handle_pb_bc_join(uint16_t handle, uint8_t pb, + uint8_t bc); + +int ble_hs_hci_acl_tx_now(struct ble_hs_conn *conn, struct os_mbuf **om); +int ble_hs_hci_acl_tx(struct ble_hs_conn *conn, struct os_mbuf **om); + +int ble_hs_hci_frag_num_mbufs(void); +int ble_hs_hci_frag_num_mbufs_free(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/src/ble_svc_tps.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_svc_tps.c similarity index 91% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/src/ble_svc_tps.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_svc_tps.c index 0099a9689..9885a9216 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/src/ble_svc_tps.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_svc_tps.c @@ -19,16 +19,16 @@ #include #include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/services/tps/ble_svc_tps.h" +#include "sysinit/sysinit.h" +#include "syscfg/syscfg.h" +#include "host/ble_hs.h" +#include "services/tps/ble_svc_tps.h" /* XXX: We shouldn't be including the host's private header files. The host * API needs to be updated with a function to query the advertising transmit * power. */ -#include "nimble/nimble/host/src/ble_hs_hci_priv.h" +#include "../src/ble_hs_hci_priv.h" int8_t ble_svc_tps_tx_power_level; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att.c similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att.c diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_clt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_clt.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_clt.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_clt.c index 2416ecbcb..09fc9ea23 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_clt.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_clt.c @@ -21,9 +21,9 @@ #include #include #include -#include "nimble/porting/nimble/include/os/os_mempool.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/host/include/host/ble_uuid.h" +#include "os/os_mempool.h" +#include "nimble/ble.h" +#include "host/ble_uuid.h" #include "ble_hs_priv.h" /***************************************************************************** diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c index 4c3af1f60..81b070f9c 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c @@ -19,11 +19,11 @@ #include #include -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/include/nimble/ble.h" +#include "os/os.h" +#include "nimble/ble.h" #include "ble_hs_priv.h" -#include "nimble/nimble/host/include/host/ble_att.h" -#include "nimble/nimble/host/include/host/ble_uuid.h" +#include "host/ble_att.h" +#include "host/ble_uuid.h" #include "ble_hs_priv.h" void * diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h new file mode 100644 index 000000000..70f33260a --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h @@ -0,0 +1,449 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_ATT_CMD_ +#define H_BLE_ATT_CMD_ + +#include +#include +#include "os/os_mbuf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_att_hdr { + uint8_t opcode; + uint8_t data[0]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Request Opcode In Error | 1 | + * | Attribute Handle In Error | 2 | + * | Error Code | 1 | + */ +#define BLE_ATT_ERROR_RSP_SZ 5 +struct ble_att_error_rsp { + uint8_t baep_req_op; + uint16_t baep_handle; + uint8_t baep_error_code; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Server Rx MTU | 2 | + */ +#define BLE_ATT_MTU_CMD_SZ 3 +struct ble_att_mtu_cmd { + uint16_t bamc_mtu; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Starting Handle | 2 | + * | Ending Handle | 2 | + */ +#define BLE_ATT_FIND_INFO_REQ_SZ 5 +struct ble_att_find_info_req { + uint16_t bafq_start_handle; + uint16_t bafq_end_handle; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Format | 1 | + * | Information Data | 4 to (ATT_MTU-2) | + */ +#define BLE_ATT_FIND_INFO_RSP_BASE_SZ 2 +struct ble_att_find_info_rsp { + uint8_t bafp_format; + /* Followed by information data. */ +} __attribute__((packed)); + +#define BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT 1 +#define BLE_ATT_FIND_INFO_RSP_FORMAT_128BIT 2 + +#define BLE_ATT_FIND_INFO_IDATA_16_SZ 4 +#define BLE_ATT_FIND_INFO_IDATA_128_SZ 18 + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Starting Handle | 2 | + * | Ending Handle | 2 | + * | Attribute Type | 2 | + * | Attribute Value | 0 to (ATT_MTU-7) | + */ +#define BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ 7 +struct ble_att_find_type_value_req { + uint16_t bavq_start_handle; + uint16_t bavq_end_handle; + uint16_t bavq_attr_type; + uint16_t bavq_value[0]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Information Data | 4 to (ATT_MTU-1) | + */ +#define BLE_ATT_FIND_TYPE_VALUE_RSP_BASE_SZ 1 +#define BLE_ATT_FIND_TYPE_VALUE_HINFO_BASE_SZ 4 + +struct ble_att_handle_group { + uint16_t attr_handle; + uint16_t group_end_handle; +} __attribute__((packed)); + +struct ble_att_find_type_value_rsp { + struct ble_att_handle_group list[0]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Starting Handle | 2 | + * | Ending Handle | 2 | + * | Attribute Type | 2 or 16 | + */ +#define BLE_ATT_READ_TYPE_REQ_BASE_SZ 5 +#define BLE_ATT_READ_TYPE_REQ_SZ_16 7 +#define BLE_ATT_READ_TYPE_REQ_SZ_128 21 +struct ble_att_read_type_req { + uint16_t batq_start_handle; + uint16_t batq_end_handle; + uint8_t uuid[0]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Length | 1 | + * | Attribute Data List | 2 to (ATT_MTU-2) | + */ +#define BLE_ATT_READ_TYPE_RSP_BASE_SZ 2 + +struct ble_att_attr_data_list { + uint16_t handle; + uint8_t value[0]; +} __attribute__((packed)); + +struct ble_att_read_type_rsp { + uint8_t batp_length; + struct ble_att_attr_data_list batp_list[0]; +} __attribute__((packed)); + +#define BLE_ATT_READ_TYPE_ADATA_BASE_SZ 2 +#define BLE_ATT_READ_TYPE_ADATA_SZ_16 6 +#define BLE_ATT_READ_TYPE_ADATA_SZ_128 20 + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Attribute Handle | 2 | + */ +#define BLE_ATT_READ_REQ_SZ 3 +struct ble_att_read_req { + uint16_t barq_handle; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Attribute Value | 0 to (ATT_MTU-1) | + */ +#define BLE_ATT_READ_RSP_BASE_SZ 1 + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Attribute Handle | 2 | + * | Value Offset | 2 | + */ +#define BLE_ATT_READ_BLOB_REQ_SZ 5 +struct ble_att_read_blob_req { + uint16_t babq_handle; + uint16_t babq_offset; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Attribute Value | 0 to (ATT_MTU-1) | + */ +#define BLE_ATT_READ_BLOB_RSP_BASE_SZ 1 + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Set Of Handles | 4 to (ATT_MTU-1) | + */ +#define BLE_ATT_READ_MULT_REQ_BASE_SZ 1 +struct ble_att_read_mult_req { + uint16_t handles[0]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Set Of Values | 4 to (ATT_MTU-1) | + */ +#define BLE_ATT_READ_MULT_RSP_BASE_SZ 1 + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Starting Handle | 2 | + * | Ending Handle | 2 | + * | Attribute Group Type | 2 or 16 | + */ +#define BLE_ATT_READ_GROUP_TYPE_REQ_BASE_SZ 5 +#define BLE_ATT_READ_GROUP_TYPE_REQ_SZ_16 7 +#define BLE_ATT_READ_GROUP_TYPE_REQ_SZ_128 21 +struct ble_att_read_group_type_req { + uint16_t bagq_start_handle; + uint16_t bagq_end_handle; + uint8_t uuid[0]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Length | 1 | + * | Attribute Data List | 2 to (ATT_MTU-2) | + */ +#define BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ 2 +struct ble_att_read_group_type_rsp { + uint8_t bagp_length; +} __attribute__((packed)); + +#define BLE_ATT_READ_GROUP_TYPE_ADATA_BASE_SZ 4 +#define BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_16 6 +#define BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_128 20 + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Attribute Handle | 2 | + * | Attribute Value | 0 to (ATT_MTU-3) | + */ +#define BLE_ATT_WRITE_REQ_BASE_SZ 3 +struct ble_att_write_req { + uint16_t bawq_handle; + uint8_t value[0]; +} __attribute__((packed)); + +#define BLE_ATT_WRITE_RSP_SZ 1 + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Attribute Handle | 2 | + * | Value Offset | 2 | + * | Part Attribute Value | 0 to (ATT_MTU-5) | + */ +#define BLE_ATT_PREP_WRITE_CMD_BASE_SZ 5 +struct ble_att_prep_write_cmd { + uint16_t bapc_handle; + uint16_t bapc_offset; + uint16_t bapc_value[0]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Flags | 1 | + */ +#define BLE_ATT_EXEC_WRITE_REQ_SZ 2 +struct ble_att_exec_write_req { + uint8_t baeq_flags; +} __attribute__((packed)); + +#define BLE_ATT_EXEC_WRITE_F_CANCEL 0x00 +#define BLE_ATT_EXEC_WRITE_F_EXECUTE 0x01 + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + */ +#define BLE_ATT_EXEC_WRITE_RSP_SZ 1 + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Attribute Handle | 2 | + * | Attribute Value | 0 to (ATT_MTU-3) | + */ +#define BLE_ATT_NOTIFY_REQ_BASE_SZ 3 +struct ble_att_notify_req { + uint16_t banq_handle; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Attribute Handle | 2 | + * | Attribute Value | 0 to (ATT_MTU-3) | + */ +#define BLE_ATT_INDICATE_REQ_BASE_SZ 3 +struct ble_att_indicate_req { + uint16_t baiq_handle; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + */ +#define BLE_ATT_INDICATE_RSP_SZ 1 + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Attribute Handle | 2 | + * | Attribute Value | 0 to (ATT_MTU-3) | + */ +#define BLE_ATT_WRITE_CMD_BASE_SZ 3 +struct ble_att_write_cmd { + uint16_t handle; + uint8_t value[0]; +} __attribute__((packed)); + +void ble_att_error_rsp_parse(const void *payload, int len, + struct ble_att_error_rsp *rsp); +void ble_att_error_rsp_write(void *payload, int len, + const struct ble_att_error_rsp *rsp); +void ble_att_mtu_req_parse(const void *payload, int len, + struct ble_att_mtu_cmd *cmd); +void ble_att_mtu_req_write(void *payload, int len, + const struct ble_att_mtu_cmd *cmd); +void ble_att_mtu_rsp_parse(const void *payload, int len, + struct ble_att_mtu_cmd *cmd); +void ble_att_mtu_rsp_write(void *payload, int len, + const struct ble_att_mtu_cmd *cmd); +void ble_att_find_info_req_parse(const void *payload, int len, + struct ble_att_find_info_req *req); +void ble_att_find_info_req_write(void *payload, int len, + const struct ble_att_find_info_req *req); +void ble_att_find_info_rsp_parse(const void *payload, int len, + struct ble_att_find_info_rsp *rsp); +void ble_att_find_info_rsp_write(void *payload, int len, + const struct ble_att_find_info_rsp *rsp); +void ble_att_find_type_value_req_parse( + const void *payload, int len, struct ble_att_find_type_value_req *req); +void ble_att_find_type_value_req_write( + void *payload, int len, const struct ble_att_find_type_value_req *req); +void ble_att_read_type_req_parse(const void *payload, int len, + struct ble_att_read_type_req *req); +void ble_att_read_type_req_write(void *payload, int len, + const struct ble_att_read_type_req *req); +void ble_att_read_type_rsp_parse(const void *payload, int len, + struct ble_att_read_type_rsp *rsp); +void ble_att_read_type_rsp_write(void *payload, int len, + const struct ble_att_read_type_rsp *rsp); +void ble_att_read_req_parse(const void *payload, int len, + struct ble_att_read_req *req); +void ble_att_read_req_write(void *payload, int len, + const struct ble_att_read_req *req); +void ble_att_read_blob_req_parse(const void *payload, int len, + struct ble_att_read_blob_req *req); +void ble_att_read_blob_req_write(void *payload, int len, + const struct ble_att_read_blob_req *req); +void ble_att_read_mult_req_parse(const void *payload, int len); +void ble_att_read_mult_req_write(void *payload, int len); +void ble_att_read_mult_rsp_parse(const void *payload, int len); +void ble_att_read_mult_rsp_write(void *payload, int len); +void ble_att_read_group_type_req_parse( + const void *payload, int len, struct ble_att_read_group_type_req *req); +void ble_att_read_group_type_req_write( + void *payload, int len, const struct ble_att_read_group_type_req *req); +void ble_att_read_group_type_rsp_parse( + const void *payload, int len, struct ble_att_read_group_type_rsp *rsp); +void ble_att_read_group_type_rsp_write( + void *payload, int len, const struct ble_att_read_group_type_rsp *rsp); +void ble_att_write_req_parse(const void *payload, int len, + struct ble_att_write_req *req); +void ble_att_write_req_write(void *payload, int len, + const struct ble_att_write_req *req); +void ble_att_write_cmd_parse(const void *payload, int len, + struct ble_att_write_req *req); +void ble_att_write_cmd_write(void *payload, int len, + const struct ble_att_write_req *req); +void ble_att_prep_write_req_parse(const void *payload, int len, + struct ble_att_prep_write_cmd *cmd); +void ble_att_prep_write_req_write(void *payload, int len, + const struct ble_att_prep_write_cmd *cmd); +void ble_att_prep_write_rsp_parse(const void *payload, int len, + struct ble_att_prep_write_cmd *cmd); +void ble_att_prep_write_rsp_write(void *payload, int len, + const struct ble_att_prep_write_cmd *cmd); +void ble_att_exec_write_req_parse(const void *payload, int len, + struct ble_att_exec_write_req *req); +void ble_att_exec_write_req_write(void *payload, int len, + const struct ble_att_exec_write_req *req); +void ble_att_exec_write_rsp_parse(const void *payload, int len); +void ble_att_exec_write_rsp_write(void *payload, int len); +void ble_att_notify_req_parse(const void *payload, int len, + struct ble_att_notify_req *req); +void ble_att_notify_req_write(void *payload, int len, + const struct ble_att_notify_req *req); +void ble_att_indicate_req_parse(const void *payload, int len, + struct ble_att_indicate_req *req); +void ble_att_indicate_req_write(void *payload, int len, + const struct ble_att_indicate_req *req); +void ble_att_indicate_rsp_parse(const void *payload, int len); +void ble_att_indicate_rsp_write(void *payload, int len); + +void *ble_att_cmd_prepare(uint8_t opcode, size_t len, struct os_mbuf *txom); +void *ble_att_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom); +int ble_att_tx(uint16_t conn_handle, struct os_mbuf *txom); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_priv.h new file mode 100644 index 000000000..73b6aeab0 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_priv.h @@ -0,0 +1,301 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_ATT_PRIV_ +#define H_BLE_ATT_PRIV_ + +#include +#include "stats/stats.h" +#include "host/ble_att.h" +#include "host/ble_uuid.h" +#include "nimble/nimble_npl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct os_mbuf; +struct ble_hs_conn; +struct ble_l2cap_chan; +struct ble_att_find_info_req; +struct ble_att_error_rsp; +struct ble_att_mtu_cmd; +struct ble_att_read_req; +struct ble_att_read_blob_req; +struct ble_att_read_type_req; +struct ble_att_read_group_type_req; +struct ble_att_read_group_type_rsp; +struct ble_att_find_type_value_req; +struct ble_att_write_req; +struct ble_att_prep_write_cmd; +struct ble_att_exec_write_req; +struct ble_att_notify_req; +struct ble_att_indicate_req; + +STATS_SECT_START(ble_att_stats) + STATS_SECT_ENTRY(error_rsp_rx) + STATS_SECT_ENTRY(error_rsp_tx) + STATS_SECT_ENTRY(mtu_req_rx) + STATS_SECT_ENTRY(mtu_req_tx) + STATS_SECT_ENTRY(mtu_rsp_rx) + STATS_SECT_ENTRY(mtu_rsp_tx) + STATS_SECT_ENTRY(find_info_req_rx) + STATS_SECT_ENTRY(find_info_req_tx) + STATS_SECT_ENTRY(find_info_rsp_rx) + STATS_SECT_ENTRY(find_info_rsp_tx) + STATS_SECT_ENTRY(find_type_value_req_rx) + STATS_SECT_ENTRY(find_type_value_req_tx) + STATS_SECT_ENTRY(find_type_value_rsp_rx) + STATS_SECT_ENTRY(find_type_value_rsp_tx) + STATS_SECT_ENTRY(read_type_req_rx) + STATS_SECT_ENTRY(read_type_req_tx) + STATS_SECT_ENTRY(read_type_rsp_rx) + STATS_SECT_ENTRY(read_type_rsp_tx) + STATS_SECT_ENTRY(read_req_rx) + STATS_SECT_ENTRY(read_req_tx) + STATS_SECT_ENTRY(read_rsp_rx) + STATS_SECT_ENTRY(read_rsp_tx) + STATS_SECT_ENTRY(read_blob_req_rx) + STATS_SECT_ENTRY(read_blob_req_tx) + STATS_SECT_ENTRY(read_blob_rsp_rx) + STATS_SECT_ENTRY(read_blob_rsp_tx) + STATS_SECT_ENTRY(read_mult_req_rx) + STATS_SECT_ENTRY(read_mult_req_tx) + STATS_SECT_ENTRY(read_mult_rsp_rx) + STATS_SECT_ENTRY(read_mult_rsp_tx) + STATS_SECT_ENTRY(read_group_type_req_rx) + STATS_SECT_ENTRY(read_group_type_req_tx) + STATS_SECT_ENTRY(read_group_type_rsp_rx) + STATS_SECT_ENTRY(read_group_type_rsp_tx) + STATS_SECT_ENTRY(write_req_rx) + STATS_SECT_ENTRY(write_req_tx) + STATS_SECT_ENTRY(write_rsp_rx) + STATS_SECT_ENTRY(write_rsp_tx) + STATS_SECT_ENTRY(prep_write_req_rx) + STATS_SECT_ENTRY(prep_write_req_tx) + STATS_SECT_ENTRY(prep_write_rsp_rx) + STATS_SECT_ENTRY(prep_write_rsp_tx) + STATS_SECT_ENTRY(exec_write_req_rx) + STATS_SECT_ENTRY(exec_write_req_tx) + STATS_SECT_ENTRY(exec_write_rsp_rx) + STATS_SECT_ENTRY(exec_write_rsp_tx) + STATS_SECT_ENTRY(notify_req_rx) + STATS_SECT_ENTRY(notify_req_tx) + STATS_SECT_ENTRY(indicate_req_rx) + STATS_SECT_ENTRY(indicate_req_tx) + STATS_SECT_ENTRY(indicate_rsp_rx) + STATS_SECT_ENTRY(indicate_rsp_tx) + STATS_SECT_ENTRY(write_cmd_rx) + STATS_SECT_ENTRY(write_cmd_tx) +STATS_SECT_END +extern STATS_SECT_DECL(ble_att_stats) ble_att_stats; + +struct ble_att_prep_entry { + SLIST_ENTRY(ble_att_prep_entry) bape_next; + uint16_t bape_handle; + uint16_t bape_offset; + + /* XXX: This is wasteful; we should use one mbuf chain for the entire + * prepared write, and compress the data into as few mbufs as possible. + */ + struct os_mbuf *bape_value; +}; + +SLIST_HEAD(ble_att_prep_entry_list, ble_att_prep_entry); + +struct ble_att_svr_conn { + /** This list is sorted by attribute handle ID. */ + struct ble_att_prep_entry_list basc_prep_list; + ble_npl_time_t basc_prep_timeout_at; +}; + +/** + * Handles a host attribute request. + * + * @param entry The host attribute being requested. + * @param op The operation being performed on the attribute. + * @param arg The request data associated with that host + * attribute. + * + * @return 0 on success; + * One of the BLE_ATT_ERR_[...] codes on + * failure. + */ +typedef int ble_att_svr_access_fn(uint16_t conn_handle, uint16_t attr_handle, + uint8_t op, uint16_t offset, + struct os_mbuf **om, void *arg); + +int ble_att_svr_register(const ble_uuid_t *uuid, uint8_t flags, + uint8_t min_key_size, uint16_t *handle_id, + ble_att_svr_access_fn *cb, void *cb_arg); + +struct ble_att_svr_entry { + STAILQ_ENTRY(ble_att_svr_entry) ha_next; + + const ble_uuid_t *ha_uuid; + uint8_t ha_flags; + uint8_t ha_min_key_size; + uint16_t ha_handle_id; + ble_att_svr_access_fn *ha_cb; + void *ha_cb_arg; +}; + +SLIST_HEAD(ble_att_clt_entry_list, ble_att_clt_entry); + +/*** @gen */ + +struct ble_l2cap_chan *ble_att_create_chan(uint16_t conn_handle); +int ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn, + struct ble_l2cap_chan **out_chan); +void ble_att_inc_tx_stat(uint8_t att_op); +void ble_att_truncate_to_mtu(const struct ble_l2cap_chan *att_chan, + struct os_mbuf *txom); +void ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu); +uint16_t ble_att_chan_mtu(const struct ble_l2cap_chan *chan); +int ble_att_init(void); + +/*** @svr */ + +int ble_att_svr_start(void); +void ble_att_svr_stop(void); + +struct ble_att_svr_entry * +ble_att_svr_find_by_uuid(struct ble_att_svr_entry *start_at, + const ble_uuid_t *uuid, + uint16_t end_handle); +uint16_t ble_att_svr_prev_handle(void); +int ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom); +struct ble_att_svr_entry *ble_att_svr_find_by_handle(uint16_t handle_id); +int32_t ble_att_svr_ticks_until_tmo(const struct ble_att_svr_conn *svr, + ble_npl_time_t now); +int ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_svr_rx_find_type_value(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_read_type(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_read_group_type(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_read(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_read_blob(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_read_mult(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_write(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_svr_rx_prep_write(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_exec_write(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_notify(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_svr_rx_indicate(uint16_t conn_handle, + struct os_mbuf **rxom); +void ble_att_svr_prep_clear(struct ble_att_prep_entry_list *prep_list); +int ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle, + uint16_t offset, struct os_mbuf *om, + uint8_t *out_att_err); +void ble_att_svr_reset(void); +int ble_att_svr_init(void); + +void ble_att_svr_hide_range(uint16_t start_handle, uint16_t end_handle); +void ble_att_svr_restore_range(uint16_t start_handle, uint16_t end_handle); + +int ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, + uint8_t req_op, uint16_t handle, + uint8_t error_code); +/*** $clt */ + +/** An information-data entry in a find information response. */ +struct ble_att_find_info_idata { + uint16_t attr_handle; + ble_uuid_any_t uuid; +}; + +/** A handles-information entry in a find by type value response. */ +struct ble_att_find_type_value_hinfo { + uint16_t attr_handle; + uint16_t group_end_handle; +}; + +/** An attribute-data entry in a read by type response. */ +struct ble_att_read_type_adata { + uint16_t att_handle; + int value_len; + uint8_t *value; + +}; + +/** An attribute-data entry in a read by group type response. */ +struct ble_att_read_group_type_adata { + uint16_t att_handle; + uint16_t end_group_handle; + int value_len; + uint8_t *value; +}; + +int ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu); +int ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle); +int ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, + uint16_t offset); +int ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_read_mult(uint16_t conn_handle, + const uint16_t *handles, int num_handles); +int ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t start_handle, + uint16_t end_handle, const ble_uuid_t *uuid); +int ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_read_group_type(uint16_t conn_handle, + uint16_t start_handle, uint16_t end_handle, + const ble_uuid_t *uuid128); +int ble_att_clt_rx_read_group_type(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t start_handle, + uint16_t end_handle); +int ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t start_handle, + uint16_t end_handle, uint16_t attribute_type, + const void *attribute_value, int value_len); +int ble_att_clt_rx_find_type_value(uint16_t conn_handle, + struct os_mbuf **rxom); +int ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t handle, + struct os_mbuf *txom); +int ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t handle, + struct os_mbuf *txom); +int ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, + uint16_t offset, struct os_mbuf *txom); +int ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags); +int ble_att_clt_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_rx_write(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_notify(uint16_t conn_handle, uint16_t handle, + struct os_mbuf *txom); +int ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t handle, + struct os_mbuf *txom); +int ble_att_clt_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_svr.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_svr.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_svr.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_svr.c index 73172ef73..afcf90372 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_svr.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_svr.c @@ -20,14 +20,11 @@ #include #include #include -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/host/include/host/ble_uuid.h" +#include "os/os.h" +#include "nimble/ble.h" +#include "host/ble_uuid.h" #include "ble_hs_priv.h" - -#ifdef ESP_PLATFORM -#include "nimble/esp_port/port/include/esp_nimble_mem.h" -#endif +#include "esp_nimble_mem.h" /** * ATT server - Attribute Protocol @@ -2672,11 +2669,7 @@ ble_att_svr_reset(void) static void ble_att_svr_free_start_mem(void) { -#ifdef ESP_PLATFORM nimble_platform_mem_free(ble_att_svr_entry_mem); -#else - free(ble_att_svr_entry_mem); -#endif ble_att_svr_entry_mem = NULL; } @@ -2688,11 +2681,7 @@ ble_att_svr_start(void) ble_att_svr_free_start_mem(); if (ble_hs_max_attrs > 0) { -#ifdef ESP_PLATFORM ble_att_svr_entry_mem = nimble_platform_mem_malloc( -#else - ble_att_svr_entry_mem = malloc( -#endif OS_MEMPOOL_BYTES(ble_hs_max_attrs, sizeof (struct ble_att_svr_entry))); if (ble_att_svr_entry_mem == NULL) { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_eddystone.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_eddystone.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_eddystone.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_eddystone.c index ad0f449df..eccb3e988 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_eddystone.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_eddystone.c @@ -18,9 +18,9 @@ */ #include -#include "nimble/porting/nimble/include/os/endian.h" -#include "../include/host/ble_eddystone.h" -#include "nimble/nimble/host/include/host/ble_hs_adv.h" +#include "os/endian.h" +#include "host/ble_eddystone.h" +#include "host/ble_hs_adv.h" #include "ble_hs_priv.h" #define BLE_EDDYSTONE_MAX_SVC_DATA_LEN 22 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap.c index 068414bbf..17ff4eae0 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap.c @@ -20,9 +20,9 @@ #include #include #include -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/host/include/host/ble_hs_adv.h" -#include "nimble/nimble/host/include/host/ble_hs_hci.h" +#include "nimble/nimble_opt.h" +#include "host/ble_hs_adv.h" +#include "host/ble_hs_hci.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" @@ -2246,6 +2246,11 @@ ble_gap_wl_set(const ble_addr_t *addrs, uint8_t white_list_count) ble_hs_lock(); + if (white_list_count == 0) { + rc = BLE_HS_EINVAL; + goto done; + } + for (i = 0; i < white_list_count; i++) { if (addrs[i].type != BLE_ADDR_PUBLIC && addrs[i].type != BLE_ADDR_RANDOM) { @@ -5612,11 +5617,6 @@ done: #endif } -int ble_gap_set_data_len(uint16_t conn_handle, uint16_t tx_octets, uint16_t tx_time) -{ - return ble_hs_hci_util_set_data_len(conn_handle, tx_octets, tx_time); -} - /***************************************************************************** * $security * *****************************************************************************/ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h new file mode 100644 index 000000000..2b6b40696 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_GAP_CONN_ +#define H_BLE_GAP_CONN_ + +#include +#include "syscfg/syscfg.h" +#include "stats/stats.h" +#include "host/ble_gap.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct hci_le_conn_upd_complete; +struct hci_le_conn_param_req; +struct hci_le_conn_complete; +struct hci_disconn_complete; +struct hci_encrypt_change; +struct ble_hs_hci_ack; +struct ble_hs_adv; + +STATS_SECT_START(ble_gap_stats) + STATS_SECT_ENTRY(wl_set) + STATS_SECT_ENTRY(wl_set_fail) + STATS_SECT_ENTRY(adv_stop) + STATS_SECT_ENTRY(adv_stop_fail) + STATS_SECT_ENTRY(adv_start) + STATS_SECT_ENTRY(adv_start_fail) + STATS_SECT_ENTRY(adv_set_data) + STATS_SECT_ENTRY(adv_set_data_fail) + STATS_SECT_ENTRY(adv_rsp_set_data) + STATS_SECT_ENTRY(adv_rsp_set_data_fail) + STATS_SECT_ENTRY(discover) + STATS_SECT_ENTRY(discover_fail) + STATS_SECT_ENTRY(initiate) + STATS_SECT_ENTRY(initiate_fail) + STATS_SECT_ENTRY(terminate) + STATS_SECT_ENTRY(terminate_fail) + STATS_SECT_ENTRY(cancel) + STATS_SECT_ENTRY(cancel_fail) + STATS_SECT_ENTRY(update) + STATS_SECT_ENTRY(update_fail) + STATS_SECT_ENTRY(connect_mst) + STATS_SECT_ENTRY(connect_slv) + STATS_SECT_ENTRY(disconnect) + STATS_SECT_ENTRY(rx_disconnect) + STATS_SECT_ENTRY(rx_update_complete) + STATS_SECT_ENTRY(rx_adv_report) + STATS_SECT_ENTRY(rx_conn_complete) + STATS_SECT_ENTRY(discover_cancel) + STATS_SECT_ENTRY(discover_cancel_fail) + STATS_SECT_ENTRY(security_initiate) + STATS_SECT_ENTRY(security_initiate_fail) +STATS_SECT_END + +extern STATS_SECT_DECL(ble_gap_stats) ble_gap_stats; + +#define BLE_GAP_CONN_MODE_MAX 3 +#define BLE_GAP_DISC_MODE_MAX 3 + +#if MYNEWT_VAL(BLE_EXT_ADV) && NIMBLE_BLE_SCAN +void ble_gap_rx_le_scan_timeout(void); +#endif + +#if MYNEWT_VAL(BLE_EXT_ADV) +void ble_gap_rx_ext_adv_report(struct ble_gap_ext_disc_desc *desc); +void ble_gap_rx_adv_set_terminated(const struct ble_hci_ev_le_subev_adv_set_terminated *ev); +#if MYNEWT_VAL(BLE_PERIODIC_ADV) +void ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev); +void ble_gap_rx_periodic_adv_rpt(const struct ble_hci_ev_le_subev_periodic_adv_rpt *ev); +void ble_gap_rx_periodic_adv_sync_lost(const struct ble_hci_ev_le_subev_periodic_adv_sync_lost *ev); +void ble_gap_rx_periodic_adv_sync_transfer(const struct ble_hci_ev_le_subev_periodic_adv_sync_transfer *ev); +#endif +void ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd *ev); +#endif +void ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc); +void ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used_feat *ev); + +struct ble_gap_conn_complete +{ + uint8_t status; + uint16_t connection_handle; + uint8_t role; + uint8_t peer_addr_type; + uint8_t peer_addr[BLE_DEV_ADDR_LEN]; + uint16_t conn_itvl; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint8_t master_clk_acc; + uint8_t local_rpa[BLE_DEV_ADDR_LEN]; + uint8_t peer_rpa[BLE_DEV_ADDR_LEN]; +}; + +int ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance); +void ble_gap_rx_disconn_complete(const struct ble_hci_ev_disconn_cmp *ev); +void ble_gap_rx_update_complete(const struct ble_hci_ev_le_subev_conn_upd_complete *ev); +void ble_gap_rx_param_req(const struct ble_hci_ev_le_subev_rem_conn_param_req *ev); +int ble_gap_rx_l2cap_update_req(uint16_t conn_handle, + struct ble_gap_upd_params *params); +void ble_gap_rx_phy_update_complete(const struct ble_hci_ev_le_subev_phy_update_complete *ev); +void ble_gap_enc_event(uint16_t conn_handle, int status, + int security_restored, int bonded); +void ble_gap_passkey_event(uint16_t conn_handle, + struct ble_gap_passkey_params *passkey_params); +void ble_gap_notify_rx_event(uint16_t conn_handle, uint16_t attr_handle, + struct os_mbuf *om, int is_indication); +void ble_gap_notify_tx_event(int status, uint16_t conn_handle, + uint16_t attr_handle, int is_indication); +void ble_gap_subscribe_event(uint16_t conn_handle, uint16_t attr_handle, + uint8_t reason, + uint8_t prev_notify, uint8_t cur_notify, + uint8_t prev_indicate, uint8_t cur_indicate); +void ble_gap_mtu_event(uint16_t conn_handle, uint16_t cid, uint16_t mtu); +void ble_gap_identity_event(uint16_t conn_handle); +int ble_gap_repeat_pairing_event(const struct ble_gap_repeat_pairing *rp); +int ble_gap_master_in_progress(void); + +void ble_gap_preempt(void); +void ble_gap_preempt_done(void); + +int ble_gap_terminate_with_conn(struct ble_hs_conn *conn, uint8_t hci_reason); +void ble_gap_conn_broken(uint16_t conn_handle, int reason); +void ble_gap_reset_state(int reason); +int32_t ble_gap_timer(void); + +int ble_gap_init(void); +void ble_gap_deinit(void); + +#if MYNEWT_VAL(BLE_HS_DEBUG) +int ble_gap_dbg_update_active(uint16_t conn_handle); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h new file mode 100644 index 000000000..4a59635b8 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h @@ -0,0 +1,199 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_GATT_PRIV_ +#define H_BLE_GATT_PRIV_ + +#include "syscfg/syscfg.h" +#include "stats/stats.h" +#include "host/ble_gatt.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_att_read_type_adata; +struct ble_att_find_type_value_hinfo; +struct ble_att_find_info_idata; +struct ble_att_read_group_type_adata; +struct ble_att_prep_write_cmd; + +STATS_SECT_START(ble_gattc_stats) + STATS_SECT_ENTRY(mtu) + STATS_SECT_ENTRY(mtu_fail) + STATS_SECT_ENTRY(disc_all_svcs) + STATS_SECT_ENTRY(disc_all_svcs_fail) + STATS_SECT_ENTRY(disc_svc_uuid) + STATS_SECT_ENTRY(disc_svc_uuid_fail) + STATS_SECT_ENTRY(find_inc_svcs) + STATS_SECT_ENTRY(find_inc_svcs_fail) + STATS_SECT_ENTRY(disc_all_chrs) + STATS_SECT_ENTRY(disc_all_chrs_fail) + STATS_SECT_ENTRY(disc_chrs_uuid) + STATS_SECT_ENTRY(disc_chrs_uuid_fail) + STATS_SECT_ENTRY(disc_all_dscs) + STATS_SECT_ENTRY(disc_all_dscs_fail) + STATS_SECT_ENTRY(read) + STATS_SECT_ENTRY(read_fail) + STATS_SECT_ENTRY(read_uuid) + STATS_SECT_ENTRY(read_uuid_fail) + STATS_SECT_ENTRY(read_long) + STATS_SECT_ENTRY(read_long_fail) + STATS_SECT_ENTRY(read_mult) + STATS_SECT_ENTRY(read_mult_fail) + STATS_SECT_ENTRY(write_no_rsp) + STATS_SECT_ENTRY(write_no_rsp_fail) + STATS_SECT_ENTRY(write) + STATS_SECT_ENTRY(write_fail) + STATS_SECT_ENTRY(write_long) + STATS_SECT_ENTRY(write_long_fail) + STATS_SECT_ENTRY(write_reliable) + STATS_SECT_ENTRY(write_reliable_fail) + STATS_SECT_ENTRY(notify) + STATS_SECT_ENTRY(notify_fail) + STATS_SECT_ENTRY(indicate) + STATS_SECT_ENTRY(indicate_fail) + STATS_SECT_ENTRY(proc_timeout) +STATS_SECT_END +extern STATS_SECT_DECL(ble_gattc_stats) ble_gattc_stats; + +STATS_SECT_START(ble_gatts_stats) + STATS_SECT_ENTRY(svcs) + STATS_SECT_ENTRY(chrs) + STATS_SECT_ENTRY(dscs) + STATS_SECT_ENTRY(svc_def_reads) + STATS_SECT_ENTRY(svc_inc_reads) + STATS_SECT_ENTRY(chr_def_reads) + STATS_SECT_ENTRY(chr_val_reads) + STATS_SECT_ENTRY(chr_val_writes) + STATS_SECT_ENTRY(dsc_reads) + STATS_SECT_ENTRY(dsc_writes) +STATS_SECT_END +extern STATS_SECT_DECL(ble_gatts_stats) ble_gatts_stats; + +#define BLE_GATT_CHR_DECL_SZ_16 5 +#define BLE_GATT_CHR_DECL_SZ_128 19 + +typedef uint8_t ble_gatts_conn_flags; + +struct ble_gatts_conn { + struct ble_gatts_clt_cfg *clt_cfgs; + int num_clt_cfgs; + + uint16_t indicate_val_handle; +}; + +/*** @client. */ + +int ble_gattc_locked_by_cur_task(void); +void ble_gatts_indicate_fail_notconn(uint16_t conn_handle); + +void ble_gattc_rx_err(uint16_t conn_handle, uint16_t handle, uint16_t status); +void ble_gattc_rx_mtu(uint16_t conn_handle, int status, uint16_t chan_mtu); +void ble_gattc_rx_read_type_adata(uint16_t conn_handle, + struct ble_att_read_type_adata *adata); +void ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status); +void ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, + struct os_mbuf **rxom); +void ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, + struct os_mbuf **rxom); +void ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, + struct os_mbuf **rxom); +void ble_gattc_rx_read_group_type_adata( + uint16_t conn_handle, struct ble_att_read_group_type_adata *adata); +void ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int rc); +void ble_gattc_rx_find_type_value_hinfo( + uint16_t conn_handle, struct ble_att_find_type_value_hinfo *hinfo); +void ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status); +void ble_gattc_rx_write_rsp(uint16_t conn_handle); +void ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, + uint16_t handle, uint16_t offset, + struct os_mbuf **rxom); +void ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status); +void ble_gattc_rx_indicate_rsp(uint16_t conn_handle); +void ble_gattc_rx_find_info_idata(uint16_t conn_handle, + struct ble_att_find_info_idata *idata); +void ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status); +void ble_gattc_connection_txable(uint16_t conn_handle); +void ble_gattc_connection_broken(uint16_t conn_handle); +int32_t ble_gattc_timer(void); + +int ble_gattc_any_jobs(void); +int ble_gattc_init(void); + +/*** @server. */ +#define BLE_GATTS_CLT_CFG_F_NOTIFY 0x0001 +#define BLE_GATTS_CLT_CFG_F_INDICATE 0x0002 +#define BLE_GATTS_CLT_CFG_F_MODIFIED 0x0080 /* Internal only. */ +#define BLE_GATTS_CLT_CFG_F_RESERVED 0xfffc + +#define BLE_GATTS_INC_SVC_LEN_NO_UUID 4 +#define BLE_GATTS_INC_SVC_LEN_UUID 6 + +/** + * Contains counts of resources required by the GATT server. The contents of + * this struct are generally used to populate a configuration struct before + * the host is initialized. + */ +struct ble_gatt_resources { + /** Number of services. */ + uint16_t svcs; + + /** Number of included services. */ + uint16_t incs; + + /** Number of characteristics. */ + uint16_t chrs; + + /** Number of descriptors. */ + uint16_t dscs; + + /** + * Number of client characteristic configuration descriptors. Each of + * these also contributes to the total descriptor count. + */ + uint16_t cccds; + + /** Total number of ATT attributes. */ + uint16_t attrs; +}; + +int ble_gatts_rx_indicate_ack(uint16_t conn_handle, uint16_t chr_val_handle); +int ble_gatts_send_next_indicate(uint16_t conn_handle); +void ble_gatts_tx_notifications(void); +void ble_gatts_bonding_established(uint16_t conn_handle); +void ble_gatts_bonding_restored(uint16_t conn_handle); +void ble_gatts_connection_broken(uint16_t conn_handle); +void ble_gatts_lcl_svc_foreach(ble_gatt_svc_foreach_fn cb, void *arg); +int ble_gatts_register_svcs(const struct ble_gatt_svc_def *svcs, + ble_gatt_register_fn *register_cb, + void *cb_arg); +int ble_gatts_clt_cfg_access(uint16_t conn_handle, uint16_t attr_handle, + uint8_t op, uint16_t offset, struct os_mbuf **om, + void *arg); + +/*** @misc. */ +int ble_gatts_conn_can_alloc(void); +int ble_gatts_conn_init(struct ble_gatts_conn *gatts_conn); +int ble_gatts_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gattc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gattc.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gattc.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gattc.c index f7bc9f47f..a6e114cc2 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gattc.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gattc.c @@ -54,10 +54,10 @@ #include #include #include -#include "nimble/porting/nimble/include/os/os_mempool.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/host/include/host/ble_uuid.h" -#include "nimble/nimble/host/include/host/ble_gap.h" +#include "os/os_mempool.h" +#include "nimble/ble.h" +#include "host/ble_uuid.h" +#include "host/ble_gap.h" #include "ble_hs_priv.h" /***************************************************************************** diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c index c805d2ab2..e53cc116f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c @@ -20,14 +20,11 @@ #include #include #include -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/host/include/host/ble_uuid.h" -#include "nimble/nimble/host/include/host/ble_store.h" +#include "nimble/ble.h" +#include "host/ble_uuid.h" +#include "host/ble_store.h" #include "ble_hs_priv.h" - -#ifdef ESP_PLATFORM -#include "nimble/esp_port/port/include/esp_nimble_mem.h" -#endif +#include "esp_nimble_mem.h" #define BLE_GATTS_INCLUDE_SZ 6 #define BLE_GATTS_CHR_MAX_SZ 19 @@ -1158,11 +1155,7 @@ ble_gatts_connection_broken(uint16_t conn_handle) static void ble_gatts_free_svc_defs(void) { -#ifdef ESP_PLATFORM nimble_platform_mem_free(ble_gatts_svc_defs); -#else - free(ble_gatts_svc_defs); -#endif ble_gatts_svc_defs = NULL; ble_gatts_num_svc_defs = 0; } @@ -1170,19 +1163,11 @@ ble_gatts_free_svc_defs(void) static void ble_gatts_free_mem(void) { -#ifdef ESP_PLATFORM nimble_platform_mem_free(ble_gatts_clt_cfg_mem); ble_gatts_clt_cfg_mem = NULL; nimble_platform_mem_free(ble_gatts_svc_entries); ble_gatts_svc_entries = NULL; -#else - free(ble_gatts_clt_cfg_mem); - ble_gatts_clt_cfg_mem = NULL; - - free(ble_gatts_svc_entries); - ble_gatts_svc_entries = NULL; -#endif } @@ -1225,11 +1210,7 @@ ble_gatts_start(void) } if (ble_hs_max_client_configs > 0) { -#ifdef ESP_PLATFORM ble_gatts_clt_cfg_mem = nimble_platform_mem_malloc( -#else - ble_gatts_clt_cfg_mem = malloc( -#endif OS_MEMPOOL_BYTES(ble_hs_max_client_configs, sizeof (struct ble_gatts_clt_cfg))); if (ble_gatts_clt_cfg_mem == NULL) { @@ -1240,11 +1221,7 @@ ble_gatts_start(void) if (ble_hs_max_services > 0) { ble_gatts_svc_entries = -#ifdef ESP_PLATFORM nimble_platform_mem_malloc(ble_hs_max_services * sizeof *ble_gatts_svc_entries); -#else - malloc(ble_hs_max_services * sizeof *ble_gatts_svc_entries); -#endif if (ble_gatts_svc_entries == NULL) { rc = BLE_HS_ENOMEM; goto done; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts_lcl.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts_lcl.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts_lcl.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts_lcl.c index 989eb5c27..a45f397bc 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts_lcl.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts_lcl.c @@ -19,9 +19,9 @@ #include #include -#include "nimble/nimble/host/include/host/ble_uuid.h" -#include "nimble/console/console.h" -#include "nimble/nimble/include/nimble/ble.h" +#include "host/ble_uuid.h" +#include "console/console.h" +#include "nimble/ble.h" #include "ble_hs_priv.h" static const ble_uuid_t *uuid_ccc = diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs.c index 4a7087b15..d819e20df 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs.c @@ -20,15 +20,15 @@ #include #include #include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/stats/stats.h" -#include "nimble/nimble/include/nimble/ble_hci_trans.h" +#include "sysinit/sysinit.h" +#include "syscfg/syscfg.h" +#include "stats/stats.h" +#include "nimble/ble_hci_trans.h" #include "ble_hs_priv.h" #include "ble_monitor_priv.h" -#include "nimble/nimble/include/nimble/nimble_npl.h" +#include "nimble/nimble_npl.h" #ifndef MYNEWT -#include "nimble/porting/nimble/include/nimble/nimble_port.h" +#include "nimble/nimble_port.h" #endif #define BLE_HS_HCI_EVT_COUNT \ @@ -86,10 +86,8 @@ uint16_t ble_hs_max_services; uint16_t ble_hs_max_client_configs; #if MYNEWT_VAL(BLE_HS_DEBUG) -#ifdef ESP_PLATFORM static uint8_t ble_hs_mutex_locked; static TaskHandle_t ble_hs_task_handle; -#endif static uint8_t ble_hs_dbg_mutex_locked; #endif @@ -133,10 +131,8 @@ ble_hs_locked_by_cur_task(void) owner = ble_hs_mutex.mu.mu_owner; return owner != NULL && owner == os_sched_get_current_task(); -#elif ESP_PLATFORM - return (ble_hs_mutex_locked && ble_hs_task_handle == xTaskGetCurrentTaskHandle()); #else - return 1; + return (ble_hs_mutex_locked && ble_hs_task_handle == xTaskGetCurrentTaskHandle()); #endif } #endif @@ -168,7 +164,7 @@ ble_hs_lock_nested(void) rc = ble_npl_mutex_pend(&ble_hs_mutex, 0xffffffff); -#if MYNEWT_VAL(BLE_HS_DEBUG) && defined(ESP_PLATFORM) +#if MYNEWT_VAL(BLE_HS_DEBUG) ble_hs_mutex_locked = 1; ble_hs_task_handle = xTaskGetCurrentTaskHandle(); #endif @@ -188,12 +184,10 @@ ble_hs_unlock_nested(void) ble_hs_dbg_mutex_locked = 0; return; } -#ifdef ESP_PLATFORM if(ble_hs_task_handle == xTaskGetCurrentTaskHandle()) { ble_hs_task_handle = NULL; ble_hs_mutex_locked = 0; } -#endif #endif rc = ble_npl_mutex_release(&ble_hs_mutex); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_adv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_adv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv.c index 1fe183977..1d938b958 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_adv.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv.c @@ -19,8 +19,8 @@ #include #include -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/host/include/host/ble_hs_adv.h" +#include "nimble/ble.h" +#include "host/ble_hs_adv.h" #include "ble_hs_priv.h" struct find_field_data { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_utils.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h similarity index 58% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_utils.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h index 248309009..5c8a6ecc9 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_utils.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h @@ -17,13 +17,20 @@ * under the License. */ -#include +#ifndef H_BLE_HS_ADV_PRIV_ +#define H_BLE_HS_ADV_PRIV_ -uint32_t ble_ll_utils_calc_access_addr(void); -uint8_t ble_ll_utils_remapped_channel(uint8_t remap_index, const uint8_t *chanmap); -uint8_t ble_ll_utils_calc_dci_csa2(uint16_t event_cntr, uint16_t channel_id, - uint8_t num_used_chans, const uint8_t *chanmap); -uint8_t ble_ll_utils_calc_num_used_chans(const uint8_t *chanmap); -uint32_t ble_ll_utils_calc_window_widening(uint32_t anchor_point, - uint32_t last_anchor_point, - uint8_t master_sca); +#ifdef __cplusplus +extern "C" { +#endif + +int ble_hs_adv_set_flat(uint8_t type, int data_len, const void *data, + uint8_t *dst, uint8_t *dst_len, uint8_t max_len); +int ble_hs_adv_find_field(uint8_t type, const uint8_t *data, uint8_t length, + const struct ble_hs_adv_field **out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_atomic.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic.c similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_atomic.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic.c diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic_priv.h new file mode 100644 index 000000000..9f7d8d16b --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic_priv.h @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_HS_ATOMIC_ +#define H_BLE_HS_ATOMIC_ + +#include "ble_hs_conn_priv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int ble_hs_atomic_conn_delete(uint16_t conn_handle); +void ble_hs_atomic_conn_insert(struct ble_hs_conn *conn); +int ble_hs_atomic_conn_flags(uint16_t conn_handle, + ble_hs_conn_flags_t *out_flags); +int ble_hs_atomic_conn_set_flags(uint16_t conn_handle, + ble_hs_conn_flags_t flags, int on); +uint16_t ble_hs_atomic_first_conn_handle(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_cfg.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_cfg.c similarity index 92% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_cfg.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_cfg.c index 0569ccee8..a46a604ac 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_cfg.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_cfg.c @@ -17,8 +17,8 @@ * under the License. */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/nimble/host/include/host/ble_hs.h" +#include "syscfg/syscfg.h" +#include "host/ble_hs.h" struct ble_hs_cfg ble_hs_cfg = { /** Security manager settings. */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_conn.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_conn.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c index 1625e7305..31830c98a 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_conn.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c @@ -19,9 +19,9 @@ #include #include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/host/include/host/ble_hs_id.h" +#include "syscfg/syscfg.h" +#include "os/os.h" +#include "host/ble_hs_id.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h new file mode 100644 index 000000000..0e451194d --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_HS_CONN_ +#define H_BLE_HS_CONN_ + +#include +#include "ble_l2cap_priv.h" +#include "ble_gatt_priv.h" +#include "ble_att_priv.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct hci_le_conn_complete; +struct hci_create_conn; +struct ble_l2cap_chan; + +typedef uint8_t ble_hs_conn_flags_t; + +#define BLE_HS_CONN_F_MASTER 0x01 +#define BLE_HS_CONN_F_TERMINATING 0x02 +#define BLE_HS_CONN_F_TX_FRAG 0x04 /* Cur ACL packet partially txed. */ + +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) +#define BLE_HS_CONN_L2CAP_COC_CID_MASK_LEN_REM \ + ((MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) % (8 * sizeof(uint32_t))) ? 1 : 0) + +#define BLE_HS_CONN_L2CAP_COC_CID_MASK_LEN \ + (MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) / (8 * sizeof(uint32_t)) + \ + BLE_HS_CONN_L2CAP_COC_CID_MASK_LEN_REM) +#endif + +struct ble_hs_conn { + SLIST_ENTRY(ble_hs_conn) bhc_next; + uint16_t bhc_handle; + uint8_t bhc_our_addr_type; +#if MYNEWT_VAL(BLE_EXT_ADV) + uint8_t bhc_our_rnd_addr[6]; +#endif + ble_addr_t bhc_peer_addr; + ble_addr_t bhc_our_rpa_addr; + ble_addr_t bhc_peer_rpa_addr; + + uint16_t bhc_itvl; + uint16_t bhc_latency; + uint16_t bhc_supervision_timeout; + uint8_t bhc_master_clock_accuracy; + + uint32_t supported_feat; + + ble_hs_conn_flags_t bhc_flags; + + struct ble_l2cap_chan_list bhc_channels; + struct ble_l2cap_chan *bhc_rx_chan; /* Channel rxing current packet. */ + ble_npl_time_t bhc_rx_timeout; +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) + uint32_t l2cap_coc_cid_mask[BLE_HS_CONN_L2CAP_COC_CID_MASK_LEN]; +#endif + + /** + * Count of packets sent over this connection that the controller has not + * transmitted or flushed yet. + */ + uint16_t bhc_outstanding_pkts; + +#if MYNEWT_VAL(BLE_HS_FLOW_CTRL) + /** + * Count of packets received over this connection that have been processed + * and freed. + */ + uint16_t bhc_completed_pkts; +#endif + + /** Queue of outgoing packets that could not be sent. */ + STAILQ_HEAD(, os_mbuf_pkthdr) bhc_tx_q; + + struct ble_att_svr_conn bhc_att_svr; + struct ble_gatts_conn bhc_gatt_svr; + + struct ble_gap_sec_state bhc_sec_state; + + ble_gap_event_fn *bhc_cb; + void *bhc_cb_arg; + +#if MYNEWT_VAL(BLE_PERIODIC_ADV) + struct ble_hs_periodic_sync *psync; +#endif +}; + +struct ble_hs_conn_addrs { + ble_addr_t our_id_addr; + ble_addr_t peer_id_addr; + ble_addr_t our_ota_addr; + ble_addr_t peer_ota_addr; +}; + +int ble_hs_conn_can_alloc(void); +struct ble_hs_conn *ble_hs_conn_alloc(uint16_t conn_handle); +void ble_hs_conn_free(struct ble_hs_conn *conn); +void ble_hs_conn_insert(struct ble_hs_conn *conn); +void ble_hs_conn_remove(struct ble_hs_conn *conn); +struct ble_hs_conn *ble_hs_conn_find(uint16_t conn_handle); +struct ble_hs_conn *ble_hs_conn_find_assert(uint16_t conn_handle); +struct ble_hs_conn *ble_hs_conn_find_by_addr(const ble_addr_t *addr); +struct ble_hs_conn *ble_hs_conn_find_by_idx(int idx); +int ble_hs_conn_exists(uint16_t conn_handle); +struct ble_hs_conn *ble_hs_conn_first(void); +struct ble_l2cap_chan *ble_hs_conn_chan_find_by_scid(struct ble_hs_conn *conn, + uint16_t cid); +struct ble_l2cap_chan *ble_hs_conn_chan_find_by_dcid(struct ble_hs_conn *conn, + uint16_t cid); +bool ble_hs_conn_chan_exist(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan); +int ble_hs_conn_chan_insert(struct ble_hs_conn *conn, + struct ble_l2cap_chan *chan); +void ble_hs_conn_delete_chan(struct ble_hs_conn *conn, + struct ble_l2cap_chan *chan); + +void ble_hs_conn_addrs(const struct ble_hs_conn *conn, + struct ble_hs_conn_addrs *addrs); +int32_t ble_hs_conn_timer(void); + +typedef int ble_hs_conn_foreach_fn(struct ble_hs_conn *conn, void *arg); +void ble_hs_conn_foreach(ble_hs_conn_foreach_fn *cb, void *arg); + +int ble_hs_conn_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_flow.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_flow.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow.c index e74f5da36..2520c8541 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_flow.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow.c @@ -17,8 +17,8 @@ * under the License. */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/nimble/include/nimble/ble_hci_trans.h" +#include "syscfg/syscfg.h" +#include "nimble/ble_hci_trans.h" #include "ble_hs_priv.h" #if MYNEWT_VAL(BLE_HS_FLOW_CTRL) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/include/transport/ram/ble_hci_ram.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow_priv.h similarity index 80% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/include/transport/ram/ble_hci_ram.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow_priv.h index 00530798d..753eaf8ff 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/include/transport/ram/ble_hci_ram.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow_priv.h @@ -17,16 +17,17 @@ * under the License. */ -#ifndef H_BLE_HCI_RAM_ -#define H_BLE_HCI_RAM_ - -#include "nimble/nimble/include/nimble/ble_hci_trans.h" +#ifndef H_BLE_HS_FLOW_PRIV_ +#define H_BLE_HS_FLOW_PRIV_ +#include #ifdef __cplusplus extern "C" { #endif -void ble_hci_ram_init(void); +void ble_hs_flow_connection_broken(uint16_t conn_handle); +void ble_hs_flow_track_data_mbuf(struct os_mbuf *om); +int ble_hs_flow_startup(void); #ifdef __cplusplus } diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c index 214fc8214..3cfed27e2 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c @@ -20,10 +20,10 @@ #include #include #include -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/porting/nimble/include/mem/mem.h" -#include "nimble/nimble/include/nimble/ble_hci_trans.h" -#include "nimble/nimble/host/include/host/ble_monitor.h" +#include "os/os.h" +#include "mem/mem.h" +#include "nimble/ble_hci_trans.h" +#include "host/ble_monitor.h" #include "ble_hs_priv.h" #include "ble_monitor_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_cmd.c similarity index 79% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_cmd.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_cmd.c index 63242ca88..7aa9e4e74 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_cmd.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_cmd.c @@ -21,13 +21,24 @@ #include #include #include -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "nimble/nimble/include/nimble/ble_hci_trans.h" -#include "nimble/nimble/host/include/host/ble_monitor.h" +#include "os/os.h" +#include "nimble/hci_common.h" +#include "nimble/ble_hci_trans.h" +#include "host/ble_monitor.h" #include "ble_hs_priv.h" #include "ble_monitor_priv.h" +/* + * HCI Command Header + * + * Comprises the following fields + * -> Opcode group field & Opcode command field (2) + * -> Parameter Length (1) + * Length of all the parameters (does not include any part of the hci + * command header + */ +#define BLE_HCI_CMD_HDR_LEN (3) + static int ble_hs_hci_cmd_transport(struct ble_hci_cmd *cmd) { @@ -51,18 +62,6 @@ ble_hs_hci_cmd_transport(struct ble_hci_cmd *cmd) } } -#ifdef ESP_PLATFORM -/* - * HCI Command Header - * - * Comprises the following fields - * -> Opcode group field & Opcode command field (2) - * -> Parameter Length (1) - * Length of all the parameters (does not include any part of the hci - * command header - */ -#define BLE_HCI_CMD_HDR_LEN (3) - static int ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) { @@ -99,34 +98,6 @@ ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) return rc; } -#else -static int -ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) -{ - struct ble_hci_cmd *cmd; - int rc; - - cmd = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD); - BLE_HS_DBG_ASSERT(cmd != NULL); - - cmd->opcode = htole16(opcode); - cmd->length = len; - if (len != 0) { - memcpy(cmd->data, cmddata, len); - } - - rc = ble_hs_hci_cmd_transport(cmd); - - if (rc == 0) { - STATS_INC(ble_hs_stats, hci_cmd); - } else { - BLE_HS_LOG(DEBUG, "ble_hs_hci_cmd_send failure; rc=%d\n", rc); - } - - return rc; -} -#endif - int ble_hs_hci_cmd_send_buf(uint16_t opcode, const void *buf, uint8_t buf_len) { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_evt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_evt.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c index 9b97f433b..4a6b0716e 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_evt.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c @@ -20,11 +20,11 @@ #include #include #include -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "nimble/nimble/include/nimble/ble_hci_trans.h" -#include "nimble/nimble/host/include/host/ble_gap.h" -#include "nimble/nimble/host/include/host/ble_monitor.h" +#include "os/os.h" +#include "nimble/hci_common.h" +#include "nimble/ble_hci_trans.h" +#include "host/ble_gap.h" +#include "host/ble_monitor.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h new file mode 100644 index 000000000..362f12cbd --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_HS_HCI_PRIV_ +#define H_BLE_HS_HCI_PRIV_ + +#include "nimble/hci_common.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_hs_conn; +struct os_mbuf; + +#define BLE_HS_HCI_LE_FEAT_ENCRYPTION (0x00000001) +#define BLE_HS_HCI_LE_FEAT_CONN_PARAM_REQUEST (0x00000002) +#define BLE_HS_HCI_LE_FEAT_EXT_REJECT (0x00000004) +#define BLE_HS_HCI_LE_FEAT_SLAVE_FEAT_EXCHANGE (0x00000008) +#define BLE_HS_HCI_LE_FEAT_PING (0x00000010) +#define BLE_HS_HCI_LE_FEAT_DATA_PACKET_LENGTH_EXT (0x00000020) +#define BLE_HS_HCI_LE_FEAT_LL_PRIVACY (0x00000040) +#define BLE_HS_HCI_LE_FEAT_EXT_SCANNER_FILTER_POLICIES (0x00000080) +#define BLE_HS_HCI_LE_FEAT_2M_PHY (0x00000100) +#define BLE_HS_HCI_LE_FEAT_STABLE_MOD_INDEX_TX (0x00000200) +#define BLE_HS_HCI_LE_FEAT_STABLE_MOD_INDEX_RX (0x00000400) +#define BLE_HS_HCI_LE_FEAT_CODED_PHY (0x00000800) +#define BLE_HS_HCI_LE_FEAT_EXT_ADV (0x00001000) +#define BLE_HS_HCI_LE_FEAT_PERIODIC_ADV (0x00002000) +#define BLE_HS_HCI_LE_FEAT_CSA2 (0x00004000) +#define BLE_HS_HCI_LE_FEAT_POWER_CLASS_1 (0x00008000) +#define BLE_HS_HCI_LE_FEAT_MIN_NUM_USED_CHAN (0x00010000) + +struct ble_hs_hci_ack { + int bha_status; /* A BLE_HS_E<...> error; NOT a naked HCI code. */ + const uint8_t *bha_params; + int bha_params_len; + uint16_t bha_opcode; + uint8_t bha_hci_handle; +}; + +#if MYNEWT_VAL(BLE_EXT_ADV) +struct ble_hs_hci_ext_scan_param { + uint8_t scan_type; + uint16_t scan_itvl; + uint16_t scan_window; +}; + +struct ble_hs_hci_ext_conn_params { + uint16_t scan_itvl; + uint16_t scan_window; + uint16_t conn_itvl; + uint16_t conn_windows; +}; + +#if MYNEWT_VAL(BLE_PERIODIC_ADV) +/* Periodic Advertising Parameters */ +struct hci_periodic_adv_params +{ + uint16_t min_interval; + uint16_t max_interval; + uint16_t properties; +}; +#endif +#endif + +extern uint16_t ble_hs_hci_avail_pkts; + +int ble_hs_hci_cmd_tx(uint16_t opcode, const void *cmd, uint8_t cmd_len, + void *rsp, uint8_t rsp_len); +void ble_hs_hci_init(void); +void ble_hs_hci_deinit(void); + +void ble_hs_hci_set_le_supported_feat(uint32_t feat); +uint32_t ble_hs_hci_get_le_supported_feat(void); +void ble_hs_hci_set_hci_version(uint8_t hci_version); +uint8_t ble_hs_hci_get_hci_version(void); + +#if MYNEWT_VAL(BLE_HS_PHONY_HCI_ACKS) +typedef int ble_hs_hci_phony_ack_fn(uint8_t *ack, int ack_buf_len); +void ble_hs_hci_set_phony_ack_cb(ble_hs_hci_phony_ack_fn *cb); +#endif + +int ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_pwr); +int ble_hs_hci_util_rand(void *dst, int len); +int ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi); +int ble_hs_hci_util_set_random_addr(const uint8_t *addr); +int ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om, + struct hci_data_hdr *out_hdr); +int ble_hs_hci_evt_process(const struct ble_hci_ev *ev); + +int ble_hs_hci_cmd_send_buf(uint16_t opcode, const void *buf, uint8_t buf_len); +int ble_hs_hci_set_buf_sz(uint16_t pktlen, uint16_t max_pkts); +void ble_hs_hci_add_avail_pkts(uint16_t delta); + +uint16_t ble_hs_hci_util_handle_pb_bc_join(uint16_t handle, uint8_t pb, + uint8_t bc); + +int ble_hs_hci_acl_tx_now(struct ble_hs_conn *conn, struct os_mbuf **om); +int ble_hs_hci_acl_tx(struct ble_hs_conn *conn, struct os_mbuf **om); + +int ble_hs_hci_frag_num_mbufs(void); +int ble_hs_hci_frag_num_mbufs_free(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_util.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_util.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_util.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_util.c index 1f63acc94..996e0fc10 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_util.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_util.c @@ -18,8 +18,8 @@ */ #include -#include "nimble/nimble/include/nimble/hci_common.h" -#include "nimble/nimble/host/include/host/ble_hs_hci.h" +#include "nimble/hci_common.h" +#include "host/ble_hs_hci.h" #include "ble_hs_priv.h" uint16_t diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_id.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_id.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id.c index 83ee49393..e30a3a1bc 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_id.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id.c @@ -18,7 +18,7 @@ */ #include -#include "nimble/nimble/host/include/host/ble_hs_id.h" +#include "host/ble_hs_id.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h new file mode 100644 index 000000000..85260ec48 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_HS_ID_PRIV_ +#define H_BLE_HS_ID_PRIV_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void ble_hs_id_set_pub(const uint8_t *pub_addr); +int ble_hs_id_addr(uint8_t id_addr_type, const uint8_t **out_id_addr, + int *out_is_nrpa); +int ble_hs_id_use_addr(uint8_t addr_type); +void ble_hs_id_reset(void); +void ble_hs_id_rnd_reset(void); + +#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) +bool ble_hs_is_rpa(uint8_t *addr, uint8_t addr_type); +int ble_hs_id_set_pseudo_rnd(const uint8_t *); +int ble_hs_id_set_nrpa_rnd(void); +#endif +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_log.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_log.c similarity index 92% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_log.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_log.c index b4d496703..7ec69469e 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_log.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_log.c @@ -17,8 +17,8 @@ * under the License. */ -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/host/include/host/ble_hs.h" +#include "os/os.h" +#include "host/ble_hs.h" struct log ble_hs_log; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mbuf.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mbuf.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf.c index 680fbe38a..ea660c633 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mbuf.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf.c @@ -17,7 +17,7 @@ * under the License. */ -#include "nimble/nimble/host/include/host/ble_hs.h" +#include "host/ble_hs.h" #include "ble_hs_priv.h" /** diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf_priv.h new file mode 100644 index 000000000..8923678a3 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf_priv.h @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_HS_MBUF_PRIV_ +#define H_BLE_HS_MBUF_PRIV_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct os_mbuf; + +struct os_mbuf *ble_hs_mbuf_bare_pkt(void); +struct os_mbuf *ble_hs_mbuf_acl_pkt(void); +struct os_mbuf *ble_hs_mbuf_l2cap_pkt(void); +int ble_hs_mbuf_pullup_base(struct os_mbuf **om, int base_len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_misc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_misc.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c index b9567f382..dfb46b741 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_misc.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c @@ -19,7 +19,7 @@ #include #include -#include "nimble/porting/nimble/include/os/os.h" +#include "os/os.h" #include "ble_hs_priv.h" const uint8_t ble_hs_misc_null_addr[6]; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mqueue.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mqueue.c similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mqueue.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mqueue.c diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync.c similarity index 95% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync.c index 05a928201..dad535138 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync.c @@ -19,9 +19,9 @@ #include #include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/host/include/host/ble_hs_id.h" +#include "syscfg/syscfg.h" +#include "os/os.h" +#include "host/ble_hs_id.h" #include "ble_hs_priv.h" #if MYNEWT_VAL(BLE_PERIODIC_ADV) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h new file mode 100644 index 000000000..c82ea7904 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_HS_PERIODIC_SYNC_ +#define H_BLE_HS_PERIODIC_SYNC_ + +#include +#include "os/queue.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_hs_periodic_sync { + SLIST_ENTRY(ble_hs_periodic_sync) next; + uint16_t sync_handle; + ble_addr_t advertiser_addr; + uint8_t adv_sid; + + ble_gap_event_fn *cb; + void *cb_arg; + + struct ble_npl_event lost_ev; +}; + +struct ble_hs_periodic_sync *ble_hs_periodic_sync_alloc(void); +void ble_hs_periodic_sync_free(struct ble_hs_periodic_sync *psync); +void ble_hs_periodic_sync_insert(struct ble_hs_periodic_sync *psync); +void ble_hs_periodic_sync_remove(struct ble_hs_periodic_sync *psync); +struct ble_hs_periodic_sync *ble_hs_periodic_sync_find_by_handle(uint16_t sync_handle); +struct ble_hs_periodic_sync *ble_hs_periodic_sync_find(const ble_addr_t *addr, + uint8_t sid); +struct ble_hs_periodic_sync *ble_hs_periodic_sync_first(void); +int ble_hs_periodic_sync_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h new file mode 100644 index 000000000..538d07a97 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_HS_PRIV_ +#define H_BLE_HS_PRIV_ + +#include +#include +#include "ble_att_cmd_priv.h" +#include "ble_att_priv.h" +#include "ble_gap_priv.h" +#include "ble_gatt_priv.h" +#include "ble_hs_hci_priv.h" +#include "ble_hs_atomic_priv.h" +#include "ble_hs_conn_priv.h" +#include "ble_hs_atomic_priv.h" +#include "ble_hs_mbuf_priv.h" +#include "ble_hs_startup_priv.h" +#include "ble_l2cap_priv.h" +#include "ble_l2cap_sig_priv.h" +#include "ble_l2cap_coc_priv.h" +#include "ble_sm_priv.h" +#include "ble_hs_adv_priv.h" +#include "ble_hs_flow_priv.h" +#include "ble_hs_pvcy_priv.h" +#include "ble_hs_id_priv.h" +#include "ble_hs_periodic_sync_priv.h" +#include "ble_uuid_priv.h" +#include "host/ble_hs.h" +#include "host/ble_monitor.h" +#include "nimble/nimble_opt.h" +#include "stats/stats.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_hs_conn; +struct ble_l2cap_chan; +struct os_mbuf; +struct os_mempool; +struct os_event; + +#define BLE_HS_SYNC_STATE_BAD 0 +#define BLE_HS_SYNC_STATE_BRINGUP 1 +#define BLE_HS_SYNC_STATE_GOOD 2 + +#define BLE_HS_ENABLED_STATE_OFF 0 +#define BLE_HS_ENABLED_STATE_STOPPING 1 +#define BLE_HS_ENABLED_STATE_ON 2 + +#if NIMBLE_BLE_CONNECT +#define BLE_HS_MAX_CONNECTIONS MYNEWT_VAL(BLE_MAX_CONNECTIONS) +#else +#define BLE_HS_MAX_CONNECTIONS 0 +#endif + +#if !MYNEWT_VAL(BLE_ATT_SVR_QUEUED_WRITE) +#define BLE_HS_ATT_SVR_QUEUED_WRITE_TMO 0 +#else +#define BLE_HS_ATT_SVR_QUEUED_WRITE_TMO \ + MYNEWT_VAL(BLE_ATT_SVR_QUEUED_WRITE_TMO) +#endif + +STATS_SECT_START(ble_hs_stats) + STATS_SECT_ENTRY(conn_create) + STATS_SECT_ENTRY(conn_delete) + STATS_SECT_ENTRY(hci_cmd) + STATS_SECT_ENTRY(hci_event) + STATS_SECT_ENTRY(hci_invalid_ack) + STATS_SECT_ENTRY(hci_unknown_event) + STATS_SECT_ENTRY(hci_timeout) + STATS_SECT_ENTRY(reset) + STATS_SECT_ENTRY(sync) + STATS_SECT_ENTRY(pvcy_add_entry) + STATS_SECT_ENTRY(pvcy_add_entry_fail) +STATS_SECT_END +extern STATS_SECT_DECL(ble_hs_stats) ble_hs_stats; + +extern struct os_mbuf_pool ble_hs_mbuf_pool; +extern uint8_t ble_hs_sync_state; +extern uint8_t ble_hs_enabled_state; + +extern const uint8_t ble_hs_misc_null_addr[6]; + +extern uint16_t ble_hs_max_attrs; +extern uint16_t ble_hs_max_services; +extern uint16_t ble_hs_max_client_configs; + +void ble_hs_process_rx_data_queue(void); +int ble_hs_tx_data(struct os_mbuf *om); +void ble_hs_wakeup_tx(void); +void ble_hs_enqueue_hci_event(uint8_t *hci_evt); +void ble_hs_event_enqueue(struct os_event *ev); + +int ble_hs_hci_rx_evt(uint8_t *hci_ev, void *arg); +int ble_hs_hci_evt_acl_process(struct os_mbuf *om); + +int ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid, + struct ble_hs_conn **out_conn, + struct ble_l2cap_chan **out_chan); +int ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid, + struct ble_hs_conn **out_conn, + struct ble_l2cap_chan **out_chan); +uint8_t ble_hs_misc_own_addr_type_to_id(uint8_t addr_type); +uint8_t ble_hs_misc_peer_addr_type_to_id(uint8_t addr_type); +int ble_hs_misc_restore_irks(void); + +int ble_hs_locked_by_cur_task(void); +int ble_hs_is_parent_task(void); +void ble_hs_lock_nested(void); +void ble_hs_unlock_nested(void); +void ble_hs_lock(void); +void ble_hs_unlock(void); +void ble_hs_hw_error(uint8_t hw_code); +void ble_hs_timer_resched(void); +void ble_hs_notifications_sched(void); +struct ble_npl_eventq *ble_hs_evq_get(void); +void ble_hs_stop_init(void); + +struct ble_mqueue { + STAILQ_HEAD(, os_mbuf_pkthdr) head; + struct ble_npl_event ev; +}; + +int ble_mqueue_init(struct ble_mqueue *mq, ble_npl_event_fn *ev_fn, void *ev_arg); +struct os_mbuf *ble_mqueue_get(struct ble_mqueue *mq); +int ble_mqueue_put(struct ble_mqueue *mq, struct ble_npl_eventq *evq, struct os_mbuf *om); + +#if MYNEWT_VAL(BLE_HS_DEBUG) + #define BLE_HS_DBG_ASSERT(x) assert(x) + #define BLE_HS_DBG_ASSERT_EVAL(x) assert(x) +#else + #define BLE_HS_DBG_ASSERT(x) + #define BLE_HS_DBG_ASSERT_EVAL(x) ((void)(x)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_pvcy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_pvcy.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy.c index 2d7db0bcc..9e92c660f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_pvcy.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy.c @@ -19,10 +19,10 @@ #include #include #include -#include "nimble/porting/nimble/include/stats/stats.h" +#include "stats/stats.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" -#include "nimble/nimble/host/include/host/ble_hs_pvcy.h" +#include "host/ble_hs_pvcy.h" static uint8_t ble_hs_pvcy_started; static uint8_t ble_hs_pvcy_irk[16]; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy_priv.h new file mode 100644 index 000000000..86157da0f --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy_priv.h @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_HS_PVCY_PRIV_ +#define H_BLE_HS_PVCY_PRIV_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern const uint8_t ble_hs_pvcy_default_irk[16]; + +int ble_hs_pvcy_set_our_irk(const uint8_t *irk); +int ble_hs_pvcy_our_irk(const uint8_t **out_irk); +int ble_hs_pvcy_remove_entry(uint8_t addr_type, const uint8_t *addr); +int ble_hs_pvcy_add_entry(const uint8_t *addr, uint8_t addrtype, + const uint8_t *irk); +int ble_hs_pvcy_ensure_started(void); +int ble_hs_pvcy_set_mode(const ble_addr_t *addr, uint8_t priv_mode); +#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) +bool ble_hs_pvcy_enabled(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_resolv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_resolv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv.c index 7ae9ef12b..6add1018b 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_resolv.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv.c @@ -19,17 +19,17 @@ * under the License. */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "syscfg/syscfg.h" #if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) #include #include #include "ble_hs_priv.h" -#include "../include/host/ble_hs_id.h" -#include "../../include/nimble/ble.h" -#include "../../include/nimble/nimble_opt.h" +#include "host/ble_hs_id.h" +#include "nimble/ble.h" +#include "nimble/nimble_opt.h" #include "ble_hs_resolv_priv.h" -#include "../store/config/include/store/config/ble_store_config.h" +#include "store/config/ble_store_config.h" #include "../store/config/src/ble_store_config_priv.h" /* Resolve list size, additional space to save local device's configuration */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h new file mode 100644 index 000000000..7bc8a2fe6 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h @@ -0,0 +1,111 @@ +/* + * Copyright 2020 Espressif Systems (Shanghai) PTE LTD + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) +/* + * An entry in the resolving list. + */ +struct ble_hs_resolv_entry { + uint8_t rl_addr_type; + uint8_t rl_local_irk[16]; + uint8_t rl_peer_irk[16]; + uint8_t rl_identity_addr[BLE_DEV_ADDR_LEN]; + uint8_t rl_pseudo_id[BLE_DEV_ADDR_LEN]; + uint8_t rl_local_rpa[BLE_DEV_ADDR_LEN]; + uint8_t rl_peer_rpa[BLE_DEV_ADDR_LEN]; +}; + +#if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) +/* Persist peer records in NVS. XXX Need to handle this in `store` module */ +int ble_store_persist_peer_records(void); +#endif + +struct ble_hs_peer_sec { + ble_addr_t peer_addr; + uint8_t irk[16]; + uint8_t irk_present: 1; +}; +/* + * BLE host peer device record, this helps in storing peer RPA before bond is + * created and IRKs are exchanged. + */ +struct ble_hs_dev_records { + bool rec_used; + uint8_t rand_addr_type; + uint8_t pseudo_addr[BLE_DEV_ADDR_LEN]; + uint8_t rand_addr[BLE_DEV_ADDR_LEN]; + uint8_t identity_addr[BLE_DEV_ADDR_LEN]; + struct ble_hs_peer_sec peer_sec; +}; + +/* Add a device to the resolving list */ +int ble_hs_resolv_list_add(uint8_t *cmdbuf); +int ble_hs_gen_own_private_rnd(void); +uint8_t *ble_hs_get_rpa_local(void); + +/* Remove a device from the resolving list */ +int ble_hs_resolv_list_rmv(uint8_t, uint8_t *); +/* Clear the resolving list and peer dev record */ +void ble_hs_resolv_list_clear_all(void); + +/* Address resolution enable command */ +void ble_hs_resolv_enable(bool); +void ble_hs_resolv_nrpa_enable(void); +void ble_hs_resolv_nrpa_disable(void); + +/* Finds 'addr' in resolving list. Doesnt check if address resolution enabled */ +struct ble_hs_resolv_entry * +ble_hs_resolv_list_find(uint8_t *addr); + +/* Returns true if host based RPA (privacy) is enabled */ +bool ble_host_rpa_enabled(void); + +/* Searches peer device records (RPA) and fetches matching RL, peer_address + * into input parameters if RL is found */ +void +ble_rpa_replace_peer_params_with_rl(uint8_t *, uint8_t *, struct ble_hs_resolv_entry **); + +int ble_rpa_resolv_add_peer_rec(uint8_t *); + +struct ble_hs_dev_records *ble_rpa_get_peer_dev_records(void); +int ble_rpa_get_num_peer_dev_records(void); +void ble_rpa_set_num_peer_dev_records(int); +int ble_rpa_remove_peer_dev_rec(struct ble_hs_dev_records *); +struct ble_hs_dev_records *ble_rpa_find_peer_dev_rec(uint8_t *); + +/* Set the resolvable private address timeout */ +int ble_hs_resolv_set_rpa_tmo(uint16_t); + +/* Resolve a resolvable private address */ +int ble_hs_resolv_rpa(uint8_t *rpa, uint8_t *irk); + +/* Initialize resolv*/ +void ble_hs_resolv_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_shutdown.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_shutdown.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_shutdown.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_shutdown.c index 9dacccbaf..f29d4a669 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_shutdown.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_shutdown.c @@ -19,7 +19,7 @@ #if MYNEWT -#include "nimble/porting/nimble/include/os/mynewt.h" +#include "os/mynewt.h" #include "ble_hs_priv.h" static struct ble_hs_stop_listener ble_hs_shutdown_stop_listener; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_startup.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_startup.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup.c index 2ec17a13b..83026ac18 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_startup.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup.c @@ -19,8 +19,8 @@ #include #include -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "nimble/nimble/host/include/host/ble_hs_hci.h" +#include "host/ble_hs.h" +#include "host/ble_hs_hci.h" #include "ble_hs_priv.h" #if !MYNEWT_VAL(BLE_CONTROLLER) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_test.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup_priv.h similarity index 90% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_test.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup_priv.h index 32984c6b3..a2d328756 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_test.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup_priv.h @@ -17,16 +17,14 @@ * under the License. */ -#ifndef H_LL_TEST_ -#define H_LL_TEST_ - -#include +#ifndef H_BLE_HS_STARTUP_ +#define H_BLE_HS_STARTUP_ #ifdef __cplusplus extern "C" { #endif -int ble_ll_csa2_test_all(void); +int ble_hs_startup_go(void); #ifdef __cplusplus } diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_stop.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_stop.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_stop.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_stop.c index 92fae1263..b90d3ec6f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_stop.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_stop.c @@ -18,12 +18,12 @@ */ #include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "sysinit/sysinit.h" +#include "syscfg/syscfg.h" #include "ble_hs_priv.h" -#include "nimble/nimble/include/nimble/nimble_npl.h" +#include "nimble/nimble_npl.h" #ifndef MYNEWT -#include "nimble/porting/nimble/include/nimble/nimble_port.h" +#include "nimble/nimble_port.h" #endif #define BLE_HOST_STOP_TIMEOUT_MS MYNEWT_VAL(BLE_HS_STOP_ON_SHUTDOWN_TIMEOUT) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_ibeacon.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_ibeacon.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_ibeacon.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_ibeacon.c index 62c7bc1d1..0c6ef99d5 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_ibeacon.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_ibeacon.c @@ -18,7 +18,7 @@ */ #include -#include "nimble/nimble/host/include/host/ble_hs_adv.h" +#include "host/ble_hs_adv.h" #include "ble_hs_priv.h" #define BLE_IBEACON_MFG_DATA_SIZE 25 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap.c index a4b98a9e7..0d9f082d4 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap.c @@ -19,10 +19,10 @@ #include #include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/hci_common.h" +#include "syscfg/syscfg.h" +#include "os/os.h" +#include "nimble/ble.h" +#include "nimble/hci_common.h" #include "ble_hs_priv.h" #include "ble_l2cap_coc_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc.c index 5258da84d..41a831565 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc.c @@ -19,7 +19,7 @@ #include #include -#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/ble.h" #include "ble_hs_priv.h" #include "ble_l2cap_priv.h" #include "ble_l2cap_coc_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc_priv.h new file mode 100644 index 000000000..5ebdaa050 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc_priv.h @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_L2CAP_COC_PRIV_ +#define H_L2CAP_COC_PRIV_ + +#include +#include "syscfg/syscfg.h" +#include "os/queue.h" +#include "os/os_mbuf.h" +#include "host/ble_l2cap.h" +#include "ble_l2cap_sig_priv.h" +#ifdef __cplusplus +extern "C" { +#endif + +#define BLE_L2CAP_COC_CID_START 0x0040 +#define BLE_L2CAP_COC_CID_END 0x007F + +struct ble_l2cap_chan; + +#define BLE_L2CAP_COC_FLAG_STALLED 0x01 + +struct ble_l2cap_coc_endpoint { + struct os_mbuf *sdu; + uint16_t mtu; + uint16_t credits; + uint16_t data_offset; + uint8_t flags; +}; + +struct ble_l2cap_coc_srv { + STAILQ_ENTRY(ble_l2cap_coc_srv) next; + uint16_t psm; + uint16_t mtu; + ble_l2cap_event_fn *cb; + void *cb_arg; +}; + +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 +int ble_l2cap_coc_init(void); +int ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu, + ble_l2cap_event_fn *cb, void *cb_arg); +int ble_l2cap_coc_create_srv_chan(struct ble_hs_conn *conn, uint16_t psm, + struct ble_l2cap_chan **chan); +struct ble_l2cap_chan * ble_l2cap_coc_chan_alloc(struct ble_hs_conn *conn, + uint16_t psm, uint16_t mtu, + struct os_mbuf *sdu_rx, + ble_l2cap_event_fn *cb, + void *cb_arg); +void ble_l2cap_coc_cleanup_chan(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan); +void ble_l2cap_coc_le_credits_update(uint16_t conn_handle, uint16_t dcid, + uint16_t credits); +int ble_l2cap_coc_recv_ready(struct ble_l2cap_chan *chan, + struct os_mbuf *sdu_rx); +int ble_l2cap_coc_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx); +void ble_l2cap_coc_set_new_mtu_mps(struct ble_l2cap_chan *chan, uint16_t mtu, uint16_t mps); +#else +static inline int +ble_l2cap_coc_init(void) { + return 0; +} + +static inline int +ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu, + ble_l2cap_event_fn *cb, void *cb_arg) { + return BLE_HS_ENOTSUP; +} + +static inline int +ble_l2cap_coc_recv_ready(struct ble_l2cap_chan *chan, + struct os_mbuf *sdu_rx) { + return BLE_HS_ENOTSUP; +} + +static inline void +ble_l2cap_coc_cleanup_chan(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan) { +} + +static inline int +ble_l2cap_coc_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx) { + return BLE_HS_ENOTSUP; +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* H_L2CAP_COC_PRIV_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_priv.h new file mode 100644 index 000000000..e3409743b --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_priv.h @@ -0,0 +1,144 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_L2CAP_PRIV_ +#define H_L2CAP_PRIV_ + +#include "ble_l2cap_coc_priv.h" +#include "host/ble_l2cap.h" +#include +#include "stats/stats.h" +#include "os/queue.h" +#include "os/os_mbuf.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_hs_conn; +struct hci_data_hdr; + +STATS_SECT_START(ble_l2cap_stats) + STATS_SECT_ENTRY(chan_create) + STATS_SECT_ENTRY(chan_delete) + STATS_SECT_ENTRY(update_init) + STATS_SECT_ENTRY(update_rx) + STATS_SECT_ENTRY(update_fail) + STATS_SECT_ENTRY(proc_timeout) + STATS_SECT_ENTRY(sig_tx) + STATS_SECT_ENTRY(sig_rx) + STATS_SECT_ENTRY(sm_tx) + STATS_SECT_ENTRY(sm_rx) +STATS_SECT_END +extern STATS_SECT_DECL(ble_l2cap_stats) ble_l2cap_stats; + +extern struct os_mempool ble_l2cap_chan_pool; + +/* This is nimble specific; packets sent to the black hole CID do not elicit + * an "invalid CID" response. + */ +#define BLE_L2CAP_CID_BLACK_HOLE 0xffff + +#define BLE_L2CAP_HDR_SZ 4 + +typedef uint8_t ble_l2cap_chan_flags; + +typedef int ble_l2cap_rx_fn(struct ble_l2cap_chan *chan); + +struct ble_l2cap_chan { + SLIST_ENTRY(ble_l2cap_chan) next; + uint16_t conn_handle; + uint16_t dcid; + uint16_t scid; + + /* Unions just to avoid confusion on MPS/MTU. + * In CoC context, L2CAP MTU is MPS + */ + union { + uint16_t my_mtu; + uint16_t my_coc_mps; + }; + + union { + uint16_t peer_mtu; + uint16_t peer_coc_mps; + }; + + ble_l2cap_chan_flags flags; + + struct os_mbuf *rx_buf; + uint16_t rx_len; /* Length of current reassembled rx packet. */ + + ble_l2cap_rx_fn *rx_fn; + +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 + uint16_t psm; + struct ble_l2cap_coc_endpoint coc_rx; + struct ble_l2cap_coc_endpoint coc_tx; + uint16_t initial_credits; + ble_l2cap_event_fn *cb; + void *cb_arg; +#endif +}; + +struct ble_l2cap_hdr { + uint16_t len; + uint16_t cid; +}; + +typedef int ble_l2cap_tx_fn(struct ble_hs_conn *conn, + struct ble_l2cap_chan *chan); + +#define BLE_L2CAP_CHAN_F_TXED_MTU 0x01 /* We have sent our MTU. */ + +SLIST_HEAD(ble_l2cap_chan_list, ble_l2cap_chan); + +int ble_l2cap_parse_hdr(struct os_mbuf *om, int off, + struct ble_l2cap_hdr *l2cap_hdr); +struct os_mbuf *ble_l2cap_prepend_hdr(struct os_mbuf *om, uint16_t cid, + uint16_t len); + +struct ble_l2cap_chan *ble_l2cap_chan_alloc(uint16_t conn_handle); +void ble_l2cap_chan_free(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan); + +bool ble_l2cap_is_mtu_req_sent(const struct ble_l2cap_chan *chan); + +int ble_l2cap_rx(struct ble_hs_conn *conn, + struct hci_data_hdr *hci_hdr, + struct os_mbuf *om, + ble_l2cap_rx_fn **out_rx_cb, + int *out_reject_cid); +int ble_l2cap_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan, + struct os_mbuf *txom); + +void ble_l2cap_remove_rx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan); + +int ble_l2cap_init(void); + +/* Below experimental API is available when BLE_VERSION >= 52 */ +int ble_l2cap_enhanced_connect(uint16_t conn_handle, + uint16_t psm, uint16_t mtu, + uint8_t num, struct os_mbuf *sdu_rx[], + ble_l2cap_event_fn *cb, void *cb_arg); +int ble_l2cap_reconfig(struct ble_l2cap_chan *chans[], uint8_t num, uint16_t new_mtu); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c index f9d32d0ac..58f96b0f3 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c @@ -44,8 +44,8 @@ #include #include -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/host/include/host/ble_monitor.h" +#include "nimble/ble.h" +#include "host/ble_monitor.h" #include "ble_hs_priv.h" /***************************************************************************** diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig_cmd.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_priv.h new file mode 100644 index 000000000..a698cd0d8 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_priv.h @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_L2CAP_SIG_ +#define H_BLE_L2CAP_SIG_ + +#include "syscfg/syscfg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLE_L2CAP_SIG_MTU 100 /* This is our own default. */ + +#define BLE_L2CAP_SIG_HDR_SZ 4 +struct ble_l2cap_sig_hdr { + uint8_t op; + uint8_t identifier; + uint16_t length; + uint8_t data[0]; +} __attribute__((packed)); + +#define BLE_L2CAP_SIG_REJECT_MIN_SZ 2 +struct ble_l2cap_sig_reject { + uint16_t reason; + uint8_t data[0]; +} __attribute__((packed)); + +#define BLE_L2CAP_SIG_UPDATE_REQ_SZ 8 +struct ble_l2cap_sig_update_req { + uint16_t itvl_min; + uint16_t itvl_max; + uint16_t slave_latency; + uint16_t timeout_multiplier; +} __attribute__((packed)); + +#define BLE_L2CAP_SIG_UPDATE_RSP_SZ 2 +struct ble_l2cap_sig_update_rsp { + uint16_t result; +} __attribute__((packed)); + +#define BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT 0x0000 +#define BLE_L2CAP_SIG_UPDATE_RSP_RESULT_REJECT 0x0001 + +struct ble_l2cap_sig_le_con_req { + uint16_t psm; + uint16_t scid; + uint16_t mtu; + uint16_t mps; + uint16_t credits; +} __attribute__((packed)); + +struct ble_l2cap_sig_le_con_rsp { + uint16_t dcid; + uint16_t mtu; + uint16_t mps; + uint16_t credits; + uint16_t result; +} __attribute__((packed)); + +struct ble_l2cap_sig_credit_base_connect_req { + uint16_t psm; + uint16_t mtu; + uint16_t mps; + uint16_t credits; + uint16_t scids[0]; +} __attribute__((packed)); + +struct ble_l2cap_sig_credit_base_connect_rsp { + uint16_t mtu; + uint16_t mps; + uint16_t credits; + uint16_t result; + uint16_t dcids[0]; +} __attribute__((packed)); + +struct ble_l2cap_sig_credit_base_reconfig_req { + uint16_t mtu; + uint16_t mps; + uint16_t dcids[0]; +} __attribute__((packed)); + +struct ble_l2cap_sig_credit_base_reconfig_rsp { + uint16_t result; +} __attribute__((packed)); + +struct ble_l2cap_sig_disc_req { + uint16_t dcid; + uint16_t scid; +} __attribute__((packed)); + +struct ble_l2cap_sig_disc_rsp { + uint16_t dcid; + uint16_t scid; +} __attribute__((packed)); + +struct ble_l2cap_sig_le_credits { + uint16_t scid; + uint16_t credits; +} __attribute__((packed)); + +void ble_l2cap_sig_hdr_parse(void *payload, uint16_t len, + struct ble_l2cap_sig_hdr *hdr); +int ble_l2cap_sig_reject_tx(uint16_t conn_handle, + uint8_t id, uint16_t reason, + void *data, int data_len); +int ble_l2cap_sig_reject_invalid_cid_tx(uint16_t conn_handle, uint8_t id, + uint16_t src_cid, uint16_t dst_cid); +int ble_l2cap_sig_tx(uint16_t conn_handle, struct os_mbuf *txom); +void *ble_l2cap_sig_cmd_get(uint8_t opcode, uint8_t id, uint16_t len, + struct os_mbuf **txom); +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 +int ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu, + struct os_mbuf *sdu_rx, + ble_l2cap_event_fn *cb, void *cb_arg); +int ble_l2cap_sig_disconnect(struct ble_l2cap_chan *chan); +int ble_l2cap_sig_le_credits(uint16_t conn_handle, uint16_t scid, + uint16_t credits); +#else +static inline int +ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu, + struct os_mbuf *sdu_rx, + ble_l2cap_event_fn *cb, void *cb_arg) +{ + return BLE_HS_ENOTSUP; +} + +static inline int +ble_l2cap_sig_disconnect(struct ble_l2cap_chan *chan) +{ + return BLE_HS_ENOTSUP; +} +#endif + +#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC) +int ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, + uint16_t psm, uint16_t mtu, + uint8_t num, struct os_mbuf *sdu_rx[], + ble_l2cap_event_fn *cb, void *cb_arg); +int ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[], + uint8_t num, uint16_t new_mtu); +#else +static inline int +ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, + uint16_t psm, uint16_t mtu, + uint8_t num, struct os_mbuf *sdu_rx[], + ble_l2cap_event_fn *cb, void *cb_arg) +{ + return BLE_HS_ENOTSUP; +} +static inline int +ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[], + uint8_t num, uint16_t new_mtu) +{ + return BLE_HS_ENOTSUP; +} +#endif + +void ble_l2cap_sig_conn_broken(uint16_t conn_handle, int reason); +int32_t ble_l2cap_sig_timer(void); +struct ble_l2cap_chan *ble_l2cap_sig_create_chan(uint16_t conn_handle); +int ble_l2cap_sig_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_monitor.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_monitor.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor.c index d4a468284..e6db48b82 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_monitor.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor.c @@ -17,7 +17,7 @@ * under the License. */ -#include "nimble/nimble/host/include/host/ble_monitor.h" +#include "host/ble_monitor.h" #if BLE_MONITOR @@ -28,10 +28,10 @@ #include #include #include -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/porting/nimble/include/log/log.h" +#include "os/os.h" +#include "log/log.h" #if MYNEWT_VAL(BLE_MONITOR_UART) -#include "nimble/porting/nimble/include/uart/uart.h" +#include "uart/uart.h" #endif #if MYNEWT_VAL(BLE_MONITOR_RTT) #include "rtt/SEGGER_RTT.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h new file mode 100644 index 000000000..935787040 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_MONITOR_PRIV_ +#define H_BLE_MONITOR_PRIV_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLE_MONITOR_OPCODE_NEW_INDEX 0 +#define BLE_MONITOR_OPCODE_DEL_INDEX 1 +#define BLE_MONITOR_OPCODE_COMMAND_PKT 2 +#define BLE_MONITOR_OPCODE_EVENT_PKT 3 +#define BLE_MONITOR_OPCODE_ACL_TX_PKT 4 +#define BLE_MONITOR_OPCODE_ACL_RX_PKT 5 +#define BLE_MONITOR_OPCODE_SCO_TX_PKT 6 +#define BLE_MONITOR_OPCODE_SCO_RX_PKT 7 +#define BLE_MONITOR_OPCODE_OPEN_INDEX 8 +#define BLE_MONITOR_OPCODE_CLOSE_INDEX 9 +#define BLE_MONITOR_OPCODE_INDEX_INFO 10 +#define BLE_MONITOR_OPCODE_VENDOR_DIAG 11 +#define BLE_MONITOR_OPCODE_SYSTEM_NOTE 12 +#define BLE_MONITOR_OPCODE_USER_LOGGING 13 + +#define BLE_MONITOR_EXTHDR_COMMAND_DROPS 1 +#define BLE_MONITOR_EXTHDR_EVENT_DROPS 2 +#define BLE_MONITOR_EXTHDR_ACL_RX_DROPS 3 +#define BLE_MONITOR_EXTHDR_ACL_TX_DROPS 4 +#define BLE_MONITOR_EXTHDR_SCO_RX_DROPS 5 +#define BLE_MONITOR_EXTHDR_SCO_TX_DROPS 6 +#define BLE_MONITOR_EXTHDR_OTHER_DROPS 7 +#define BLE_MONITOR_EXTHDR_TS32 8 + +struct ble_monitor_hdr { + uint16_t data_len; + uint16_t opcode; + uint8_t flags; + uint8_t hdr_len; +} __attribute__((packed)); + +struct ble_monitor_drops_hdr { + uint8_t type_cmd; + uint8_t cmd; + uint8_t type_evt; + uint8_t evt; + uint8_t type_acl_tx; + uint8_t acl_tx; + uint8_t type_acl_rx; + uint8_t acl_rx; + uint8_t type_other; + uint8_t other; +} __attribute__((packed)); + +struct ble_monitor_ts_hdr { + uint8_t type; + uint32_t ts32; +} __attribute__((packed)); + +struct ble_monitor_new_index { + uint8_t type; + uint8_t bus; + uint8_t bdaddr[6]; + char name[8]; +} __attribute__((packed)); + +struct ble_monitor_user_logging { + uint8_t priority; + uint8_t ident_len; +} __attribute__((packed)); + +int ble_monitor_init(void); + +int ble_monitor_send(uint16_t opcode, const void *data, size_t len); + +int ble_monitor_send_om(uint16_t opcode, const struct os_mbuf *om); + +int ble_monitor_new_index(uint8_t bus, uint8_t *addr, const char *name); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm.c index acbe8a1c1..8422c044f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm.c @@ -43,9 +43,9 @@ #include #include -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/host/include/host/ble_sm.h" +#include "nimble/ble.h" +#include "nimble/nimble_opt.h" +#include "host/ble_sm.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" #include "../store/config/src/ble_store_config_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_alg.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_alg.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_alg.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_alg.c index e17760efe..ee8b937c5 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_alg.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_alg.c @@ -20,12 +20,12 @@ #include #include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "syscfg/syscfg.h" +#include "nimble/nimble_opt.h" #if NIMBLE_BLE_SM -#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/ble.h" #include "ble_hs_priv.h" #if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS) @@ -41,13 +41,13 @@ #endif #else -#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" +#include "tinycrypt/aes.h" +#include "tinycrypt/constants.h" +#include "tinycrypt/utils.h" #if MYNEWT_VAL(BLE_SM_SC) -#include "nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h" +#include "tinycrypt/cmac_mode.h" +#include "tinycrypt/ecc_dh.h" #if MYNEWT_VAL(TRNG) #include "trng/trng.h" #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c similarity index 92% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_cmd.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c index 92a34ed36..01651f1df 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_cmd.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c @@ -19,9 +19,9 @@ #include #include -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/host/include/host/ble_sm.h" +#include "nimble/ble.h" +#include "nimble/nimble_opt.h" +#include "host/ble_sm.h" #include "ble_hs_priv.h" void * diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_lgcy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_lgcy.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_lgcy.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_lgcy.c index 2f150eeb3..bb2d66d5d 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_lgcy.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_lgcy.c @@ -19,9 +19,9 @@ #include #include -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/host/include/host/ble_sm.h" +#include "nimble/ble.h" +#include "nimble/nimble_opt.h" +#include "host/ble_sm.h" #include "ble_hs_priv.h" #if MYNEWT_VAL(BLE_SM_LEGACY) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h new file mode 100644 index 000000000..def0a32f5 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h @@ -0,0 +1,428 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_SM_PRIV_ +#define H_BLE_SM_PRIV_ + +#include +#include "syscfg/syscfg.h" +#include "os/queue.h" +#include "nimble/nimble_opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_gap_sec_state; +struct hci_le_lt_key_req; +struct hci_encrypt_change; + +#define BLE_SM_MTU 65 + +#define BLE_SM_OP_PAIR_REQ 0x01 +#define BLE_SM_OP_PAIR_RSP 0x02 +#define BLE_SM_OP_PAIR_CONFIRM 0x03 +#define BLE_SM_OP_PAIR_RANDOM 0x04 +#define BLE_SM_OP_PAIR_FAIL 0x05 +#define BLE_SM_OP_ENC_INFO 0x06 +#define BLE_SM_OP_MASTER_ID 0x07 +#define BLE_SM_OP_IDENTITY_INFO 0x08 +#define BLE_SM_OP_IDENTITY_ADDR_INFO 0x09 +#define BLE_SM_OP_SIGN_INFO 0x0a +#define BLE_SM_OP_SEC_REQ 0x0b +#define BLE_SM_OP_PAIR_PUBLIC_KEY 0x0c +#define BLE_SM_OP_PAIR_DHKEY_CHECK 0x0d +#define BLE_SM_OP_PAIR_KEYPRESS_NOTIFY 0x0e + +struct ble_sm_hdr { + uint8_t opcode; + uint8_t data[0]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x01/0x02 [req/rsp]) | 1 | + * | IO Capability | 1 | + * | OOB data flag | 1 | + * | AuthReq | 1 | + * | Maximum Encryption Key Size | 1 | + * | Initiator Key Distribution | 1 | + * | Responder Key Distribution | 1 | + */ + +struct ble_sm_pair_cmd { + uint8_t io_cap; + uint8_t oob_data_flag; + uint8_t authreq; + uint8_t max_enc_key_size; + uint8_t init_key_dist; + uint8_t resp_key_dist; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x03) | 1 | + * | Confirm Value | 16 | + */ + +struct ble_sm_pair_confirm { + uint8_t value[16]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x04) | 1 | + * | Random Value | 16 | + */ +struct ble_sm_pair_random { + uint8_t value[16]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x05) | 1 | + * | Reason | 1 | + */ +struct ble_sm_pair_fail { + uint8_t reason; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x06) | 1 | + * | ltk | 16 | + */ +struct ble_sm_enc_info { + uint8_t ltk[16]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x07) | 1 | + * | EDIV | 2 | + * | RAND | 8 | + */ +struct ble_sm_master_id { + uint16_t ediv; + uint64_t rand_val; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x08) | 1 | + * | irk | 16 | + */ +struct ble_sm_id_info { + uint8_t irk[16]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x09) | 1 | + * | addr_type | 1 | + * | address | 6 | + */ +struct ble_sm_id_addr_info { + uint8_t addr_type; + uint8_t bd_addr[6]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x0A) | 1 | + * | csrk | 16 | + */ +struct ble_sm_sign_info { + uint8_t sig_key[16]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x0B) | 1 | + * | authreq | 1 | + */ +struct ble_sm_sec_req { + uint8_t authreq; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x0c) | 1 | + * | Public Key X | 32 | + * | Public Key Y | 32 | + */ +struct ble_sm_public_key { + uint8_t x[32]; + uint8_t y[32]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x0d) | 1 | + * | DHKey Check | 16 | + */ +struct ble_sm_dhkey_check { + uint8_t value[16]; +} __attribute__((packed)); + +#if NIMBLE_BLE_SM + +#define BLE_SM_PROC_STATE_NONE ((uint8_t)-1) + +#define BLE_SM_PROC_STATE_PAIR 0 +#define BLE_SM_PROC_STATE_CONFIRM 1 +#define BLE_SM_PROC_STATE_RANDOM 2 +#define BLE_SM_PROC_STATE_LTK_START 3 +#define BLE_SM_PROC_STATE_LTK_RESTORE 4 +#define BLE_SM_PROC_STATE_ENC_START 5 +#define BLE_SM_PROC_STATE_ENC_RESTORE 6 +#define BLE_SM_PROC_STATE_KEY_EXCH 7 +#define BLE_SM_PROC_STATE_SEC_REQ 8 +#define BLE_SM_PROC_STATE_PUBLIC_KEY 9 +#define BLE_SM_PROC_STATE_DHKEY_CHECK 10 +#define BLE_SM_PROC_STATE_CNT 11 + +#define BLE_SM_PROC_F_INITIATOR 0x01 +#define BLE_SM_PROC_F_IO_INJECTED 0x02 +#define BLE_SM_PROC_F_ADVANCE_ON_IO 0x04 +#define BLE_SM_PROC_F_AUTHENTICATED 0x08 +#define BLE_SM_PROC_F_SC 0x10 +#define BLE_SM_PROC_F_BONDING 0x20 + +#define BLE_SM_KE_F_ENC_INFO 0x01 +#define BLE_SM_KE_F_MASTER_ID 0x02 +#define BLE_SM_KE_F_ID_INFO 0x04 +#define BLE_SM_KE_F_ADDR_INFO 0x08 +#define BLE_SM_KE_F_SIGN_INFO 0x10 + +typedef uint8_t ble_sm_proc_flags; + +struct ble_sm_keys { + unsigned ltk_valid:1; + unsigned ediv_rand_valid:1; + unsigned irk_valid:1; + unsigned csrk_valid:1; + unsigned addr_valid:1; + uint16_t ediv; + uint64_t rand_val; + uint8_t addr_type; + uint8_t key_size; + uint8_t ltk[16]; /* Little endian. */ + uint8_t irk[16]; /* Little endian. */ + uint8_t csrk[16]; /* Little endian. */ + uint8_t addr[6]; /* Little endian. */ +}; + +struct ble_sm_proc { + STAILQ_ENTRY(ble_sm_proc) next; + + ble_npl_time_t exp_os_ticks; + ble_sm_proc_flags flags; + uint16_t conn_handle; + uint8_t pair_alg; + uint8_t state; + uint8_t rx_key_flags; + uint8_t key_size; + + uint8_t pair_req[sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_cmd)]; + uint8_t pair_rsp[sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_cmd)]; + uint8_t tk[16]; + uint8_t confirm_peer[16]; + uint8_t randm[16]; + uint8_t rands[16]; + uint8_t ltk[16]; /* Little endian. */ + struct ble_sm_keys our_keys; + struct ble_sm_keys peer_keys; + +#if MYNEWT_VAL(BLE_SM_SC) + /* Secure connections. */ + uint8_t passkey_bits_exchanged; + uint8_t ri; + struct ble_sm_public_key pub_key_peer; + uint8_t mackey[16]; + uint8_t dhkey[32]; + const struct ble_sm_sc_oob_data *oob_data_local; + const struct ble_sm_sc_oob_data *oob_data_remote; +#endif +}; + +struct ble_sm_result { + int app_status; + uint8_t sm_err; + struct ble_gap_passkey_params passkey_params; + void *state_arg; + unsigned execute : 1; + unsigned enc_cb : 1; + unsigned bonded : 1; + unsigned restore : 1; +}; + +#if MYNEWT_VAL(BLE_HS_DEBUG) +void ble_sm_dbg_set_next_pair_rand(uint8_t *next_pair_rand); +void ble_sm_dbg_set_next_ediv(uint16_t next_ediv); +void ble_sm_dbg_set_next_master_id_rand(uint64_t next_master_id_rand); +void ble_sm_dbg_set_next_ltk(uint8_t *next_ltk); +void ble_sm_dbg_set_next_csrk(uint8_t *next_csrk); +void ble_sm_dbg_set_sc_keys(uint8_t *pubkey, uint8_t *privkey); +#endif + +int ble_sm_num_procs(void); + +int ble_sm_alg_s1(const uint8_t *k, const uint8_t *r1, const uint8_t *r2, + uint8_t *out); +int ble_sm_alg_c1(const uint8_t *k, const uint8_t *r, + const uint8_t *preq, const uint8_t *pres, + uint8_t iat, uint8_t rat, + const uint8_t *ia, const uint8_t *ra, + uint8_t *out_enc_data); +int ble_sm_alg_f4(const uint8_t *u, const uint8_t *v, const uint8_t *x, + uint8_t z, uint8_t *out_enc_data); +int ble_sm_alg_g2(const uint8_t *u, const uint8_t *v, const uint8_t *x, + const uint8_t *y, uint32_t *passkey); +int ble_sm_alg_f5(const uint8_t *w, const uint8_t *n1, const uint8_t *n2, + uint8_t a1t, const uint8_t *a1, uint8_t a2t, + const uint8_t *a2, uint8_t *mackey, uint8_t *ltk); +int ble_sm_alg_f6(const uint8_t *w, const uint8_t *n1, const uint8_t *n2, + const uint8_t *r, const uint8_t *iocap, uint8_t a1t, + const uint8_t *a1, uint8_t a2t, const uint8_t *a2, + uint8_t *check); +int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, + const uint8_t *peer_pub_key_y, + const uint8_t *our_priv_key, uint8_t *out_dhkey); +int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv); +void ble_sm_alg_ecc_init(void); + +void ble_sm_enc_change_rx(const struct ble_hci_ev_enrypt_chg *ev); +void ble_sm_enc_key_refresh_rx(const struct ble_hci_ev_enc_key_refresh *ev); +int ble_sm_ltk_req_rx(const struct ble_hci_ev_le_subev_lt_key_req *ev); + +#if MYNEWT_VAL(BLE_SM_LEGACY) +int ble_sm_lgcy_io_action(struct ble_sm_proc *proc, uint8_t *action); +void ble_sm_lgcy_confirm_exec(struct ble_sm_proc *proc, + struct ble_sm_result *res); +void ble_sm_lgcy_random_exec(struct ble_sm_proc *proc, + struct ble_sm_result *res); +void ble_sm_lgcy_random_rx(struct ble_sm_proc *proc, + struct ble_sm_result *res); +#else +#define ble_sm_lgcy_io_action(proc, action) (BLE_HS_ENOTSUP) +#define ble_sm_lgcy_confirm_exec(proc, res) +#define ble_sm_lgcy_random_exec(proc, res) +#define ble_sm_lgcy_random_rx(proc, res) +#endif + +#if MYNEWT_VAL(BLE_SM_SC) +int ble_sm_sc_io_action(struct ble_sm_proc *proc, uint8_t *action); +void ble_sm_sc_confirm_exec(struct ble_sm_proc *proc, + struct ble_sm_result *res); +void ble_sm_sc_random_exec(struct ble_sm_proc *proc, + struct ble_sm_result *res); +void ble_sm_sc_random_rx(struct ble_sm_proc *proc, struct ble_sm_result *res); +void ble_sm_sc_public_key_exec(struct ble_sm_proc *proc, + struct ble_sm_result *res, + void *arg); +void ble_sm_sc_public_key_rx(uint16_t conn_handle, struct os_mbuf **rxom, + struct ble_sm_result *res); +void ble_sm_sc_dhkey_check_exec(struct ble_sm_proc *proc, + struct ble_sm_result *res, void *arg); +void ble_sm_sc_dhkey_check_rx(uint16_t conn_handle, struct os_mbuf **rxom, + struct ble_sm_result *res); +bool ble_sm_sc_oob_data_check(struct ble_sm_proc *proc, + bool oob_data_local_present, + bool oob_data_remote_present); +void ble_sm_sc_oob_confirm(struct ble_sm_proc *proc, struct ble_sm_result *res); +void ble_sm_sc_init(void); +#else +#define ble_sm_sc_io_action(proc, action) (BLE_HS_ENOTSUP) +#define ble_sm_sc_confirm_exec(proc, res) +#define ble_sm_sc_random_exec(proc, res) +#define ble_sm_sc_random_rx(proc, res) +#define ble_sm_sc_public_key_exec(proc, res, arg) +#define ble_sm_sc_public_key_rx(conn_handle, op, om, res) +#define ble_sm_sc_dhkey_check_exec(proc, res, arg) +#define ble_sm_sc_dhkey_check_rx(conn_handle, op, om, res) +#define ble_sm_sc_init() + +#endif + +struct ble_sm_proc *ble_sm_proc_find(uint16_t conn_handle, uint8_t state, + int is_initiator, + struct ble_sm_proc **out_prev); +int ble_sm_gen_pair_rand(uint8_t *pair_rand); +uint8_t *ble_sm_our_pair_rand(struct ble_sm_proc *proc); +uint8_t *ble_sm_peer_pair_rand(struct ble_sm_proc *proc); +int ble_sm_ioact_state(uint8_t action); +int ble_sm_proc_can_advance(struct ble_sm_proc *proc); +void ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res); +void ble_sm_confirm_advance(struct ble_sm_proc *proc); +void ble_sm_ia_ra(struct ble_sm_proc *proc, + uint8_t *out_iat, uint8_t *out_ia, + uint8_t *out_rat, uint8_t *out_ra); + +int32_t ble_sm_timer(void); +void ble_sm_connection_broken(uint16_t conn_handle); +int ble_sm_pair_initiate(uint16_t conn_handle); +int ble_sm_slave_initiate(uint16_t conn_handle); +int ble_sm_enc_initiate(uint16_t conn_handle, uint8_t key_size, + const uint8_t *ltk, uint16_t ediv, + uint64_t rand_val, int auth); +int ble_sm_alg_encrypt(const uint8_t *key, const uint8_t *plaintext, + uint8_t *enc_data); +int ble_sm_init(void); +#else + +#define ble_sm_enc_change_rx(evt) ((void)(evt)) +#define ble_sm_ltk_req_rx(evt) ((void)(evt)) +#define ble_sm_enc_key_refresh_rx(evt) ((void)(evt)) + +#define ble_sm_timer() BLE_HS_FOREVER +#define ble_sm_connection_broken(conn_handle) +#define ble_sm_pair_initiate(conn_handle) BLE_HS_ENOTSUP +#define ble_sm_slave_initiate(conn_handle) BLE_HS_ENOTSUP +#define ble_sm_enc_initiate(conn_handle, keysize, ltk, ediv, rand_val, auth) \ + BLE_HS_ENOTSUP + +#define ble_sm_init() 0 + +#define ble_sm_alg_encrypt(key, plaintext, enc_data) \ + BLE_HS_ENOTSUP + +#endif + +struct ble_l2cap_chan *ble_sm_create_chan(uint16_t handle); +void *ble_sm_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom); +int ble_sm_tx(uint16_t conn_handle, struct os_mbuf *txom); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_sc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_sc.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_sc.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_sc.c index ffc807fa6..333310702 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_sc.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_sc.c @@ -19,8 +19,8 @@ #include -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/host/include/host/ble_sm.h" +#include "nimble/nimble_opt.h" +#include "host/ble_sm.h" #include "ble_hs_priv.h" #include "ble_sm_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_store.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_store.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store.c index e5a475530..22e608947 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_store.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store.c @@ -19,7 +19,7 @@ #include -#include "nimble/nimble/host/include/host/ble_store.h" +#include "host/ble_store.h" #include "ble_hs_priv.h" int diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_store_util.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_store_util.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c index 033261242..73c71d93b 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_store_util.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c @@ -17,7 +17,7 @@ * under the License. */ -#include "nimble/nimble/host/include/host/ble_store.h" +#include "host/ble_store.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid.c index 1b2443683..3a1642480 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid.c @@ -22,10 +22,10 @@ #include #include #include -#include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "nimble/nimble/include/nimble/ble.h" +#include "os/os_mbuf.h" +#include "nimble/ble.h" #include "ble_hs_priv.h" -#include "nimble/nimble/host/include/host/ble_uuid.h" +#include "host/ble_uuid.h" static uint8_t ble_uuid_base[16] = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid_priv.h new file mode 100644 index 000000000..3dbcc6b8e --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid_priv.h @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_UUID_PRIV_ +#define H_BLE_UUID_PRIV_ + +#include "host/ble_uuid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct os_mbuf; + +int ble_uuid_init_from_att_mbuf(ble_uuid_any_t *uuid, struct os_mbuf *om, + int off, int len); +int ble_uuid_init_from_att_buf(ble_uuid_any_t *uuid, const void *buf, + size_t len); + +int ble_uuid_to_any(const ble_uuid_t *uuid, ble_uuid_any_t *uuid_any); +int ble_uuid_to_mbuf(const ble_uuid_t *uuid, struct os_mbuf *om); +int ble_uuid_flat(const ble_uuid_t *uuid, void *dst); +int ble_uuid_length(const ble_uuid_t *uuid); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config.c index 4ffaaf4e1..a2c9aaf27 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config.c @@ -20,10 +20,10 @@ #include #include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/store/config/ble_store_config.h" +#include "sysinit/sysinit.h" +#include "syscfg/syscfg.h" +#include "host/ble_hs.h" +#include "store/config/ble_store_config.h" #include "ble_store_config_priv.h" struct ble_store_value_sec diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_nvs.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_nvs.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c index e09182d9f..49ca6ed73 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_nvs.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c @@ -19,16 +19,16 @@ * under the License. */ -#ifdef ESP_PLATFORM -#include "nimble/porting/nimble/include/syscfg/syscfg.h" + +#include "syscfg/syscfg.h" #if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) #include #include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "../../../include/host/ble_hs.h" -#include "../include/store/config/ble_store_config.h" +#include "sysinit/sysinit.h" +#include "host/ble_hs.h" +#include "store/config/ble_store_config.h" #include "ble_store_config_priv.h" #include "esp_log.h" #include "nvs.h" @@ -650,4 +650,3 @@ void ble_store_config_conf_init(void) /***************************************************************************************/ #endif /* MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) */ -#endif /* ESP_PLATFORM */ \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c new file mode 100644 index 000000000..ab5cdb9f6 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c @@ -0,0 +1,497 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * This file implements a simple in-RAM key database for BLE host security + * material and CCCDs. As this database is only ble_store_ramd in RAM, its + * contents are lost when the application terminates. + */ + +#include +#include + +#include "sysinit/sysinit.h" +#include "syscfg/syscfg.h" +#include "host/ble_hs.h" +#include "store/ram/ble_store_ram.h" + +static struct ble_store_value_sec + ble_store_ram_our_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; +static int ble_store_ram_num_our_secs; + +static struct ble_store_value_sec + ble_store_ram_peer_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; +static int ble_store_ram_num_peer_secs; + +static struct ble_store_value_cccd + ble_store_ram_cccds[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)]; +static int ble_store_ram_num_cccds; + +/***************************************************************************** + * $sec * + *****************************************************************************/ + +static void +ble_store_ram_print_value_sec(const struct ble_store_value_sec *sec) +{ + if (sec->ltk_present) { + BLE_HS_LOG(DEBUG, "ediv=%u rand=%llu authenticated=%d ltk=", + sec->ediv, sec->rand_num, sec->authenticated); + ble_hs_log_flat_buf(sec->ltk, 16); + BLE_HS_LOG(DEBUG, " "); + } + if (sec->irk_present) { + BLE_HS_LOG(DEBUG, "irk="); + ble_hs_log_flat_buf(sec->irk, 16); + BLE_HS_LOG(DEBUG, " "); + } + if (sec->csrk_present) { + BLE_HS_LOG(DEBUG, "csrk="); + ble_hs_log_flat_buf(sec->csrk, 16); + BLE_HS_LOG(DEBUG, " "); + } + + BLE_HS_LOG(DEBUG, "\n"); +} + +static void +ble_store_ram_print_key_sec(const struct ble_store_key_sec *key_sec) +{ + if (ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY)) { + BLE_HS_LOG(DEBUG, "peer_addr_type=%d peer_addr=", + key_sec->peer_addr.type); + ble_hs_log_flat_buf(key_sec->peer_addr.val, 6); + BLE_HS_LOG(DEBUG, " "); + } + if (key_sec->ediv_rand_present) { + BLE_HS_LOG(DEBUG, "ediv=0x%02x rand=0x%llx ", + key_sec->ediv, key_sec->rand_num); + } +} + +static int +ble_store_ram_find_sec(const struct ble_store_key_sec *key_sec, + const struct ble_store_value_sec *value_secs, + int num_value_secs) +{ + const struct ble_store_value_sec *cur; + int skipped; + int i; + + skipped = 0; + + for (i = 0; i < num_value_secs; i++) { + cur = value_secs + i; + + if (ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY)) { + if (ble_addr_cmp(&cur->peer_addr, &key_sec->peer_addr)) { + continue; + } + } + + if (key_sec->ediv_rand_present) { + if (cur->ediv != key_sec->ediv) { + continue; + } + + if (cur->rand_num != key_sec->rand_num) { + continue; + } + } + + if (key_sec->idx > skipped) { + skipped++; + continue; + } + + return i; + } + + return -1; +} + +static int +ble_store_ram_read_our_sec(const struct ble_store_key_sec *key_sec, + struct ble_store_value_sec *value_sec) +{ + int idx; + + idx = ble_store_ram_find_sec(key_sec, ble_store_ram_our_secs, + ble_store_ram_num_our_secs); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + *value_sec = ble_store_ram_our_secs[idx]; + return 0; +} + +static int +ble_store_ram_write_our_sec(const struct ble_store_value_sec *value_sec) +{ + struct ble_store_key_sec key_sec; + int idx; + + BLE_HS_LOG(DEBUG, "persisting our sec; "); + ble_store_ram_print_value_sec(value_sec); + + ble_store_key_from_value_sec(&key_sec, value_sec); + idx = ble_store_ram_find_sec(&key_sec, ble_store_ram_our_secs, + ble_store_ram_num_our_secs); + if (idx == -1) { + if (ble_store_ram_num_our_secs >= MYNEWT_VAL(BLE_STORE_MAX_BONDS)) { + BLE_HS_LOG(DEBUG, "error persisting our sec; too many entries " + "(%d)\n", ble_store_ram_num_our_secs); + return BLE_HS_ESTORE_CAP; + } + + idx = ble_store_ram_num_our_secs; + ble_store_ram_num_our_secs++; + } + + ble_store_ram_our_secs[idx] = *value_sec; + return 0; +} + +static int +ble_store_ram_delete_obj(void *values, int value_size, int idx, + int *num_values) +{ + uint8_t *dst; + uint8_t *src; + int move_count; + + (*num_values)--; + if (idx < *num_values) { + dst = values; + dst += idx * value_size; + src = dst + value_size; + + move_count = *num_values - idx; + memmove(dst, src, move_count); + } + + return 0; +} + +static int +ble_store_ram_delete_sec(const struct ble_store_key_sec *key_sec, + struct ble_store_value_sec *value_secs, + int *num_value_secs) +{ + int idx; + int rc; + + idx = ble_store_ram_find_sec(key_sec, value_secs, *num_value_secs); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + rc = ble_store_ram_delete_obj(value_secs, sizeof *value_secs, idx, + num_value_secs); + if (rc != 0) { + return rc; + } + + return 0; +} + +static int +ble_store_ram_delete_our_sec(const struct ble_store_key_sec *key_sec) +{ + int rc; + + rc = ble_store_ram_delete_sec(key_sec, ble_store_ram_our_secs, + &ble_store_ram_num_our_secs); + if (rc != 0) { + return rc; + } + + return 0; +} + +static int +ble_store_ram_delete_peer_sec(const struct ble_store_key_sec *key_sec) +{ + int rc; + + rc = ble_store_ram_delete_sec(key_sec, ble_store_ram_peer_secs, + &ble_store_ram_num_peer_secs); + if (rc != 0) { + return rc; + } + + return 0; +} + +static int +ble_store_ram_read_peer_sec(const struct ble_store_key_sec *key_sec, + struct ble_store_value_sec *value_sec) +{ + int idx; + + idx = ble_store_ram_find_sec(key_sec, ble_store_ram_peer_secs, + ble_store_ram_num_peer_secs); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + *value_sec = ble_store_ram_peer_secs[idx]; + return 0; +} + +static int +ble_store_ram_write_peer_sec(const struct ble_store_value_sec *value_sec) +{ + struct ble_store_key_sec key_sec; + int idx; + + BLE_HS_LOG(DEBUG, "persisting peer sec; "); + ble_store_ram_print_value_sec(value_sec); + + ble_store_key_from_value_sec(&key_sec, value_sec); + idx = ble_store_ram_find_sec(&key_sec, ble_store_ram_peer_secs, + ble_store_ram_num_peer_secs); + if (idx == -1) { + if (ble_store_ram_num_peer_secs >= MYNEWT_VAL(BLE_STORE_MAX_BONDS)) { + BLE_HS_LOG(DEBUG, "error persisting peer sec; too many entries " + "(%d)\n", ble_store_ram_num_peer_secs); + return BLE_HS_ESTORE_CAP; + } + + idx = ble_store_ram_num_peer_secs; + ble_store_ram_num_peer_secs++; + } + + ble_store_ram_peer_secs[idx] = *value_sec; + return 0; +} + +/***************************************************************************** + * $cccd * + *****************************************************************************/ + +static int +ble_store_ram_find_cccd(const struct ble_store_key_cccd *key) +{ + struct ble_store_value_cccd *cccd; + int skipped; + int i; + + skipped = 0; + for (i = 0; i < ble_store_ram_num_cccds; i++) { + cccd = ble_store_ram_cccds + i; + + if (ble_addr_cmp(&key->peer_addr, BLE_ADDR_ANY)) { + if (ble_addr_cmp(&cccd->peer_addr, &key->peer_addr)) { + continue; + } + } + + if (key->chr_val_handle != 0) { + if (cccd->chr_val_handle != key->chr_val_handle) { + continue; + } + } + + if (key->idx > skipped) { + skipped++; + continue; + } + + return i; + } + + return -1; +} + +static int +ble_store_ram_delete_cccd(const struct ble_store_key_cccd *key_cccd) +{ + int idx; + int rc; + + idx = ble_store_ram_find_cccd(key_cccd); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + rc = ble_store_ram_delete_obj(ble_store_ram_cccds, + sizeof *ble_store_ram_cccds, + idx, + &ble_store_ram_num_cccds); + if (rc != 0) { + return rc; + } + + return 0; +} + +static int +ble_store_ram_read_cccd(const struct ble_store_key_cccd *key_cccd, + struct ble_store_value_cccd *value_cccd) +{ + int idx; + + idx = ble_store_ram_find_cccd(key_cccd); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + *value_cccd = ble_store_ram_cccds[idx]; + return 0; +} + +static int +ble_store_ram_write_cccd(const struct ble_store_value_cccd *value_cccd) +{ + struct ble_store_key_cccd key_cccd; + int idx; + + ble_store_key_from_value_cccd(&key_cccd, value_cccd); + idx = ble_store_ram_find_cccd(&key_cccd); + if (idx == -1) { + if (ble_store_ram_num_cccds >= MYNEWT_VAL(BLE_STORE_MAX_CCCDS)) { + BLE_HS_LOG(DEBUG, "error persisting cccd; too many entries (%d)\n", + ble_store_ram_num_cccds); + return BLE_HS_ESTORE_CAP; + } + + idx = ble_store_ram_num_cccds; + ble_store_ram_num_cccds++; + } + + ble_store_ram_cccds[idx] = *value_cccd; + return 0; +} + +/***************************************************************************** + * $api * + *****************************************************************************/ + +/** + * Searches the database for an object matching the specified criteria. + * + * @return 0 if a key was found; else BLE_HS_ENOENT. + */ +int +ble_store_ram_read(int obj_type, const union ble_store_key *key, + union ble_store_value *value) +{ + int rc; + + switch (obj_type) { + case BLE_STORE_OBJ_TYPE_PEER_SEC: + /* An encryption procedure (bonding) is being attempted. The nimble + * stack is asking us to look in our key database for a long-term key + * corresponding to the specified ediv and random number. + * + * Perform a key lookup and populate the context object with the + * result. The nimble stack will use this key if this function returns + * success. + */ + BLE_HS_LOG(DEBUG, "looking up peer sec; "); + ble_store_ram_print_key_sec(&key->sec); + BLE_HS_LOG(DEBUG, "\n"); + rc = ble_store_ram_read_peer_sec(&key->sec, &value->sec); + return rc; + + case BLE_STORE_OBJ_TYPE_OUR_SEC: + BLE_HS_LOG(DEBUG, "looking up our sec; "); + ble_store_ram_print_key_sec(&key->sec); + BLE_HS_LOG(DEBUG, "\n"); + rc = ble_store_ram_read_our_sec(&key->sec, &value->sec); + return rc; + + case BLE_STORE_OBJ_TYPE_CCCD: + rc = ble_store_ram_read_cccd(&key->cccd, &value->cccd); + return rc; + + default: + return BLE_HS_ENOTSUP; + } +} + +/** + * Adds the specified object to the database. + * + * @return 0 on success; BLE_HS_ESTORE_CAP if the database + * is full. + */ +int +ble_store_ram_write(int obj_type, const union ble_store_value *val) +{ + int rc; + + switch (obj_type) { + case BLE_STORE_OBJ_TYPE_PEER_SEC: + rc = ble_store_ram_write_peer_sec(&val->sec); + return rc; + + case BLE_STORE_OBJ_TYPE_OUR_SEC: + rc = ble_store_ram_write_our_sec(&val->sec); + return rc; + + case BLE_STORE_OBJ_TYPE_CCCD: + rc = ble_store_ram_write_cccd(&val->cccd); + return rc; + + default: + return BLE_HS_ENOTSUP; + } +} + +int +ble_store_ram_delete(int obj_type, const union ble_store_key *key) +{ + int rc; + + switch (obj_type) { + case BLE_STORE_OBJ_TYPE_PEER_SEC: + rc = ble_store_ram_delete_peer_sec(&key->sec); + return rc; + + case BLE_STORE_OBJ_TYPE_OUR_SEC: + rc = ble_store_ram_delete_our_sec(&key->sec); + return rc; + + case BLE_STORE_OBJ_TYPE_CCCD: + rc = ble_store_ram_delete_cccd(&key->cccd); + return rc; + + default: + return BLE_HS_ENOTSUP; + } +} + +void +ble_store_ram_init(void) +{ + /* Ensure this function only gets called by sysinit. */ + SYSINIT_ASSERT_ACTIVE(); + + ble_hs_cfg.store_read_cb = ble_store_ram_read; + ble_hs_cfg.store_write_cb = ble_store_ram_write; + ble_hs_cfg.store_delete_cb = ble_store_ram_delete; + + /* Re-initialize BSS values in case of unit tests. */ + ble_store_ram_num_our_secs = 0; + ble_store_ram_num_peer_secs = 0; + ble_store_ram_num_cccds = 0; +} diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/src/addr.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/util/src/addr.c similarity index 94% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/src/addr.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/util/src/addr.c index b8195a5b7..9b43d237c 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/src/addr.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/util/src/addr.c @@ -17,11 +17,11 @@ * under the License. */ -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/host/util/util.h" +#include "host/ble_hs.h" +#include "host/util/util.h" #if MYNEWT_VAL(BLE_CONTROLLER) -#include "nimble/nimble/controller/include/controller/ble_hw.h" +#include "controller/ble_hw.h" #endif static int diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_hw.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_hw.h deleted file mode 100644 index dfac69b60..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_hw.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_HW_ -#define H_BLE_HW_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "nimble/porting/nimble/include/syscfg/syscfg.h" - -#if defined(ARCH_sim) -#define BLE_USES_HW_WHITELIST (0) -#else -#define BLE_USES_HW_WHITELIST MYNEWT_VAL(BLE_HW_WHITELIST_ENABLE) -#endif - -/* Returns the number of hw whitelist elements */ -uint8_t ble_hw_whitelist_size(void); - -/* Clear the whitelist */ -void ble_hw_whitelist_clear(void); - -/* Remove a device from the hw whitelist */ -void ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type); - -/* Add a device to the hw whitelist */ -int ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type); - -/* Enable hw whitelisting */ -void ble_hw_whitelist_enable(void); - -/* Enable hw whitelisting */ -void ble_hw_whitelist_disable(void); - -/* Boolean function returning true if address matches a whitelist entry */ -int ble_hw_whitelist_match(void); - -/* Encrypt data */ -struct ble_encryption_block; -int ble_hw_encrypt_block(struct ble_encryption_block *ecb); - -/* Random number generation */ -typedef void (*ble_rng_isr_cb_t)(uint8_t rnum); -int ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias); - -/** - * Start the random number generator - * - * @return int - */ -int ble_hw_rng_start(void); - -/** - * Stop the random generator - * - * @return int - */ -int ble_hw_rng_stop(void); - -/** - * Read the random number generator. - * - * @return uint8_t - */ -uint8_t ble_hw_rng_read(void); - -/* Clear the resolving list*/ -void ble_hw_resolv_list_clear(void); - -/* Add a device to the hw resolving list */ -int ble_hw_resolv_list_add(uint8_t *irk); - -/* Remove a device from the hw resolving list */ -void ble_hw_resolv_list_rmv(int index); - -/* Returns the size of the whitelist in HW */ -uint8_t ble_hw_resolv_list_size(void); - -/* Enable the resolving list */ -void ble_hw_resolv_list_enable(void); - -/* Disables resolving list devices */ -void ble_hw_resolv_list_disable(void); - -/* Returns index of resolved address; -1 if not resolved */ -int ble_hw_resolv_list_match(void); - -/* Returns public device address or -1 if not present */ -int ble_hw_get_public_addr(ble_addr_t *addr); - -/* Returns random static address or -1 if not present */ -int ble_hw_get_static_addr(ble_addr_t *addr); - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_HW_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll.h deleted file mode 100644 index 3b165a706..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll.h +++ /dev/null @@ -1,584 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_ -#define H_BLE_LL_ - -#include "nimble/porting/nimble/include/stats/stats.h" -#include "nimble/porting/nimble/include/os/os_cputime.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/include/nimble/nimble_npl.h" -#include "ble_phy.h" - -#ifdef MYNEWT -#include "./ble_ll_ctrl.h" -#include "hal/hal_system.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#if MYNEWT_VAL(OS_CPUTIME_FREQ) != 32768 -#error 32.768kHz clock required -#endif - -#if defined(MYNEWT) && MYNEWT_VAL(BLE_LL_VND_EVENT_ON_ASSERT) -#ifdef NDEBUG -#define BLE_LL_ASSERT(cond) (void(0)) -#else -#define BLE_LL_ASSERT(cond) \ - if (!(cond)) { \ - if (hal_debugger_connected()) { \ - assert(0);\ - } else {\ - ble_ll_hci_ev_send_vendor_err(__FILE__, __LINE__); \ - while(1) {}\ - }\ - } -#endif -#else -#define BLE_LL_ASSERT(cond) assert(cond) -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) -#define BLE_LL_BT5_PHY_SUPPORTED (1) -#else -#define BLE_LL_BT5_PHY_SUPPORTED (0) -#endif - -/* Controller revision. */ -#define BLE_LL_SUB_VERS_NR (0x0000) - -/* Timing jitter as per spec is +/16 usecs */ -#define BLE_LL_JITTER_USECS (16) - -/* Packet queue header definition */ -STAILQ_HEAD(ble_ll_pkt_q, os_mbuf_pkthdr); - -/* - * Global Link Layer data object. There is only one Link Layer data object - * per controller although there may be many instances of the link layer state - * machine running. - */ -struct ble_ll_obj -{ - /* Supported features */ - uint64_t ll_supp_features; - - /* Current Link Layer state */ - uint8_t ll_state; - - /* Number of ACL data packets supported */ - uint8_t ll_num_acl_pkts; - - /* ACL data packet size */ - uint16_t ll_acl_pkt_size; - - /* Preferred PHY's */ - uint8_t ll_pref_tx_phys; - uint8_t ll_pref_rx_phys; - - /* Task event queue */ - struct ble_npl_eventq ll_evq; - - /* Wait for response timer */ - struct hal_timer ll_wfr_timer; - - /* Packet receive queue (and event). Holds received packets from PHY */ - struct ble_npl_event ll_rx_pkt_ev; - struct ble_ll_pkt_q ll_rx_pkt_q; - - /* Packet transmit queue */ - struct ble_npl_event ll_tx_pkt_ev; - struct ble_ll_pkt_q ll_tx_pkt_q; - - /* Data buffer overflow event */ - struct ble_npl_event ll_dbuf_overflow_ev; - - /* Number of completed packets event */ - struct ble_npl_event ll_comp_pkt_ev; - - /* HW error callout */ - struct ble_npl_callout ll_hw_err_timer; -}; -extern struct ble_ll_obj g_ble_ll_data; - -/* Link layer statistics */ -STATS_SECT_START(ble_ll_stats) - STATS_SECT_ENTRY(hci_cmds) - STATS_SECT_ENTRY(hci_cmd_errs) - STATS_SECT_ENTRY(hci_events_sent) - STATS_SECT_ENTRY(bad_ll_state) - STATS_SECT_ENTRY(bad_acl_hdr) - STATS_SECT_ENTRY(no_bufs) - STATS_SECT_ENTRY(rx_adv_pdu_crc_ok) - STATS_SECT_ENTRY(rx_adv_pdu_crc_err) - STATS_SECT_ENTRY(rx_adv_bytes_crc_ok) - STATS_SECT_ENTRY(rx_adv_bytes_crc_err) - STATS_SECT_ENTRY(rx_data_pdu_crc_ok) - STATS_SECT_ENTRY(rx_data_pdu_crc_err) - STATS_SECT_ENTRY(rx_data_bytes_crc_ok) - STATS_SECT_ENTRY(rx_data_bytes_crc_err) - STATS_SECT_ENTRY(rx_adv_malformed_pkts) - STATS_SECT_ENTRY(rx_adv_ind) - STATS_SECT_ENTRY(rx_adv_direct_ind) - STATS_SECT_ENTRY(rx_adv_nonconn_ind) - STATS_SECT_ENTRY(rx_adv_ext_ind) - STATS_SECT_ENTRY(rx_scan_reqs) - STATS_SECT_ENTRY(rx_scan_rsps) - STATS_SECT_ENTRY(rx_connect_reqs) - STATS_SECT_ENTRY(rx_scan_ind) - STATS_SECT_ENTRY(rx_aux_connect_rsp) - STATS_SECT_ENTRY(adv_txg) - STATS_SECT_ENTRY(adv_late_starts) - STATS_SECT_ENTRY(adv_resched_pdu_fail) - STATS_SECT_ENTRY(adv_drop_event) - STATS_SECT_ENTRY(sched_state_conn_errs) - STATS_SECT_ENTRY(sched_state_adv_errs) - STATS_SECT_ENTRY(scan_starts) - STATS_SECT_ENTRY(scan_stops) - STATS_SECT_ENTRY(scan_req_txf) - STATS_SECT_ENTRY(scan_req_txg) - STATS_SECT_ENTRY(scan_rsp_txg) - STATS_SECT_ENTRY(aux_missed_adv) - STATS_SECT_ENTRY(aux_scheduled) - STATS_SECT_ENTRY(aux_received) - STATS_SECT_ENTRY(aux_fired_for_read) - STATS_SECT_ENTRY(aux_allocated) - STATS_SECT_ENTRY(aux_freed) - STATS_SECT_ENTRY(aux_sched_cb) - STATS_SECT_ENTRY(aux_conn_req_tx) - STATS_SECT_ENTRY(aux_conn_rsp_tx) - STATS_SECT_ENTRY(aux_conn_rsp_err) - STATS_SECT_ENTRY(aux_scan_req_tx) - STATS_SECT_ENTRY(aux_scan_rsp_err) - STATS_SECT_ENTRY(aux_chain_cnt) - STATS_SECT_ENTRY(aux_chain_err) - STATS_SECT_ENTRY(aux_scan_drop) - STATS_SECT_ENTRY(adv_evt_dropped) - STATS_SECT_ENTRY(scan_timer_stopped) - STATS_SECT_ENTRY(scan_timer_restarted) - STATS_SECT_ENTRY(periodic_adv_drop_event) - STATS_SECT_ENTRY(periodic_chain_drop_event) - STATS_SECT_ENTRY(sync_event_failed) - STATS_SECT_ENTRY(sync_received) - STATS_SECT_ENTRY(sync_chain_failed) - STATS_SECT_ENTRY(sync_missed_err) - STATS_SECT_ENTRY(sync_crc_err) - STATS_SECT_ENTRY(sync_rx_buf_err) - STATS_SECT_ENTRY(sync_scheduled) - STATS_SECT_ENTRY(sched_state_sync_errs) - STATS_SECT_ENTRY(sched_invalid_pdu) -STATS_SECT_END -extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats; - -/* States */ -#define BLE_LL_STATE_STANDBY (0) -#define BLE_LL_STATE_ADV (1) -#define BLE_LL_STATE_SCANNING (2) -#define BLE_LL_STATE_INITIATING (3) -#define BLE_LL_STATE_CONNECTION (4) -#define BLE_LL_STATE_DTM (5) -#define BLE_LL_STATE_SYNC (6) - -/* LL Features */ -#define BLE_LL_FEAT_LE_ENCRYPTION (0x0000000001) -#define BLE_LL_FEAT_CONN_PARM_REQ (0x0000000002) -#define BLE_LL_FEAT_EXTENDED_REJ (0x0000000004) -#define BLE_LL_FEAT_SLAVE_INIT (0x0000000008) -#define BLE_LL_FEAT_LE_PING (0x0000000010) -#define BLE_LL_FEAT_DATA_LEN_EXT (0x0000000020) -#define BLE_LL_FEAT_LL_PRIVACY (0x0000000040) -#define BLE_LL_FEAT_EXT_SCAN_FILT (0x0000000080) -#define BLE_LL_FEAT_LE_2M_PHY (0x0000000100) -#define BLE_LL_FEAT_STABLE_MOD_ID_TX (0x0000000200) -#define BLE_LL_FEAT_STABLE_MOD_ID_RX (0x0000000400) -#define BLE_LL_FEAT_LE_CODED_PHY (0x0000000800) -#define BLE_LL_FEAT_EXT_ADV (0x0000001000) -#define BLE_LL_FEAT_PERIODIC_ADV (0x0000002000) -#define BLE_LL_FEAT_CSA2 (0x0000004000) -#define BLE_LL_FEAT_LE_POWER_CLASS_1 (0x0000008000) -#define BLE_LL_FEAT_MIN_USED_CHAN (0x0000010000) -#define BLE_LL_FEAT_CTE_REQ (0x0000020000) -#define BLE_LL_FEAT_CTE_RSP (0x0000040000) -#define BLE_LL_FEAT_CTE_TX (0x0000080000) -#define BLE_LL_FEAT_CTE_RX (0x0000100000) -#define BLE_LL_FEAT_CTE_AOD (0x0000200000) -#define BLE_LL_FEAT_CTE_AOA (0x0000400000) -#define BLE_LL_FEAT_CTE_RECV (0x0000800000) -#define BLE_LL_FEAT_SYNC_TRANS_SEND (0x0001000000) -#define BLE_LL_FEAT_SYNC_TRANS_RECV (0x0002000000) -#define BLE_LL_FEAT_SCA_UPDATE (0x0004000000) -#define BLE_LL_FEAT_REM_PKEY (0x0008000000) -#define BLE_LL_FEAT_CIS_MASTER (0x0010000000) -#define BLE_LL_FEAT_CIS_SLAVE (0x0020000000) -#define BLE_LL_FEAT_ISO_BROADCASTER (0x0040000000) -#define BLE_LL_FEAT_SYNC_RECV (0x0080000000) -#define BLE_LL_FEAT_ISO_HOST_SUPPORT (0x0100000000) -#define BLE_LL_FEAT_POWER_CTRL_REQ (0x0200000000) -#define BLE_LL_FEAT_POWER_CHANGE_IND (0x0400000000) -#define BLE_LL_FEAT_PATH_LOSS_MON (0x0800000000) - -/* This is initial mask, so if feature exchange will not happen, - * but host will want to use this procedure, we will try. If not - * succeed, feature bit will be cleared. - * Look at LL Features above to find out what is allowed - */ -#define BLE_LL_CONN_INITIAL_FEATURES (0x00000022) -#define BLE_LL_CONN_CLEAR_FEATURE(connsm, feature) (connsm->conn_features &= ~(feature)) - -/* All the features which can be controlled by the Host */ -#define BLE_LL_HOST_CONTROLLED_FEATURES (BLE_LL_FEAT_ISO_HOST_SUPPORT) - -/* LL timing */ -#define BLE_LL_IFS (150) /* usecs */ -#define BLE_LL_MAFS (300) /* usecs */ - -/* - * BLE LL device address. Note that element 0 of the array is the LSB and - * is sent over the air first. Byte 5 is the MSB and is the last one sent over - * the air. - */ -#define BLE_DEV_ADDR_LEN (6) /* bytes */ - -struct ble_dev_addr -{ - uint8_t u8[BLE_DEV_ADDR_LEN]; -}; - -#define BLE_IS_DEV_ADDR_STATIC(addr) ((addr->u8[5] & 0xc0) == 0xc0) -#define BLE_IS_DEV_ADDR_RESOLVABLE(addr) ((addr->u8[5] & 0xc0) == 0x40) -#define BLE_IS_DEV_ADDR_UNRESOLVABLE(addr) ((addr->u8[5] & 0xc0) == 0x00) - -/* - * LL packet format - * - * -> Preamble (1/2 bytes) - * -> Access Address (4 bytes) - * -> PDU (2 to 257 octets) - * -> CRC (3 bytes) - */ -#define BLE_LL_PREAMBLE_LEN (1) -#define BLE_LL_ACC_ADDR_LEN (4) -#define BLE_LL_CRC_LEN (3) -#define BLE_LL_PDU_HDR_LEN (2) -#define BLE_LL_MAX_PAYLOAD_LEN (255) -#define BLE_LL_MIN_PDU_LEN (BLE_LL_PDU_HDR_LEN) -#define BLE_LL_MAX_PDU_LEN ((BLE_LL_PDU_HDR_LEN) + (BLE_LL_MAX_PAYLOAD_LEN)) -#define BLE_LL_CRCINIT_ADV (0x555555) - -/* Access address for advertising channels */ -#define BLE_ACCESS_ADDR_ADV (0x8E89BED6) - -/* - * Advertising PDU format: - * -> 2 byte header - * -> LSB contains pdu type, txadd and rxadd bits. - * -> MSB contains length (6 bits). Length is length of payload. Does - * not include the header length itself. - * -> Payload (max 37 bytes) - */ -#define BLE_ADV_PDU_HDR_TYPE_MASK (0x0F) -#define BLE_ADV_PDU_HDR_CHSEL_MASK (0x20) -#define BLE_ADV_PDU_HDR_TXADD_MASK (0x40) -#define BLE_ADV_PDU_HDR_RXADD_MASK (0x80) - -/* Advertising channel PDU types */ -#define BLE_ADV_PDU_TYPE_ADV_IND (0) -#define BLE_ADV_PDU_TYPE_ADV_DIRECT_IND (1) -#define BLE_ADV_PDU_TYPE_ADV_NONCONN_IND (2) -#define BLE_ADV_PDU_TYPE_SCAN_REQ (3) -#define BLE_ADV_PDU_TYPE_SCAN_RSP (4) -#define BLE_ADV_PDU_TYPE_CONNECT_IND (5) -#define BLE_ADV_PDU_TYPE_ADV_SCAN_IND (6) -#define BLE_ADV_PDU_TYPE_ADV_EXT_IND (7) -#define BLE_ADV_PDU_TYPE_AUX_ADV_IND BLE_ADV_PDU_TYPE_ADV_EXT_IND -#define BLE_ADV_PDU_TYPE_AUX_SCAN_RSP BLE_ADV_PDU_TYPE_ADV_EXT_IND -#define BLE_ADV_PDU_TYPE_AUX_SYNC_IND BLE_ADV_PDU_TYPE_ADV_EXT_IND -#define BLE_ADV_PDU_TYPE_AUX_CHAIN_IND BLE_ADV_PDU_TYPE_ADV_EXT_IND -#define BLE_ADV_PDU_TYPE_AUX_CONNECT_REQ BLE_ADV_PDU_TYPE_CONNECT_IND -#define BLE_ADV_PDU_TYPE_AUX_SCAN_REQ BLE_ADV_PDU_TYPE_SCAN_REQ -#define BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP (8) - -/* Extended Header Length (6b) + AdvMode (2b) */ -#define BLE_LL_EXT_ADV_HDR_LEN (1) - -#define BLE_LL_EXT_ADV_ADVA_BIT (0) -#define BLE_LL_EXT_ADV_TARGETA_BIT (1) -#define BLE_LL_EXT_ADV_CTE_INFO_BIT (2) -#define BLE_LL_EXT_ADV_DATA_INFO_BIT (3) -#define BLE_LL_EXT_ADV_AUX_PTR_BIT (4) -#define BLE_LL_EXT_ADV_SYNC_INFO_BIT (5) -#define BLE_LL_EXT_ADV_TX_POWER_BIT (6) - -#define BLE_LL_EXT_ADV_FLAGS_SIZE (1) -#define BLE_LL_EXT_ADV_ADVA_SIZE (6) -#define BLE_LL_EXT_ADV_TARGETA_SIZE (6) -#define BLE_LL_EXT_ADV_DATA_INFO_SIZE (2) -#define BLE_LL_EXT_ADV_AUX_PTR_SIZE (3) -#define BLE_LL_EXT_ADV_SYNC_INFO_SIZE (18) -#define BLE_LL_EXT_ADV_TX_POWER_SIZE (1) - -#define BLE_LL_EXT_ADV_MODE_NON_CONN (0x00) -#define BLE_LL_EXT_ADV_MODE_CONN (0x01) -#define BLE_LL_EXT_ADV_MODE_SCAN (0x02) - -/* If Channel Selection Algorithm #2 is supported */ -#define BLE_ADV_PDU_HDR_CHSEL (0x20) - -/* - * TxAdd and RxAdd bit definitions. A 0 is a public address; a 1 is a - * random address. - */ -#define BLE_ADV_PDU_HDR_TXADD_RAND (0x40) -#define BLE_ADV_PDU_HDR_RXADD_RAND (0x80) - -/* - * Data Channel format - * - * -> Header (2 bytes) - * -> LSB contains llid, nesn, sn and md - * -> MSB contains length (8 bits) - * -> Payload (0 to 251) - * -> MIC (0 or 4 bytes) - */ -#define BLE_LL_DATA_HDR_LLID_MASK (0x03) -#define BLE_LL_DATA_HDR_NESN_MASK (0x04) -#define BLE_LL_DATA_HDR_SN_MASK (0x08) -#define BLE_LL_DATA_HDR_MD_MASK (0x10) -#define BLE_LL_DATA_HDR_RSRVD_MASK (0xE0) -#define BLE_LL_DATA_PDU_MAX_PYLD (251) -#define BLE_LL_DATA_MIC_LEN (4) - -/* LLID definitions */ -#define BLE_LL_LLID_RSRVD (0) -#define BLE_LL_LLID_DATA_FRAG (1) -#define BLE_LL_LLID_DATA_START (2) -#define BLE_LL_LLID_CTRL (3) - -/* - * CONNECT_REQ - * -> InitA (6 bytes) - * -> AdvA (6 bytes) - * -> LLData (22 bytes) - * -> Access address (4 bytes) - * -> CRC init (3 bytes) - * -> WinSize (1 byte) - * -> WinOffset (2 bytes) - * -> Interval (2 bytes) - * -> Latency (2 bytes) - * -> Timeout (2 bytes) - * -> Channel Map (5 bytes) - * -> Hop Increment (5 bits) - * -> SCA (3 bits) - * - * InitA is the initiators public (TxAdd=0) or random (TxAdd=1) address. - * AdvaA is the advertisers public (RxAdd=0) or random (RxAdd=1) address. - * LLData contains connection request data. - * aa: Link Layer's access address - * crc_init: The CRC initialization value used for CRC calculation. - * winsize: The transmit window size = winsize * 1.25 msecs - * winoffset: The transmit window offset = winoffset * 1.25 msecs - * interval: The connection interval = interval * 1.25 msecs. - * latency: connection slave latency = latency - * timeout: Connection supervision timeout = timeout * 10 msecs. - * chanmap: contains channel mapping indicating used and unused data - * channels. Only bits that are 1 are usable. LSB is channel 0. - * hop_inc: Hop increment used for frequency hopping. Random value in - * range of 5 to 16. - */ -#define BLE_CONNECT_REQ_LEN (34) -#define BLE_CONNECT_REQ_PDU_LEN (BLE_CONNECT_REQ_LEN + BLE_LL_PDU_HDR_LEN) - -#define BLE_SCAN_REQ_LEN (12) -#define BLE_SCAN_RSP_MAX_LEN (37) -#define BLE_SCAN_RSP_MAX_EXT_LEN (251) - -#define BLE_LL_ADDR_SUBTYPE_IDENTITY (0) -#define BLE_LL_ADDR_SUBTYPE_RPA (1) -#define BLE_LL_ADDR_SUBTYPE_NRPA (2) - -/*--- External API ---*/ -/* Initialize the Link Layer */ -void ble_ll_init(void); - -/* Reset the Link Layer */ -int ble_ll_reset(void); - -int ble_ll_is_valid_public_addr(const uint8_t *addr); - -/* 'Boolean' function returning true if address is a valid random address */ -int ble_ll_is_valid_random_addr(const uint8_t *addr); - -/* - * Check if given own_addr_type is valid for current controller configuration - * given the random address provided (when applicable) - */ -int ble_ll_is_valid_own_addr_type(uint8_t own_addr_type, - const uint8_t *random_addr); - -/* Calculate the amount of time in microseconds a PDU with payload length of - * 'payload_len' will take to transmit on a PHY 'phy_mode'. */ -uint32_t ble_ll_pdu_tx_time_get(uint16_t payload_len, int phy_mode); - -/* Calculate maximum octets of PDU payload which can be transmitted during - * 'usecs' on a PHY 'phy_mode'. */ -uint16_t ble_ll_pdu_max_tx_octets_get(uint32_t usecs, int phy_mode); - -/* Is this address a resolvable private address? */ -int ble_ll_is_rpa(const uint8_t *addr, uint8_t addr_type); - -int ble_ll_addr_subtype(const uint8_t *addr, uint8_t addr_type); - -/* Is this address an identity address? */ -int ble_ll_addr_is_id(uint8_t *addr, uint8_t addr_type); - -/* Is 'addr' our device address? 'addr_type' is public (0) or random (!=0) */ -int ble_ll_is_our_devaddr(uint8_t *addr, int addr_type); - -/* Get identity address 'addr_type' is public (0) or random (!=0) */ -uint8_t *ble_ll_get_our_devaddr(uint8_t addr_type); - -/** - * Called to put a packet on the Link Layer transmit packet queue. - * - * @param txpdu Pointer to transmit packet - */ -void ble_ll_acl_data_in(struct os_mbuf *txpkt); - -/** - * Allocates mbuf for received PDU - * - * This allocated mbuf (may be chained if necessary) that has capacity large - * enough to store received PDU of given length. It does not set mbufs length - * as this has to be done by PHY when copying data. - * - * @param len Length of PDU, including PDU header and excluding MIC (if encrypted) - * - * @return mbuf large enough to store received PDU on success - * NULL on failure (oom) - */ -struct os_mbuf *ble_ll_rxpdu_alloc(uint16_t len); - -/* Tell the Link Layer there has been a data buffer overflow */ -void ble_ll_data_buffer_overflow(void); - -/* Tell the link layer there has been a hardware error */ -void ble_ll_hw_error(void); - -/*--- PHY interfaces ---*/ -struct ble_mbuf_hdr; - -/* Called by the PHY when a packet has started */ -int ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *hdr); - -/* Called by the PHY when a packet reception ends */ -int ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr); - -/* Helper callback to tx mbuf using ble_phy_tx() */ -uint8_t ble_ll_tx_mbuf_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte); -uint8_t ble_ll_tx_flat_mbuf_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte); - -/*--- Controller API ---*/ -void ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr); - -/* Set the link layer state */ -void ble_ll_state_set(uint8_t ll_state); - -/* Get the link layer state */ -uint8_t ble_ll_state_get(void); - -/* Send an event to LL task */ -void ble_ll_event_send(struct ble_npl_event *ev); - -/* Hand received pdu's to LL task */ -void ble_ll_rx_pdu_in(struct os_mbuf *rxpdu); - -/* - * Set public address - * - * This can be used to set controller public address from vendor specific storage, - * usually should be done in hal_bsp_init(). - * Shall be *only* called before LL is initialized, i.e. before sysinit stage. - */ -int ble_ll_set_public_addr(const uint8_t *addr); - -/* Set random address */ -int ble_ll_set_random_addr(const uint8_t *cmdbuf, uint8_t len, bool hci_adv_ext); - -/* Wait for response timer expiration callback */ -void ble_ll_wfr_timer_exp(void *arg); - -/* Read set of features supported by the Link Layer */ -uint64_t ble_ll_read_supp_features(void); - -/* Set host supported features */ -int ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len); - -/* Read set of states supported by the Link Layer */ -uint64_t ble_ll_read_supp_states(void); - -/* Check if octets and time are valid. Returns 0 if not valid */ -int ble_ll_chk_txrx_octets(uint16_t octets); -int ble_ll_chk_txrx_time(uint16_t time); - -/* Random numbers */ -int ble_ll_rand_init(void); -void ble_ll_rand_sample(uint8_t rnum); -int ble_ll_rand_data_get(uint8_t *buf, uint8_t len); -void ble_ll_rand_prand_get(uint8_t *prand); -int ble_ll_rand_start(void); - -static inline int -ble_ll_get_addr_type(uint8_t txrxflag) -{ - if (txrxflag) { - return BLE_HCI_ADV_OWN_ADDR_RANDOM; - } - return BLE_HCI_ADV_OWN_ADDR_PUBLIC; -} - -/* Convert usecs to ticks and round up to nearest tick */ -static inline uint32_t -ble_ll_usecs_to_ticks_round_up(uint32_t usecs) -{ - return os_cputime_usecs_to_ticks(usecs + 30); -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/* LTK 0x4C68384139F574D836BCF34E9DFB01BF */ -extern const uint8_t g_bletest_LTK[]; -extern uint16_t g_bletest_EDIV; -extern uint64_t g_bletest_RAND; -extern uint64_t g_bletest_SKDm; -extern uint64_t g_bletest_SKDs; -extern uint32_t g_bletest_IVm; -extern uint32_t g_bletest_IVs; -#endif - -#if MYNEWT_VAL(BLE_LL_DTM) -void ble_ll_dtm_init(void); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* H_LL_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_adv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_adv.h deleted file mode 100644 index eee07cbf0..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_adv.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_ADV_ -#define H_BLE_LL_ADV_ - -#include "nimble/porting/nimble/include/syscfg/syscfg.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * ADV event timing - * T_advEvent = advInterval + advDelay - * - * advInterval: increments of 625 usecs - * advDelay: RAND[0, 10] msecs - * - */ -#define BLE_LL_ADV_ITVL (625) /* usecs */ -#define BLE_LL_ADV_ITVL_MIN (32) /* units */ -#define BLE_LL_ADV_ITVL_MAX (16384) /* units */ -#define BLE_LL_ADV_ITVL_MS_MIN (20) /* msecs */ -#define BLE_LL_ADV_ITVL_MS_MAX (10240) /* msecs */ -#define BLE_LL_ADV_ITVL_SCAN_MIN (160) /* units */ -#define BLE_LL_ADV_ITVL_SCAN_MS_MIN (100) /* msecs */ -#define BLE_LL_ADV_ITVL_NONCONN_MS_MIN (100) /* msecs */ -#define BLE_LL_ADV_DELAY_MS_MIN (0) /* msecs */ -#define BLE_LL_ADV_DELAY_MS_MAX (10) /* msecs */ -#define BLE_LL_ADV_PDU_ITVL_LD_MS_MAX (10) /* msecs */ -#define BLE_LL_ADV_PDU_ITVL_HD_MS_MAX (3750) /* usecs */ -#define BLE_LL_ADV_STATE_HD_MAX (1280) /* msecs */ -#define BLE_LL_ADV_PERIODIC_ITVL (1250) /* usecs */ - -/* Maximum advertisement data length */ -#define BLE_ADV_LEGACY_DATA_MAX_LEN (31) -#define BLE_ADV_LEGACY_MAX_PKT_LEN (37) - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#define BLE_ADV_DATA_MAX_LEN MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) -#else -#define BLE_ADV_DATA_MAX_LEN BLE_ADV_LEGACY_DATA_MAX_LEN -#endif - -/* - * ADV_IND - * -> AdvA (6 bytes) - * -> AdvData (0 - 31 bytes) - * - * The advertising address (AdvA) is a public address (TxAdd=0) or random - * address (TxAdd = 1) - */ -#define BLE_ADV_IND_MIN_LEN (6) -#define BLE_ADV_IND_MAX_LEN (37) - -/* - * ADV_DIRECT_IND - * -> AdvA (6 bytes) - * -> InitA (6 bytes) - * - * AdvA is the advertisers public address (TxAdd=0) or random address - * (TxAdd = 1). - * - * InitA is the initiators public or random address. This is the address - * to which this packet is addressed. - * - */ -#define BLE_ADV_DIRECT_IND_LEN (12) - -/* - * ADV_NONCONN_IND - * -> AdvA (6 bytes) - * -> AdvData (0 - 31 bytes) - * - * The advertising address (AdvA) is a public address (TxAdd=0) or random - * address (TxAdd = 1) - * - */ -#define BLE_ADV_NONCONN_IND_MIN_LEN (6) -#define BLE_ADV_NONCONN_IND_MAX_LEN (37) - -/* - * ADV_SCAN_IND - * -> AdvA (6 bytes) - * -> AdvData (0 - 31 bytes) - * - * The advertising address (AdvA) is a public address (TxAdd=0) or random - * address (TxAdd = 1) - * - */ -#define BLE_ADV_SCAN_IND_MIN_LEN (6) -#define BLE_ADV_SCAN_IND_MAX_LEN (37) - -/*---- HCI ----*/ -struct ble_ll_adv_sm; -struct ble_ll_conn_sm; - -/* Start an advertiser */ -int ble_ll_adv_start_req(uint8_t adv_chanmask, uint8_t adv_type, - uint8_t *init_addr, uint16_t adv_itvl, void *handle); - -/* Start or stop advertising */ -int ble_ll_hci_adv_set_enable(const uint8_t *cmdbuf, uint8_t len); - -/* Set legacy advertising data */ -int ble_ll_hci_set_adv_data(const uint8_t *cmdbuf, uint8_t len); - -/* Set scan response data */ -int ble_ll_hci_set_scan_rsp_data(const uint8_t *cmd, uint8_t cmd_len); - -/* Set advertising parameters */ -int ble_ll_adv_set_adv_params(const uint8_t *cmdbuf, uint8_t len); - -/* Read advertising channel power */ -int ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen); - -/*---- API used by BLE LL ----*/ -/* Send the connection complete event */ -void ble_ll_adv_send_conn_comp_ev(struct ble_ll_conn_sm *connsm, - struct ble_mbuf_hdr *rxhdr); - -/* Returns local resolvable private address */ -uint8_t *ble_ll_adv_get_local_rpa(struct ble_ll_adv_sm *advsm); - -/* Returns peer resolvable private address */ -uint8_t *ble_ll_adv_get_peer_rpa(struct ble_ll_adv_sm *advsm); - -/* Called to initialize advertising functionality. */ -void ble_ll_adv_init(void); - -/* Called when LL wait for response timer expires in advertising state */ -void ble_ll_adv_wfr_timer_exp(void); - -/* Called to reset the advertiser. */ -void ble_ll_adv_reset(void); - -/* Called on rx pdu start when in advertising state */ -int ble_ll_adv_rx_isr_start(uint8_t pdu_type); - -/* Called on rx pdu end when in advertising state */ -int ble_ll_adv_rx_isr_end(uint8_t pdu_type, struct os_mbuf *rxpdu, int crcok); - -/* Processes received packets at the link layer task */ -void ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, - struct ble_mbuf_hdr *hdr); - -/* Boolean function denoting whether or not the whitelist can be changed */ -int ble_ll_adv_can_chg_whitelist(void); - -/* - * Called when an advertising event has been removed from the scheduler - * without being run. - */ -void ble_ll_adv_event_rmvd_from_sched(struct ble_ll_adv_sm *advsm); - -/* - * Called when a periodic event has been removed from the scheduler - * without being run. - */ -void ble_ll_adv_periodic_rmvd_from_sched(struct ble_ll_adv_sm *advsm); - -/* Called to halt currently running advertising event */ -void ble_ll_adv_halt(void); - -/* Called to determine if advertising is enabled */ -uint8_t ble_ll_adv_enabled(void); - -int ble_ll_adv_hci_set_random_addr(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_adv_set_random_addr(const uint8_t *addr, uint8_t instance); -int ble_ll_adv_remove(const uint8_t *addr, uint8_t len); -int ble_ll_adv_clear_all(void); -int ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_adv_ext_set_adv_data(const uint8_t *cmdbuf, uint8_t cmdlen); -int ble_ll_adv_ext_set_scan_rsp(const uint8_t *cmdbuf, uint8_t cmdlen); -int ble_ll_adv_ext_set_enable(const uint8_t *cmdbuf, uint8_t len); - -int ble_ll_adv_periodic_set_param(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_adv_periodic_set_data(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_adv_periodic_enable(const uint8_t *cmdbuf, uint8_t len); - -int ble_ll_adv_periodic_set_info_transfer(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen); - -/* Called to notify adv code about RPA rotation */ -void ble_ll_adv_rpa_timeout(void); - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_LL_ADV_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_conn.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_conn.h deleted file mode 100644 index 178d67117..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_conn.h +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_CONN_ -#define H_BLE_LL_CONN_ - -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "nimble/nimble/include/nimble/nimble_npl.h" -#include "ble_ll_sched.h" -#include "ble_ll_ctrl.h" -#include "ble_phy.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Roles */ -#define BLE_LL_CONN_ROLE_NONE (0) -#define BLE_LL_CONN_ROLE_MASTER (1) -#define BLE_LL_CONN_ROLE_SLAVE (2) - -/* Connection states */ -#define BLE_LL_CONN_STATE_IDLE (0) -#define BLE_LL_CONN_STATE_CREATED (1) -#define BLE_LL_CONN_STATE_ESTABLISHED (2) - -/* Channel map size */ -#define BLE_LL_CONN_CHMAP_LEN (5) - -/* Definitions for source clock accuracy */ -#define BLE_MASTER_SCA_251_500_PPM (0) -#define BLE_MASTER_SCA_151_250_PPM (1) -#define BLE_MASTER_SCA_101_150_PPM (2) -#define BLE_MASTER_SCA_76_100_PPM (3) -#define BLE_MASTER_SCA_51_75_PPM (4) -#define BLE_MASTER_SCA_31_50_PPM (5) -#define BLE_MASTER_SCA_21_30_PPM (6) -#define BLE_MASTER_SCA_0_20_PPM (7) - -/* Definition for RSSI when the RSSI is unknown */ -#define BLE_LL_CONN_UNKNOWN_RSSI (127) - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/* - * Encryption states for a connection - * - * NOTE: the states are ordered so that we can check to see if the state - * is greater than ENCRYPTED. If so, it means that the start or pause - * encryption procedure is running and we should not send data pdu's. - */ -enum conn_enc_state { - CONN_ENC_S_UNENCRYPTED = 1, - CONN_ENC_S_ENCRYPTED, - CONN_ENC_S_ENC_RSP_WAIT, - CONN_ENC_S_PAUSE_ENC_RSP_WAIT, - CONN_ENC_S_PAUSED, - CONN_ENC_S_START_ENC_REQ_WAIT, - CONN_ENC_S_START_ENC_RSP_WAIT, - CONN_ENC_S_LTK_REQ_WAIT, - CONN_ENC_S_LTK_NEG_REPLY -}; - -/* - * Note that the LTK is the key, the SDK is the plain text, and the - * session key is the cipher text portion of the encryption block. - * - * NOTE: we have intentionally violated the specification by making the - * transmit and receive packet counters 32-bits as opposed to 39 (as per the - * specification). We do this to save code space, ram and calculation time. The - * only drawback is that any encrypted connection that sends more than 2^32 - * packets will suffer a MIC failure and thus be disconnected. - */ -struct ble_ll_conn_enc_data -{ - uint8_t enc_state; - uint8_t tx_encrypted; - uint16_t enc_div; - uint32_t tx_pkt_cntr; - uint32_t rx_pkt_cntr; - uint64_t host_rand_num; - uint8_t iv[8]; - struct ble_encryption_block enc_block; -}; -#endif - -/* Connection state machine flags. */ -union ble_ll_conn_sm_flags { - struct { - uint32_t pkt_rxd:1; - uint32_t terminate_ind_txd:1; - uint32_t terminate_ind_rxd:1; - uint32_t terminate_ind_rxd_acked:1; - uint32_t allow_slave_latency:1; - uint32_t slave_set_last_anchor:1; - uint32_t awaiting_host_reply:1; - uint32_t terminate_started:1; - uint32_t conn_update_sched:1; - uint32_t host_expects_upd_event:1; - uint32_t version_ind_sent:1; - uint32_t rxd_version_ind:1; - uint32_t chanmap_update_scheduled:1; - uint32_t conn_empty_pdu_txd:1; - uint32_t last_txd_md:1; - uint32_t conn_req_txd:1; - uint32_t send_ltk_req:1; - uint32_t encrypted:1; - uint32_t encrypt_chg_sent:1; - uint32_t le_ping_supp:1; - uint32_t csa2_supp:1; - uint32_t host_phy_update: 1; - uint32_t phy_update_sched: 1; - uint32_t ctrlr_phy_update: 1; - uint32_t phy_update_event: 1; - uint32_t peer_phy_update: 1; /* XXX:combine with ctrlr udpate bit? */ - uint32_t aux_conn_req: 1; - uint32_t rxd_features:1; - uint32_t pending_hci_rd_features:1; - uint32_t pending_initiate_dle:1; - } cfbit; - uint32_t conn_flags; -} __attribute__((packed)); - -/** - * Structure used for PHY data inside a connection. - * - * NOTE: the new phy's are the phys we will change to when a phy update - * procedure is ongoing and the event counter hits the instant. - * - * tx_phy_mode: chip specific phy mode for tx - * rx_phy_mode: chip specific phy mode for rx - * cur_tx_phy: value denoting current tx_phy (not a bitmask!) - * cur_rx_phy: value denoting current rx phy (not a bitmask!) - * new_tx_phy: value denoting new tx_phy (not a bitmask!) - * new_rx_phy: value denoting new rx phy (not a bitmask!) - * req_pref_tx_phy: tx phy sent in a phy request (may be different than host) - * req_pref_rx_phy: rx phy sent in a phy request (may be different than host) - * host_pref_tx_phys: bitmask of preferred transmit PHYs sent by host - * host_pref_rx_phys: bitmask of preferred receive PHYs sent by host - * phy_options: preferred phy options for coded phy - */ -struct ble_ll_conn_phy_data -{ - uint32_t tx_phy_mode: 2; - uint32_t rx_phy_mode: 2; - uint32_t cur_tx_phy: 2; - uint32_t cur_rx_phy: 2; - uint32_t new_tx_phy: 2; - uint32_t new_rx_phy: 2; - uint32_t host_pref_tx_phys_mask: 3; - uint32_t host_pref_rx_phys_mask: 3; - uint32_t req_pref_tx_phys_mask: 3; - uint32_t req_pref_rx_phys_mask: 3; - uint32_t phy_options: 2; -} __attribute__((packed)); - -#define CONN_CUR_TX_PHY_MASK(csm) (1 << ((csm)->phy_data.cur_tx_phy - 1)) -#define CONN_CUR_RX_PHY_MASK(csm) (1 << ((csm)->phy_data.cur_rx_phy - 1)) - -struct hci_conn_update -{ - uint16_t handle; - uint16_t conn_itvl_min; - uint16_t conn_itvl_max; - uint16_t conn_latency; - uint16_t supervision_timeout; - uint16_t min_ce_len; - uint16_t max_ce_len; -}; - -struct hci_ext_conn_params -{ - uint16_t scan_itvl; - uint16_t scan_window; - uint16_t conn_itvl_min; - uint16_t conn_itvl_max; - uint16_t conn_latency; - uint16_t supervision_timeout; - uint16_t min_ce_len; - uint16_t max_ce_len; -}; - -struct hci_ext_create_conn -{ - uint8_t filter_policy; - uint8_t own_addr_type; - uint8_t peer_addr_type; - uint8_t peer_addr[BLE_DEV_ADDR_LEN]; - uint8_t init_phy_mask; - struct hci_ext_conn_params params[3]; -}; - -/* Connection state machine */ -struct ble_ll_conn_sm -{ - /* Connection state machine flags */ - union ble_ll_conn_sm_flags csmflags; - - /* Current connection handle, state and role */ - uint16_t conn_handle; - uint8_t conn_state; - uint8_t conn_role; /* Can possibly be 1 bit */ - - /* RSSI */ - int8_t conn_rssi; - - /* For privacy */ - int8_t rpa_index; - - /* Connection data length management */ - uint8_t max_tx_octets; - uint8_t max_rx_octets; - uint8_t rem_max_tx_octets; - uint8_t rem_max_rx_octets; - uint8_t eff_max_tx_octets; - uint8_t eff_max_rx_octets; - uint16_t max_tx_time; - uint16_t max_rx_time; - uint16_t rem_max_tx_time; - uint16_t rem_max_rx_time; - uint16_t eff_max_tx_time; - uint16_t eff_max_rx_time; - uint8_t max_tx_octets_phy_mode[BLE_PHY_NUM_MODE]; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - uint16_t host_req_max_tx_time; -#endif - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - struct ble_ll_conn_phy_data phy_data; - uint16_t phy_instant; - uint8_t phy_tx_transition; -#endif - - /* Used to calculate data channel index for connection */ - uint8_t chanmap[BLE_LL_CONN_CHMAP_LEN]; - uint8_t req_chanmap[BLE_LL_CONN_CHMAP_LEN]; - uint16_t chanmap_instant; - uint16_t channel_id; /* TODO could be union with hop and last chan used */ - uint8_t hop_inc; - uint8_t data_chan_index; - uint8_t last_unmapped_chan; - uint8_t num_used_chans; - -#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) - uint8_t period_occ_mask; /* mask: period 0 = 0x01, period 3 = 0x08 */ -#endif - - /* Ack/Flow Control */ - uint8_t tx_seqnum; /* note: can be 1 bit */ - uint8_t next_exp_seqnum; /* note: can be 1 bit */ - uint8_t cons_rxd_bad_crc; /* note: can be 1 bit */ - uint8_t last_rxd_sn; /* note: cant be 1 bit given current code */ - uint8_t last_rxd_hdr_byte; /* note: possibly can make 1 bit since we - only use the MD bit now */ - - /* connection event mgmt */ - uint8_t reject_reason; - uint8_t host_reply_opcode; - uint8_t master_sca; - uint8_t tx_win_size; - uint8_t cur_ctrl_proc; - uint8_t disconnect_reason; - uint8_t rxd_disconnect_reason; - uint8_t vers_nr; - uint8_t conn_features; - uint8_t remote_features[7]; - uint16_t pending_ctrl_procs; - uint16_t event_cntr; - uint16_t completed_pkts; - uint16_t comp_id; - uint16_t sub_vers_nr; - uint16_t auth_pyld_tmo; /* could be ifdef'd. 10 msec units */ - - uint32_t access_addr; - uint32_t crcinit; /* only low 24 bits used */ - /* XXX: do we need ce_end_time? Cant this be sched end time? */ - uint32_t ce_end_time; /* cputime at which connection event should end */ - uint32_t terminate_timeout; - uint32_t last_scheduled; - - /* Connection timing */ - uint16_t conn_itvl; - uint16_t slave_latency; - uint16_t supervision_tmo; - uint16_t min_ce_len; - uint16_t max_ce_len; - uint16_t tx_win_off; - uint32_t anchor_point; - uint8_t anchor_point_usecs; /* XXX: can this be uint8_t ?*/ - uint8_t conn_itvl_usecs; - uint32_t conn_itvl_ticks; - uint32_t last_anchor_point; /* Slave only */ - uint32_t slave_cur_tx_win_usecs; - uint32_t slave_cur_window_widening; - uint32_t last_rxd_pdu_cputime; /* Used exclusively for supervision timer */ - - /* - * Used to mark that identity address was used as InitA - */ - uint8_t inita_identity_used; - - /* address information */ - uint8_t own_addr_type; - uint8_t peer_addr_type; - uint8_t peer_addr[BLE_DEV_ADDR_LEN]; - - /* - * XXX: TODO. Could save memory. Have single event at LL and put these - * on a singly linked list. Only would need list pointer here. - */ - /* Connection end event */ - struct ble_npl_event conn_ev_end; - - /* Packet transmit queue */ - struct os_mbuf *cur_tx_pdu; - STAILQ_HEAD(conn_txq_head, os_mbuf_pkthdr) conn_txq; - - /* List entry for active/free connection pools */ - union { - SLIST_ENTRY(ble_ll_conn_sm) act_sle; - STAILQ_ENTRY(ble_ll_conn_sm) free_stqe; - }; - - /* LL control procedure response timer */ - struct ble_npl_callout ctrl_proc_rsp_timer; - - /* For scheduling connections */ - struct ble_ll_sched_item conn_sch; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) - struct ble_npl_callout auth_pyld_timer; -#endif - - /* - * XXX: a note on all these structures for control procedures. First off, - * all of these need to be ifdef'd to save memory. Another thing to - * consider is this: since most control procedures can only run when no - * others are running, can I use just one structure (a union)? Should I - * allocate these from a pool? Not sure what to do. For now, I just use - * a large chunk of memory per connection. - */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - struct ble_ll_conn_enc_data enc_data; -#endif - /* - * For connection update procedure. XXX: can make this a pointer and - * malloc it if we want to save space. - */ - struct hci_conn_update conn_param_req; - - /* For connection update procedure */ - struct ble_ll_conn_upd_req conn_update_req; - - /* XXX: for now, just store them all */ - struct ble_ll_conn_params conn_cp; - - struct ble_ll_scan_sm *scansm; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct hci_ext_create_conn initial_params; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - uint8_t sync_transfer_mode; - uint16_t sync_transfer_skip; - uint32_t sync_transfer_sync_timeout; -#endif -}; - -/* Flags */ -#define CONN_F_UPDATE_SCHED(csm) ((csm)->csmflags.cfbit.conn_update_sched) -#define CONN_F_EMPTY_PDU_TXD(csm) ((csm)->csmflags.cfbit.conn_empty_pdu_txd) -#define CONN_F_LAST_TXD_MD(csm) ((csm)->csmflags.cfbit.last_txd_md) -#define CONN_F_CONN_REQ_TXD(csm) ((csm)->csmflags.cfbit.conn_req_txd) -#define CONN_F_ENCRYPTED(csm) ((csm)->csmflags.cfbit.encrypted) -#define CONN_F_ENC_CHANGE_SENT(csm) ((csm)->csmflags.cfbit.encrypt_chg_sent) -#define CONN_F_LE_PING_SUPP(csm) ((csm)->csmflags.cfbit.le_ping_supp) -#define CONN_F_TERMINATE_STARTED(csm) ((csm)->csmflags.cfbit.terminate_started) -#define CONN_F_CSA2_SUPP(csm) ((csm)->csmflags.cfbit.csa2_supp) -#define CONN_F_HOST_PHY_UPDATE(csm) ((csm)->csmflags.cfbit.host_phy_update) -#define CONN_F_PHY_UPDATE_SCHED(csm) ((csm)->csmflags.cfbit.phy_update_sched) -#define CONN_F_CTRLR_PHY_UPDATE(csm) ((csm)->csmflags.cfbit.ctrlr_phy_update) -#define CONN_F_PHY_UPDATE_EVENT(csm) ((csm)->csmflags.cfbit.phy_update_event) -#define CONN_F_PEER_PHY_UPDATE(csm) ((csm)->csmflags.cfbit.peer_phy_update) -#define CONN_F_AUX_CONN_REQ(csm) ((csm)->csmflags.cfbit.aux_conn_req) - -/* Role */ -#define CONN_IS_MASTER(csm) (csm->conn_role == BLE_LL_CONN_ROLE_MASTER) -#define CONN_IS_SLAVE(csm) (csm->conn_role == BLE_LL_CONN_ROLE_SLAVE) - -/* - * Given a handle, returns an active connection state machine (or NULL if the - * handle does not exist - * - */ -struct ble_ll_conn_sm *ble_ll_conn_find_active_conn(uint16_t handle); - -/* required for unit testing */ -uint8_t ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn, uint16_t latency); - -/* used to get anchor point for connection event specified */ -void ble_ll_conn_get_anchor(struct ble_ll_conn_sm *connsm, uint16_t conn_event, - uint32_t *anchor, uint8_t *anchor_usecs); - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_LL_CONN_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h deleted file mode 100644 index b0da1e736..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_CTRL_ -#define H_BLE_LL_CTRL_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * LL control procedures. This "enumeration" is not in the specification; - * It is used to determine which LL control procedure is currently running - * in a connection and which ones may be pending. - */ -#define BLE_LL_CTRL_PROC_CONN_UPDATE (0) -#define BLE_LL_CTRL_PROC_CHAN_MAP_UPD (1) -#define BLE_LL_CTRL_PROC_ENCRYPT (2) -#define BLE_LL_CTRL_PROC_FEATURE_XCHG (3) -#define BLE_LL_CTRL_PROC_VERSION_XCHG (4) -#define BLE_LL_CTRL_PROC_TERMINATE (5) -#define BLE_LL_CTRL_PROC_CONN_PARAM_REQ (6) -#define BLE_LL_CTRL_PROC_LE_PING (7) -#define BLE_LL_CTRL_PROC_DATA_LEN_UPD (8) -#define BLE_LL_CTRL_PROC_PHY_UPDATE (9) -#define BLE_LL_CTRL_PROC_NUM (10) -#define BLE_LL_CTRL_PROC_IDLE (255) - -/* Checks if a particular control procedure is running */ -#define IS_PENDING_CTRL_PROC(sm, proc) (sm->pending_ctrl_procs & (1 << proc)) -#define CLR_PENDING_CTRL_PROC(sm, proc) (sm->pending_ctrl_procs &= ~(1 << proc)) - -/* LL control procedure timeout */ -#define BLE_LL_CTRL_PROC_TIMEOUT_MS (40000) /* ms */ - -/* - * LL CTRL PDU format - * -> Opcode (1 byte) - * -> Data (0 - 26 bytes) - */ -#define BLE_LL_CTRL_CONN_UPDATE_IND (0) -#define BLE_LL_CTRL_CHANNEL_MAP_REQ (1) -#define BLE_LL_CTRL_TERMINATE_IND (2) -#define BLE_LL_CTRL_ENC_REQ (3) -#define BLE_LL_CTRL_ENC_RSP (4) -#define BLE_LL_CTRL_START_ENC_REQ (5) -#define BLE_LL_CTRL_START_ENC_RSP (6) -#define BLE_LL_CTRL_UNKNOWN_RSP (7) -#define BLE_LL_CTRL_FEATURE_REQ (8) -#define BLE_LL_CTRL_FEATURE_RSP (9) -#define BLE_LL_CTRL_PAUSE_ENC_REQ (10) -#define BLE_LL_CTRL_PAUSE_ENC_RSP (11) -#define BLE_LL_CTRL_VERSION_IND (12) -#define BLE_LL_CTRL_REJECT_IND (13) -#define BLE_LL_CTRL_SLAVE_FEATURE_REQ (14) -#define BLE_LL_CTRL_CONN_PARM_REQ (15) -#define BLE_LL_CTRL_CONN_PARM_RSP (16) -#define BLE_LL_CTRL_REJECT_IND_EXT (17) -#define BLE_LL_CTRL_PING_REQ (18) -#define BLE_LL_CTRL_PING_RSP (19) -#define BLE_LL_CTRL_LENGTH_REQ (20) -#define BLE_LL_CTRL_LENGTH_RSP (21) -#define BLE_LL_CTRL_PHY_REQ (22) -#define BLE_LL_CTRL_PHY_RSP (23) -#define BLE_LL_CTRL_PHY_UPDATE_IND (24) -#define BLE_LL_CTRL_MIN_USED_CHAN_IND (25) -#define BLE_LL_CTRL_CTE_REQ (26) -#define BLE_LL_CTRL_CTE_RSP (27) -#define BLE_LL_CTRL_PERIODIC_SYNC_IND (28) -#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ (29) -#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP (30) - -/* Maximum opcode value */ -#define BLE_LL_CTRL_OPCODES (BLE_LL_CTRL_CLOCK_ACCURACY_RSP + 1) - -extern const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES]; - -/* Maximum LL control PDU size */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -#define BLE_LL_CTRL_MAX_PDU_LEN (35) -#else -#define BLE_LL_CTRL_MAX_PDU_LEN (27) -#endif - -/* LL control connection update request */ -struct ble_ll_conn_upd_req -{ - uint8_t winsize; - uint16_t winoffset; - uint16_t interval; - uint16_t latency; - uint16_t timeout; - uint16_t instant; -}; -#define BLE_LL_CTRL_CONN_UPD_REQ_LEN (11) - -/* LL control channel map request */ -struct ble_ll_chan_map_req -{ - uint8_t chmap[5]; - uint16_t instant; -}; -#define BLE_LL_CTRL_CHAN_MAP_LEN (7) - -/* - * LL control terminate ind - * -> error code (1 byte) - */ -#define BLE_LL_CTRL_TERMINATE_IND_LEN (1) - -/* LL control enc req */ -struct ble_ll_enc_req -{ - uint8_t rand[8]; - uint16_t ediv; - uint8_t skdm[8]; - uint32_t ivm; -}; - -#define BLE_LL_CTRL_ENC_REQ_LEN (22) - -/* LL control enc rsp */ -struct ble_ll_enc_rsp -{ - uint8_t skds[8]; - uint32_t ivs; -}; - -#define BLE_LL_CTRL_ENC_RSP_LEN (12) - -/* LL control start/pause enc request and response */ -#define BLE_LL_CTRL_START_ENC_REQ_LEN (0) -#define BLE_LL_CTRL_START_ENC_RSP_LEN (0) -#define BLE_LL_CTRL_PAUSE_ENC_REQ_LEN (0) -#define BLE_LL_CTRL_PAUSE_ENC_RSP_LEN (0) - -/* - * LL control unknown response - * -> 1 byte which contains the unknown or un-supported opcode. - */ -#define BLE_LL_CTRL_UNK_RSP_LEN (1) - -/* - * LL control feature req and LL control feature rsp - * -> 8 bytes of data containing features supported by device. - */ -#define BLE_LL_CTRL_FEATURE_LEN (8) - -/* - * LL control version ind - * -> version (1 byte): - * Contains the version number of the bluetooth controller specification. - * -> comp_id (2 bytes) - * Contains the company identifier of the manufacturer of the controller. - * -> sub_ver_num: Contains a unique value for implementation or revision of - * the bluetooth controller. - */ -struct ble_ll_version_ind -{ - uint8_t ble_ctrlr_ver; - uint16_t company_id; - uint16_t sub_ver_num; -}; - -#define BLE_LL_CTRL_VERSION_IND_LEN (5) - -/* - * LL control reject ind - * -> error code (1 byte): contains reason why request was rejected. - */ -#define BLE_LL_CTRL_REJ_IND_LEN (1) - -/* - * LL control slave feature req - * -> 8 bytes of data containing features supported by device. - */ -#define BLE_LL_CTRL_SLAVE_FEATURE_REQ_LEN (8) - -/* LL control connection param req and connection param rsp */ -struct ble_ll_conn_params -{ - uint16_t interval_min; - uint16_t interval_max; - uint16_t latency; - uint16_t timeout; - uint8_t pref_periodicity; - uint16_t ref_conn_event_cnt; - uint16_t offset0; - uint16_t offset1; - uint16_t offset2; - uint16_t offset3; - uint16_t offset4; - uint16_t offset5; -}; - -#define BLE_LL_CTRL_CONN_PARAMS_LEN (23) - -/* LL control reject ind ext */ -struct ble_ll_reject_ind_ext -{ - uint8_t reject_opcode; - uint8_t err_code; -}; - -#define BLE_LL_CTRL_REJECT_IND_EXT_LEN (2) - -/* LL control ping req and ping rsp (contain no data) */ -#define BLE_LL_CTRL_PING_LEN (0) - -/* - * LL control length req and length rsp - * -> max_rx_bytes (2 bytes): defines connMaxRxOctets. Range 27 to 251 - * -> max_rx_time (2 bytes): defines connMaxRxTime. Range 328 to 2120 usecs. - * -> max_tx_bytes (2 bytes): defines connMaxTxOctets. Range 27 to 251 - * -> max_tx_time (2 bytes): defines connMaxTxTime. Range 328 to 2120 usecs. - */ -struct ble_ll_len_req -{ - uint16_t max_rx_bytes; - uint16_t max_rx_time; - uint16_t max_tx_bytes; - uint16_t max_tx_time; -}; - -#define BLE_LL_CTRL_LENGTH_REQ_LEN (8) - -/* PHY request/response */ -#define BLE_LL_CTRL_PHY_REQ_LEN (2) -#define BLE_LL_CTRL_PHY_RSP_LEN (2) -#define BLE_LL_CTRL_PHY_UPD_IND_LEN (4) - -/* Min used channels */ -#define BLE_LL_CTRL_MIN_USED_CHAN_LEN (2) - -/* CTE REQ */ -#define BLE_LL_CTRL_CTE_REQ_LEN (1) - -/* CTE RSP (contains no data) */ -#define BLE_LL_CTRL_CTE_RSP_LEN (0) - -/* Periodic Sync Transfer IND */ -#define BLE_LL_CTRL_PERIODIC_SYNC_IND_LEN (34) - -/* Clock accuracy request/response */ -#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ_LEN (1) -#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP_LEN (1) - -/* API */ -struct ble_ll_conn_sm; -void ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc); -void ble_ll_ctrl_proc_stop(struct ble_ll_conn_sm *connsm, int ctrl_proc); -int ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om); -void ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm); -void ble_ll_ctrl_terminate_start(struct ble_ll_conn_sm *connsm); -int ble_ll_ctrl_is_terminate_ind(uint8_t hdr, uint8_t opcode); -uint8_t ble_ll_ctrl_conn_param_reply(struct ble_ll_conn_sm *connsm, - uint8_t *rsp, - struct ble_ll_conn_params *req); -int ble_ll_ctrl_reject_ind_send(struct ble_ll_conn_sm *connsm, - uint8_t rej_opcode, uint8_t err); -int ble_ll_ctrl_start_enc_send(struct ble_ll_conn_sm *connsm); -int ble_ll_ctrl_enc_allowed_pdu_rx(struct os_mbuf *rxpdu); -int ble_ll_ctrl_enc_allowed_pdu_tx(struct os_mbuf_pkthdr *pkthdr); -int ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm); -int ble_ll_ctrl_is_start_enc_rsp(struct os_mbuf *txpdu); - -void ble_ll_hci_ev_datalen_chg(struct ble_ll_conn_sm *connsm); -void ble_ll_hci_ev_rem_conn_parm_req(struct ble_ll_conn_sm *connsm, - struct ble_ll_conn_params *cp); -void ble_ll_hci_ev_conn_update(struct ble_ll_conn_sm *connsm, uint8_t status); -void ble_ll_hci_ev_rd_rem_used_feat(struct ble_ll_conn_sm *connsm, - uint8_t status); -void ble_ll_hci_ev_rd_rem_ver(struct ble_ll_conn_sm *connsm, uint8_t status); -void ble_ll_hci_ev_encrypt_chg(struct ble_ll_conn_sm *connsm, uint8_t status); -int ble_ll_hci_ev_ltk_req(struct ble_ll_conn_sm *connsm); -int ble_ll_hci_ev_hw_err(uint8_t hw_err); -void ble_ll_hci_ev_databuf_overflow(void); -void ble_ll_hci_ev_le_csa(struct ble_ll_conn_sm *connsm); -void ble_ll_hci_ev_send_scan_req_recv(uint8_t adv_handle, const uint8_t *peer, - uint8_t peer_addr_type); -void ble_ll_hci_ev_send_scan_timeout(void); -void ble_ll_hci_ev_send_adv_set_terminated(uint8_t status, uint8_t adv_handle, - uint16_t conn_handle, uint8_t events); -int ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status); -void ble_ll_calc_session_key(struct ble_ll_conn_sm *connsm); -void ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm); -void ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm); -void ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line); - -uint8_t ble_ll_ctrl_phy_tx_transition_get(uint8_t phy_mask); -uint8_t ble_ll_ctrl_phy_from_phy_mask(uint8_t phy_mask); - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_LL_CTRL_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_hci.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_hci.h deleted file mode 100644 index 5806f6737..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_hci.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_HCI_ -#define H_BLE_LL_HCI_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "nimble/nimble/include/nimble/hci_common.h" - -/* For supported commands */ -#define BLE_LL_SUPP_CMD_LEN (42) -extern const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN]; - -/* The largest event the controller will send. */ -#define BLE_LL_MAX_EVT_LEN MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE) - -/* - * This determines the number of outstanding commands allowed from the - * host to the controller. NOTE: you cannot change this without modifying - * other portions of the code as we currently use a global os event for - * the command; you would need to allocate a pool of these. - */ -#define BLE_LL_CFG_NUM_HCI_CMD_PKTS (1) - -typedef void (*ble_ll_hci_post_cmd_complete_cb)(void); - -/* Initialize LL HCI */ -void ble_ll_hci_init(void); - -/* Used to determine if the LE event is enabled/disabled */ -bool ble_ll_hci_is_le_event_enabled(unsigned int subev); - -/* Used to determine if event is enabled/disabled */ -bool ble_ll_hci_is_event_enabled(unsigned int evcode); - -/* Send event from controller to host */ -int ble_ll_hci_event_send(struct ble_hci_ev *hci_ev); - -/* Sends a command complete with a no-op opcode to host */ -void ble_ll_hci_send_noop(void); - -/* Checks the preferref phy masks from set default phy and set phy commands */ -int ble_ll_hci_chk_phy_masks(uint8_t all_phys, uint8_t tx_phys, uint8_t rx_phys, - uint8_t *txphy, uint8_t *rxphy); - -/* Returns true if Extended Advertising HCI commands are in use */ -bool ble_ll_hci_adv_mode_ext(void); - -/* Get TX power compensation rounded to integer dB */ -int8_t ble_ll_get_tx_pwr_compensation(void); - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_LL_HCI_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_resolv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_resolv.h deleted file mode 100644 index 228e0a370..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_resolv.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_RESOLV_ -#define H_BLE_LL_RESOLV_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * An entry in the resolving list. - * The identity address is stored in little endian format. - * The local rpa is stored in little endian format. - * The IRKs are stored in big endian format. - * - * Note: - * rl_local_irk and rl_peer_irk need to be word aligned - */ -struct ble_ll_resolv_entry -{ - uint8_t rl_addr_type; - uint8_t rl_priv_mode; - uint8_t rl_has_local; - uint8_t rl_has_peer; - uint8_t rl_local_irk[16]; - uint8_t rl_peer_irk[16]; - uint8_t rl_identity_addr[BLE_DEV_ADDR_LEN]; - uint8_t rl_local_rpa[BLE_DEV_ADDR_LEN]; - uint8_t rl_peer_rpa[BLE_DEV_ADDR_LEN]; -}; - -extern struct ble_ll_resolv_entry g_ble_ll_resolv_list[]; - -/* Clear the resolving list */ -int ble_ll_resolv_list_clr(void); - -/* Read the size of the resolving list */ -int ble_ll_resolv_list_read_size(uint8_t *rspbuf, uint8_t *rsplen); - -/* Add a device to the resolving list */ -int ble_ll_resolv_list_add(const uint8_t *cmdbuf, uint8_t len); - -/* Remove a device from the resolving list */ -int ble_ll_resolv_list_rmv(const uint8_t *cmdbuf, uint8_t len); - -/* Address resolution enable command */ -int ble_ll_resolv_enable_cmd(const uint8_t *cmdbuf, uint8_t len); - -int ble_ll_resolv_peer_addr_rd(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_resolv_local_addr_rd(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen); - -/* Finds 'addr' in resolving list. Doesnt check if address resolution enabled */ -struct ble_ll_resolv_entry * -ble_ll_resolv_list_find(const uint8_t *addr, uint8_t addr_type); - -/* Returns true if address resolution is enabled */ -uint8_t ble_ll_resolv_enabled(void); - -/* Reset private address resolution */ -void ble_ll_resolv_list_reset(void); - -/* Generate local or peer RPA. It is up to caller to make sure required IRK - * is present on RL - */ -void ble_ll_resolv_get_priv_addr(struct ble_ll_resolv_entry *rl, int local, - uint8_t *addr); - -void ble_ll_resolv_set_peer_rpa(int index, uint8_t *rpa); -void ble_ll_resolv_set_local_rpa(int index, uint8_t *rpa); - -/* Generate a resolvable private address. */ -int ble_ll_resolv_gen_rpa(uint8_t *addr, uint8_t addr_type, uint8_t *rpa, - int local); - -/* Set the resolvable private address timeout */ -int ble_ll_resolv_set_rpa_tmo(const uint8_t *cmdbuf, uint8_t len); - -/* Set the privacy mode */ -int ble_ll_resolve_set_priv_mode(const uint8_t *cmdbuf, uint8_t len); - -/* Get the RPA timeout, in seconds */ -uint32_t ble_ll_resolv_get_rpa_tmo(void); - -/* Resolve a resolvable private address */ -int ble_ll_resolv_rpa(const uint8_t *rpa, const uint8_t *irk); - -/* Try to resolve peer RPA and return index on RL if matched */ -int ble_ll_resolv_peer_rpa_any(const uint8_t *rpa); - -/* Initialize resolv*/ -void ble_ll_resolv_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h deleted file mode 100644 index 37b81a88b..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_RFMGMT_ -#define H_BLE_LL_RFMGMT_ - -#ifdef __cplusplus -extern "C" { -#endif - -void ble_ll_rfmgmt_init(void); - -#if MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME) > 0 - -void ble_ll_rfmgmt_reset(void); - -/* Notify rfmgmt that scan window has changed (only called from ble_ll_scan) */ -void ble_ll_rfmgmt_scan_changed(bool enabled, uint32_t next_window); - -/* Notify rfmgmt that 1st scheduled item has changed (only called from ble_ll_sched) */ -void ble_ll_rfmgmt_sched_changed(struct ble_ll_sched_item *first); - -/* Notify rfmgmt that RF is no longer needed by current event */ -void ble_ll_rfmgmt_release(void); - -/* Enables RF immediately and returns tick at which RF will be fully enabled */ -uint32_t ble_ll_rfmgmt_enable_now(void); - -/* Returns true only if RF is currently fully enabled (i.e. not off or enabling) */ -bool ble_ll_rfmgmt_is_enabled(void); - -#else - -static inline void ble_ll_rfmgmt_reset(void) { } -static inline void ble_ll_rfmgmt_scan_changed(bool e, uint32_t n) { } -static inline void ble_ll_rfmgmt_sched_changed(struct ble_ll_sched_item *f) { } -static inline void ble_ll_rfmgmt_release(void) { } -static inline uint32_t ble_ll_rfmgmt_enable_now(void) { return 0; } -static inline bool ble_ll_rfmgmt_is_enabled(void) { return true; } - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_LL_RFMGMT_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_scan.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_scan.h deleted file mode 100644 index ca50824d0..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_scan.h +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_SCAN_ -#define H_BLE_LL_SCAN_ - -#include "ble_ll_sched.h" -#include "nimble/porting/nimble/include/hal/hal_timer.h" -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/nimble/include/nimble/nimble_npl.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * SCAN_REQ - * -> ScanA (6 bytes) - * -> AdvA (6 bytes) - * - * ScanA is the scanners public (TxAdd=0) or random (TxAdd = 1) address - * AdvaA is the advertisers public (RxAdd=0) or random (RxAdd=1) address. - * - * Sent by the LL in the Scanning state; received by the LL in the advertising - * state. The advertising address is the intended recipient of this frame. - */ -#define BLE_SCAN_REQ_LEN (12) - -/* - * SCAN_RSP - * -> AdvA (6 bytes) - * -> ScanRspData (0 - 31 bytes) - * - * AdvaA is the advertisers public (TxAdd=0) or random (TxAdd=1) address. - * ScanRspData may contain any data from the advertisers host. - * - * Sent by the LL in the advertising state; received by the LL in the - * scanning state. - */ -#define BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN (31) -#define BLE_SCAN_LEGACY_MAX_PKT_LEN (37) - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#define BLE_SCAN_RSP_DATA_MAX_LEN MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) - -/* For Bluetooth 5.0 we need state machine for two PHYs*/ -#define BLE_LL_SCAN_PHY_NUMBER (2) -#else -#define BLE_LL_SCAN_PHY_NUMBER (1) -#define BLE_SCAN_RSP_DATA_MAX_LEN BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN -#endif - -#define PHY_UNCODED (0) -#define PHY_CODED (1) - -#define BLE_LL_EXT_ADV_MODE_NON_CONN (0x00) -#define BLE_LL_EXT_ADV_MODE_CONN (0x01) -#define BLE_LL_EXT_ADV_MODE_SCAN (0x02) - -/* All values are stored as ticks */ -struct ble_ll_scan_timing { - uint32_t interval; - uint32_t window; - uint32_t start_time; -}; - -struct ble_ll_scan_params -{ - uint8_t phy; - uint8_t own_addr_type; - uint8_t scan_filt_policy; - uint8_t configured; - uint8_t scan_type; - uint8_t scan_chan; - struct ble_ll_scan_timing timing; -}; - -#define BLE_LL_AUX_HAS_ADVA 0x01 -#define BLE_LL_AUX_HAS_TARGETA 0x02 -#define BLE_LL_AUX_HAS_ADI 0x04 -#define BLE_LL_AUX_IS_MATCHED 0x08 -#define BLE_LL_AUX_IS_TARGETA_RESOLVED 0x10 - -#define BLE_LL_AUX_FLAG_HCI_SENT_ANY 0x02 -#define BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED 0x04 -#define BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED 0x08 -#define BLE_LL_AUX_FLAG_SCAN_COMPLETE 0x10 -#define BLE_LL_AUX_FLAG_SCAN_ERROR 0x20 -#define BLE_LL_AUX_FLAG_AUX_ADV_RECEIVED 0x40 -#define BLE_LL_AUX_FLAG_AUX_CHAIN_RECEIVED 0x80 - -struct ble_ll_aux_data { - uint8_t flags; - - /* - * Since aux_data can be accessed from ISR and LL, we have separate copies - * of flags to make sure that ISR does not modify flags while LL uses them. - * ISR updates 'flags_isr' and LL adds these to 'flags_ll' which it then - * uses for further processing allowing to update 'flags_isr' if another - * scan for given 'aux_data' is scheduled. Note that flags must not be unset - * while aux_data is valid. - */ - uint8_t flags_isr; - uint8_t flags_ll; - - uint8_t ref_cnt; - uint8_t chan; - uint8_t aux_phy; - uint8_t aux_primary_phy; - uint8_t mode; - uint8_t scanning; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - int8_t rpa_index; -#endif - uint16_t adi; - uint32_t offset; - uint8_t offset_units; - uint8_t adva[6]; - uint8_t adva_type; - uint8_t targeta[6]; - uint8_t targeta_type; - uint16_t evt_type; - struct ble_ll_sched_item sch; - struct ble_hci_ev *evt; - struct ble_npl_event ev; -}; - -struct ble_ll_scan_pdu_data { - uint8_t hdr_byte; - /* ScanA for SCAN_REQ and InitA for CONNECT_IND */ - union { - uint8_t scana[BLE_DEV_ADDR_LEN]; - uint8_t inita[BLE_DEV_ADDR_LEN]; - }; - uint8_t adva[BLE_DEV_ADDR_LEN]; -}; - -struct ble_ll_scan_sm -{ - uint8_t scan_enabled; - uint8_t own_addr_type; - uint8_t scan_filt_dups; - uint8_t scan_rsp_pending; - uint8_t scan_rsp_cons_fails; - uint8_t scan_rsp_cons_ok; - uint8_t scan_peer_rpa[BLE_DEV_ADDR_LEN]; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - ble_npl_time_t scan_nrpa_timer; - uint8_t scan_nrpa[BLE_DEV_ADDR_LEN]; -#endif - struct ble_ll_scan_pdu_data pdu_data; - - /* XXX: Shall we count backoff per phy? */ - uint16_t upper_limit; - uint16_t backoff_count; - uint32_t scan_win_start_time; - struct ble_npl_event scan_sched_ev; - struct hal_timer scan_timer; - struct ble_npl_event scan_interrupted_ev; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct hal_timer duration_timer; - struct hal_timer period_timer; - uint32_t duration_ticks; - uint32_t period_ticks; - uint8_t ext_scanning; -#endif - - uint8_t restart_timer_needed; - struct ble_ll_aux_data *cur_aux_data; - - struct ble_ll_scan_params *scanp; - struct ble_ll_scan_params *scanp_next; - struct ble_ll_scan_params scanp_phys[BLE_LL_SCAN_PHY_NUMBER]; -}; - -/* Scan types */ -#define BLE_SCAN_TYPE_PASSIVE (BLE_HCI_SCAN_TYPE_PASSIVE) -#define BLE_SCAN_TYPE_ACTIVE (BLE_HCI_SCAN_TYPE_ACTIVE) -#define BLE_SCAN_TYPE_INITIATE (2) - -/*---- HCI ----*/ -/* Set scanning parameters */ -int ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len); - -/* Turn scanning on/off */ -int ble_ll_hci_scan_set_enable(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_hci_ext_scan_set_enable(const uint8_t *cmdbuf, uint8_t len); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -int ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len); -#endif - -/*--- Controller Internal API ---*/ -/* Initialize the scanner */ -void ble_ll_scan_init(void); - -/* Reset the scanner */ -void ble_ll_scan_reset(void); - -/* Called when Link Layer starts to receive a PDU and is in scanning state */ -int ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags); - -/* Called when Link Layer has finished receiving a PDU while scanning */ -int ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok); - -/* Process a scan response PDU */ -void ble_ll_scan_rx_pkt_in(uint8_t pdu_type, struct os_mbuf *om, - struct ble_mbuf_hdr *hdr); - -/* Boolean function denoting whether or not the whitelist can be changed */ -int ble_ll_scan_can_chg_whitelist(void); - -/* Boolean function returning true if scanning enabled */ -int ble_ll_scan_enabled(void); - -/* Boolean function returns true if whitelist is enabled for scanning */ -int ble_ll_scan_whitelist_enabled(void); - -/* Initialize the scanner when we start initiating */ -struct hci_create_conn; -int ble_ll_scan_initiator_start(struct hci_create_conn *hcc, - struct ble_ll_scan_sm **sm); - -/* Returns storage for PDU data (for SCAN_REQ or CONNECT_IND) */ -struct ble_ll_scan_pdu_data *ble_ll_scan_get_pdu_data(void); - -/* Called to set the resolvable private address of the last connected peer */ -void ble_ll_scan_set_peer_rpa(uint8_t *rpa); - -/* Returns peer RPA of last connection made */ -uint8_t *ble_ll_scan_get_peer_rpa(void); - -/* Returns the local RPA used by the scanner/initiator */ -uint8_t *ble_ll_scan_get_local_rpa(void); - -/* Stop the scanning state machine */ -void ble_ll_scan_sm_stop(int chk_disable); - -/* Resume scanning */ -void ble_ll_scan_chk_resume(void); - -/* Called when wait for response timer expires in scanning mode */ -void ble_ll_scan_wfr_timer_exp(void); - -/* Called when scan could be interrupted */ -void ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm); - -int ble_ll_scan_adv_decode_addr(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_mbuf_hdr *ble_hdr, - uint8_t **addr, uint8_t *addr_type, - uint8_t **inita, uint8_t *init_addr_type, - int *ext_mode); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -int ble_ll_scan_update_aux_data(struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf, - bool *adva_present); - -/* Initialize the extended scanner when we start initiating */ -struct hci_ext_create_conn; -int ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, - struct ble_ll_scan_sm **sm); - -/* Called to parse extended advertising*/ -struct ble_ll_aux_data *ble_ll_scan_aux_data_ref(struct ble_ll_aux_data *aux_scan); -void ble_ll_scan_aux_data_unref(struct ble_ll_aux_data *aux_scan); -void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data); -#endif - -/* Called to halt currently running scan */ -void ble_ll_scan_halt(void); - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_LL_SCAN_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_sched.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_sched.h deleted file mode 100644 index a614cf090..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_sched.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_SCHED_ -#define H_BLE_LL_SCHED_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Time per BLE scheduler slot */ -#define BLE_LL_SCHED_USECS_PER_SLOT (1250) -#define BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT (41) /* 1 tick = 30.517 usecs */ - -/* - * Worst case time needed for scheduled advertising item. This is the longest - * possible time to receive a scan request and send a scan response (with the - * appropriate IFS time between them). This number is calculated using the - * following formula: IFS + SCAN_REQ + IFS + SCAN_RSP = 150 + 176 + 150 + 376. - * Note: worst case time to tx adv, rx scan req and send scan rsp is 1228 usecs. - * This assumes maximum sized advertising PDU and scan response PDU. - * - * For connectable advertising events no scan request is allowed. In this case - * we just need to receive a connect request PDU: IFS + CONNECT_REQ = 150 + 352. - * Note: worst-case is 376 + 150 + 352 = 878 usecs - * - * NOTE: The advertising PDU transmit time is NOT included here since we know - * how long that will take (worst-case is 376 usecs). - */ -#define BLE_LL_SCHED_ADV_MAX_USECS (852) -#define BLE_LL_SCHED_DIRECT_ADV_MAX_USECS (502) -#define BLE_LL_SCHED_MAX_ADV_PDU_USECS (376) - -/* - * This is the offset from the start of the scheduled item until the actual - * tx/rx should occur, in ticks. - */ -extern uint8_t g_ble_ll_sched_offset_ticks; - -/* - * This is the number of slots needed to transmit and receive a maximum - * size PDU, including an IFS time before each. The actual time is - * 2120 usecs for tx/rx and 150 for IFS = 4540 usecs. - */ -#define BLE_LL_SCHED_MAX_TXRX_SLOT (4 * BLE_LL_SCHED_USECS_PER_SLOT) - -/* BLE scheduler errors */ -#define BLE_LL_SCHED_ERR_OVERLAP (1) - -/* Types of scheduler events */ -#define BLE_LL_SCHED_TYPE_ADV (1) -#define BLE_LL_SCHED_TYPE_SCAN (2) -#define BLE_LL_SCHED_TYPE_CONN (3) -#define BLE_LL_SCHED_TYPE_AUX_SCAN (4) -#define BLE_LL_SCHED_TYPE_DTM (5) -#define BLE_LL_SCHED_TYPE_PERIODIC (6) -#define BLE_LL_SCHED_TYPE_SYNC (7) - -/* Return values for schedule callback. */ -#define BLE_LL_SCHED_STATE_RUNNING (0) -#define BLE_LL_SCHED_STATE_DONE (1) - -/* Callback function */ -struct ble_ll_sched_item; -typedef int (*sched_cb_func)(struct ble_ll_sched_item *sch); -typedef void (*sched_remove_cb_func)(struct ble_ll_sched_item *sch); -/* - * Strict connection scheduling (for the master) is different than how - * connections are normally scheduled. With strict connection scheduling we - * introduce the concept of a "period". A period is a collection of slots. Each - * slot is 1.25 msecs in length. The number of slots in a period is determined - * by the syscfg value BLE_LL_CONN_INIT_SLOTS. A collection of periods is called - * an epoch. The length of an epoch is determined by the number of connections - * (BLE_MAX_CONNECTIONS plus BLE_LL_ADD_STRICT_SCHED_PERIODS). Connections - * will be scheduled at period boundaries. Any scanning/initiating/advertising - * will be done in unused periods, if possible. - */ -#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) -#define BLE_LL_SCHED_PERIODS (MYNEWT_VAL(BLE_MAX_CONNECTIONS) + \ - MYNEWT_VAL(BLE_LL_ADD_STRICT_SCHED_PERIODS)) - -struct ble_ll_sched_obj -{ - uint8_t sch_num_occ_periods; - uint32_t sch_occ_period_mask; - uint32_t sch_ticks_per_period; - uint32_t sch_ticks_per_epoch; - uint32_t sch_epoch_start; -}; - -extern struct ble_ll_sched_obj g_ble_ll_sched_data; - -/* - * XXX: TODO: - * -> How do we know epoch start is up to date? Not wrapped? - * -> for now, only do this with no more than 32 connections. - * -> Do not let initiating occur if no empty sched slots - */ -#endif - -/* - * Schedule item - * sched_type: This is the type of the schedule item. - * enqueued: Flag denoting if item is on the scheduler list. 0: no, 1:yes - * remainder: # of usecs from offset till tx/rx should occur - * txrx_offset: Number of ticks from start time until tx/rx should occur. - * - */ -struct ble_ll_sched_item -{ - uint8_t sched_type; - uint8_t enqueued; - uint8_t remainder; - uint32_t start_time; - uint32_t end_time; - void *cb_arg; - sched_cb_func sched_cb; - TAILQ_ENTRY(ble_ll_sched_item) link; -}; - -/* Initialize the scheduler */ -int ble_ll_sched_init(void); - -/* Remove item(s) from schedule */ -int ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch); - -void ble_ll_sched_rmv_elem_type(uint8_t type, sched_remove_cb_func remove_cb); - -/* Schedule a new master connection */ -struct ble_ll_conn_sm; -int ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, - struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len); - -/* Schedule a new slave connection */ -int ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm); - -struct ble_ll_adv_sm; -typedef void ble_ll_sched_adv_new_cb(struct ble_ll_adv_sm *advsm, - uint32_t sch_start, void *arg); - -/* Schedule a new advertising event */ -int ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, - ble_ll_sched_adv_new_cb cb, void *arg); - -/* Schedule periodic advertising event */ -int ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, uint32_t *start, - bool after_overlap); - -int ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch, - uint32_t anchor_point, - uint8_t anchor_point_usecs, - uint32_t window_widening, int8_t phy_mode); -int ble_ll_sched_sync(struct ble_ll_sched_item *sch, - uint32_t beg_cputime, uint32_t rem_usecs, uint32_t offset, - int8_t phy_mode); - -/* Reschedule an advertising event */ -int ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start, - uint32_t max_delay_ticks); - -/* Reschedule and advertising pdu */ -int ble_ll_sched_adv_resched_pdu(struct ble_ll_sched_item *sch); - -/* Reschedule a connection that had previously been scheduled or that is over */ -int ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm * connsm); - -/** - * Called to determine when the next scheduled event will occur. - * - * If there are not scheduled events this function returns 0; otherwise it - * returns 1 and *next_event_time is set to the start time of the next event. - * - * @param next_event_time cputime at which next scheduled event will occur - * - * @return int 0: No events are scheduled 1: there is an upcoming event - */ -int ble_ll_sched_next_time(uint32_t *next_event_time); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -struct ble_ll_scan_sm; -struct ble_ll_aux_data; -int ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr, - struct ble_ll_scan_sm *scansm, - struct ble_ll_aux_data *aux_scan); - -int ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode); -#endif - -/* Stop the scheduler */ -void ble_ll_sched_stop(void); - -#if MYNEWT_VAL(BLE_LL_DTM) -int ble_ll_sched_dtm(struct ble_ll_sched_item *sch); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* H_LL_SCHED_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_sync.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_sync.h deleted file mode 100644 index 96c52a92a..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_sync.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_SYNC_ -#define H_BLE_LL_SYNC_ - -#include - -#include "nimble/nimble/include/nimble/ble.h" -#include "ble_ll_hci.h" -#include "ble_ll_conn.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct ble_ll_sync_sm; - -int ble_ll_sync_create(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_sync_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb); -int ble_ll_sync_terminate(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_sync_list_add(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_sync_list_remove(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_sync_list_clear(void); -int ble_ll_sync_list_size(uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_sync_receive_enable(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_sync_transfer(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen); - -void ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, - const uint8_t *sync_ind, bool reports_disabled, - uint16_t max_skip, uint32_t sync_timeout); -void ble_ll_sync_transfer_disconnected(struct ble_ll_conn_sm *connsm); - -void ble_ll_sync_info_event(const uint8_t *addr, uint8_t addr_type, - int rpa_index, uint8_t sid, - struct ble_mbuf_hdr *rxhdr, - const uint8_t *syncinfo); - -int ble_ll_sync_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr); -int ble_ll_sync_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr); -void ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr); -void ble_ll_sync_wfr_timer_exp(void); -void ble_ll_sync_halt(void); -void ble_ll_sync_rmvd_from_sched(struct ble_ll_sync_sm *sm); - -uint32_t ble_ll_sync_get_event_end_time(void); - -bool ble_ll_sync_enabled(void); - -void ble_ll_sync_reset(void); -void ble_ll_sync_init(void); - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_LL_SYNC_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_trace.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_trace.h deleted file mode 100644 index f0af4de50..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_trace.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_TRACE_ -#define H_BLE_LL_TRACE_ - -#include "nimble/porting/nimble/include/os/os_trace_api.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define BLE_LL_TRACE_ID_SCHED 0 -#define BLE_LL_TRACE_ID_RX_START 1 -#define BLE_LL_TRACE_ID_RX_END 2 -#define BLE_LL_TRACE_ID_WFR_EXP 3 -#define BLE_LL_TRACE_ID_CTRL_RX 4 -#define BLE_LL_TRACE_ID_CONN_EV_START 5 -#define BLE_LL_TRACE_ID_CONN_EV_END 6 -#define BLE_LL_TRACE_ID_CONN_END 7 -#define BLE_LL_TRACE_ID_CONN_TX 8 -#define BLE_LL_TRACE_ID_CONN_RX 9 -#define BLE_LL_TRACE_ID_ADV_TXDONE 10 -#define BLE_LL_TRACE_ID_ADV_HALT 11 -#define BLE_LL_TRACE_ID_AUX_REF 12 -#define BLE_LL_TRACE_ID_AUX_UNREF 13 - -#if MYNEWT_VAL(BLE_LL_SYSVIEW) - -extern uint32_t ble_ll_trace_off; - -void ble_ll_trace_init(void); - -static inline void -ble_ll_trace_u32(unsigned id, uint32_t p1) -{ - os_trace_api_u32(ble_ll_trace_off + id, p1); -} - -static inline void -ble_ll_trace_u32x2(unsigned id, uint32_t p1, uint32_t p2) -{ - os_trace_api_u32x2(ble_ll_trace_off + id, p1, p2); -} - -static inline void -ble_ll_trace_u32x3(unsigned id, uint32_t p1, uint32_t p2, uint32_t p3) -{ - os_trace_api_u32x3(ble_ll_trace_off + id, p1, p2, p3); -} - -#else - -static inline void -ble_ll_trace_init(void) -{ -} - -static inline void -ble_ll_trace_u32(unsigned id, uint32_t p1) -{ -} - -static inline void -ble_ll_trace_u32x2(unsigned id, uint32_t p1, uint32_t p2) -{ -} - -static inline void -ble_ll_trace_u32x3(unsigned id, uint32_t p1, uint32_t p2, uint32_t p3) -{ -} - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_LL_TRACE_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_whitelist.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_whitelist.h deleted file mode 100644 index 2d3b6c5dd..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_whitelist.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_WHITELIST_ -#define H_BLE_LL_WHITELIST_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Clear the whitelist */ -int ble_ll_whitelist_clear(void); - -/* Read the size of the whitelist */ -int ble_ll_whitelist_read_size(uint8_t *rspbuf, uint8_t *rsplen); - -/* Add a device to the whitelist */ -int ble_ll_whitelist_add(const uint8_t *cmdbuf, uint8_t len); - -/* Remove a device fromthe whitelist */ -int ble_ll_whitelist_rmv(const uint8_t *cmdbuf, uint8_t len); - -/* Enable whitelisting */ -void ble_ll_whitelist_enable(void); - -/* Disable whitelisting */ -void ble_ll_whitelist_disable(void); - -/* Boolean function returning true if address matches a whitelist entry */ -int ble_ll_whitelist_match(uint8_t *addr, uint8_t addr_type, int is_ident); - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_LL_WHITELIST_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy.h deleted file mode 100644 index 8a6fd174e..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy.h +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_PHY_ -#define H_BLE_PHY_ - -#include "nimble/nimble/include/nimble/hci_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Forward declarations */ -struct os_mbuf; - -/* Channel/Frequency defintions */ -#define BLE_PHY_NUM_CHANS (40) -#define BLE_PHY_NUM_DATA_CHANS (37) -#define BLE_PHY_CHAN0_FREQ_MHZ (2402) -#define BLE_PHY_DATA_CHAN0_FREQ_MHZ (2404) -#define BLE_PHY_CHAN_SPACING_MHZ (2) -#define BLE_PHY_NUM_ADV_CHANS (3) -#define BLE_PHY_ADV_CHAN_START (37) - -/* Power */ -#define BLE_PHY_MAX_PWR_DBM (10) - -/* Deviation */ -#define BLE_PHY_DEV_KHZ (185) -#define BLE_PHY_BINARY_ZERO (-BLE_PHY_DEV) -#define BLE_PHY_BINARY_ONE (BLE_PHY_DEV) - -/* Max. clock drift */ -#define BLE_PHY_MAX_DRIFT_PPM (50) - -/* Data rate */ -#define BLE_PHY_BIT_RATE_BPS (1000000) - -/* Macros */ -#define BLE_IS_ADV_CHAN(chan) (chan >= BLE_PHY_ADV_CHAN_START) -#define BLE_IS_DATA_CHAN(chan) (chan < BLE_PHY_ADV_CHAN_START) - -/* PHY states */ -#define BLE_PHY_STATE_IDLE (0) -#define BLE_PHY_STATE_RX (1) -#define BLE_PHY_STATE_TX (2) - -/* BLE PHY transitions */ -#define BLE_PHY_TRANSITION_NONE (0) -#define BLE_PHY_TRANSITION_RX_TX (1) -#define BLE_PHY_TRANSITION_TX_RX (2) - -/* PHY error codes */ -#define BLE_PHY_ERR_RADIO_STATE (1) -#define BLE_PHY_ERR_INIT (2) -#define BLE_PHY_ERR_INV_PARAM (3) -#define BLE_PHY_ERR_NO_BUFS (4) -#define BLE_PHY_ERR_TX_LATE (5) -#define BLE_PHY_ERR_RX_LATE (6) - -/* Maximun PDU length. Includes LL header of 2 bytes and 255 bytes payload. */ -#define BLE_PHY_MAX_PDU_LEN (257) - -/* Wait for response timer */ -typedef void (*ble_phy_tx_end_func)(void *arg); - -/* Initialize the PHY */ -int ble_phy_init(void); - -/* Reset the PHY */ -int ble_phy_reset(void); - -/* Set the PHY channel */ -int ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit); - -/* Set transmit start time */ -int ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs); - -/* Set receive start time */ -int ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs); - -/* Set the transmit end callback and argument */ -void ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg); - -typedef uint8_t (*ble_phy_tx_pducb_t)(uint8_t *dptr, void *pducb_arg, - uint8_t *hdr_byte); - -/* Place the PHY into transmit mode */ -int ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans); - -/* Place the PHY into receive mode */ -int ble_phy_rx(void); - -/* Copies the received PHY buffer into the allocated pdu */ -void ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu); - -/* Set the transmit power */ -int ble_phy_txpwr_set(int dbm); - -/* Get highest allowed power from range */ -int ble_phy_txpower_round(int dbm); - -/* Get the transmit power */ -int ble_phy_txpwr_get(void); - -/* Set RX path power compensation value rounded to integer dB */ -void ble_phy_set_rx_pwr_compensation(int8_t compensation); - -/* Disable the PHY */ -void ble_phy_disable(void); - -#define BLE_PHY_WFR_ENABLE_RX (0) -#define BLE_PHY_WFR_ENABLE_TXRX (1) - -void ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs); - -/* Starts rf clock */ -void ble_phy_rfclk_enable(void); - -/* Stops rf clock */ -void ble_phy_rfclk_disable(void); - -/* - * Used to restart reception on same channel after wfr timer expiration or - * frame received. - */ -void ble_phy_restart_rx(void); - -/* Gets the current state of the PHY */ -int ble_phy_state_get(void); - -/* Gets current state of transceiver */ -uint8_t ble_phy_xcvr_state_get(void); - -/* Returns 'true' if a reception has started */ -int ble_phy_rx_started(void); - -/* - * Returns the maximum supported tx/rx PDU payload size, in bytes, for data - * channel PDUs (this does not apply to advertising channel PDUs). Note - * that the data channel PDU is composed of a 2-byte header, the payload, and - * an optional MIC. The maximum payload is 251 bytes. - */ -uint8_t ble_phy_max_data_pdu_pyld(void); - -/* Gets the current access address */ -uint32_t ble_phy_access_addr_get(void); - -/* Enable encryption */ -void ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, - uint8_t is_master); - -/* Disable encryption */ -void ble_phy_encrypt_disable(void); - -/* Set the packet counters and dir used by LE encyption */ -void ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir); - -/* Enable phy resolving list */ -void ble_phy_resolv_list_enable(void); - -/* Disable phy resolving list */ -void ble_phy_resolv_list_disable(void); - -/* - * PHY mode values for 1M, 2M and Coded S=8 are the same as corresponding values - * of PHY. This makes conversion between 'phy' and 'phy_mode' easier and it also - * means that default coding for Coded will be S=8, unless explicitly translated - * to S=2. - */ -#define BLE_PHY_MODE_CODED_500KBPS (0) -#define BLE_PHY_MODE_1M (1) -#define BLE_PHY_MODE_2M (2) -#define BLE_PHY_MODE_CODED_125KBPS (3) - -/* The number of different modes */ -#define BLE_PHY_NUM_MODE (4) - -/* PHY numbers (compatible with HCI) */ -#define BLE_PHY_1M (BLE_HCI_LE_PHY_1M) -#define BLE_PHY_2M (BLE_HCI_LE_PHY_2M) -#define BLE_PHY_CODED (BLE_HCI_LE_PHY_CODED) - -/* PHY bitmasks (compatible with HCI) */ -#define BLE_PHY_MASK_1M (BLE_HCI_LE_PHY_1M_PREF_MASK) -#define BLE_PHY_MASK_2M (BLE_HCI_LE_PHY_2M_PREF_MASK) -#define BLE_PHY_MASK_CODED (BLE_HCI_LE_PHY_CODED_PREF_MASK) - -#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)) -uint32_t ble_phy_mode_pdu_start_off(int phy); -void ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode); -#else -#define ble_phy_mode_pdu_start_off(phy) (40) - -#endif - -int ble_phy_get_cur_phy(void); -static inline int ble_ll_phy_to_phy_mode(int phy, int phy_options) -{ - int phy_mode; - - /* - * 'phy' value can be used as 'phy_mode' value unless S=2 coding is explicitly - * required. By default we'll use S=2 for Coded. - */ - phy_mode = phy; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - if (phy == BLE_PHY_CODED && phy_options == BLE_HCI_LE_PHY_CODED_S2_PREF) { - phy_mode = BLE_PHY_MODE_CODED_500KBPS; - } -#endif - - return phy_mode; -} - -#if MYNEWT_VAL(BLE_LL_DTM) -void ble_phy_enable_dtm(void); -void ble_phy_disable_dtm(void); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_PHY_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy_trace.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy_trace.h deleted file mode 100644 index c0dca7a0f..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy_trace.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_PHY_TRACE_ -#define H_BLE_PHY_TRACE_ - -#include "nimble/porting/nimble/include/os/os_trace_api.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define BLE_PHY_TRACE_ID_START_TX 0 -#define BLE_PHY_TRACE_ID_START_RX 1 -#define BLE_PHY_TRACE_ID_DISABLE 2 - -#if MYNEWT_VAL(BLE_PHY_SYSVIEW) - -extern uint32_t ble_phy_trace_off; - -void ble_phy_trace_init(void); - -static inline void -ble_phy_trace_void(unsigned id) -{ - os_trace_api_void(ble_phy_trace_off + id); -} - -static inline void -ble_phy_trace_u32(unsigned id, uint32_t p1) -{ - os_trace_api_u32(ble_phy_trace_off + id, p1); -} - -static inline void -ble_phy_trace_u32x2(unsigned id, uint32_t p1, uint32_t p2) -{ - os_trace_api_u32x2(ble_phy_trace_off + id, p1, p2); -} - -static inline void -ble_phy_trace_u32x3(unsigned id, uint32_t p1, uint32_t p2, uint32_t p3) -{ - os_trace_api_u32x3(ble_phy_trace_off + id, p1, p2, p3); -} - -#else - -static inline void -ble_phy_trace_init(void) -{ -} - -static inline void -ble_phy_trace_void(unsigned id) -{ -} - -static inline void -ble_phy_trace_u32(unsigned id, uint32_t p1) -{ -} - -static inline void -ble_phy_trace_u32x2(unsigned id, uint32_t p1, uint32_t p2) -{ -} - -static inline void -ble_phy_trace_u32x3(unsigned id, uint32_t p1, uint32_t p2, uint32_t p3) -{ -} - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_PHY_TRACE_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/pkg.yml deleted file mode 100644 index 96c636798..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/pkg.yml +++ /dev/null @@ -1,38 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/controller -pkg.description: Controller side of the nimble Bluetooth Smart stack. -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - -pkg.req_apis: - - ble_driver - - ble_transport - - stats - -pkg.deps: - - "@apache-mynewt-core/kernel/os" - - nimble - -pkg.init: - ble_ll_init: 'MYNEWT_VAL(BLE_LL_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll.c deleted file mode 100644 index 6a2ca63b9..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll.c +++ /dev/null @@ -1,1720 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include -#include -#include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/porting/nimble/include/os/os_cputime.h" -#include "nimble/porting/nimble/include/stats/stats.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "nimble/nimble/include/nimble/ble_hci_trans.h" -#include "../include/controller/ble_hw.h" -#include "../include/controller/ble_phy.h" -#include "../include/controller/ble_phy_trace.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_whitelist.h" -#include "../include/controller/ble_ll_resolv.h" -#include "../include/controller/ble_ll_rfmgmt.h" -#include "../include/controller/ble_ll_trace.h" -#include "../include/controller/ble_ll_sync.h" -#include "ble_ll_conn_priv.h" - -#if MYNEWT_VAL(BLE_LL_DTM) -#include "ble_ll_dtm_priv.h" -#endif - -/* XXX: - * - * 1) use the sanity task! - * 2) Need to figure out what to do with packets that we hand up that did - * not pass the filter policy for the given state. Currently I count all - * packets I think. Need to figure out what to do with this. - * 3) For the features defined, we need to conditionally compile code. - * 4) Should look into always disabled the wfr interrupt if we receive the - * start of a frame. Need to look at the various states to see if this is the - * right thing to do. - */ - -/* Supported states */ -#define BLE_LL_S_NCA (0x00000000001) -#define BLE_LL_S_SA (0x00000000002) -#define BLE_LL_S_CA (0x00000000004) -#define BLE_LL_S_HDCA (0x00000000008) -#define BLE_LL_S_PS (0x00000000010) -#define BLE_LL_S_AS (0x00000000020) -#define BLE_LL_S_INIT (0x00000000040) -#define BLE_LL_S_SLAVE (0x00000000080) -#define BLE_LL_S_NCA_PS (0x00000000100) -#define BLE_LL_S_SA_PS (0x00000000200) -#define BLE_LL_S_CA_PS (0x00000000400) -#define BLE_LL_S_HDCA_PS (0x00000000800) -#define BLE_LL_S_NCA_AS (0x00000001000) -#define BLE_LL_S_SA_AS (0x00000002000) -#define BLE_LL_S_CA_AS (0x00000004000) -#define BLE_LL_S_HDCA_AS (0x00000008000) -#define BLE_LL_S_NCA_INIT (0x00000010000) -#define BLE_LL_S_SA_INIT (0x00000020000) -#define BLE_LL_S_NCA_MASTER (0x00000040000) -#define BLE_LL_S_SA_MASTER (0x00000080000) -#define BLE_LL_S_NCA_SLAVE (0x00000100000) -#define BLE_LL_S_SA_SLAVE (0x00000200000) -#define BLE_LL_S_PS_INIT (0x00000400000) -#define BLE_LL_S_AS_INIT (0x00000800000) -#define BLE_LL_S_PS_MASTER (0x00001000000) -#define BLE_LL_S_AS_MASTER (0x00002000000) -#define BLE_LL_S_PS_SLAVE (0x00004000000) -#define BLE_LL_S_AS_SLAVE (0x00008000000) -#define BLE_LL_S_INIT_MASTER (0x00010000000) -#define BLE_LL_S_LDCA (0x00020000000) -#define BLE_LL_S_LDCA_PS (0x00040000000) -#define BLE_LL_S_LDCA_AS (0x00080000000) -#define BLE_LL_S_CA_INIT (0x00100000000) -#define BLE_LL_S_HDCA_INIT (0x00200000000) -#define BLE_LL_S_LDCA_INIT (0x00400000000) -#define BLE_LL_S_CA_MASTER (0x00800000000) -#define BLE_LL_S_HDCA_MASTER (0x01000000000) -#define BLE_LL_S_LDCA_MASTER (0x02000000000) -#define BLE_LL_S_CA_SLAVE (0x04000000000) -#define BLE_LL_S_HDCA_SLAVE (0x08000000000) -#define BLE_LL_S_LDCA_SLAVE (0x10000000000) -#define BLE_LL_S_INIT_SLAVE (0x20000000000) - -#define BLE_LL_SUPPORTED_STATES \ -( \ - BLE_LL_S_NCA | \ - BLE_LL_S_SA | \ - BLE_LL_S_CA | \ - BLE_LL_S_HDCA | \ - BLE_LL_S_PS | \ - BLE_LL_S_AS | \ - BLE_LL_S_INIT | \ - BLE_LL_S_SLAVE | \ - BLE_LL_S_NCA_PS | \ - BLE_LL_S_SA_PS | \ - BLE_LL_S_CA_PS | \ - BLE_LL_S_HDCA_PS | \ - BLE_LL_S_NCA_AS | \ - BLE_LL_S_SA_AS | \ - BLE_LL_S_CA_AS | \ - BLE_LL_S_HDCA_AS | \ - BLE_LL_S_NCA_INIT | \ - BLE_LL_S_SA_INIT | \ - BLE_LL_S_NCA_MASTER | \ - BLE_LL_S_SA_MASTER | \ - BLE_LL_S_NCA_SLAVE | \ - BLE_LL_S_SA_SLAVE | \ - BLE_LL_S_PS_INIT | \ - BLE_LL_S_AS_INIT | \ - BLE_LL_S_PS_MASTER | \ - BLE_LL_S_AS_MASTER | \ - BLE_LL_S_PS_SLAVE | \ - BLE_LL_S_AS_SLAVE | \ - BLE_LL_S_INIT_MASTER | \ - BLE_LL_S_LDCA | \ - BLE_LL_S_LDCA_PS | \ - BLE_LL_S_LDCA_AS | \ - BLE_LL_S_CA_INIT | \ - BLE_LL_S_HDCA_INIT | \ - BLE_LL_S_LDCA_INIT | \ - BLE_LL_S_CA_MASTER | \ - BLE_LL_S_HDCA_MASTER | \ - BLE_LL_S_LDCA_MASTER | \ - BLE_LL_S_CA_SLAVE | \ - BLE_LL_S_HDCA_SLAVE | \ - BLE_LL_S_LDCA_SLAVE | \ - BLE_LL_S_INIT_SLAVE) - -/* The global BLE LL data object */ -struct ble_ll_obj g_ble_ll_data; - -/* Global link layer statistics */ -STATS_SECT_DECL(ble_ll_stats) ble_ll_stats; -STATS_NAME_START(ble_ll_stats) - STATS_NAME(ble_ll_stats, hci_cmds) - STATS_NAME(ble_ll_stats, hci_cmd_errs) - STATS_NAME(ble_ll_stats, hci_events_sent) - STATS_NAME(ble_ll_stats, bad_ll_state) - STATS_NAME(ble_ll_stats, bad_acl_hdr) - STATS_NAME(ble_ll_stats, no_bufs) - STATS_NAME(ble_ll_stats, rx_adv_pdu_crc_ok) - STATS_NAME(ble_ll_stats, rx_adv_pdu_crc_err) - STATS_NAME(ble_ll_stats, rx_adv_bytes_crc_ok) - STATS_NAME(ble_ll_stats, rx_adv_bytes_crc_err) - STATS_NAME(ble_ll_stats, rx_data_pdu_crc_ok) - STATS_NAME(ble_ll_stats, rx_data_pdu_crc_err) - STATS_NAME(ble_ll_stats, rx_data_bytes_crc_ok) - STATS_NAME(ble_ll_stats, rx_data_bytes_crc_err) - STATS_NAME(ble_ll_stats, rx_adv_malformed_pkts) - STATS_NAME(ble_ll_stats, rx_adv_ind) - STATS_NAME(ble_ll_stats, rx_adv_direct_ind) - STATS_NAME(ble_ll_stats, rx_adv_nonconn_ind) - STATS_NAME(ble_ll_stats, rx_adv_ext_ind) - STATS_NAME(ble_ll_stats, rx_scan_reqs) - STATS_NAME(ble_ll_stats, rx_scan_rsps) - STATS_NAME(ble_ll_stats, rx_connect_reqs) - STATS_NAME(ble_ll_stats, rx_scan_ind) - STATS_NAME(ble_ll_stats, rx_aux_connect_rsp) - STATS_NAME(ble_ll_stats, adv_txg) - STATS_NAME(ble_ll_stats, adv_late_starts) - STATS_NAME(ble_ll_stats, adv_resched_pdu_fail) - STATS_NAME(ble_ll_stats, adv_drop_event) - STATS_NAME(ble_ll_stats, sched_state_conn_errs) - STATS_NAME(ble_ll_stats, sched_state_adv_errs) - STATS_NAME(ble_ll_stats, scan_starts) - STATS_NAME(ble_ll_stats, scan_stops) - STATS_NAME(ble_ll_stats, scan_req_txf) - STATS_NAME(ble_ll_stats, scan_req_txg) - STATS_NAME(ble_ll_stats, scan_rsp_txg) - STATS_NAME(ble_ll_stats, aux_missed_adv) - STATS_NAME(ble_ll_stats, aux_scheduled) - STATS_NAME(ble_ll_stats, aux_received) - STATS_NAME(ble_ll_stats, aux_fired_for_read) - STATS_NAME(ble_ll_stats, aux_allocated) - STATS_NAME(ble_ll_stats, aux_freed) - STATS_NAME(ble_ll_stats, aux_sched_cb) - STATS_NAME(ble_ll_stats, aux_conn_req_tx) - STATS_NAME(ble_ll_stats, aux_conn_rsp_tx) - STATS_NAME(ble_ll_stats, aux_conn_rsp_err) - STATS_NAME(ble_ll_stats, aux_scan_req_tx) - STATS_NAME(ble_ll_stats, aux_scan_rsp_err) - STATS_NAME(ble_ll_stats, aux_chain_cnt) - STATS_NAME(ble_ll_stats, aux_chain_err) - STATS_NAME(ble_ll_stats, aux_scan_drop) - STATS_NAME(ble_ll_stats, adv_evt_dropped) - STATS_NAME(ble_ll_stats, scan_timer_stopped) - STATS_NAME(ble_ll_stats, scan_timer_restarted) - STATS_NAME(ble_ll_stats, periodic_adv_drop_event) - STATS_NAME(ble_ll_stats, periodic_chain_drop_event) - STATS_NAME(ble_ll_stats, sync_event_failed) - STATS_NAME(ble_ll_stats, sync_received) - STATS_NAME(ble_ll_stats, sync_chain_failed) - STATS_NAME(ble_ll_stats, sync_missed_err) - STATS_NAME(ble_ll_stats, sync_crc_err) - STATS_NAME(ble_ll_stats, sync_rx_buf_err) - STATS_NAME(ble_ll_stats, sync_scheduled) - STATS_NAME(ble_ll_stats, sched_state_sync_errs) - STATS_NAME(ble_ll_stats, sched_invalid_pdu) -STATS_NAME_END(ble_ll_stats) - -static void ble_ll_event_rx_pkt(struct ble_npl_event *ev); -static void ble_ll_event_tx_pkt(struct ble_npl_event *ev); -static void ble_ll_event_dbuf_overflow(struct ble_npl_event *ev); - -#if MYNEWT - -/* The BLE LL task data structure */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#define BLE_LL_STACK_SIZE (120) -#else -#define BLE_LL_STACK_SIZE (90) -#endif - -struct os_task g_ble_ll_task; - -OS_TASK_STACK_DEFINE(g_ble_ll_stack, BLE_LL_STACK_SIZE); - -#endif /* MYNEWT */ - -/** Our global device address (public) */ -uint8_t g_dev_addr[BLE_DEV_ADDR_LEN]; - -/** Our random address */ -uint8_t g_random_addr[BLE_DEV_ADDR_LEN]; - -/** Our supported features which can be controller by the host */ -uint64_t g_ble_ll_supported_host_features = 0; - -static const uint16_t g_ble_ll_pdu_header_tx_time[BLE_PHY_NUM_MODE] = -{ - [BLE_PHY_MODE_1M] = - (BLE_LL_PREAMBLE_LEN + BLE_LL_ACC_ADDR_LEN + BLE_LL_CRC_LEN + - BLE_LL_PDU_HDR_LEN) << 3, - [BLE_PHY_MODE_2M] = - (BLE_LL_PREAMBLE_LEN * 2 + BLE_LL_ACC_ADDR_LEN + BLE_LL_CRC_LEN + - BLE_LL_PDU_HDR_LEN) << 2, - /* For Coded PHY we have exact TX times provided by specification: - * - Preamble, Access Address, CI, TERM1 (always coded as S=8) - * - PDU, CRC, TERM2 (coded as S=2 or S=8) - * (Vol 6, Part B, 2.2). - */ - [BLE_PHY_MODE_CODED_125KBPS] = - (80 + 256 + 16 + 24 + 8 * (BLE_LL_PDU_HDR_LEN * 8 + 24 + 3)), - [BLE_PHY_MODE_CODED_500KBPS] = - (80 + 256 + 16 + 24 + 2 * (BLE_LL_PDU_HDR_LEN * 8 + 24 + 3)), -}; - -/** - * Counts the number of advertising PDU's received, by type. For advertising - * PDU's that contain a destination address, we still count these packets even - * if they are not for us. - * - * @param pdu_type - */ -static void -ble_ll_count_rx_adv_pdus(uint8_t pdu_type) -{ - /* Count received packet types */ - switch (pdu_type) { - case BLE_ADV_PDU_TYPE_ADV_EXT_IND: - STATS_INC(ble_ll_stats, rx_adv_ext_ind); - break; - case BLE_ADV_PDU_TYPE_ADV_IND: - STATS_INC(ble_ll_stats, rx_adv_ind); - break; - case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND: - STATS_INC(ble_ll_stats, rx_adv_direct_ind); - break; - case BLE_ADV_PDU_TYPE_ADV_NONCONN_IND: - STATS_INC(ble_ll_stats, rx_adv_nonconn_ind); - break; - case BLE_ADV_PDU_TYPE_SCAN_REQ: - STATS_INC(ble_ll_stats, rx_scan_reqs); - break; - case BLE_ADV_PDU_TYPE_SCAN_RSP: - STATS_INC(ble_ll_stats, rx_scan_rsps); - break; - case BLE_ADV_PDU_TYPE_CONNECT_IND: - STATS_INC(ble_ll_stats, rx_connect_reqs); - break; - case BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP: - STATS_INC(ble_ll_stats, rx_aux_connect_rsp); - break; - case BLE_ADV_PDU_TYPE_ADV_SCAN_IND: - STATS_INC(ble_ll_stats, rx_scan_ind); - break; - default: - break; - } -} - -struct os_mbuf * -ble_ll_rxpdu_alloc(uint16_t len) -{ - struct os_mbuf *om_ret; - struct os_mbuf *om_next; - struct os_mbuf *om; - struct os_mbuf_pkthdr *pkthdr; - uint16_t databuf_len; - int rem_len; - - /* - * Make sure that data in mbuf are word-aligned with and without packet - * header. This is essential for proper and quick copying of received PDUs - * into mbufs. - */ - _Static_assert((offsetof(struct os_mbuf, om_data) & 3) == 0, - "Unaligned om_data"); - _Static_assert(((offsetof(struct os_mbuf, om_data) + - sizeof(struct os_mbuf_pkthdr) + - sizeof(struct ble_mbuf_hdr)) & 3) == 0, - "Unaligned data trailing packet header"); - - om_ret = os_msys_get_pkthdr(len, sizeof(struct ble_mbuf_hdr)); - if (!om_ret) { - goto rxpdu_alloc_fail; - } - - /* Set complete PDU length in packet header */ - pkthdr = OS_MBUF_PKTHDR(om_ret); - pkthdr->omp_len = len; - - rem_len = len; - - /* - * Calculate length of data in memory block. We assume length is rounded - * down to word size so PHY can do word-size aligned data copy to mbufs - * (except for last one) and leave remainder unused. - * - * Note that there likely won't be any remainder here since all pools have - * block size aligned to word size anyway. - */ - databuf_len = om_ret->om_omp->omp_databuf_len & ~3; - - /* - * First mbuf can store less data due to packet header. Also we reserve one - * word for leading space to prepend header when necessary (like for data - * PDU before handing over to HCI) - */ - om_ret->om_data += 4; - rem_len -= databuf_len - om_ret->om_pkthdr_len - 4; - - /* Allocate and chain mbufs until there's enough space to store complete PDU */ - om = om_ret; - while (rem_len > 0) { - om_next = os_msys_get(rem_len, 0); - if (!om_next) { - os_mbuf_free_chain(om_ret); - goto rxpdu_alloc_fail; - } - - SLIST_NEXT(om, om_next) = om_next; - om = om_next; - - rem_len -= databuf_len; - } - - return om_ret; - -rxpdu_alloc_fail: - STATS_INC(ble_ll_stats, no_bufs); - return NULL; -} - -int -ble_ll_chk_txrx_octets(uint16_t octets) -{ - int rc; - - if ((octets < BLE_LL_CONN_SUPP_BYTES_MIN) || - (octets > BLE_LL_CONN_SUPP_BYTES_MAX)) { - rc = 0; - } else { - rc = 1; - } - - return rc; -} - -int -ble_ll_chk_txrx_time(uint16_t time) -{ - int rc; - - if ((time < BLE_LL_CONN_SUPP_TIME_MIN) || - (time > BLE_LL_CONN_SUPP_TIME_MAX)) { - rc = 0; - } else { - rc = 1; - } - - return rc; -} - -/** - * Checks to see if the address is a resolvable private address. - * - * NOTE: the addr_type parameter will be 0 if the address is public; - * any other value is random (all non-zero values). - * - * @param addr - * @param addr_type Public (zero) or Random (non-zero) address - * - * @return int - */ -int -ble_ll_is_rpa(const uint8_t *addr, uint8_t addr_type) -{ - int rc; - - if (addr_type && ((addr[5] & 0xc0) == 0x40)) { - rc = 1; - } else { - rc = 0; - } - return rc; -} - -int -ble_ll_addr_is_id(uint8_t *addr, uint8_t addr_type) -{ - return !addr_type || ((addr[5] & 0xc0) == 0xc0); -} - -int -ble_ll_addr_subtype(const uint8_t *addr, uint8_t addr_type) -{ - if (!addr_type) { - return BLE_LL_ADDR_SUBTYPE_IDENTITY; - } - - switch (addr[5] >> 6) { - case 0: - return BLE_LL_ADDR_SUBTYPE_NRPA; /* NRPA */ - case 1: - return BLE_LL_ADDR_SUBTYPE_RPA; /* RPA */ - default: - return BLE_LL_ADDR_SUBTYPE_IDENTITY; /* static random */ - } -} - -int -ble_ll_is_valid_public_addr(const uint8_t *addr) -{ - int i; - - for (i = 0; i < BLE_DEV_ADDR_LEN; ++i) { - if (addr[i]) { - return 1; - } - } - - return 0; -} - -/* Checks to see that the device is a valid random address */ -int -ble_ll_is_valid_random_addr(const uint8_t *addr) -{ - int i; - int rc; - uint16_t sum; - uint8_t addr_type; - - /* Make sure all bits are neither one nor zero */ - sum = 0; - for (i = 0; i < (BLE_DEV_ADDR_LEN -1); ++i) { - sum += addr[i]; - } - sum += addr[5] & 0x3f; - - if ((sum == 0) || (sum == ((5*255) + 0x3f))) { - return 0; - } - - /* Get the upper two bits of the address */ - rc = 1; - addr_type = addr[5] & 0xc0; - if (addr_type == 0xc0) { - /* Static random address. No other checks needed */ - } else if (addr_type == 0x40) { - /* Resolvable */ - sum = addr[3] + addr[4] + (addr[5] & 0x3f); - if ((sum == 0) || (sum == (255 + 255 + 0x3f))) { - rc = 0; - } - } else if (addr_type == 0) { - /* non-resolvable. Cant be equal to public */ - if (!memcmp(g_dev_addr, addr, BLE_DEV_ADDR_LEN)) { - rc = 0; - } - } else { - /* Invalid upper two bits */ - rc = 0; - } - - return rc; -} -int -ble_ll_is_valid_own_addr_type(uint8_t own_addr_type, const uint8_t *random_addr) -{ - int rc; - - switch (own_addr_type) { - case BLE_HCI_ADV_OWN_ADDR_PUBLIC: -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - case BLE_HCI_ADV_OWN_ADDR_PRIV_PUB: -#endif - rc = ble_ll_is_valid_public_addr(g_dev_addr); - break; - case BLE_HCI_ADV_OWN_ADDR_RANDOM: -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - case BLE_HCI_ADV_OWN_ADDR_PRIV_RAND: -#endif - rc = ble_ll_is_valid_random_addr(random_addr); - break; - default: - rc = 0; - break; - } - - return rc; -} - -int -ble_ll_set_public_addr(const uint8_t *addr) -{ - memcpy(g_dev_addr, addr, BLE_DEV_ADDR_LEN); - - return BLE_ERR_SUCCESS; -} - -/** - * Called from the HCI command parser when the set random address command - * is received. - * - * Context: Link Layer task (HCI command parser) - * - * @param addr Pointer to address - * - * @return int 0: success - */ -int -ble_ll_set_random_addr(const uint8_t *cmdbuf, uint8_t len, bool hci_adv_ext) -{ - const struct ble_hci_le_set_rand_addr_cp *cmd = (const void *) cmdbuf; - - if (len < sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* If the Host issues this command when scanning or legacy advertising is - * enabled, the Controller shall return the error code Command Disallowed. - * - * Test specification extends this also to initiating. - */ - - if (g_ble_ll_conn_create_sm || ble_ll_scan_enabled() || - (!hci_adv_ext && ble_ll_adv_enabled())) { - return BLE_ERR_CMD_DISALLOWED; - } - - if (!ble_ll_is_valid_random_addr(cmd->addr)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - memcpy(g_random_addr, cmd->addr, BLE_DEV_ADDR_LEN); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* For instance 0 we need same address if legacy advertising might be - * used. If extended advertising is in use than this command doesn't - * affect instance 0. - */ - if (!hci_adv_ext) - ble_ll_adv_set_random_addr(cmd->addr, 0); -#endif - - return BLE_ERR_SUCCESS; -} - -/** - * Checks to see if an address is our device address (either public or - * random) - * - * @param addr - * @param addr_type - * - * @return int 0: not our device address. 1: is our device address - */ -int -ble_ll_is_our_devaddr(uint8_t *addr, int addr_type) -{ - int rc; - uint8_t *our_addr; - - if (addr_type) { - our_addr = g_random_addr; - } else { - our_addr = g_dev_addr; - } - - rc = 0; - if (!memcmp(our_addr, addr, BLE_DEV_ADDR_LEN)) { - rc = 1; - } - - return rc; -} - -/** - * Get identity address - * - * @param addr_type Random (1). Public(0) - * - * @return pointer to identity address of given type. - */ -uint8_t* -ble_ll_get_our_devaddr(uint8_t addr_type) -{ - if (addr_type) { - return g_random_addr; - } - - return g_dev_addr; -} - -/** - * Wait for response timeout function - * - * Context: interrupt (ble scheduler) - * - * @param arg - */ -void -ble_ll_wfr_timer_exp(void *arg) -{ - int rx_start; - uint8_t lls; - - rx_start = ble_phy_rx_started(); - lls = g_ble_ll_data.ll_state; - - ble_ll_trace_u32x3(BLE_LL_TRACE_ID_WFR_EXP, lls, ble_phy_xcvr_state_get(), - (uint32_t)rx_start); - - /* If we have started a reception, there is nothing to do here */ - if (!rx_start) { - switch (lls) { - case BLE_LL_STATE_ADV: - ble_ll_adv_wfr_timer_exp(); - break; - case BLE_LL_STATE_CONNECTION: - ble_ll_conn_wfr_timer_exp(); - break; - case BLE_LL_STATE_SCANNING: - ble_ll_scan_wfr_timer_exp(); - break; - case BLE_LL_STATE_INITIATING: - ble_ll_conn_init_wfr_timer_exp(); - break; -#if MYNEWT_VAL(BLE_LL_DTM) - case BLE_LL_STATE_DTM: - ble_ll_dtm_wfr_timer_exp(); - break; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - case BLE_LL_STATE_SYNC: - ble_ll_sync_wfr_timer_exp(); - break; -#endif - default: - break; - } - } -} - -/** - * ll tx pkt in proc - * - * Process ACL data packet input from host - * - * Context: Link layer task - * - */ -static void -ble_ll_tx_pkt_in(void) -{ - uint16_t handle; - uint16_t length; - uint16_t pb; - struct os_mbuf_pkthdr *pkthdr; - struct os_mbuf *om; - - /* Drain all packets off the queue */ - while (STAILQ_FIRST(&g_ble_ll_data.ll_tx_pkt_q)) { - /* Get mbuf pointer from packet header pointer */ - pkthdr = STAILQ_FIRST(&g_ble_ll_data.ll_tx_pkt_q); - om = (struct os_mbuf *)((uint8_t *)pkthdr - sizeof(struct os_mbuf)); - - /* Remove from queue */ - STAILQ_REMOVE_HEAD(&g_ble_ll_data.ll_tx_pkt_q, omp_next); - - /* Strip HCI ACL header to get handle and length */ - handle = get_le16(om->om_data); - length = get_le16(om->om_data + 2); - os_mbuf_adj(om, sizeof(struct hci_data_hdr)); - - /* Do some basic error checking */ - pb = handle & 0x3000; - if ((pkthdr->omp_len != length) || (pb > 0x1000) || (length == 0)) { - /* This is a bad ACL packet. Count a stat and free it */ - STATS_INC(ble_ll_stats, bad_acl_hdr); - os_mbuf_free_chain(om); - continue; - } - - /* Hand to connection state machine */ - ble_ll_conn_tx_pkt_in(om, handle, length); - } -} - -/** - * Count Link Layer statistics for received PDUs - * - * Context: Link layer task - * - * @param hdr - * @param len - */ -static void -ble_ll_count_rx_stats(struct ble_mbuf_hdr *hdr, uint16_t len, uint8_t pdu_type) -{ - uint8_t crcok; - bool connection_data; - - crcok = BLE_MBUF_HDR_CRC_OK(hdr); - connection_data = (BLE_MBUF_HDR_RX_STATE(hdr) == BLE_LL_STATE_CONNECTION); - -#if MYNEWT_VAL(BLE_LL_DTM) - /* Reuse connection stats for DTM */ - if (!connection_data) { - connection_data = (BLE_MBUF_HDR_RX_STATE(hdr) == BLE_LL_STATE_DTM); - } -#endif - - if (crcok) { - if (connection_data) { - STATS_INC(ble_ll_stats, rx_data_pdu_crc_ok); - STATS_INCN(ble_ll_stats, rx_data_bytes_crc_ok, len); - } else { - STATS_INC(ble_ll_stats, rx_adv_pdu_crc_ok); - STATS_INCN(ble_ll_stats, rx_adv_bytes_crc_ok, len); - ble_ll_count_rx_adv_pdus(pdu_type); - } - } else { - if (connection_data) { - STATS_INC(ble_ll_stats, rx_data_pdu_crc_err); - STATS_INCN(ble_ll_stats, rx_data_bytes_crc_err, len); - } else { - STATS_INC(ble_ll_stats, rx_adv_pdu_crc_err); - STATS_INCN(ble_ll_stats, rx_adv_bytes_crc_err, len); - } - } -} - -/** - * ll rx pkt in - * - * Process received packet from PHY. - * - * Context: Link layer task - * - */ -static void -ble_ll_rx_pkt_in(void) -{ - os_sr_t sr; - uint8_t pdu_type; - uint8_t *rxbuf; - struct os_mbuf_pkthdr *pkthdr; - struct ble_mbuf_hdr *ble_hdr; - struct os_mbuf *m; - - /* Drain all packets off the queue */ - while (STAILQ_FIRST(&g_ble_ll_data.ll_rx_pkt_q)) { - /* Get mbuf pointer from packet header pointer */ - pkthdr = STAILQ_FIRST(&g_ble_ll_data.ll_rx_pkt_q); - m = (struct os_mbuf *)((uint8_t *)pkthdr - sizeof(struct os_mbuf)); - - /* Remove from queue */ - OS_ENTER_CRITICAL(sr); - STAILQ_REMOVE_HEAD(&g_ble_ll_data.ll_rx_pkt_q, omp_next); - OS_EXIT_CRITICAL(sr); - - /* Note: pdu type wont get used unless this is an advertising pdu */ - ble_hdr = BLE_MBUF_HDR_PTR(m); - rxbuf = m->om_data; - pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK; - ble_ll_count_rx_stats(ble_hdr, pkthdr->omp_len, pdu_type); - - /* Process the data or advertising pdu */ - /* Process the PDU */ - switch (BLE_MBUF_HDR_RX_STATE(ble_hdr)) { - case BLE_LL_STATE_CONNECTION: - ble_ll_conn_rx_data_pdu(m, ble_hdr); - /* m is going to be free by function above */ - m = NULL; - break; - case BLE_LL_STATE_ADV: - ble_ll_adv_rx_pkt_in(pdu_type, rxbuf, ble_hdr); - break; - case BLE_LL_STATE_SCANNING: - ble_ll_scan_rx_pkt_in(pdu_type, m, ble_hdr); - break; - case BLE_LL_STATE_INITIATING: - ble_ll_init_rx_pkt_in(pdu_type, rxbuf, ble_hdr); - break; -#if MYNEWT_VAL(BLE_LL_DTM) - case BLE_LL_STATE_DTM: - ble_ll_dtm_rx_pkt_in(m, ble_hdr); - break; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - case BLE_LL_STATE_SYNC: - ble_ll_sync_rx_pkt_in(m, ble_hdr); - break; -#endif - default: - /* Any other state should never occur */ - STATS_INC(ble_ll_stats, bad_ll_state); - break; - } - if (m) { - /* Free the packet buffer */ - os_mbuf_free_chain(m); - } - } -} - -/** - * Called to put a packet on the Link Layer receive packet queue. - * - * @param rxpdu Pointer to received PDU - */ -void -ble_ll_rx_pdu_in(struct os_mbuf *rxpdu) -{ - struct os_mbuf_pkthdr *pkthdr; - - pkthdr = OS_MBUF_PKTHDR(rxpdu); - STAILQ_INSERT_TAIL(&g_ble_ll_data.ll_rx_pkt_q, pkthdr, omp_next); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_rx_pkt_ev); -} - -/** - * Called to put a packet on the Link Layer transmit packet queue. - * - * @param txpdu Pointer to transmit packet - */ -void -ble_ll_acl_data_in(struct os_mbuf *txpkt) -{ - os_sr_t sr; - struct os_mbuf_pkthdr *pkthdr; - - pkthdr = OS_MBUF_PKTHDR(txpkt); - OS_ENTER_CRITICAL(sr); - STAILQ_INSERT_TAIL(&g_ble_ll_data.ll_tx_pkt_q, pkthdr, omp_next); - OS_EXIT_CRITICAL(sr); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_tx_pkt_ev); -} - -/** - * Called to post event to Link Layer when a data buffer overflow has - * occurred. - * - * Context: Interrupt - * - */ -void -ble_ll_data_buffer_overflow(void) -{ - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_dbuf_overflow_ev); -} - -/** - * Called when a HW error occurs. - * - * Context: Interrupt - */ -void -ble_ll_hw_error(void) -{ - ble_npl_callout_reset(&g_ble_ll_data.ll_hw_err_timer, 0); -} - -/** - * Called when the HW error timer expires. - * - * @param arg - */ -static void -ble_ll_hw_err_timer_cb(struct ble_npl_event *ev) -{ - if (ble_ll_hci_ev_hw_err(BLE_HW_ERR_HCI_SYNC_LOSS)) { - /* - * Restart callout if failed to allocate event. Try to allocate an - * event every 50 milliseconds (or each OS tick if a tick is longer - * than 100 msecs). - */ - ble_npl_callout_reset(&g_ble_ll_data.ll_hw_err_timer, - ble_npl_time_ms_to_ticks32(50)); - } -} - -/** - * Called upon start of received PDU - * - * Context: Interrupt - * - * @param rxpdu - * chan - * - * @return int - * < 0: A frame we dont want to receive. - * = 0: Continue to receive frame. Dont go from rx to tx - * > 0: Continue to receive frame and go from rx to tx when done - */ -int -ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *rxhdr) -{ - int rc; - uint8_t pdu_type; - - /* Advertising channel PDU */ - pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK; - - ble_ll_trace_u32x2(BLE_LL_TRACE_ID_RX_START, g_ble_ll_data.ll_state, - pdu_type); - - switch (g_ble_ll_data.ll_state) { - case BLE_LL_STATE_CONNECTION: - rc = ble_ll_conn_rx_isr_start(rxhdr, ble_phy_access_addr_get()); - break; - case BLE_LL_STATE_ADV: - rc = ble_ll_adv_rx_isr_start(pdu_type); - break; - case BLE_LL_STATE_INITIATING: - rc = ble_ll_init_rx_isr_start(pdu_type, rxhdr); - break; - case BLE_LL_STATE_SCANNING: - rc = ble_ll_scan_rx_isr_start(pdu_type, &rxhdr->rxinfo.flags); - break; -#if MYNEWT_VAL(BLE_LL_DTM) - case BLE_LL_STATE_DTM: - rc = ble_ll_dtm_rx_isr_start(rxhdr, ble_phy_access_addr_get()); - break; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - case BLE_LL_STATE_SYNC: - rc = ble_ll_sync_rx_isr_start(pdu_type, rxhdr); - break; -#endif - default: - /* Should not be in this state! */ - rc = -1; - STATS_INC(ble_ll_stats, bad_ll_state); - break; - } - - return rc; -} - -/** - * Called by the PHY when a receive packet has ended. - * - * NOTE: Called from interrupt context! - * - * @param rxbuf Pointer to received PDU data - * rxhdr Pointer to BLE header of received mbuf - * - * @return int - * < 0: Disable the phy after reception. - * == 0: Success. Do not disable the PHY. - * > 0: Do not disable PHY as that has already been done. - */ -int -ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) -{ - int rc; - int badpkt; - uint8_t pdu_type; - uint8_t len; - uint8_t crcok; - struct os_mbuf *rxpdu; - - /* Get CRC status from BLE header */ - crcok = BLE_MBUF_HDR_CRC_OK(rxhdr); - - /* Get advertising PDU type and length */ - pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK; - len = rxbuf[1]; - - ble_ll_trace_u32x3(BLE_LL_TRACE_ID_RX_END, pdu_type, len, - rxhdr->rxinfo.flags); - -#if MYNEWT_VAL(BLE_LL_DTM) - if (BLE_MBUF_HDR_RX_STATE(rxhdr) == BLE_LL_STATE_DTM) { - rc = ble_ll_dtm_rx_isr_end(rxbuf, rxhdr); - return rc; - } -#endif - - if (BLE_MBUF_HDR_RX_STATE(rxhdr) == BLE_LL_STATE_CONNECTION) { - rc = ble_ll_conn_rx_isr_end(rxbuf, rxhdr); - return rc; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - if (BLE_MBUF_HDR_RX_STATE(rxhdr) == BLE_LL_STATE_SYNC) { - rc = ble_ll_sync_rx_isr_end(rxbuf, rxhdr); - return rc; - } -#endif - - /* If the CRC checks, make sure lengths check! */ - badpkt = 0; - if (crcok) { - switch (pdu_type) { - case BLE_ADV_PDU_TYPE_SCAN_REQ: - case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND: - if (len != BLE_SCAN_REQ_LEN) { - badpkt = 1; - } - break; - case BLE_ADV_PDU_TYPE_SCAN_RSP: - case BLE_ADV_PDU_TYPE_ADV_IND: - case BLE_ADV_PDU_TYPE_ADV_SCAN_IND: - case BLE_ADV_PDU_TYPE_ADV_NONCONN_IND: - if ((len < BLE_DEV_ADDR_LEN) || (len > BLE_ADV_SCAN_IND_MAX_LEN)) { - badpkt = 1; - } - break; - case BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP: - break; - case BLE_ADV_PDU_TYPE_ADV_EXT_IND: - break; - case BLE_ADV_PDU_TYPE_CONNECT_IND: - if (len != BLE_CONNECT_REQ_LEN) { - badpkt = 1; - } - break; - default: - badpkt = 1; - break; - } - - /* If this is a malformed packet, just kill it here */ - if (badpkt) { - STATS_INC(ble_ll_stats, rx_adv_malformed_pkts); - } - } - - /* Hand packet to the appropriate state machine (if crc ok) */ - rxpdu = NULL; - switch (BLE_MBUF_HDR_RX_STATE(rxhdr)) { - case BLE_LL_STATE_ADV: - if (!badpkt) { - rxpdu = ble_ll_rxpdu_alloc(len + BLE_LL_PDU_HDR_LEN); - if (rxpdu) { - ble_phy_rxpdu_copy(rxbuf, rxpdu); - } - } - rc = ble_ll_adv_rx_isr_end(pdu_type, rxpdu, crcok); - break; - case BLE_LL_STATE_SCANNING: - if (!badpkt) { - rxpdu = ble_ll_rxpdu_alloc(len + BLE_LL_PDU_HDR_LEN); - if (rxpdu) { - ble_phy_rxpdu_copy(rxbuf, rxpdu); - } - } - rc = ble_ll_scan_rx_isr_end(rxpdu, crcok); - break; - case BLE_LL_STATE_INITIATING: - rc = ble_ll_init_rx_isr_end(rxbuf, crcok, rxhdr); - break; - default: - rc = -1; - STATS_INC(ble_ll_stats, bad_ll_state); - break; - } - - /* Hand packet up to higher layer (regardless of CRC failure) */ - if (rxpdu) { - ble_ll_rx_pdu_in(rxpdu); - } - - return rc; -} - -uint8_t -ble_ll_tx_mbuf_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) -{ - struct os_mbuf *txpdu; - struct ble_mbuf_hdr *ble_hdr; - - txpdu = pducb_arg; - BLE_LL_ASSERT(txpdu); - ble_hdr = BLE_MBUF_HDR_PTR(txpdu); - - os_mbuf_copydata(txpdu, ble_hdr->txinfo.offset, ble_hdr->txinfo.pyld_len, - dptr); - - *hdr_byte = ble_hdr->txinfo.hdr_byte; - - return ble_hdr->txinfo.pyld_len; -} - -uint8_t -ble_ll_tx_flat_mbuf_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) -{ - struct os_mbuf *txpdu; - struct ble_mbuf_hdr *ble_hdr; - - txpdu = pducb_arg; - BLE_LL_ASSERT(txpdu); - ble_hdr = BLE_MBUF_HDR_PTR(txpdu); - - memcpy(dptr, txpdu->om_data, ble_hdr->txinfo.pyld_len); - - *hdr_byte = ble_hdr->txinfo.hdr_byte; - - return ble_hdr->txinfo.pyld_len; -} - -static void -ble_ll_event_rx_pkt(struct ble_npl_event *ev) -{ - ble_ll_rx_pkt_in(); -} - -static void -ble_ll_event_tx_pkt(struct ble_npl_event *ev) -{ - ble_ll_tx_pkt_in(); -} - -static void -ble_ll_event_dbuf_overflow(struct ble_npl_event *ev) -{ - ble_ll_hci_ev_databuf_overflow(); -} - -static void -ble_ll_event_comp_pkts(struct ble_npl_event *ev) -{ - ble_ll_conn_num_comp_pkts_event_send(NULL); -} - -/** - * Link Layer task. - * - * This is the task that runs the Link Layer. - * - * @param arg - */ -void -ble_ll_task(void *arg) -{ - struct ble_npl_event *ev; - - /* Init ble phy */ - ble_phy_init(); - - /* Set output power to 1mW (0 dBm) */ - ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM)); - - /* Register callback for transport */ - ble_hci_trans_cfg_ll(ble_ll_hci_cmd_rx, NULL, ble_ll_hci_acl_rx, NULL); - - /* Tell the host that we are ready to receive packets */ - ble_ll_hci_send_noop(); - - ble_ll_rand_start(); - - while (1) { - ev = ble_npl_eventq_get(&g_ble_ll_data.ll_evq, BLE_NPL_TIME_FOREVER); - assert(ev); - ble_npl_event_run(ev); - } -} - -/** - * ble ll state set - * - * Called to set the current link layer state. - * - * Context: Interrupt and Link Layer task - * - * @param ll_state - */ -void -ble_ll_state_set(uint8_t ll_state) -{ - g_ble_ll_data.ll_state = ll_state; -} - -/** - * ble ll state get - * - * Called to get the current link layer state. - * - * Context: Link Layer task (can be called from interrupt context though). - * - * @return ll_state - */ -uint8_t -ble_ll_state_get(void) -{ - return g_ble_ll_data.ll_state; -} - -/** - * ble ll event send - * - * Send an event to the Link Layer task - * - * @param ev Event to add to the Link Layer event queue. - */ -void -ble_ll_event_send(struct ble_npl_event *ev) -{ - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, ev); -} - -/** - * Returns the features supported by the link layer - * - * @return uint8_t bitmask of supported features. - */ -uint64_t -ble_ll_read_supp_states(void) -{ - return BLE_LL_SUPPORTED_STATES; -} - -/** - * Returns the features supported by the link layer - * - * @return uint64_t bitmask of supported features. - */ -uint64_t -ble_ll_read_supp_features(void) -{ - return g_ble_ll_data.ll_supp_features; -} - -/** - * Sets the features controlled by the host. - * - * @return HCI command status - */ -int -ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_host_feat_cp *cmd = (const void *) cmdbuf; - uint64_t mask; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (!SLIST_EMPTY(&g_ble_ll_conn_active_list)) { - return BLE_ERR_CMD_DISALLOWED; - } - - if ((cmd->bit_num > 0x3F) || (cmd->val > 1)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - mask = (uint64_t)1 << (cmd->bit_num); - if (!(mask & BLE_LL_HOST_CONTROLLED_FEATURES)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (!(mask & g_ble_ll_supported_host_features)) { - return BLE_ERR_UNSUPPORTED; - } - - if (cmd->val == 0) { - g_ble_ll_data.ll_supp_features &= ~(mask); - } else { - g_ble_ll_data.ll_supp_features |= mask; - } - - return BLE_ERR_SUCCESS; -} -/** - * Flush a link layer packet queue. - * - * @param pktq - */ -static void -ble_ll_flush_pkt_queue(struct ble_ll_pkt_q *pktq) -{ - struct os_mbuf_pkthdr *pkthdr; - struct os_mbuf *om; - - /* FLush all packets from Link layer queues */ - while (STAILQ_FIRST(pktq)) { - /* Get mbuf pointer from packet header pointer */ - pkthdr = STAILQ_FIRST(pktq); - om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); - - /* Remove from queue and free the mbuf */ - STAILQ_REMOVE_HEAD(pktq, omp_next); - os_mbuf_free_chain(om); - } -} - -/** - * Called to initialize a mbuf used by the controller - * - * NOTE: this is only used when the mbuf is created by the controller; - * it should not be used for data packets (ACL data packets) that come from - * the host. This routine assumes that the entire pdu length can fit in - * one mbuf contiguously. - * - * @param m - * @param pdulen - * @param hdr - */ -void -ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr) -{ - struct ble_mbuf_hdr *ble_hdr; - - /* Set mbuf length and packet length */ - m->om_len = pdulen; - OS_MBUF_PKTHDR(m)->omp_len = pdulen; - - /* Set BLE transmit header */ - ble_hdr = BLE_MBUF_HDR_PTR(m); - ble_hdr->txinfo.flags = 0; - ble_hdr->txinfo.offset = 0; - ble_hdr->txinfo.pyld_len = pdulen; - ble_hdr->txinfo.hdr_byte = hdr; -} - -/** - * Called to reset the controller. This performs a "software reset" of the link - * layer; it does not perform a HW reset of the controller nor does it reset - * the HCI interface. - * - * Context: Link Layer task (HCI command) - * - * @return int The ble error code to place in the command complete event that - * is returned when this command is issued. - */ -int -ble_ll_reset(void) -{ - int rc; - os_sr_t sr; - - OS_ENTER_CRITICAL(sr); - ble_phy_disable(); - ble_ll_sched_stop(); - ble_ll_scan_reset(); - ble_ll_rfmgmt_reset(); - OS_EXIT_CRITICAL(sr); - - /* Stop any advertising */ - ble_ll_adv_reset(); - -#if MYNEWT_VAL(BLE_LL_DTM) - ble_ll_dtm_reset(); -#endif - - /* Stop sync */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - ble_ll_sync_reset(); -#endif - - /* FLush all packets from Link layer queues */ - ble_ll_flush_pkt_queue(&g_ble_ll_data.ll_tx_pkt_q); - ble_ll_flush_pkt_queue(&g_ble_ll_data.ll_rx_pkt_q); - - /* Reset LL stats */ - STATS_RESET(ble_ll_stats); - - /* Reset any preferred PHYs */ - g_ble_ll_data.ll_pref_tx_phys = 0; - g_ble_ll_data.ll_pref_rx_phys = 0; - - /* Reset connection module */ - ble_ll_conn_module_reset(); - - /* All this does is re-initialize the event masks so call the hci init */ - ble_ll_hci_init(); - - /* Reset scheduler */ - ble_ll_sched_init(); - - /* Set state to standby */ - ble_ll_state_set(BLE_LL_STATE_STANDBY); - - /* Reset our random address */ - memset(g_random_addr, 0, BLE_DEV_ADDR_LEN); - - /* Clear the whitelist */ - ble_ll_whitelist_clear(); - - /* Reset resolving list */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - ble_ll_resolv_list_reset(); -#endif - - /* Re-initialize the PHY */ - rc = ble_phy_init(); - - return rc; -} - -static void -ble_ll_seed_prng(void) -{ - uint32_t seed; - int i; - - /* Seed random number generator with least significant bytes of device - * address. - */ - seed = 0; - for (i = 0; i < 4; ++i) { - seed |= g_dev_addr[i]; - seed <<= 8; - } - srand(seed); -} - -uint32_t -ble_ll_pdu_tx_time_get(uint16_t payload_len, int phy_mode) -{ - uint32_t usecs; - -#if (BLE_LL_BT5_PHY_SUPPORTED) - if (phy_mode == BLE_PHY_MODE_1M) { - /* 8 usecs per byte */ - usecs = payload_len << 3; - } else if (phy_mode == BLE_PHY_MODE_2M) { - /* 4 usecs per byte */ - usecs = payload_len << 2; - } else if (phy_mode == BLE_PHY_MODE_CODED_125KBPS) { - /* S=8 => 8 * 8 = 64 usecs per byte */ - usecs = payload_len << 6; - } else if (phy_mode == BLE_PHY_MODE_CODED_500KBPS) { - /* S=2 => 2 * 8 = 16 usecs per byte */ - usecs = payload_len << 4; - } else { - BLE_LL_ASSERT(0); - } - - usecs += g_ble_ll_pdu_header_tx_time[phy_mode]; -#else - usecs = (((payload_len) + BLE_LL_PDU_HDR_LEN + BLE_LL_ACC_ADDR_LEN - + BLE_LL_PREAMBLE_LEN + BLE_LL_CRC_LEN) << 3); -#endif - - return usecs; -} - -uint16_t -ble_ll_pdu_max_tx_octets_get(uint32_t usecs, int phy_mode) -{ - uint32_t header_tx_time; - uint16_t octets = 0; - - BLE_LL_ASSERT(phy_mode < BLE_PHY_NUM_MODE); - - header_tx_time = g_ble_ll_pdu_header_tx_time[phy_mode]; - - /* - * Current conn max tx time can be too short to even send a packet header - * and this can happen if we changed connection form uncoded to coded phy. - * However, the lower bound for conn max tx time (all of them) depends on - * current phy (uncoded/coded) but it always allows to send at least 27 - * bytes of payload thus we alwyas return at least 27 from here. - * - * Reference: - * Core v5.0, Vol 6, Part B, section 4.5.10 - * see connEffectiveMaxTxTime and connEffectiveMaxRxTime definitions - */ - - if (usecs < header_tx_time) { - return 27; - } - - usecs -= header_tx_time; - - if (phy_mode == BLE_PHY_MODE_1M) { - /* 8 usecs per byte */ - octets = usecs >> 3; - } else if (phy_mode == BLE_PHY_MODE_2M) { - /* 4 usecs per byte */ - octets = usecs >> 2; - } else if (phy_mode == BLE_PHY_MODE_CODED_125KBPS) { - /* S=8 => 8 * 8 = 64 usecs per byte */ - octets = usecs >> 6; - } else if (phy_mode == BLE_PHY_MODE_CODED_500KBPS) { - /* S=2 => 2 * 8 = 16 usecs per byte */ - octets = usecs >> 4; - } else { - BLE_LL_ASSERT(0); - } - - /* see comment at the beginning */ - return max(27, octets); -} - -static inline bool -ble_ll_is_addr_empty(const uint8_t *addr) -{ - return memcmp(addr, BLE_ADDR_ANY, BLE_DEV_ADDR_LEN) == 0; -} - -/** - * Initialize the Link Layer. Should be called only once - * - * @return int - */ -void -ble_ll_init(void) -{ - int rc; - uint64_t features; - ble_addr_t addr; - struct ble_ll_obj *lldata; - - /* Ensure this function only gets called by sysinit. */ - SYSINIT_ASSERT_ACTIVE(); - - ble_ll_trace_init(); - ble_phy_trace_init(); - - /* Set public device address if not already set */ - if (ble_ll_is_addr_empty(g_dev_addr)) { - /* Use sycfg address if configured, otherwise try to read from HW */ - if (!ble_ll_is_addr_empty(MYNEWT_VAL(BLE_PUBLIC_DEV_ADDR))) { - memcpy(g_dev_addr, MYNEWT_VAL(BLE_PUBLIC_DEV_ADDR), BLE_DEV_ADDR_LEN); - } else { - rc = ble_hw_get_public_addr(&addr); - if (!rc) { - memcpy(g_dev_addr, &addr.val[0], BLE_DEV_ADDR_LEN); - } - } - } - - ble_ll_rfmgmt_init(); - - /* Get pointer to global data object */ - lldata = &g_ble_ll_data; - - /* Set acl pkt size and number */ - lldata->ll_num_acl_pkts = MYNEWT_VAL(BLE_ACL_BUF_COUNT); - lldata->ll_acl_pkt_size = MYNEWT_VAL(BLE_ACL_BUF_SIZE); - - /* Initialize eventq */ - ble_npl_eventq_init(&lldata->ll_evq); - - /* Initialize the transmit (from host) and receive (from phy) queues */ - STAILQ_INIT(&lldata->ll_tx_pkt_q); - STAILQ_INIT(&lldata->ll_rx_pkt_q); - - /* Initialize transmit (from host) and receive packet (from phy) event */ - ble_npl_event_init(&lldata->ll_rx_pkt_ev, ble_ll_event_rx_pkt, NULL); - ble_npl_event_init(&lldata->ll_tx_pkt_ev, ble_ll_event_tx_pkt, NULL); - - /* Initialize data buffer overflow event and completed packets */ - ble_npl_event_init(&lldata->ll_dbuf_overflow_ev, ble_ll_event_dbuf_overflow, NULL); - ble_npl_event_init(&lldata->ll_comp_pkt_ev, ble_ll_event_comp_pkts, NULL); - - /* Initialize the HW error timer */ - /* NOT USED WITH RAM HCI - * Commented out to prevent creating an unnecessary timer - ble_npl_callout_init(&g_ble_ll_data.ll_hw_err_timer, - &g_ble_ll_data.ll_evq, - ble_ll_hw_err_timer_cb, - NULL); - */ - - /* Initialize LL HCI */ - ble_ll_hci_init(); - - /* Init the scheduler */ - ble_ll_sched_init(); - - /* Initialize advertiser */ - ble_ll_adv_init(); - - /* Initialize a scanner */ - ble_ll_scan_init(); - - /* Initialize the connection module */ - ble_ll_conn_module_init(); - - /* Set the supported features. NOTE: we always support extended reject. */ - features = BLE_LL_FEAT_EXTENDED_REJ; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) - features |= BLE_LL_FEAT_DATA_LEN_EXT; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CONN_PARAM_REQ) - features |= BLE_LL_FEAT_CONN_PARM_REQ; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG) - features |= BLE_LL_FEAT_SLAVE_INIT; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - features |= BLE_LL_FEAT_LE_ENCRYPTION; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - features |= (BLE_LL_FEAT_LL_PRIVACY | BLE_LL_FEAT_EXT_SCAN_FILT); - ble_ll_resolv_init(); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) - features |= BLE_LL_FEAT_LE_PING; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - features |= BLE_LL_FEAT_EXT_ADV; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) - /* CSA2 */ - features |= BLE_LL_FEAT_CSA2; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - features |= BLE_LL_FEAT_LE_2M_PHY; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - features |= BLE_LL_FEAT_LE_CODED_PHY; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - features |= BLE_LL_FEAT_PERIODIC_ADV; - ble_ll_sync_init(); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - features |= BLE_LL_FEAT_SYNC_TRANS_RECV; - features |= BLE_LL_FEAT_SYNC_TRANS_SEND; -#endif - - /* Initialize random number generation */ - ble_ll_rand_init(); - - /* XXX: This really doesn't belong here, as the address probably has not - * been set yet. - */ - ble_ll_seed_prng(); - - lldata->ll_supp_features = features; - - rc = stats_init_and_reg(STATS_HDR(ble_ll_stats), - STATS_SIZE_INIT_PARMS(ble_ll_stats, STATS_SIZE_32), - STATS_NAME_INIT_PARMS(ble_ll_stats), - "ble_ll"); - SYSINIT_PANIC_ASSERT(rc == 0); - -#if MYNEWT_VAL(BLE_LL_DTM) - ble_ll_dtm_init(); -#endif - -#if MYNEWT - /* Initialize the LL task */ - os_task_init(&g_ble_ll_task, "ble_ll", ble_ll_task, NULL, - MYNEWT_VAL(BLE_LL_PRIO), OS_WAIT_FOREVER, g_ble_ll_stack, - BLE_LL_STACK_SIZE); -#else - -/* - * For non-Mynewt OS it is required that OS creates task for LL and run LL - * routine which is wrapped by nimble_port_ll_task_func(). - */ - -#endif -} - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_adv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_adv.c deleted file mode 100644 index 83fd2506c..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_adv.c +++ /dev/null @@ -1,5143 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/porting/nimble/include/os/os_cputime.h" - -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) -#include "nimble/nimble/drivers/nrf51/include/ble/xcvr.h" -#elif defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) -#include "nimble/nimble/drivers/nrf52/include/ble/xcvr.h" -#endif - -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "nimble/nimble/include/nimble/ble_hci_trans.h" -#include "../include/controller/ble_phy.h" -#include "../include/controller/ble_hw.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_whitelist.h" -#include "../include/controller/ble_ll_resolv.h" -#include "../include/controller/ble_ll_trace.h" -#include "../include/controller/ble_ll_utils.h" -#include "../include/controller/ble_ll_rfmgmt.h" -#include "ble_ll_conn_priv.h" - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(array) \ - (sizeof(array) / sizeof((array)[0])) -#endif - -/* XXX: TODO - * 1) Need to look at advertising and scan request PDUs. Do I allocate these - * once? Do I use a different pool for smaller ones? Do I statically declare - * them? - * 3) How do features get supported? What happens if device does not support - * advertising? (for example) - * 4) How to determine the advertising interval we will actually use. As of - * now, we set it to max. - */ - -/* Scheduling data for secondary channel */ -struct ble_ll_adv_aux { - struct ble_ll_sched_item sch; - uint32_t start_time; - uint16_t aux_data_offset; - uint8_t chan; - uint8_t ext_hdr; - uint8_t aux_data_len; - uint8_t payload_len; -}; - -/* Scheduling data for sync PDUs */ -struct ble_ll_adv_sync { - struct ble_ll_sched_item sch; - uint32_t start_time; - uint16_t sync_data_offset; - uint8_t chan; - uint8_t ext_hdr; - uint8_t sync_data_len; - uint8_t payload_len; -}; - -/* - * Advertising state machine - * - * The advertising state machine data structure. - * - * adv_pdu_len - * The length of the advertising PDU that will be sent. This does not - * include the preamble, access address and CRC. - * - * initiator_addr: - * This is the address that we send in directed advertisements (the - * INITA field). If we are using Privacy this is a RPA that we need to - * generate. We reserve space in the advsm to save time when creating - * the ADV_DIRECT_IND. If own address type is not 2 or 3, this is simply - * the peer address from the set advertising parameters. - */ -struct ble_ll_adv_sm -{ - uint8_t adv_enabled; - uint8_t adv_instance; - uint8_t adv_chanmask; - uint8_t adv_filter_policy; - uint8_t own_addr_type; - uint8_t peer_addr_type; - uint8_t adv_chan; - uint8_t adv_pdu_len; - int8_t adv_rpa_index; - int8_t adv_txpwr; - uint16_t flags; - uint16_t props; - uint16_t adv_itvl_min; - uint16_t adv_itvl_max; - uint32_t adv_itvl_usecs; - uint32_t adv_event_start_time; - uint32_t adv_pdu_start_time; - uint32_t adv_end_time; - uint32_t adv_rpa_timer; - uint8_t adva[BLE_DEV_ADDR_LEN]; - uint8_t adv_rpa[BLE_DEV_ADDR_LEN]; - uint8_t peer_addr[BLE_DEV_ADDR_LEN]; - uint8_t initiator_addr[BLE_DEV_ADDR_LEN]; - struct os_mbuf *adv_data; - struct os_mbuf *new_adv_data; - struct os_mbuf *scan_rsp_data; - struct os_mbuf *new_scan_rsp_data; - uint8_t *conn_comp_ev; - struct ble_npl_event adv_txdone_ev; - struct ble_ll_sched_item adv_sch; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) - uint16_t channel_id; - uint16_t event_cntr; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - uint8_t aux_active : 1; - uint8_t aux_index : 1; - uint8_t aux_first_pdu : 1; - uint8_t aux_not_scanned : 1; - struct ble_mbuf_hdr *rx_ble_hdr; - struct os_mbuf **aux_data; - struct ble_ll_adv_aux aux[2]; - struct ble_npl_event adv_sec_txdone_ev; - uint16_t duration; - uint16_t adi; - uint8_t adv_random_addr[BLE_DEV_ADDR_LEN]; - uint8_t events_max; - uint8_t events; - uint8_t pri_phy; - uint8_t sec_phy; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - struct os_mbuf *periodic_adv_data; - struct os_mbuf *periodic_new_data; - uint32_t periodic_crcinit; /* only 3 bytes are used */ - uint32_t periodic_access_addr; - uint16_t periodic_adv_itvl_min; - uint16_t periodic_adv_itvl_max; - uint16_t periodic_adv_props; - uint16_t periodic_channel_id; - uint16_t periodic_event_cntr; - uint16_t periodic_chain_event_cntr; - uint8_t periodic_adv_enabled : 1; - uint8_t periodic_adv_active : 1; - uint8_t periodic_sync_active : 1; - uint8_t periodic_sync_index : 1; - uint8_t periodic_num_used_chans; - uint8_t periodic_chanmap[BLE_LL_CONN_CHMAP_LEN]; - uint32_t periodic_adv_itvl_ticks; - uint8_t periodic_adv_itvl_rem_usec; - uint8_t periodic_adv_event_start_time_remainder; - uint32_t periodic_adv_event_start_time; - struct ble_ll_adv_sync periodic_sync[2]; - struct ble_npl_event adv_periodic_txdone_ev; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - uint16_t periodic_event_cntr_last_sent; -#endif -#endif -#endif -}; - -#define BLE_LL_ADV_SM_FLAG_TX_ADD 0x0001 -#define BLE_LL_ADV_SM_FLAG_RX_ADD 0x0002 -#define BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF 0x0004 -#define BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD 0x0008 -#define BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK 0x0030 /* use helpers! */ -#define BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE 0x0040 -#define BLE_LL_ADV_SM_FLAG_CONFIGURED 0x0080 -#define BLE_LL_ADV_SM_FLAG_ADV_RPA_TMO 0x0100 -#define BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA 0x0200 -#define BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA 0x0400 -#define BLE_LL_ADV_SM_FLAG_PERIODIC_CONFIGURED 0x0800 -#define BLE_LL_ADV_SM_FLAG_PERIODIC_DATA_INCOMPLETE 0x1000 -#define BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING 0x2000 -#define BLE_LL_ADV_SM_FLAG_PERIODIC_NEW_DATA 0x4000 - -#define ADV_DATA_LEN(_advsm) \ - ((_advsm->adv_data) ? OS_MBUF_PKTLEN(advsm->adv_data) : 0) -#define SCAN_RSP_DATA_LEN(_advsm) \ - ((_advsm->scan_rsp_data) ? OS_MBUF_PKTLEN(advsm->scan_rsp_data) : 0) -#define AUX_DATA_LEN(_advsm) \ - (*(_advsm->aux_data) ? OS_MBUF_PKTLEN(*advsm->aux_data) : 0) - -#define AUX_CURRENT(_advsm) (&(_advsm->aux[_advsm->aux_index])) -#define AUX_NEXT(_advsm) (&(_advsm->aux[_advsm->aux_index ^ 1])) - -#define SYNC_CURRENT(_advsm) (&(_advsm->periodic_sync[_advsm->periodic_sync_index])) -#define SYNC_NEXT(_advsm) (&(_advsm->periodic_sync[_advsm->periodic_sync_index ^ 1])) -#define SYNC_DATA_LEN(_advsm) \ - (_advsm->periodic_adv_data ? OS_MBUF_PKTLEN(advsm->periodic_adv_data) : 0) - -/* The advertising state machine global object */ -struct ble_ll_adv_sm g_ble_ll_adv_sm[BLE_ADV_INSTANCES]; -struct ble_ll_adv_sm *g_ble_ll_cur_adv_sm; - -static struct ble_ll_adv_sm * -ble_ll_adv_sm_find_configured(uint8_t instance) -{ - struct ble_ll_adv_sm *advsm; - int i; - - /* in legacy mode we only allow instance 0 */ - if (!ble_ll_hci_adv_mode_ext()) { - BLE_LL_ASSERT(instance == 0); - return &g_ble_ll_adv_sm[0]; - } - - for (i = 0; i < ARRAY_SIZE(g_ble_ll_adv_sm); i++) { - advsm = &g_ble_ll_adv_sm[i]; - - if ((advsm->flags & BLE_LL_ADV_SM_FLAG_CONFIGURED) && - (advsm->adv_instance == instance)) { - return advsm; - } - } - - return NULL; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static int -ble_ll_adv_active_chanset_is_pri(struct ble_ll_adv_sm *advsm) -{ - return (advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK) == 0x10; -} - -static int -ble_ll_adv_active_chanset_is_sec(struct ble_ll_adv_sm *advsm) -{ - return (advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK) == 0x20; -} -#endif - -static void -ble_ll_adv_active_chanset_clear(struct ble_ll_adv_sm *advsm) -{ - os_sr_t sr; - - OS_ENTER_CRITICAL(sr); - advsm->flags &= ~BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK; - OS_EXIT_CRITICAL(sr); -} - -static void -ble_ll_adv_active_chanset_set_pri(struct ble_ll_adv_sm *advsm) -{ - os_sr_t sr; - - OS_ENTER_CRITICAL(sr); - assert((advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK) == 0); - advsm->flags &= ~BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK; - advsm->flags |= 0x10; - OS_EXIT_CRITICAL(sr); -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static void -ble_ll_adv_active_chanset_set_sec(struct ble_ll_adv_sm *advsm) -{ - os_sr_t sr; - - OS_ENTER_CRITICAL(sr); - assert((advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK) == 0); - advsm->flags &= ~BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK; - advsm->flags |= 0x20; - OS_EXIT_CRITICAL(sr); -} -#endif - -static void -ble_ll_adv_flags_set(struct ble_ll_adv_sm *advsm, uint16_t flags) -{ - os_sr_t sr; - - OS_ENTER_CRITICAL(sr); - advsm->flags |= flags; - OS_EXIT_CRITICAL(sr); -} - -static void -ble_ll_adv_flags_clear(struct ble_ll_adv_sm *advsm, uint16_t flags) -{ - os_sr_t sr; - - OS_ENTER_CRITICAL(sr); - advsm->flags &= ~flags; - OS_EXIT_CRITICAL(sr); -} - -static void ble_ll_adv_make_done(struct ble_ll_adv_sm *advsm, struct ble_mbuf_hdr *hdr); -static void ble_ll_adv_sm_init(struct ble_ll_adv_sm *advsm); -static void ble_ll_adv_sm_stop_timeout(struct ble_ll_adv_sm *advsm); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -static void -ble_ll_adv_rpa_update(struct ble_ll_adv_sm *advsm) -{ - if (ble_ll_resolv_gen_rpa(advsm->peer_addr, advsm->peer_addr_type, - advsm->adva, 1)) { - ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_TX_ADD); - } else { - if (advsm->own_addr_type & 1) { - ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_TX_ADD); - } else { - ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_TX_ADD); - } - } - - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { - if (ble_ll_resolv_gen_rpa(advsm->peer_addr, advsm->peer_addr_type, - advsm->initiator_addr, 0)) { - ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_RX_ADD); - } else { - if (advsm->peer_addr_type & 1) { - ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_RX_ADD); - } else { - ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_RX_ADD); - } - } - } -} - -/** - * Called to change advertisers ADVA and INITA (for directed advertisements) - * as an advertiser needs to adhere to the resolvable private address generation - * timer. - * - * NOTE: the resolvable private address code uses its own timer to regenerate - * local resolvable private addresses. The advertising code uses its own - * timer to reset the INITA (for directed advertisements). This code also sets - * the appropriate txadd and rxadd bits that will go into the advertisement. - * - * Another thing to note: it is possible that an IRK is all zeroes in the - * resolving list. That is why we need to check if the generated address is - * in fact a RPA as a resolving list entry with all zeroes will use the - * identity address (which may be a private address or public). - * - * @param advsm - */ -void -ble_ll_adv_chk_rpa_timeout(struct ble_ll_adv_sm *advsm) -{ - if (advsm->own_addr_type < BLE_HCI_ADV_OWN_ADDR_PRIV_PUB) { - return; - } - - if (advsm->flags & BLE_LL_ADV_SM_FLAG_ADV_RPA_TMO) { - ble_ll_adv_rpa_update(advsm); - ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_ADV_RPA_TMO); - } -} - -void -ble_ll_adv_rpa_timeout(void) -{ - struct ble_ll_adv_sm *advsm; - int i; - - for (i = 0; i < BLE_ADV_INSTANCES; i++) { - advsm = &g_ble_ll_adv_sm[i]; - - if (advsm->adv_enabled && - advsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { - /* Mark RPA as timed out so we get a new RPA */ - ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_ADV_RPA_TMO); - } - } -} -#endif - -/** - * Calculate the first channel that we should advertise upon when we start - * an advertising event. - * - * @param advsm - * - * @return uint8_t The number of the first channel usable for advertising. - */ -static uint8_t -ble_ll_adv_first_chan(struct ble_ll_adv_sm *advsm) -{ - uint8_t adv_chan; - - /* Set first advertising channel */ - if (advsm->adv_chanmask & 0x01) { - adv_chan = BLE_PHY_ADV_CHAN_START; - } else if (advsm->adv_chanmask & 0x02) { - adv_chan = BLE_PHY_ADV_CHAN_START + 1; - } else { - adv_chan = BLE_PHY_ADV_CHAN_START + 2; - } - - return adv_chan; -} - -/** - * Calculate the final channel that we should advertise upon when we start - * an advertising event. - * - * @param advsm - * - * @return uint8_t The number of the final channel usable for advertising. - */ -static uint8_t -ble_ll_adv_final_chan(struct ble_ll_adv_sm *advsm) -{ - uint8_t adv_chan; - - if (advsm->adv_chanmask & 0x04) { - adv_chan = BLE_PHY_ADV_CHAN_START + 2; - } else if (advsm->adv_chanmask & 0x02) { - adv_chan = BLE_PHY_ADV_CHAN_START + 1; - } else { - adv_chan = BLE_PHY_ADV_CHAN_START; - } - - return adv_chan; -} - -/** - * Create the advertising legacy PDU - * - * @param advsm Pointer to advertisement state machine - */ -static uint8_t -ble_ll_adv_legacy_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) -{ - struct ble_ll_adv_sm *advsm; - uint8_t adv_data_len; - uint8_t pdulen; - uint8_t pdu_type; - - advsm = pducb_arg; - - /* assume this is not a direct ind */ - adv_data_len = ADV_DATA_LEN(advsm); - pdulen = BLE_DEV_ADDR_LEN + adv_data_len; - - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { - pdu_type = BLE_ADV_PDU_TYPE_ADV_DIRECT_IND; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) - pdu_type |= BLE_ADV_PDU_HDR_CHSEL; -#endif - - if (advsm->flags & BLE_LL_ADV_SM_FLAG_RX_ADD) { - pdu_type |= BLE_ADV_PDU_HDR_RXADD_RAND; - } - - adv_data_len = 0; - pdulen = BLE_ADV_DIRECT_IND_LEN; - } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { - pdu_type = BLE_ADV_PDU_TYPE_ADV_IND; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) - pdu_type |= BLE_ADV_PDU_HDR_CHSEL; -#endif - } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { - pdu_type = BLE_ADV_PDU_TYPE_ADV_SCAN_IND; - } else { - pdu_type = BLE_ADV_PDU_TYPE_ADV_NONCONN_IND; - } - - /* An invalid advertising data length indicates a memory overwrite */ - assert(adv_data_len <= BLE_ADV_LEGACY_DATA_MAX_LEN); - - /* Set the PDU length in the state machine (includes header) */ - advsm->adv_pdu_len = pdulen + BLE_LL_PDU_HDR_LEN; - - /* Set TxAdd to random if needed. */ - if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { - pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND; - } - - *hdr_byte = pdu_type; - - /* Construct advertisement */ - memcpy(dptr, advsm->adva, BLE_DEV_ADDR_LEN); - dptr += BLE_DEV_ADDR_LEN; - - /* For ADV_DIRECT_IND add inita */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { - memcpy(dptr, advsm->initiator_addr, BLE_DEV_ADDR_LEN); - } - - /* Copy in advertising data, if any */ - if (adv_data_len != 0) { - os_mbuf_copydata(advsm->adv_data, 0, adv_data_len, dptr); - } - - return pdulen; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static void -ble_ll_adv_put_aux_ptr(uint8_t chan, uint8_t phy, uint32_t offset, - uint8_t *dptr) -{ - dptr[0] = chan; - - if (offset > 245700) { - dptr[0] |= 0x80; - offset = offset / 300; - } else { - offset = offset / 30; - } - - if (offset > 0x1fff) { - offset = 0; - } - - /* offset is 13bits and PHY 3 bits */ - dptr[1] = (offset & 0x000000ff); - dptr[2] = ((offset >> 8) & 0x0000001f) | (phy - 1) << 5; -} - -/** - * Create the advertising PDU - */ -static uint8_t -ble_ll_adv_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) -{ - struct ble_ll_adv_sm *advsm; - uint8_t pdu_type; - uint8_t adv_mode; - uint8_t ext_hdr_len; - uint8_t ext_hdr_flags; - uint32_t offset; - - advsm = pducb_arg; - - assert(ble_ll_adv_active_chanset_is_pri(advsm)); - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - return ble_ll_adv_legacy_pdu_make(dptr, advsm, hdr_byte); - } - - /* only ADV_EXT_IND goes on primary advertising channels */ - pdu_type = BLE_ADV_PDU_TYPE_ADV_EXT_IND; - - /* Set TxAdd to random if needed. */ - if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { - pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND; - } - - *hdr_byte = pdu_type; - - adv_mode = 0; - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { - adv_mode |= BLE_LL_EXT_ADV_MODE_CONN; - } - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { - adv_mode |= BLE_LL_EXT_ADV_MODE_SCAN; - } - - ext_hdr_len = BLE_LL_EXT_ADV_FLAGS_SIZE + BLE_LL_EXT_ADV_DATA_INFO_SIZE + - BLE_LL_EXT_ADV_AUX_PTR_SIZE; - ext_hdr_flags = (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT) | - (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT); - - /* ext hdr len and adv mode */ - dptr[0] = ext_hdr_len | (adv_mode << 6); - dptr += 1; - - /* ext hdr flags */ - dptr[0] = ext_hdr_flags; - dptr += 1; - - /* ADI */ - dptr[0] = advsm->adi & 0x00ff; - dptr[1] = advsm->adi >> 8; - dptr += BLE_LL_EXT_ADV_DATA_INFO_SIZE; - - /* AuxPtr */ - if (AUX_CURRENT(advsm)->sch.enqueued) { - offset = os_cputime_ticks_to_usecs(AUX_CURRENT(advsm)->start_time - advsm->adv_pdu_start_time); - } else { - offset = 0; - } - /* Always use channel from 1st AUX */ - ble_ll_adv_put_aux_ptr(AUX_CURRENT(advsm)->chan, advsm->sec_phy, - offset, dptr); - - return BLE_LL_EXT_ADV_HDR_LEN + ext_hdr_len; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) -static void -ble_ll_adv_put_syncinfo(struct ble_ll_adv_sm *advsm, - struct ble_ll_conn_sm *connsm, uint8_t *conn_event_cnt, - uint8_t *dptr) -{ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - uint8_t anchor_usecs; - uint16_t conn_cnt; -#endif - unsigned int event_cnt_off = 0; - uint32_t offset = 0; - uint32_t anchor; - uint8_t units; - - if (connsm) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - anchor = connsm->anchor_point; - anchor_usecs = connsm->anchor_point_usecs; - conn_cnt = connsm->event_cntr; - - /* get anchor for conn event that is before periodic_adv_event_start_time */ - while (CPUTIME_GT(anchor, advsm->periodic_adv_event_start_time)) { - ble_ll_conn_get_anchor(connsm, --conn_cnt, &anchor, &anchor_usecs); - } - - offset = os_cputime_ticks_to_usecs(advsm->periodic_adv_event_start_time - anchor); - offset -= anchor_usecs; - offset += advsm->periodic_adv_event_start_time_remainder; - - /* connEventCount */ - put_le16(conn_event_cnt, conn_cnt); -#endif - } else { - anchor = advsm->periodic_adv_event_start_time; - - /* Get periodic event that is past AUX start time (so that we always - * provide valid offset if it is not too far in future). This can - * happen if advertising event is interleaved with periodic advertising - * event (when chaining). - */ - while (CPUTIME_GT(AUX_CURRENT(advsm)->start_time, anchor)) { - anchor += advsm->periodic_adv_itvl_ticks; - event_cnt_off++; - } - - offset = os_cputime_ticks_to_usecs(anchor - AUX_CURRENT(advsm)->start_time); - offset += advsm->periodic_adv_event_start_time_remainder; - offset += advsm->periodic_adv_itvl_rem_usec; - } - - /* Sync Packet Offset (13 bits), Offset Units (1 bit), Offset Adjust (1 bit), - * RFU (1 bit) - */ - if (offset > 245700) { - units = 0x20; - offset = offset / 300; - - if (offset >= 0x2000) { - if (connsm) { - offset -= 0x2000; - units |= 0x40; - } else { - /* not able to represent time in offset */ - offset = 0; - units = 0x00; - event_cnt_off = 0; - } - } - - } else { - units = 0x00; - offset = offset / 30; - } - - dptr[0] = (offset & 0x000000ff); - dptr[1] = ((offset >> 8) & 0x0000001f) | units; - - /* Interval (2 bytes) */ - put_le16(&dptr[2], advsm->periodic_adv_itvl_max); - - /* Channels Mask (37 bits) */ - dptr[4] = advsm->periodic_chanmap[0]; - dptr[5] = advsm->periodic_chanmap[1]; - dptr[6] = advsm->periodic_chanmap[2]; - dptr[7] = advsm->periodic_chanmap[3]; - dptr[8] = advsm->periodic_chanmap[4] & 0x1f; - - /* SCA (3 bits) */ - dptr[8] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5; - - /* AA (4 bytes) */ - put_le32(&dptr[9], advsm->periodic_access_addr); - - /* CRCInit (3 bytes) */ - dptr[13] = (uint8_t)advsm->periodic_crcinit; - dptr[14] = (uint8_t)(advsm->periodic_crcinit >> 8); - dptr[15] = (uint8_t)(advsm->periodic_crcinit >> 16); - - /* Event Counter (2 bytes) */ - put_le16(&dptr[16], advsm->periodic_event_cntr + event_cnt_off); -} -#endif - -/** - * Create the AUX PDU - */ -static uint8_t -ble_ll_adv_aux_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) -{ - struct ble_ll_adv_sm *advsm; - struct ble_ll_adv_aux *aux; - uint8_t adv_mode; - uint8_t pdu_type; - uint8_t ext_hdr_len; - uint32_t offset; - - advsm = pducb_arg; - aux = AUX_CURRENT(advsm); - - assert(!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)); - assert(ble_ll_adv_active_chanset_is_sec(advsm)); - - /* It's the same for AUX_ADV_IND and AUX_CHAIN_IND */ - pdu_type = BLE_ADV_PDU_TYPE_AUX_ADV_IND; - - /* We do not create scannable PDUs here - this is handled separately */ - adv_mode = 0; - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { - adv_mode |= BLE_LL_EXT_ADV_MODE_CONN; - } - - ext_hdr_len = aux->payload_len - BLE_LL_EXT_ADV_HDR_LEN - aux->aux_data_len; - dptr[0] = (adv_mode << 6) | ext_hdr_len; - dptr += 1; - - /* only put flags if needed */ - if (aux->ext_hdr) { - dptr[0] = aux->ext_hdr; - dptr += 1; - } - - if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { - - /* Set TxAdd to random if needed. */ - if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { - pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND; - } - - memcpy(dptr, advsm->adva, BLE_LL_EXT_ADV_ADVA_SIZE); - dptr += BLE_LL_EXT_ADV_ADVA_SIZE; - } - - if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { - memcpy(dptr, advsm->initiator_addr, BLE_LL_EXT_ADV_TARGETA_SIZE); - dptr += BLE_LL_EXT_ADV_TARGETA_SIZE; - - /* Set RxAdd to random if needed. */ - if (advsm->flags & BLE_LL_ADV_SM_FLAG_RX_ADD) { - pdu_type |= BLE_ADV_PDU_HDR_RXADD_RAND; - } - } - - if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { - dptr[0] = advsm->adi & 0x00ff; - dptr[1] = advsm->adi >> 8; - dptr += BLE_LL_EXT_ADV_DATA_INFO_SIZE; - } - - if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { - if (!AUX_NEXT(advsm)->sch.enqueued) { - /* - * Trim data here in case we do not have next aux scheduled. This - * can happen if next aux was outside advertising set period and - * was removed from scheduler. - */ - offset = 0; - } else if (advsm->rx_ble_hdr) { - offset = os_cputime_ticks_to_usecs(AUX_NEXT(advsm)->start_time - advsm->rx_ble_hdr->beg_cputime); - offset -= (advsm->rx_ble_hdr->rem_usecs + ble_ll_pdu_tx_time_get(12, advsm->sec_phy) + BLE_LL_IFS); - } else { - offset = os_cputime_ticks_to_usecs(AUX_NEXT(advsm)->start_time - aux->start_time); - } - - ble_ll_adv_put_aux_ptr(AUX_NEXT(advsm)->chan, advsm->sec_phy, - offset, dptr); - - dptr += BLE_LL_EXT_ADV_AUX_PTR_SIZE; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) { - ble_ll_adv_put_syncinfo(advsm, NULL, NULL, dptr); - dptr += BLE_LL_EXT_ADV_SYNC_INFO_SIZE; - } -#endif - - if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { - dptr[0] = advsm->adv_txpwr + ble_ll_get_tx_pwr_compensation(); - dptr += BLE_LL_EXT_ADV_TX_POWER_SIZE; - } - - if (aux->aux_data_len) { - os_mbuf_copydata(*advsm->aux_data, aux->aux_data_offset, - aux->aux_data_len, dptr); - } - - *hdr_byte = pdu_type; - - return aux->payload_len; -} - -static uint8_t -ble_ll_adv_aux_scannable_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) -{ - struct ble_ll_adv_sm *advsm; - uint8_t pdu_type; - uint8_t *ext_hdr_len; - uint8_t *ext_hdr; - uint8_t pdulen; - - advsm = pducb_arg; - - assert(!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)); - assert(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE); - assert(advsm->aux_first_pdu); - assert(ble_ll_adv_active_chanset_is_sec(advsm)); - - pdu_type = BLE_ADV_PDU_TYPE_AUX_ADV_IND; - - ext_hdr_len = &dptr[0]; - ext_hdr = &dptr[1]; - dptr += 2; - - /* Flags always */ - *ext_hdr_len = BLE_LL_EXT_ADV_FLAGS_SIZE; - *ext_hdr = 0; - - /* AdvA when non anonymous */ - if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV)) { - /* Set TxAdd to random if needed. */ - if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { - pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND; - } - - *ext_hdr_len += BLE_LL_EXT_ADV_ADVA_SIZE; - *ext_hdr |= (1 << BLE_LL_EXT_ADV_ADVA_BIT); - memcpy(dptr, advsm->adva, BLE_LL_EXT_ADV_ADVA_SIZE); - dptr += BLE_LL_EXT_ADV_ADVA_SIZE; - } - - /* TargetA only for directed */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { - *ext_hdr_len += BLE_LL_EXT_ADV_TARGETA_SIZE; - *ext_hdr |= (1 << BLE_LL_EXT_ADV_TARGETA_BIT); - memcpy(dptr, advsm->initiator_addr, BLE_LL_EXT_ADV_TARGETA_SIZE); - dptr += BLE_LL_EXT_ADV_TARGETA_SIZE; - - /* Set RxAdd to random if needed. */ - if (advsm->flags & BLE_LL_ADV_SM_FLAG_RX_ADD) { - pdu_type |= BLE_ADV_PDU_HDR_RXADD_RAND; - } - } - - /* ADI always */ - *ext_hdr_len += BLE_LL_EXT_ADV_DATA_INFO_SIZE; - *ext_hdr |= (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT); - dptr[0] = advsm->adi & 0x00ff; - dptr[1] = advsm->adi >> 8; - dptr += BLE_LL_EXT_ADV_DATA_INFO_SIZE; - - /* TxPower if configured */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR) { - *ext_hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; - *ext_hdr |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT); - dptr[0] = advsm->adv_txpwr + ble_ll_get_tx_pwr_compensation(); - dptr += BLE_LL_EXT_ADV_TX_POWER_SIZE; - } - - pdulen = BLE_LL_EXT_ADV_HDR_LEN + *ext_hdr_len; - - *hdr_byte = pdu_type; - *ext_hdr_len |= (BLE_LL_EXT_ADV_MODE_SCAN << 6); - - return pdulen; -} -#endif - -static uint8_t -ble_ll_adv_scan_rsp_legacy_pdu_make(uint8_t *dptr, void *pducb_arg, - uint8_t *hdr_byte) -{ - struct ble_ll_adv_sm *advsm; - uint8_t scan_rsp_len; - uint8_t pdulen; - uint8_t hdr; - - advsm = pducb_arg; - - /* Make sure that the length is valid */ - scan_rsp_len = SCAN_RSP_DATA_LEN(advsm); - assert(scan_rsp_len <= BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN); - - /* Set BLE transmit header */ - pdulen = BLE_DEV_ADDR_LEN + scan_rsp_len; - hdr = BLE_ADV_PDU_TYPE_SCAN_RSP; - if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { - hdr |= BLE_ADV_PDU_HDR_TXADD_RAND; - } - - *hdr_byte = hdr; - - /* - * The adva in this packet will be the same one that was being advertised - * and is based on the peer identity address in the set advertising - * parameters. If a different peer sends us a scan request (for some reason) - * we will reply with an adva that was not generated based on the local irk - * of the peer sending the scan request. - */ - - /* Construct scan response */ - memcpy(dptr, advsm->adva, BLE_DEV_ADDR_LEN); - if (scan_rsp_len != 0) { - os_mbuf_copydata(advsm->scan_rsp_data, 0, scan_rsp_len, - dptr + BLE_DEV_ADDR_LEN); - } - - return pdulen; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -/** - * Create a scan response PDU - * - * @param advsm - */ -static uint8_t -ble_ll_adv_scan_rsp_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) -{ - struct ble_ll_adv_sm *advsm; - - advsm = pducb_arg; - - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - return ble_ll_adv_scan_rsp_legacy_pdu_make(dptr, pducb_arg, hdr_byte); - } - - return ble_ll_adv_aux_pdu_make(dptr, pducb_arg, hdr_byte); -} - -struct aux_conn_rsp_data { - struct ble_ll_adv_sm *advsm; - uint8_t *peer; - uint8_t rxadd; -}; - -/** - * Create a AUX connect response PDU - * - * @param advsm - */ -static uint8_t -ble_ll_adv_aux_conn_rsp_pdu_make(uint8_t *dptr, void *pducb_arg, - uint8_t *hdr_byte) -{ - struct aux_conn_rsp_data *rsp_data; - uint8_t pdulen; - uint8_t ext_hdr_len; - uint8_t ext_hdr_flags; - uint8_t hdr; - - rsp_data = pducb_arg; - - /* flags,AdvA and TargetA */ - ext_hdr_len = BLE_LL_EXT_ADV_FLAGS_SIZE + BLE_LL_EXT_ADV_ADVA_SIZE + - BLE_LL_EXT_ADV_TARGETA_SIZE; - ext_hdr_flags = (1 << BLE_LL_EXT_ADV_ADVA_BIT); - ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_TARGETA_BIT); - - pdulen = BLE_LL_EXT_ADV_HDR_LEN + ext_hdr_len; - - /* Set BLE transmit header */ - hdr = BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP; - if (rsp_data->rxadd) { - hdr |= BLE_ADV_PDU_HDR_RXADD_MASK; - } - if (rsp_data->advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { - hdr |= BLE_ADV_PDU_HDR_TXADD_MASK; - } - - *hdr_byte = hdr; - - /* ext hdr len and adv mode (00b) */ - dptr[0] = ext_hdr_len; - dptr += 1; - - /* ext hdr flags */ - dptr[0] = ext_hdr_flags; - dptr += 1; - - memcpy(dptr, rsp_data->advsm->adva, BLE_LL_EXT_ADV_ADVA_SIZE); - dptr += BLE_LL_EXT_ADV_ADVA_SIZE; - - memcpy(dptr, rsp_data->peer, BLE_LL_EXT_ADV_TARGETA_SIZE); - dptr += BLE_LL_EXT_ADV_ADVA_SIZE; - - return pdulen; -} -#endif - -/** - * Called to indicate the advertising event is over. - * - * Context: Interrupt - * - * @param advsm - * - */ -static void -ble_ll_adv_tx_done(void *arg) -{ - struct ble_ll_adv_sm *advsm; - - /* reset power to max after advertising */ - ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM)); - - advsm = (struct ble_ll_adv_sm *)arg; - - ble_ll_trace_u32x2(BLE_LL_TRACE_ID_ADV_TXDONE, advsm->adv_instance, - advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (ble_ll_adv_active_chanset_is_pri(advsm)) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); - } else if (ble_ll_adv_active_chanset_is_sec(advsm)) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); - } else { - assert(0); - } -#else - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); -#endif - - ble_ll_state_set(BLE_LL_STATE_STANDBY); - - ble_ll_adv_active_chanset_clear(advsm); - - /* We no longer have a current state machine */ - g_ble_ll_cur_adv_sm = NULL; -} - -/* - * Called when an advertising event has been removed from the scheduler - * without being run. - */ -void -ble_ll_adv_event_rmvd_from_sched(struct ble_ll_adv_sm *advsm) -{ - /* - * Need to set advertising channel to final chan so new event gets - * scheduled. - */ - advsm->adv_chan = ble_ll_adv_final_chan(advsm); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) -/* - * Called when a periodic event has been removed from the scheduler - * without being run. - */ -void -ble_ll_adv_periodic_rmvd_from_sched(struct ble_ll_adv_sm *advsm) -{ - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_periodic_txdone_ev); -} -#endif - -/** - * This is the scheduler callback (called from interrupt context) which - * transmits an advertisement. - * - * Context: Interrupt (scheduler) - * - * @param sch - * - * @return int - */ -static int -ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch) -{ - int rc; - uint8_t end_trans; - uint32_t txstart; - struct ble_ll_adv_sm *advsm; - - /* Get the state machine for the event */ - advsm = (struct ble_ll_adv_sm *)sch->cb_arg; - - /* Set the current advertiser */ - g_ble_ll_cur_adv_sm = advsm; - - ble_ll_adv_active_chanset_set_pri(advsm); - - if ((advsm->flags & BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA) || - (advsm->flags & BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA)) { - goto adv_tx_done; - } - - /* Set the power */ - ble_phy_txpwr_set(advsm->adv_txpwr); - - /* Set channel */ - rc = ble_phy_setchan(advsm->adv_chan, BLE_ACCESS_ADDR_ADV, BLE_LL_CRCINIT_ADV); - assert(rc == 0); - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - /* Set phy mode */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - ble_phy_mode_set(BLE_PHY_MODE_1M, BLE_PHY_MODE_1M); - } else { - ble_phy_mode_set(advsm->pri_phy, advsm->pri_phy); - } -#else - ble_phy_mode_set(BLE_PHY_MODE_1M, BLE_PHY_MODE_1M); -#endif -#endif - - /* Set transmit start time. */ - txstart = sch->start_time + g_ble_ll_sched_offset_ticks; - rc = ble_phy_tx_set_start_time(txstart, sch->remainder); - if (rc) { - STATS_INC(ble_ll_stats, adv_late_starts); - goto adv_tx_done; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - ble_phy_encrypt_disable(); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - advsm->adv_rpa_index = -1; - if (ble_ll_resolv_enabled()) { - ble_phy_resolv_list_enable(); - } else { - ble_phy_resolv_list_disable(); - } -#endif - - /* We switch to RX after connectable or scannable legacy packets. */ - if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) && - ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) || - (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE))) { - end_trans = BLE_PHY_TRANSITION_TX_RX; - ble_phy_set_txend_cb(NULL, NULL); - } else { - end_trans = BLE_PHY_TRANSITION_NONE; - ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm); - } - - /* Transmit advertisement */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - rc = ble_phy_tx(ble_ll_adv_pdu_make, advsm, end_trans); -#else - rc = ble_phy_tx(ble_ll_adv_legacy_pdu_make, advsm, end_trans); -#endif - if (rc) { - goto adv_tx_done; - } - - /* Enable/disable whitelisting based on filter policy */ - if (advsm->adv_filter_policy != BLE_HCI_ADV_FILT_NONE) { - ble_ll_whitelist_enable(); - } else { - ble_ll_whitelist_disable(); - } - - /* Set link layer state to advertising */ - ble_ll_state_set(BLE_LL_STATE_ADV); - - /* Count # of adv. sent */ - STATS_INC(ble_ll_stats, adv_txg); - - return BLE_LL_SCHED_STATE_RUNNING; - -adv_tx_done: - ble_ll_adv_tx_done(advsm); - return BLE_LL_SCHED_STATE_DONE; -} - -static void -ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm) -{ - uint32_t max_usecs; - struct ble_ll_sched_item *sch; - - sch = &advsm->adv_sch; - sch->cb_arg = advsm; - sch->sched_cb = ble_ll_adv_tx_start_cb; - sch->sched_type = BLE_LL_SCHED_TYPE_ADV; - - /* Set end time to maximum time this schedule item may take */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - max_usecs = ble_ll_pdu_tx_time_get(advsm->adv_pdu_len, BLE_PHY_MODE_1M); - - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { - max_usecs += BLE_LL_SCHED_DIRECT_ADV_MAX_USECS; - } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { - max_usecs += BLE_LL_SCHED_ADV_MAX_USECS; - } - } else { - /* - * In ADV_EXT_IND we always set only ADI and AUX so the payload length - * is always 7 bytes. - */ - max_usecs = ble_ll_pdu_tx_time_get(7, advsm->pri_phy); - } -#else - max_usecs = ble_ll_pdu_tx_time_get(advsm->adv_pdu_len, BLE_PHY_MODE_1M); - - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { - max_usecs += BLE_LL_SCHED_DIRECT_ADV_MAX_USECS; - } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { - max_usecs += BLE_LL_SCHED_ADV_MAX_USECS; - } -#endif - - sch->start_time = advsm->adv_pdu_start_time - g_ble_ll_sched_offset_ticks; - sch->remainder = 0; - sch->end_time = advsm->adv_pdu_start_time + - ble_ll_usecs_to_ticks_round_up(max_usecs); -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static int -ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch) -{ - int rc; - uint8_t end_trans; - uint32_t txstart; - struct ble_ll_adv_sm *advsm; - ble_phy_tx_pducb_t pducb; - struct ble_ll_adv_aux *aux; - - /* Get the state machine for the event */ - advsm = (struct ble_ll_adv_sm *)sch->cb_arg; - - /* Set the current advertiser */ - g_ble_ll_cur_adv_sm = advsm; - - ble_ll_adv_active_chanset_set_sec(advsm); - - /* Set the power */ - ble_phy_txpwr_set(advsm->adv_txpwr); - - /* Set channel */ - aux = AUX_CURRENT(advsm); - rc = ble_phy_setchan(aux->chan, BLE_ACCESS_ADDR_ADV, - BLE_LL_CRCINIT_ADV); - assert(rc == 0); - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - /* Set phy mode */ - ble_phy_mode_set(advsm->sec_phy, advsm->sec_phy); -#endif - - /* Set transmit start time. */ - txstart = sch->start_time + g_ble_ll_sched_offset_ticks; - rc = ble_phy_tx_set_start_time(txstart, sch->remainder); - if (rc) { - STATS_INC(ble_ll_stats, adv_late_starts); - goto adv_tx_done; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - ble_phy_encrypt_disable(); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - advsm->adv_rpa_index = -1; - if (ble_ll_resolv_enabled()) { - ble_phy_resolv_list_enable(); - } else { - ble_phy_resolv_list_disable(); - } -#endif - - /* Set phy mode based on type of advertisement */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { - end_trans = BLE_PHY_TRANSITION_TX_RX; - ble_phy_set_txend_cb(NULL, NULL); - pducb = ble_ll_adv_aux_pdu_make; - } else if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) && - advsm->aux_first_pdu) { - end_trans = BLE_PHY_TRANSITION_TX_RX; - ble_phy_set_txend_cb(NULL, NULL); - pducb = ble_ll_adv_aux_scannable_pdu_make; - } else { - end_trans = BLE_PHY_TRANSITION_NONE; - ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm); - pducb = ble_ll_adv_aux_pdu_make; - } - - /* Transmit advertisement */ - rc = ble_phy_tx(pducb, advsm, end_trans); - if (rc) { - goto adv_tx_done; - } - - /* Enable/disable whitelisting based on filter policy */ - if (advsm->adv_filter_policy != BLE_HCI_ADV_FILT_NONE) { - ble_ll_whitelist_enable(); - } else { - ble_ll_whitelist_disable(); - } - - /* Set link layer state to advertising */ - ble_ll_state_set(BLE_LL_STATE_ADV); - - /* Count # of adv. sent */ - STATS_INC(ble_ll_stats, adv_txg); - - return BLE_LL_SCHED_STATE_RUNNING; - -adv_tx_done: - ble_ll_adv_tx_done(advsm); - return BLE_LL_SCHED_STATE_DONE; -} - -static uint8_t -ble_ll_adv_aux_scannable_pdu_payload_len(struct ble_ll_adv_sm *advsm) -{ - uint8_t len; - - /* Flags, ADI always */ - len = BLE_LL_EXT_ADV_HDR_LEN + BLE_LL_EXT_ADV_FLAGS_SIZE - + BLE_LL_EXT_ADV_DATA_INFO_SIZE; - - /* AdvA if not anonymous */ - if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV)) { - len += BLE_LL_EXT_ADV_ADVA_SIZE; - } - - /* TargetA only for directed */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { - len += BLE_LL_EXT_ADV_TARGETA_SIZE; - } - - /* TxPower if configured */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR) { - len += BLE_LL_EXT_ADV_TX_POWER_SIZE; - } - - return len; -} - -static void -ble_ll_adv_aux_calculate(struct ble_ll_adv_sm *advsm, - struct ble_ll_adv_aux *aux, uint16_t aux_data_offset) -{ - uint16_t rem_aux_data_len; - uint8_t hdr_len; - bool chainable; - - assert(!aux->sch.enqueued); - assert((AUX_DATA_LEN(advsm) > aux_data_offset) || - (AUX_DATA_LEN(advsm) == 0 && aux_data_offset == 0)); - - aux->aux_data_offset = aux_data_offset; - aux->aux_data_len = 0; - aux->payload_len = 0; - aux->ext_hdr = 0; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) - aux->chan = ble_ll_utils_calc_dci_csa2(advsm->event_cntr++, - advsm->channel_id, - g_ble_ll_conn_params.num_used_chans, - g_ble_ll_conn_params.master_chan_map); -#else - aux->chan = ble_ll_utils_remapped_channel(rand() % BLE_PHY_NUM_DATA_CHANS, - g_ble_ll_conn_params.master_chan_map); -#endif - - rem_aux_data_len = AUX_DATA_LEN(advsm) - aux_data_offset; - chainable = !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE); - - hdr_len = BLE_LL_EXT_ADV_HDR_LEN; - - if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { - /* ADI */ - aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT); - hdr_len += BLE_LL_EXT_ADV_DATA_INFO_SIZE; - } - - /* AdvA for 1st PDU in chain (i.e. AUX_ADV_IND or AUX_SCAN_RSP) */ - if (aux_data_offset == 0 && - !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV)) { - aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_ADVA_BIT); - hdr_len += BLE_LL_EXT_ADV_ADVA_SIZE; - } - - /* Note: this function does not calculate AUX_ADV_IND when advertising is - * scannable. Instead it is calculated in ble_ll_adv_aux_schedule_first(). - * - * However this function calculates length of AUX_SCAN_RSP and according - * to BT 5.0 Vol 6 Part B, 2.3.2.3, TargetA shall not be include there. - * - * This is why TargetA is added to all directed advertising here unless it - * is scannable one. - * - * Note. TargetA shall not be also in AUX_CHAIN_IND - */ - if (aux_data_offset == 0 && - (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) && - !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { - aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_TARGETA_BIT); - hdr_len += BLE_LL_EXT_ADV_TARGETA_SIZE; - } - - /* TxPower if configured. - * Note: TxPower should not be be present in AUX_CHAIN_IND - */ - if (aux_data_offset == 0 && - (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR)) { - aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT); - hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - /* SyncInfo for 1st PDU in chain (i.e. AUX_ADV_IND only) if periodic - * advertising is enabled - */ - if (aux_data_offset == 0 && advsm->periodic_adv_active) { - aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT); - hdr_len += BLE_LL_EXT_ADV_SYNC_INFO_SIZE; - } -#endif - - /* if we have any fields in ext header we need to add flags, note that Aux - * PTR is handled later and it will account for flags if needed - */ - if (aux->ext_hdr) { - hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; - } - - /* AdvData always */ - aux->aux_data_len = min(BLE_LL_MAX_PAYLOAD_LEN - hdr_len, rem_aux_data_len); - - /* AuxPtr if there are more AdvData remaining that we can fit here */ - if (chainable && (rem_aux_data_len > aux->aux_data_len)) { - /* adjust for flags that needs to be added if AuxPtr is only field - * in Extended Header - */ - if (!aux->ext_hdr) { - hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; - aux->aux_data_len -= BLE_LL_EXT_ADV_FLAGS_SIZE; - } - - aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT); - hdr_len += BLE_LL_EXT_ADV_AUX_PTR_SIZE; - aux->aux_data_len -= BLE_LL_EXT_ADV_AUX_PTR_SIZE; - - /* PDU payload should be full if chained */ - assert(hdr_len + aux->aux_data_len == BLE_LL_MAX_PAYLOAD_LEN); - } - - aux->payload_len = hdr_len + aux->aux_data_len; -} - -static void -ble_ll_adv_aux_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start, - void *arg) -{ - struct ble_ll_adv_aux *aux = arg; - - aux->start_time = sch_start + g_ble_ll_sched_offset_ticks; -} - -static void -ble_ll_adv_aux_schedule_next(struct ble_ll_adv_sm *advsm) -{ - struct ble_ll_adv_aux *aux; - struct ble_ll_adv_aux *aux_next; - struct ble_ll_sched_item *sch; - uint16_t rem_aux_data_len; - uint16_t next_aux_data_offset; - uint32_t max_usecs; - - assert(advsm->aux_active); - - aux = AUX_CURRENT(advsm); - aux_next = AUX_NEXT(advsm); - - assert(!aux_next->sch.enqueued); - - /* - * Do not schedule next aux if current aux is no longer scheduled since we - * do not have reference time for scheduling. - */ - if (!aux->sch.enqueued) { - return; - } - - /* - * Do not schedule next aux if current aux does not have AuxPtr in extended - * header as this means we do not need subsequent ADV_CHAIN_IND to be sent. - */ - if (!(aux->ext_hdr & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT))) { - return; - } - - next_aux_data_offset = aux->aux_data_offset + aux->aux_data_len; - - assert(AUX_DATA_LEN(advsm) >= next_aux_data_offset); - - rem_aux_data_len = AUX_DATA_LEN(advsm) - next_aux_data_offset; - assert(rem_aux_data_len > 0); - - ble_ll_adv_aux_calculate(advsm, aux_next, next_aux_data_offset); - max_usecs = ble_ll_pdu_tx_time_get(aux_next->payload_len, advsm->sec_phy); - - aux_next->start_time = aux->sch.end_time + - ble_ll_usecs_to_ticks_round_up(BLE_LL_MAFS + MYNEWT_VAL(BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY)); - - sch = &aux_next->sch; - sch->start_time = aux_next->start_time - g_ble_ll_sched_offset_ticks; - sch->remainder = 0; - sch->end_time = aux_next->start_time + - ble_ll_usecs_to_ticks_round_up(max_usecs); - ble_ll_sched_adv_new(&aux_next->sch, ble_ll_adv_aux_scheduled, aux_next); - - /* - * In case duration is set for advertising set we need to check if newly - * scheduled aux will fit inside duration. If not, remove it from scheduler - * so advertising will stop after current aux. - */ - if (advsm->duration && (aux_next->sch.end_time > advsm->adv_end_time)) { - ble_ll_sched_rmv_elem(&aux_next->sch); - } -} - -static void -ble_ll_adv_aux_schedule_first(struct ble_ll_adv_sm *advsm) -{ - struct ble_ll_adv_aux *aux; - struct ble_ll_sched_item *sch; - uint32_t max_usecs; - - assert(!advsm->aux_active); - assert(!advsm->aux[0].sch.enqueued); - assert(!advsm->aux[1].sch.enqueued); - - advsm->aux_active = 1; - advsm->aux_index = 0; - advsm->aux_first_pdu = 1; - advsm->aux_not_scanned = 0; - - aux = AUX_CURRENT(advsm); - ble_ll_adv_aux_calculate(advsm, aux, 0); - - /* Set end time to maximum time this schedule item may take */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { - max_usecs = ble_ll_pdu_tx_time_get(aux->payload_len, advsm->sec_phy) + - BLE_LL_IFS + - /* AUX_CONN_REQ */ - ble_ll_pdu_tx_time_get(34 + 14, advsm->sec_phy) + - BLE_LL_IFS + - /* AUX_CONN_RSP */ - ble_ll_pdu_tx_time_get(14, advsm->sec_phy); - } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { - /* For scannable advertising we need to calculate how much time we - * need for AUX_ADV_IND along with AUX_SCAN_REQ, AUX_SCAN_RSP and - * IFS in between. - * - * Note: - * 1. aux->payload_len, which calculated by above ble_ll_adv_aux_calulcate(), - * contains AUX_SCAN_RSP length. - * 2. length of AUX_ADV_IND is calculated by special function: - * ble_ll_adv_aux_scannable_pdu_payload_len() - */ - max_usecs = ble_ll_pdu_tx_time_get(ble_ll_adv_aux_scannable_pdu_payload_len(advsm), - advsm->sec_phy) + - BLE_LL_IFS + - /* AUX_SCAN_REQ */ - ble_ll_pdu_tx_time_get(12, advsm->sec_phy) + - BLE_LL_IFS + - /* AUX_SCAN_RSP */ - ble_ll_pdu_tx_time_get(aux->payload_len, advsm->sec_phy); - } else { - max_usecs = ble_ll_pdu_tx_time_get(aux->payload_len, advsm->sec_phy); - } - - sch = &aux->sch; - sch->start_time = aux->start_time - g_ble_ll_sched_offset_ticks; - sch->remainder = 0; - sch->end_time = aux->start_time + ble_ll_usecs_to_ticks_round_up(max_usecs); - ble_ll_sched_adv_new(sch, ble_ll_adv_aux_scheduled, aux); -} - -static void -ble_ll_adv_aux_set_start_time(struct ble_ll_adv_sm *advsm) -{ - static const uint8_t bits[8] = {0, 1, 1, 2, 1, 2, 2, 3}; - struct ble_ll_sched_item *sched = &advsm->adv_sch; - uint32_t adv_pdu_dur; - uint32_t adv_event_dur; - uint8_t chans; - - assert(!advsm->aux_active); - assert(!advsm->aux[0].sch.enqueued); - assert(!advsm->aux[1].sch.enqueued); - - assert(advsm->adv_chanmask > 0 && - advsm->adv_chanmask <= BLE_HCI_ADV_CHANMASK_DEF); - - chans = bits[advsm->adv_chanmask]; - - /* - * We want to schedule auxiliary packet as soon as possible after the end - * of advertising event, but no sooner than T_MAFS. The interval between - * advertising packets is 250 usecs (8.19 ticks) on LE Coded and a bit less - * on 1M, but it can vary a bit due to scheduling which we can't really - * control. Since we round ticks up for both interval and T_MAFS, we still - * have some margin here. The worst thing that can happen is that we skip - * last advertising packet which is not a bit problem so leave it as-is, no - * need to make code more complicated. - */ - - /* - * XXX: this could be improved if phy has TX-TX transition with controlled - * or predefined interval, but since it makes advertising code even - * more complicated let's skip it for now... - */ - - adv_pdu_dur = (int32_t)(sched->end_time - sched->start_time) - - g_ble_ll_sched_offset_ticks; - - /* 9 is 8.19 ticks rounded up - see comment above */ - adv_event_dur = (adv_pdu_dur * chans) + (9 * (chans - 1)); - - advsm->aux[0].start_time = advsm->adv_event_start_time + adv_event_dur + - ble_ll_usecs_to_ticks_round_up(BLE_LL_MAFS + MYNEWT_VAL(BLE_LL_SCHED_AUX_MAFS_DELAY)); -} - -static void -ble_ll_adv_aux_schedule(struct ble_ll_adv_sm *advsm) -{ - /* - * For secondary channel we always start by scheduling two consecutive - * auxiliary packets at once. Then, after sending one packet we try to - * schedule another one as long as there are some data left to send. This - * is to make sure we can always calculate AuxPtr to subsequent packet - * without need to scheduled it in an interrupt. - */ - - ble_ll_adv_aux_set_start_time(advsm); - ble_ll_adv_aux_schedule_first(advsm); - ble_ll_adv_aux_schedule_next(advsm); - - /* - * In case duration is set for advertising set we need to check if at least - * 1st aux will fit inside duration. If not, stop advertising now so we do - * not start extended advertising event which we cannot finish in time. - */ - if (advsm->duration && - (AUX_CURRENT(advsm)->sch.end_time > advsm->adv_end_time)) { - ble_ll_adv_sm_stop_timeout(advsm); - } -} -#endif - -/** - * Called when advertising need to be halted. This normally should not be called - * and is only called when a scheduled item executes but advertising is still - * running. - * - * Context: Interrupt - */ -void -ble_ll_adv_halt(void) -{ - struct ble_ll_adv_sm *advsm; - - if (g_ble_ll_cur_adv_sm != NULL) { - advsm = g_ble_ll_cur_adv_sm; - - ble_ll_trace_u32(BLE_LL_TRACE_ID_ADV_HALT, advsm->adv_instance); - - ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM)); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - if (advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING) { - ble_ll_adv_flags_clear(advsm, - BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, - &advsm->adv_periodic_txdone_ev); - ble_ll_state_set(BLE_LL_STATE_STANDBY); - g_ble_ll_cur_adv_sm = NULL; - return; - } -#endif - - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); - } -#endif - - ble_ll_state_set(BLE_LL_STATE_STANDBY); - ble_ll_adv_active_chanset_clear(g_ble_ll_cur_adv_sm); - g_ble_ll_cur_adv_sm = NULL; - } else { - ble_ll_trace_u32(BLE_LL_TRACE_ID_ADV_HALT, UINT32_MAX); - } -} - -/** - * Called by the HCI command parser when a set advertising parameters command - * has been received. - * - * Context: Link Layer task (HCI command parser) - * - * @param cmd - * - * @return int - */ -int -ble_ll_adv_set_adv_params(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_adv_params_cp *cmd = (const void *) cmdbuf; - struct ble_ll_adv_sm *advsm; - uint8_t adv_filter_policy; - uint16_t adv_itvl_min; - uint16_t adv_itvl_max; - uint16_t props; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - advsm = &g_ble_ll_adv_sm[0]; - if (advsm->adv_enabled) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* Make sure intervals are OK (along with advertising type */ - adv_itvl_min = le16toh(cmd->min_interval); - adv_itvl_max = le16toh(cmd->max_interval); - - /* - * Get the filter policy now since we will ignore it if we are doing - * directed advertising - */ - adv_filter_policy = cmd->filter_policy; - - switch (cmd->type) { - case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD: - adv_filter_policy = BLE_HCI_ADV_FILT_NONE; - memcpy(advsm->peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); - - /* Ignore min/max interval */ - adv_itvl_min = 0; - adv_itvl_max = 0; - - props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_HD_DIR ; - break; - case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD: - adv_filter_policy = BLE_HCI_ADV_FILT_NONE; - memcpy(advsm->peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); - - props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_LD_DIR ; - break; - case BLE_HCI_ADV_TYPE_ADV_IND: - props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_IND; - break; - case BLE_HCI_ADV_TYPE_ADV_NONCONN_IND: - props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_NONCONN; - break; - case BLE_HCI_ADV_TYPE_ADV_SCAN_IND: - props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_SCAN; - break; - default: - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Make sure intervals values are valid - * (HD directed advertising ignores those parameters) - */ - if (!(props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED)) { - if ((adv_itvl_min > adv_itvl_max) || - (adv_itvl_min < BLE_HCI_ADV_ITVL_MIN) || - (adv_itvl_min > BLE_HCI_ADV_ITVL_MAX) || - (adv_itvl_max < BLE_HCI_ADV_ITVL_MIN) || - (adv_itvl_max > BLE_HCI_ADV_ITVL_MAX)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - } - - if ((cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) || - (cmd->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - advsm->adv_txpwr = MYNEWT_VAL(BLE_LL_TX_PWR_DBM); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { - /* Copy peer address */ - memcpy(advsm->peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); - } -#else - /* If we dont support privacy some address types wont work */ - if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { - return BLE_ERR_UNSUPPORTED; - } -#endif - - /* There are only three adv channels, so check for any outside the range */ - if (((cmd->chan_map & 0xF8) != 0) || (cmd->chan_map == 0)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check for valid filter policy */ - if (adv_filter_policy > BLE_HCI_ADV_FILT_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Fill out rest of advertising state machine */ - advsm->own_addr_type = cmd->own_addr_type; - advsm->peer_addr_type = cmd->peer_addr_type; - advsm->adv_filter_policy = adv_filter_policy; - advsm->adv_chanmask = cmd->chan_map; - advsm->adv_itvl_min = adv_itvl_min; - advsm->adv_itvl_max = adv_itvl_max; - advsm->props = props; - - return 0; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static void -ble_ll_adv_update_did(struct ble_ll_adv_sm *advsm) -{ - uint16_t old_adi = advsm->adi; - - /* - * The Advertising DID for a given advertising set shall be initialized - * with a randomly chosen value. Whenever the Host provides new advertising - * data or scan response data for a given advertising set (whether it is the - * same as the previous data or not), the Advertising DID shall be updated. - * The new value shall be a randomly chosen value that is not the same as - * the previously used value. - */ - do { - advsm->adi = (advsm->adi & 0xf000) | (rand() & 0x0fff); - } while (old_adi == advsm->adi); -} -#endif - -static void -ble_ll_adv_update_adv_scan_rsp_data(struct ble_ll_adv_sm *advsm) -{ - if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA) && - !(advsm->flags & BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA)) { - return; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (advsm->aux_active) { - return; - } -#endif - - if (advsm->flags & BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA) { - if (advsm->new_adv_data) { - os_mbuf_free_chain(advsm->adv_data); - advsm->adv_data = advsm->new_adv_data; - advsm->new_adv_data = NULL; - } - ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA); - } else if (advsm->flags & BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA) { - os_mbuf_free_chain(advsm->scan_rsp_data); - advsm->scan_rsp_data = advsm->new_scan_rsp_data; - advsm->new_scan_rsp_data = NULL; - ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA); - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* DID shall be updated when host provides new advertising data */ - ble_ll_adv_update_did(advsm); -#endif -} - -/** - * Stop advertising state machine - * - * Context: Link Layer task. - * - * @param advsm - */ -static void -ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm) -{ - os_sr_t sr; - - if (advsm->adv_enabled) { - ble_ll_rfmgmt_release(); - - /* Remove any scheduled advertising items */ - ble_ll_sched_rmv_elem(&advsm->adv_sch); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - advsm->aux_active = 0; - ble_ll_sched_rmv_elem(&advsm->aux[0].sch); - ble_ll_sched_rmv_elem(&advsm->aux[1].sch); -#endif - - /* Set to standby if we are no longer advertising */ - OS_ENTER_CRITICAL(sr); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if ((g_ble_ll_cur_adv_sm == advsm) && - !(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING)) { - ble_phy_disable(); - ble_ll_state_set(BLE_LL_STATE_STANDBY); - g_ble_ll_cur_adv_sm = NULL; - ble_ll_scan_chk_resume(); - } -#else - if (ble_ll_state_get() == BLE_LL_STATE_ADV) { - ble_phy_disable(); - ble_ll_state_set(BLE_LL_STATE_STANDBY); - g_ble_ll_cur_adv_sm = NULL; - ble_ll_scan_chk_resume(); - } -#endif - OS_EXIT_CRITICAL(sr); - - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); -#endif - - /* If there is an event buf we need to free it */ - if (advsm->conn_comp_ev) { - ble_hci_trans_buf_free(advsm->conn_comp_ev); - advsm->conn_comp_ev = NULL; - } - - ble_ll_adv_active_chanset_clear(advsm); - - /* Disable advertising */ - advsm->adv_enabled = 0; - - /* Check if there is outstanding update */ - ble_ll_adv_update_adv_scan_rsp_data(advsm); - } -} - -static void -ble_ll_adv_sm_stop_timeout(struct ble_ll_adv_sm *advsm) -{ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (ble_ll_hci_adv_mode_ext()) { - ble_ll_hci_ev_send_adv_set_terminated(BLE_ERR_DIR_ADV_TMO, - advsm->adv_instance, 0, - advsm->events); - } -#endif - - /* - * For high duty directed advertising we need to send connection - * complete event with proper status - */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { - ble_ll_conn_comp_event_send(NULL, BLE_ERR_DIR_ADV_TMO, - advsm->conn_comp_ev, advsm); - advsm->conn_comp_ev = NULL; - } - - /* Disable advertising */ - ble_ll_adv_sm_stop(advsm); -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static void -ble_ll_adv_sm_stop_limit_reached(struct ble_ll_adv_sm *advsm) -{ - ble_ll_hci_ev_send_adv_set_terminated(BLE_ERR_LIMIT_REACHED, - advsm->adv_instance, 0, - advsm->events); - - /* - * For high duty directed advertising we need to send connection - * complete event with proper status - * - * Spec is a bit unambiguous here since it doesn't define what code should - * be used if HD directed advertising was terminated before timeout due to - * events count limit. For now just use same code as with duration timeout. - */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { - ble_ll_conn_comp_event_send(NULL, BLE_ERR_DIR_ADV_TMO, - advsm->conn_comp_ev, advsm); - advsm->conn_comp_ev = NULL; - } - - /* Disable advertising */ - ble_ll_adv_sm_stop(advsm); -} -#endif - -static void -ble_ll_adv_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start, void *arg) -{ - /* The event start time is when we start transmission of the adv PDU */ - advsm->adv_event_start_time = sch_start + g_ble_ll_sched_offset_ticks; - advsm->adv_pdu_start_time = advsm->adv_event_start_time; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* this is validated for HD adv so no need to do additional checks here - * duration is in 10ms units - */ - if (advsm->duration) { - advsm->adv_end_time = advsm->adv_event_start_time + - os_cputime_usecs_to_ticks(advsm->duration * 10000); - } -#else - /* Set the time at which we must end directed, high-duty cycle advertising. - */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { - advsm->adv_end_time = advsm->adv_event_start_time + - os_cputime_usecs_to_ticks(BLE_LL_ADV_STATE_HD_MAX * 1000); - } -#endif -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) -static uint8_t -ble_ll_adv_sync_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) -{ - struct ble_ll_adv_sm *advsm; - struct ble_ll_adv_sync *sync; - uint8_t adv_mode; - uint8_t pdu_type; - uint8_t ext_hdr_len; - uint32_t offset; - - advsm = pducb_arg; - sync = SYNC_CURRENT(advsm); - - assert(!ble_ll_adv_active_chanset_is_sec(advsm)); - assert(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); - - /* It's the same for AUX_SYNC_IND and AUX_CHAIN_IND */ - pdu_type = BLE_ADV_PDU_TYPE_AUX_SYNC_IND; - - /* non-connectable and non-scannable */ - adv_mode = 0; - - ext_hdr_len = sync->payload_len - BLE_LL_EXT_ADV_HDR_LEN - sync->sync_data_len; - dptr[0] = (adv_mode << 6) | ext_hdr_len; - dptr += 1; - - /* only put flags if needed */ - if (sync->ext_hdr) { - dptr[0] = sync->ext_hdr; - dptr += 1; - } - - if (sync->ext_hdr & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { - if (!SYNC_NEXT(advsm)->sch.enqueued) { - /* - * Trim data here in case we do not have next sync scheduled. This - * can happen if next sync was outside advertising set period and - * was removed from scheduler. - */ - offset = 0; - } else { - offset = os_cputime_ticks_to_usecs(SYNC_NEXT(advsm)->start_time - sync->start_time); - } - - ble_ll_adv_put_aux_ptr(SYNC_NEXT(advsm)->chan, advsm->sec_phy, - offset, dptr); - - dptr += BLE_LL_EXT_ADV_AUX_PTR_SIZE; - } - - if (sync->ext_hdr & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { - dptr[0] = advsm->adv_txpwr + ble_ll_get_tx_pwr_compensation(); - dptr += BLE_LL_EXT_ADV_TX_POWER_SIZE; - } - - if (sync->sync_data_len) { - os_mbuf_copydata(advsm->periodic_adv_data, sync->sync_data_offset, - sync->sync_data_len, dptr); - } - - *hdr_byte = pdu_type; - - return sync->payload_len; -} - - -static void -ble_ll_adv_sync_tx_done(struct ble_ll_adv_sm *advsm) -{ - /* reset power to max after advertising */ - ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM)); - - /* for sync we trace a no pri nor sec set */ - ble_ll_trace_u32x2(BLE_LL_TRACE_ID_ADV_TXDONE, advsm->adv_instance, 0); - - assert(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); - assert(!ble_ll_adv_active_chanset_is_sec(advsm)); - - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_periodic_txdone_ev); - - ble_ll_state_set(BLE_LL_STATE_STANDBY); - ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); - - /* We no longer have a current state machine */ - g_ble_ll_cur_adv_sm = NULL; -} - -/** - * Called to indicate the advertising sync event is over. - * - * Context: Interrupt - * - * @param advsm - * - */ -static void -ble_ll_adv_sync_tx_end(void *arg) -{ - struct ble_ll_adv_sm *advsm = arg; - - ble_ll_adv_sync_tx_done(advsm); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - /* store last sent periodic counter */ - advsm->periodic_event_cntr_last_sent = advsm->periodic_event_cntr; -#endif -} - -static int -ble_ll_adv_sync_tx_start_cb(struct ble_ll_sched_item *sch) -{ - int rc; - uint32_t txstart; - struct ble_ll_adv_sm *advsm; - struct ble_ll_adv_sync *sync; - - /* Get the state machine for the event */ - advsm = (struct ble_ll_adv_sm *)sch->cb_arg; - - /* Set the current advertiser */ - g_ble_ll_cur_adv_sm = advsm; - - ble_ll_adv_active_chanset_clear(advsm); - ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); - - /* Set the power */ - ble_phy_txpwr_set(advsm->adv_txpwr); - - /* Set channel */ - sync = SYNC_CURRENT(advsm); - rc = ble_phy_setchan(sync->chan, advsm->periodic_access_addr, - advsm->periodic_crcinit); - - assert(rc == 0); - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - /* Set phy mode */ - ble_phy_mode_set(advsm->sec_phy, advsm->sec_phy); -#endif - - /* Set transmit start time. */ - txstart = sch->start_time + g_ble_ll_sched_offset_ticks; - rc = ble_phy_tx_set_start_time(txstart, sch->remainder); - if (rc) { - STATS_INC(ble_ll_stats, adv_late_starts); - goto adv_tx_done; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - ble_phy_encrypt_disable(); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - ble_phy_resolv_list_disable(); -#endif - - /* Transmit advertisement */ - ble_phy_set_txend_cb(ble_ll_adv_sync_tx_end, advsm); - rc = ble_phy_tx(ble_ll_adv_sync_pdu_make, advsm, BLE_PHY_TRANSITION_NONE); - if (rc) { - goto adv_tx_done; - } - - /* disable whitelisting, we are always non-connectable non-scannable */ - ble_ll_whitelist_disable(); - - /* Set link layer state to advertising */ - ble_ll_state_set(BLE_LL_STATE_ADV); - - /* Count # of adv. sent */ - STATS_INC(ble_ll_stats, adv_txg); - - return BLE_LL_SCHED_STATE_RUNNING; - -adv_tx_done: - ble_ll_adv_sync_tx_done(advsm); - return BLE_LL_SCHED_STATE_DONE; -} - -static void -ble_ll_adv_sync_calculate(struct ble_ll_adv_sm *advsm, - struct ble_ll_adv_sync *sync, - uint16_t sync_data_offset, - uint8_t chan) -{ - uint16_t rem_sync_data_len; - uint8_t hdr_len; - - assert(!sync->sch.enqueued); - assert((SYNC_DATA_LEN(advsm) > sync_data_offset) || - (SYNC_DATA_LEN(advsm) == 0 && sync_data_offset == 0)); - - sync->sync_data_offset = sync_data_offset; - sync->sync_data_len = 0; - sync->payload_len = 0; - sync->ext_hdr = 0; - sync->chan = chan; - - rem_sync_data_len = SYNC_DATA_LEN(advsm) - sync_data_offset; - - hdr_len = BLE_LL_EXT_ADV_HDR_LEN; - - /* TxPower if configured - * Note: TxPower shall not be present in chain PDU for SYNC - */ - if (sync_data_offset == 0 && - (advsm->periodic_adv_props & BLE_HCI_LE_SET_PERIODIC_ADV_PROP_INC_TX_PWR)) { - sync->ext_hdr |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT); - hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; - } - - /* if we have any fields in ext header we need to add flags, note that Aux - * PTR is handled later and it will account for flags if needed - * - * This could be handled inside TxPower but lets keep code consistent with - * how Aux calculate works and this also make it easier to add more fields - * into flags if needed in future - */ - if (sync->ext_hdr) { - hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; - } - - /* AdvData always */ - sync->sync_data_len = min(BLE_LL_MAX_PAYLOAD_LEN - hdr_len, rem_sync_data_len); - - /* AuxPtr if there are more AdvData remaining that we can fit here */ - if ((rem_sync_data_len > sync->sync_data_len)) { - /* adjust for flags that needs to be added if AuxPtr is only field - * in Extended Header - */ - if (!sync->ext_hdr) { - hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; - sync->sync_data_len -= BLE_LL_EXT_ADV_FLAGS_SIZE; - } - - sync->ext_hdr |= (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT); - hdr_len += BLE_LL_EXT_ADV_AUX_PTR_SIZE; - sync->sync_data_len -= BLE_LL_EXT_ADV_AUX_PTR_SIZE; - - /* PDU payload should be full if chained */ - assert(hdr_len + sync->sync_data_len == BLE_LL_MAX_PAYLOAD_LEN); - } - - sync->payload_len = hdr_len + sync->sync_data_len; -} - -static void -ble_ll_adv_periodic_schedule_first(struct ble_ll_adv_sm *advsm, - bool first_pdu) -{ - struct ble_ll_adv_sync *sync; - struct ble_ll_sched_item *sch; - uint32_t sch_start; - uint32_t max_usecs; - uint8_t chan; - int rc; - - assert(!advsm->periodic_sync_active); - assert(!advsm->periodic_sync[0].sch.enqueued); - assert(!advsm->periodic_sync[1].sch.enqueued); - - advsm->periodic_sync_active = 1; - advsm->periodic_sync_index = 0; - - sync = SYNC_CURRENT(advsm); - - /* For first SYNC packet in chain we use separate CSA#2 state to maintain - * freq hopping as advertised in SyncInfo - * - * Preincrement event counter as we later send this in PDU so make sure - * same values are used - */ - chan = ble_ll_utils_calc_dci_csa2(++advsm->periodic_event_cntr, - advsm->periodic_channel_id, - advsm->periodic_num_used_chans, - advsm->periodic_chanmap); - - ble_ll_adv_sync_calculate(advsm, sync, 0, chan); - - /* sync is always non-connectable and non-scannable*/ - max_usecs = ble_ll_pdu_tx_time_get(sync->payload_len, advsm->sec_phy); - - sch = &sync->sch; - - advsm->periodic_adv_event_start_time_remainder += advsm->periodic_adv_itvl_rem_usec; - if (advsm->periodic_adv_event_start_time_remainder >= 31) { - advsm->periodic_adv_event_start_time++; - advsm->periodic_adv_event_start_time_remainder -= 31; - } - - sch->start_time = advsm->periodic_adv_event_start_time; - sch->remainder = advsm->periodic_adv_event_start_time_remainder; - sch->end_time = sch->start_time + ble_ll_usecs_to_ticks_round_up(max_usecs); - sch->start_time -= g_ble_ll_sched_offset_ticks; - - rc = ble_ll_sched_periodic_adv(sch, &sch_start, first_pdu); - if (rc) { - STATS_INC(ble_ll_stats, periodic_adv_drop_event); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, - &advsm->adv_periodic_txdone_ev); - return; - } - - sync->start_time = sch_start + g_ble_ll_sched_offset_ticks; - - assert(first_pdu || - (sync->start_time == advsm->periodic_adv_event_start_time)); - - /* The event start time is when we start transmission of the SYNC PDU */ - advsm->periodic_adv_event_start_time = sync->start_time; -} - -static void -ble_ll_adv_sync_next_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start, - void *arg) -{ - struct ble_ll_adv_sync *sync = arg; - - sync->start_time = sch_start + g_ble_ll_sched_offset_ticks; -} - -static void -ble_ll_adv_periodic_schedule_next(struct ble_ll_adv_sm *advsm) -{ - struct ble_ll_adv_sync *sync; - struct ble_ll_adv_sync *sync_next; - struct ble_ll_sched_item *sch; - uint16_t rem_sync_data_len; - uint16_t next_sync_data_offset; - uint32_t max_usecs; - uint8_t chan; - - assert(advsm->periodic_sync_active); - - sync = SYNC_CURRENT(advsm); - sync_next = SYNC_NEXT(advsm); - - assert(!sync_next->sch.enqueued); - - /* - * Do not schedule next sync if current sync is no longer scheduled since we - * do not have reference time for scheduling. - */ - if (!sync->sch.enqueued) { - return; - } - - /* - * Do not schedule next sync if current sync does not have AuxPtr in extended - * header as this means we do not need subsequent ADV_CHAIN_IND to be sent. - */ - if (!(sync->ext_hdr & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT))) { - return; - } - - next_sync_data_offset = sync->sync_data_offset + sync->sync_data_len; - - assert(SYNC_DATA_LEN(advsm) >= next_sync_data_offset); - - rem_sync_data_len = SYNC_DATA_LEN(advsm) - next_sync_data_offset; - assert(rem_sync_data_len > 0); - - /* we use separate counter for chaining */ - chan = ble_ll_utils_calc_dci_csa2(advsm->periodic_chain_event_cntr++, - advsm->periodic_channel_id, - advsm->periodic_num_used_chans, - advsm->periodic_chanmap); - - ble_ll_adv_sync_calculate(advsm, sync_next, next_sync_data_offset, chan); - max_usecs = ble_ll_pdu_tx_time_get(sync_next->payload_len, advsm->sec_phy); - - sync_next->start_time = sync->sch.end_time + - ble_ll_usecs_to_ticks_round_up(BLE_LL_MAFS + MYNEWT_VAL(BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY)); - - sch = &sync_next->sch; - sch->start_time = sync_next->start_time - g_ble_ll_sched_offset_ticks; - - /* adjust for previous packets remainder */ - sch->remainder = sync->sch.remainder; - sch->end_time = sync_next->start_time + - ble_ll_usecs_to_ticks_round_up(max_usecs); - - /* here we can use ble_ll_sched_adv_new as we don't care about timing */ - ble_ll_sched_adv_new(&sync_next->sch, ble_ll_adv_sync_next_scheduled, - sync_next); - - /* if we are pass advertising interval, drop chain */ - if (sch->end_time > advsm->periodic_adv_event_start_time + - advsm->periodic_adv_itvl_ticks) { - STATS_INC(ble_ll_stats, periodic_chain_drop_event); - ble_ll_sched_rmv_elem(&sync->sch); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, - &advsm->adv_periodic_txdone_ev); - } -} - -static void -ble_ll_adv_sync_schedule(struct ble_ll_adv_sm *advsm, bool first_pdu) -{ - /* - * For secondary channel we always start by scheduling two consecutive - * auxiliary packets at once. Then, after sending one packet we try to - * schedule another one as long as there are some data left to send. This - * is to make sure we can always calculate AuxPtr to subsequent packet - * without need to scheduled it in an interrupt. - */ - - ble_ll_adv_periodic_schedule_first(advsm, first_pdu); - ble_ll_adv_periodic_schedule_next(advsm); -} - -static void -ble_ll_adv_reschedule_periodic_event(struct ble_ll_adv_sm *advsm) -{ - advsm->periodic_adv_event_start_time += advsm->periodic_adv_itvl_ticks; - ble_ll_adv_sync_schedule(advsm, false); -} - -static void -ble_ll_adv_update_periodic_data(struct ble_ll_adv_sm *advsm) -{ - if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_NEW_DATA)) { - return; - } - - if (advsm->periodic_sync_active) { - return; - } - - if (advsm->periodic_new_data) { - os_mbuf_free_chain(advsm->periodic_adv_data); - advsm->periodic_adv_data = advsm->periodic_new_data; - advsm->periodic_new_data = NULL; - } - - ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_NEW_DATA); -} - -/** - * Called when periodic packet is txd on secondary channel - * - * Context: Link Layer task. - * - * @param ev - */ -static void -ble_ll_adv_periodic_done(struct ble_ll_adv_sm *advsm) -{ - struct ble_ll_adv_sync *sync; - struct ble_ll_adv_sync *sync_next; - - assert(advsm->periodic_adv_enabled); - assert(advsm->periodic_adv_active); - assert(advsm->periodic_sync_active); - - ble_ll_rfmgmt_release(); - - sync = SYNC_CURRENT(advsm); - sync_next = SYNC_NEXT(advsm); - - /* Remove anything else scheduled for periodic */ - ble_ll_sched_rmv_elem(&sync->sch); - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_periodic_txdone_ev); - - /* If we have next SYNC scheduled, try to schedule another one */ - if (sync_next->sch.enqueued) { - advsm->periodic_sync_index ^= 1; - ble_ll_adv_periodic_schedule_next(advsm); - return; - } - - /* Check if we need to resume scanning */ - ble_ll_scan_chk_resume(); - - advsm->periodic_sync_active = 0; - ble_ll_adv_update_periodic_data(advsm); - ble_ll_adv_reschedule_periodic_event(advsm); -} - -static void -ble_ll_adv_periodic_event_done(struct ble_npl_event *ev) -{ - ble_ll_adv_periodic_done(ble_npl_event_get_arg(ev)); -} - -static void -ble_ll_adv_sm_start_periodic(struct ble_ll_adv_sm *advsm) -{ - uint32_t usecs; - uint32_t ticks; - - /* - * The Advertising DID is not required to change when a SyncInfo field is - * added to or removed from an advertising set. However, if it does not - * change, then scanners may fail to synchronize to periodic advertising - * because entries in the Advertising DID cache (see Section 4.3.3) mean - * they ignore the advertisements containing the SyncInfo field. Therefore, - * advertisers should update the Advertising DID when a periodic advertising - * train is enabled. - */ - ble_ll_adv_update_did(advsm); - - advsm->periodic_adv_active = 1; - - /* keep channel map since we cannot change it later on */ - memcpy(advsm->periodic_chanmap, g_ble_ll_conn_params.master_chan_map, - BLE_LL_CONN_CHMAP_LEN); - advsm->periodic_num_used_chans = g_ble_ll_conn_params.num_used_chans; - advsm->periodic_event_cntr = 0; - /* for chaining we start with random counter as we share access addr */ - advsm->periodic_chain_event_cntr = rand(); - advsm->periodic_access_addr = ble_ll_utils_calc_access_addr(); - advsm->periodic_channel_id = ((advsm->periodic_access_addr & 0xffff0000) >> 16) ^ - (advsm->periodic_access_addr & 0x0000ffff); - advsm->periodic_crcinit = rand() & 0xffffff; - - usecs = (uint32_t)advsm->periodic_adv_itvl_max * BLE_LL_ADV_PERIODIC_ITVL; - ticks = os_cputime_usecs_to_ticks(usecs); - - advsm->periodic_adv_itvl_rem_usec = (usecs - os_cputime_ticks_to_usecs(ticks)); - if (advsm->periodic_adv_itvl_rem_usec == 31) { - advsm->periodic_adv_itvl_rem_usec = 0; - ticks++; - } - advsm->periodic_adv_itvl_ticks = ticks; - - /* There is no point in starting periodic advertising until next advertising - * event since SyncInfo is needed for synchronization - */ - advsm->periodic_adv_event_start_time_remainder = 0; - advsm->periodic_adv_event_start_time = advsm->adv_pdu_start_time + - os_cputime_usecs_to_ticks(advsm->adv_itvl_usecs + 5000); - - ble_ll_adv_sync_schedule(advsm, true); -} - -static void -ble_ll_adv_sm_stop_periodic(struct ble_ll_adv_sm *advsm) -{ - os_sr_t sr; - - ble_ll_rfmgmt_release(); - - if (!advsm->periodic_adv_active) { - return; - } - - /* - * The Advertising DID is not required to change when a SyncInfo field is - * added to or removed from an advertising set. However, if it does not - * change, then scanners may unnecessary try to synchronize to instance that - * no longer has periodic advertising enabled because entries in the - * Advertising DID cache (see Section 4.3.3) mean they ignore the - * advertisements no longer containing the SyncInfo field. Therefore, - * advertisers should update the Advertising DID when a periodic advertising - * train is disabled. - */ - ble_ll_adv_update_did(advsm); - - /* Remove any scheduled advertising items */ - advsm->periodic_adv_active = 0; - advsm->periodic_sync_active = 0; - ble_ll_sched_rmv_elem(&advsm->periodic_sync[0].sch); - ble_ll_sched_rmv_elem(&advsm->periodic_sync[1].sch); - - /* Set to standby if we are no longer advertising */ - OS_ENTER_CRITICAL(sr); - if ((g_ble_ll_cur_adv_sm == advsm) && - (advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING)) { - ble_phy_disable(); - ble_ll_state_set(BLE_LL_STATE_STANDBY); - g_ble_ll_cur_adv_sm = NULL; - ble_ll_scan_chk_resume(); - } - OS_EXIT_CRITICAL(sr); - - ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); - - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, - &advsm->adv_periodic_txdone_ev); - - ble_ll_adv_update_periodic_data(advsm); -} -#endif - -/** - * Start the advertising state machine. This is called when the host sends - * the "enable advertising" command and is not called again while in the - * advertising state. - * - * Context: Link-layer task. - * - * @param advsm Pointer to advertising state machine - * - * @return int - */ -static int -ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) -{ - uint8_t adv_chan; - uint8_t *addr; - uint8_t *evbuf; - uint32_t start_delay_us; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) - uint32_t access_addr; -#endif - const uint8_t *random_addr; - uint32_t earliest_start_time; - int32_t delta; - - /* only clear flags that are not set from HCI */ - ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_TX_ADD | - BLE_LL_ADV_SM_FLAG_RX_ADD | - BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - random_addr = advsm->adv_random_addr; -#else - random_addr = g_random_addr; -#endif - - if (!ble_ll_is_valid_own_addr_type(advsm->own_addr_type, random_addr)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* - * Get an event with which to send the connection complete event if - * this is connectable - */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { - /* We expect this to be NULL but if not we wont allocate one... */ - if (advsm->conn_comp_ev == NULL) { - evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (!evbuf) { - return BLE_ERR_MEM_CAPACITY; - } - advsm->conn_comp_ev = evbuf; - } - } - - /* Set advertising address */ - if ((advsm->own_addr_type & 1) == 0) { - addr = g_dev_addr; - } else { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - addr = advsm->adv_random_addr; -#else - addr = g_random_addr; -#endif - advsm->flags |= BLE_LL_ADV_SM_FLAG_TX_ADD; - } - memcpy(advsm->adva, addr, BLE_DEV_ADDR_LEN); - - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { - memcpy(advsm->initiator_addr, advsm->peer_addr, BLE_DEV_ADDR_LEN); - if (advsm->peer_addr_type & 1) { - advsm->flags |= BLE_LL_ADV_SM_FLAG_RX_ADD; - } - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* This will generate an RPA for both initiator addr and adva */ - if (advsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { - ble_ll_adv_rpa_update(advsm); - } -#endif - - /* Set flag telling us that advertising is enabled */ - advsm->adv_enabled = 1; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) - advsm->event_cntr = 0; - access_addr = ble_ll_utils_calc_access_addr(); - advsm->channel_id = ((access_addr & 0xffff0000) >> 16) ^ - (access_addr & 0x0000ffff); -#endif - - /* Determine the advertising interval we will use */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { - /* Set it to max. allowed for high duty cycle advertising */ - advsm->adv_itvl_usecs = BLE_LL_ADV_PDU_ITVL_HD_MS_MAX; - } else { - advsm->adv_itvl_usecs = (uint32_t)advsm->adv_itvl_max; - advsm->adv_itvl_usecs *= BLE_LL_ADV_ITVL; - } - - /* Set first advertising channel */ - adv_chan = ble_ll_adv_first_chan(advsm); - advsm->adv_chan = adv_chan; - - /* - * Scheduling 1st PDU is a bit tricky. - * Earliest possible start time is after RF is enabled so just force RF to - * start here to see when if will be fully enabled - it will be too early, - * but this is the only reliable way to have it enabled on time. - * Next we calculate expected start time (randomize it a bit) and this is - * used to setup start time for scheduler item. - * Then we check if start time for scheduler item (which includes scheduler - * overhead) is no earlier than calculated earliest possible start time and - * adjust scheduler item if necessary. - */ - earliest_start_time = ble_ll_rfmgmt_enable_now(); - - start_delay_us = rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000); - advsm->adv_pdu_start_time = os_cputime_get32() + - os_cputime_usecs_to_ticks(start_delay_us); - - ble_ll_adv_set_sched(advsm); - - delta = (int32_t)(advsm->adv_sch.start_time - earliest_start_time); - if (delta < 0) { - advsm->adv_sch.start_time -= delta; - advsm->adv_sch.end_time -= delta; - } - - /* This does actual scheduling */ - ble_ll_sched_adv_new(&advsm->adv_sch, ble_ll_adv_scheduled, NULL); - - /* we start periodic before AE since we need PDU start time in SyncInfo */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - if (advsm->periodic_adv_enabled && !advsm->periodic_adv_active) { - ble_ll_adv_sm_start_periodic(advsm); - } -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { - ble_ll_adv_aux_schedule(advsm); - } -#endif - - return BLE_ERR_SUCCESS; -} - -/** - * Called when the LE HCI command read advertising channel tx power command - * has been received. Returns the current advertising transmit power. - * - * Context: Link Layer task (HCI command parser) - * - * @return int - */ -int -ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_le_rd_adv_chan_txpwr_rp *rsp = (void *) rspbuf; - - rsp->power_level = MYNEWT_VAL(BLE_LL_TX_PWR_DBM); - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} - -/** - * Turn advertising on/off. - * - * Context: Link Layer task - * - * @param cmd - * - * @return int - */ -static int -ble_ll_adv_set_enable(uint8_t instance, uint8_t enable, int duration, - uint8_t events) -{ - int rc; - struct ble_ll_adv_sm *advsm; - - advsm = ble_ll_adv_sm_find_configured(instance); - if (!advsm) { - return BLE_ERR_UNK_ADV_INDENT; - } - - rc = BLE_ERR_SUCCESS; - if (enable == 1) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (advsm->flags & BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE) { - return BLE_ERR_CMD_DISALLOWED; - } - - if (ble_ll_hci_adv_mode_ext() && - (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) && - !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) && - SCAN_RSP_DATA_LEN(advsm) == 0) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* handle specifics of HD dir adv enabled in legacy way */ - if (duration < 0) { - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { - duration = BLE_LL_ADV_STATE_HD_MAX / 10; - } else { - duration = 0; - } - } - advsm->duration = duration; - advsm->events_max = events; - advsm->events = 0; -#endif - - /* If already enabled, do nothing */ - if (!advsm->adv_enabled) { - /* Start the advertising state machine */ - rc = ble_ll_adv_sm_start(advsm); - } - } else if (enable == 0) { - ble_ll_adv_sm_stop(advsm); - } else { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - } - - return rc; -} - -int -ble_ll_hci_adv_set_enable(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_adv_enable_cp *cmd = (const void *) cmdbuf; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return ble_ll_adv_set_enable(0, cmd->enable, -1, 0); -} - -static void -ble_ll_adv_update_data_mbuf(struct os_mbuf **omp, bool new_data, uint16_t maxlen, - const void *data, uint16_t datalen) -{ - struct os_mbuf *om; - int ret; - - om = *omp; - - if (new_data) { - if (om) { - os_mbuf_free_chain(om); - } - - om = os_msys_get_pkthdr(datalen, 0); - if (!om) { - goto done; - } - } - - assert(om); - - if (OS_MBUF_PKTLEN(om) + datalen > maxlen) { - os_mbuf_free_chain(om); - om = NULL; - goto done; - } - - ret = os_mbuf_append(om, data, datalen); - if (ret) { - os_mbuf_free_chain(om); - om = NULL; - } - -done: - *omp = om; -} - -/** - * Set the scan response data that the controller will send. - * - * @param cmd - * @param len - * - * @return int - */ -static int -ble_ll_adv_set_scan_rsp_data(const uint8_t *data, uint8_t datalen, - uint8_t instance, uint8_t operation) -{ - struct ble_ll_adv_sm *advsm; - bool new_data; - - advsm = ble_ll_adv_sm_find_configured(instance); - if (!advsm) { - return BLE_ERR_UNK_ADV_INDENT; - } - - /* check if type of advertising support scan rsp */ - if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { - if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - } - - switch (operation) { - case BLE_HCI_LE_SET_DATA_OPER_COMPLETE: - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - if (datalen > BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - } - - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - case BLE_HCI_LE_SET_DATA_OPER_LAST: - /* TODO mark scan rsp as complete? */ - /* fall through */ - case BLE_HCI_LE_SET_DATA_OPER_INT: - if (!advsm->scan_rsp_data) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (advsm->adv_enabled) { - return BLE_ERR_CMD_DISALLOWED; - } - - if (!datalen) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - break; - case BLE_HCI_LE_SET_DATA_OPER_FIRST: - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (advsm->adv_enabled) { - return BLE_ERR_CMD_DISALLOWED; - } - - if (!datalen) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - break; -#endif - default: - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - new_data = (operation == BLE_HCI_LE_SET_DATA_OPER_COMPLETE) || - (operation == BLE_HCI_LE_SET_DATA_OPER_FIRST); - - if (advsm->adv_enabled) { - if (advsm->new_scan_rsp_data) { - ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA); - os_mbuf_free_chain(advsm->new_scan_rsp_data); - advsm->new_scan_rsp_data = NULL; - } - - ble_ll_adv_update_data_mbuf(&advsm->new_scan_rsp_data, new_data, - BLE_ADV_DATA_MAX_LEN, data, datalen); - if (!advsm->new_scan_rsp_data) { - return BLE_ERR_MEM_CAPACITY; - } - ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA); - } else { - ble_ll_adv_update_data_mbuf(&advsm->scan_rsp_data, new_data, - BLE_SCAN_RSP_DATA_MAX_LEN, data, datalen); - if (!advsm->scan_rsp_data) { - return BLE_ERR_MEM_CAPACITY; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* DID shall be updated when host provides new scan response data */ - ble_ll_adv_update_did(advsm); -#endif - } - - return BLE_ERR_SUCCESS; -} - -int -ble_ll_hci_set_scan_rsp_data(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_scan_rsp_data_cp *cmd = (const void *) cmdbuf; - - if ((len != sizeof(*cmd)) || (cmd->scan_rsp_len > sizeof(cmd->scan_rsp))) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return ble_ll_adv_set_scan_rsp_data(cmd->scan_rsp, cmd->scan_rsp_len, 0, - BLE_HCI_LE_SET_DATA_OPER_COMPLETE); -} -/** - * Called by the LL HCI command parser when a set advertising - * data command has been sent from the host to the controller. - * - * @param cmd Pointer to command data - * @param len Length of command data - * - * @return int 0: success; BLE_ERR_INV_HCI_CMD_PARMS otherwise. - */ -static int -ble_ll_adv_set_adv_data(const uint8_t *data, uint8_t datalen, uint8_t instance, - uint8_t operation) -{ - struct ble_ll_adv_sm *advsm; - bool new_data; - - advsm = ble_ll_adv_sm_find_configured(instance); - if (!advsm) { - return BLE_ERR_UNK_ADV_INDENT; - } - - /* check if type of advertising support adv data */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { - if (ble_ll_hci_adv_mode_ext()) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - } - } else { - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - } - - switch (operation) { - case BLE_HCI_LE_SET_DATA_OPER_COMPLETE: - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - if (datalen > BLE_ADV_LEGACY_DATA_MAX_LEN) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - } - - ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE); - - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - case BLE_HCI_LE_SET_DATA_OPER_UNCHANGED: - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (!advsm->adv_enabled || !ADV_DATA_LEN(advsm) || datalen) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* update DID only */ - ble_ll_adv_update_did(advsm); - return BLE_ERR_SUCCESS; - case BLE_HCI_LE_SET_DATA_OPER_LAST: - ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE); - /* fall through */ - case BLE_HCI_LE_SET_DATA_OPER_INT: - if (!advsm->adv_data) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (!datalen) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (advsm->adv_enabled) { - return BLE_ERR_CMD_DISALLOWED; - } - break; - case BLE_HCI_LE_SET_DATA_OPER_FIRST: - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (advsm->adv_enabled) { - return BLE_ERR_CMD_DISALLOWED; - } - - if (!datalen) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE); - break; -#endif - default: - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - new_data = (operation == BLE_HCI_LE_SET_DATA_OPER_COMPLETE) || - (operation == BLE_HCI_LE_SET_DATA_OPER_FIRST); - - if (advsm->adv_enabled) { - if (advsm->new_adv_data) { - ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA); - os_mbuf_free_chain(advsm->new_adv_data); - advsm->new_adv_data = NULL; - } - - ble_ll_adv_update_data_mbuf(&advsm->new_adv_data, new_data, - BLE_ADV_DATA_MAX_LEN, data, datalen); - if (!advsm->new_adv_data) { - return BLE_ERR_MEM_CAPACITY; - } - ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA); - } else { - ble_ll_adv_update_data_mbuf(&advsm->adv_data, new_data, - BLE_ADV_DATA_MAX_LEN, data, datalen); - if (!advsm->adv_data) { - return BLE_ERR_MEM_CAPACITY; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* DID shall be updated when host provides new advertising data */ - ble_ll_adv_update_did(advsm); -#endif - } - - return BLE_ERR_SUCCESS; -} - -int -ble_ll_hci_set_adv_data(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_adv_data_cp *cmd = (const void *) cmdbuf; - - if ((len != sizeof(*cmd)) || (cmd->adv_data_len > sizeof(cmd->adv_data))) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return ble_ll_adv_set_adv_data(cmd->adv_data, cmd->adv_data_len, 0, - BLE_HCI_LE_SET_DATA_OPER_COMPLETE); -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static bool -pri_phy_valid(uint8_t phy) -{ - switch (phy) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - case BLE_HCI_LE_PHY_CODED: -#endif - case BLE_HCI_LE_PHY_1M: - return true; - default: - return false; - } -} - -static bool -sec_phy_valid(uint8_t phy) -{ - switch (phy) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - case BLE_HCI_LE_PHY_CODED: -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - case BLE_HCI_LE_PHY_2M: -#endif - case BLE_HCI_LE_PHY_1M: - return true; - default: - return false; - } -} - -static struct ble_ll_adv_sm * -ble_ll_adv_sm_get(uint8_t instance) -{ - struct ble_ll_adv_sm *advsm; - int i; - - advsm = ble_ll_adv_sm_find_configured(instance); - if (advsm) { - return advsm; - } - - for (i = 0; i < ARRAY_SIZE(g_ble_ll_adv_sm); i++) { - advsm = &g_ble_ll_adv_sm[i]; - - if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_CONFIGURED)) { - ble_ll_adv_sm_init(advsm); - - /* configured flag is set by caller on success config */ - advsm->adv_instance = instance; - return advsm; - } - } - - return NULL; -} - -int -ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_set_ext_adv_params_cp *cmd = (const void *) cmdbuf; - struct ble_hci_le_set_ext_adv_params_rp *rsp = (void *) rspbuf; - struct ble_ll_adv_sm *advsm; - uint32_t adv_itvl_min; - uint32_t adv_itvl_max; - uint16_t props; - int rc; - - if (len != sizeof(*cmd )) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - advsm = ble_ll_adv_sm_get(cmd->adv_handle); - if (!advsm) { - rc = BLE_ERR_MEM_CAPACITY; - goto done; - } - - if (advsm->adv_enabled) { - rc = BLE_ERR_CMD_DISALLOWED; - goto done; - } - - props = le16toh(cmd->props); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - /* If the Host issues this command when periodic advertising is enabled for - * the specified advertising set and connectable, scannable, legacy, or - * anonymous advertising is specified, the Controller shall return the - * error code Invalid HCI Command Parameters (0x12). - */ - if (advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_CONFIGURED) { - if (advsm->periodic_adv_enabled) { - if (props & (BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE | - BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE | - BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY | - BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - } - } -#endif - - adv_itvl_min = cmd->pri_itvl_min[2] << 16 | cmd->pri_itvl_min[1] << 8 | - cmd->pri_itvl_min[0]; - adv_itvl_max = cmd->pri_itvl_max[2] << 16 | cmd->pri_itvl_max[1] << 8 | - cmd->pri_itvl_max[0]; - - if (props & ~BLE_HCI_LE_SET_EXT_ADV_PROP_MASK) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - if (ADV_DATA_LEN(advsm) > BLE_ADV_LEGACY_DATA_MAX_LEN || - SCAN_RSP_DATA_LEN(advsm) > BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - /* if legacy bit is set possible values are limited */ - switch (props) { - case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_IND: - case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_LD_DIR: - case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_HD_DIR: - case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_SCAN: - case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_NONCONN: - break; - default: - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - } else { - /* HD directed advertising allowed only on legacy PDUs */ - if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - /* if ext advertising PDUs are used then it shall not be both - * connectable and scanable - */ - if ((props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) && - (props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - } - - /* High Duty Directed advertising is special */ - if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { - if (ADV_DATA_LEN(advsm) || SCAN_RSP_DATA_LEN(advsm)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - /* Ignore min/max interval */ - adv_itvl_min = 0; - adv_itvl_max = 0; - } else { - /* validate intervals for non HD-directed advertising */ - if ((adv_itvl_min > adv_itvl_max) || - (adv_itvl_min < BLE_HCI_ADV_ITVL_MIN) || - (adv_itvl_max < BLE_HCI_ADV_ITVL_MIN)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - /* TODO for now limit those to values from legacy advertising - * - * If the primary advertising interval range is outside the advertising - * interval range supported by the Controller, then the Controller shall - * return the error code Unsupported Feature or Parameter Value (0x11). - */ - if ((adv_itvl_min > BLE_HCI_ADV_ITVL_MAX) || - (adv_itvl_max > BLE_HCI_ADV_ITVL_MAX)) { - rc = BLE_ERR_UNSUPPORTED; - goto done; - } - } - - /* There are only three adv channels, so check for any outside the range */ - if (((cmd->pri_chan_map & 0xF8) != 0) || (cmd->pri_chan_map == 0)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - -#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* If we dont support privacy some address types wont work */ - if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { - rc = BLE_ERR_UNSUPPORTED; - goto done; - } -#endif - - /* peer address type is only valid for directed */ - if ((props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) && - (cmd->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - /* Check filter policy (valid only for undirected) */ - if (!(props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) && - cmd->filter_policy > BLE_HCI_ADV_FILT_MAX) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - if (!pri_phy_valid(cmd->pri_phy)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - /* check secondary phy only if not using legacy PDUs */ - if (!(props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) && - !sec_phy_valid(cmd->sec_phy)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - if (cmd->sid > 0x0f) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - if (cmd->scan_req_notif > 0x01) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - rc = BLE_ERR_SUCCESS; - - if (cmd->tx_power == 127) { - /* no preference */ - advsm->adv_txpwr = MYNEWT_VAL(BLE_LL_TX_PWR_DBM); - } else { - advsm->adv_txpwr = ble_phy_txpower_round(cmd->tx_power); - } - - /* we can always store as those are validated and used only when needed */ - advsm->peer_addr_type = cmd->peer_addr_type; - memcpy(advsm->peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); - advsm->own_addr_type = cmd->own_addr_type; - advsm->adv_filter_policy = cmd->filter_policy; - advsm->adv_chanmask = cmd->pri_chan_map; - advsm->adv_itvl_min = adv_itvl_min; - advsm->adv_itvl_max = adv_itvl_max; - advsm->pri_phy = cmd->pri_phy; - advsm->sec_phy = cmd->sec_phy; - /* Update SID only */ - advsm->adi = (advsm->adi & 0x0fff) | ((cmd->sid << 12)); - - advsm->props = props; - - /* Set proper mbuf chain for aux data */ - if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - advsm->aux_data = NULL; - } else if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { - advsm->aux_data = &advsm->scan_rsp_data; - } else { - advsm->aux_data = &advsm->adv_data; - } - - if (cmd->scan_req_notif) { - ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF); - } else { - ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF); - } - - ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_CONFIGURED); - -done: - /* Update TX power */ - rsp->tx_power = rc ? 0 : advsm->adv_txpwr; - - *rsplen = sizeof(*rsp); - return rc; -} - -int -ble_ll_adv_ext_set_adv_data(const uint8_t *cmdbuf, uint8_t cmdlen) -{ - const struct ble_hci_le_set_ext_adv_data_cp *cmd = (const void *) cmdbuf; - - if (cmdlen < sizeof(*cmd )) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (cmd->adv_data_len > BLE_HCI_MAX_EXT_ADV_DATA_LEN || - cmd->adv_data_len > cmdlen - sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* TODO fragment preference ignored for now */ - - return ble_ll_adv_set_adv_data(cmd->adv_data, cmd->adv_data_len, - cmd->adv_handle, cmd->operation); -} - -int -ble_ll_adv_ext_set_scan_rsp(const uint8_t *cmdbuf, uint8_t cmdlen) -{ - const struct ble_hci_le_set_ext_scan_rsp_data_cp *cmd = (const void *) cmdbuf; - - if (cmdlen < sizeof(*cmd )) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (cmd->scan_rsp_len > BLE_HCI_MAX_EXT_ADV_DATA_LEN || - cmd->scan_rsp_len > cmdlen - sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* TODO fragment preference ignored for now */ - - return ble_ll_adv_set_scan_rsp_data(cmd->scan_rsp, cmd->scan_rsp_len, - cmd->adv_handle, cmd->operation); -} - -/** - * HCI LE extended advertising enable command - * - * @param cmd Pointer to command data - * @param len Command data length - * - * @return int BLE error code - */ -int -ble_ll_adv_ext_set_enable(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_ext_adv_enable_cp *cmd = (const void *) cmdbuf; - struct ble_ll_adv_sm *advsm; - int i, j, rc; - - if (len < sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* check if length is correct */ - if (len != 2 + (cmd->num_sets * sizeof(cmd->sets[0]))) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (cmd->num_sets > BLE_ADV_INSTANCES) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (cmd->num_sets == 0) { - if (cmd->enable) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* disable all instances */ - for (i = 0; i < BLE_ADV_INSTANCES; i++) { - ble_ll_adv_set_enable(i, 0, 0, 0); - } - - return BLE_ERR_SUCCESS; - } - - /* validate instances */ - for (i = 0; i < cmd->num_sets; i++) { - /* validate duplicated sets */ - for (j = i + 1; j < cmd->num_sets; j++) { - if (cmd->sets[i].adv_handle == cmd->sets[j].adv_handle) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - } - - advsm = ble_ll_adv_sm_find_configured(cmd->sets[i].adv_handle); - if (!advsm) { - return BLE_ERR_UNK_ADV_INDENT; - } - - if (cmd->enable) { - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { - if (cmd->sets[i].duration == 0 || - le16toh(cmd->sets[i].duration) > 128) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - } - } - } - - for (i = 0; i < cmd->num_sets; i++) { - rc = ble_ll_adv_set_enable(cmd->sets[i].adv_handle, cmd->enable, - le16toh(cmd->sets[i].duration), - cmd->sets[i].max_events); - if (rc) { - return rc; - } - } - - return BLE_ERR_SUCCESS; -} - -int -ble_ll_adv_set_random_addr(const uint8_t *addr, uint8_t instance) -{ - struct ble_ll_adv_sm *advsm; - - advsm = ble_ll_adv_sm_find_configured(instance); - if (!advsm) { - return BLE_ERR_UNK_ADV_INDENT; - } - - /* - * Reject if connectable advertising is on - * Core Spec Vol. 2 Part E 7.8.52 - */ - if (advsm->adv_enabled && - (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE)) { - return BLE_ERR_CMD_DISALLOWED; - } - - memcpy(advsm->adv_random_addr, addr, BLE_DEV_ADDR_LEN); - return BLE_ERR_SUCCESS; -} - -int -ble_ll_adv_hci_set_random_addr(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_adv_set_rnd_addr_cp *cmd = (const void *) cmdbuf; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return ble_ll_adv_set_random_addr(cmd->addr, cmd->adv_handle); -} - -/** - * HCI LE extended advertising remove command - * - * @return int BLE error code - */ -int -ble_ll_adv_remove(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_remove_adv_set_cp *cmd = (const void *) cmdbuf; - struct ble_ll_adv_sm *advsm; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - advsm = ble_ll_adv_sm_find_configured(cmd->adv_handle); - if (!advsm) { - return BLE_ERR_UNK_ADV_INDENT; - } - - if (advsm->adv_enabled) { - return BLE_ERR_CMD_DISALLOWED; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - if (advsm->periodic_adv_enabled) { - return BLE_ERR_CMD_DISALLOWED; - } - - if (advsm->periodic_adv_data) { - os_mbuf_free_chain(advsm->periodic_adv_data); - } -#endif - - if (advsm->adv_data) { - os_mbuf_free_chain(advsm->adv_data); - } - if (advsm->scan_rsp_data) { - os_mbuf_free_chain(advsm->scan_rsp_data); - } - - ble_ll_adv_sm_init(advsm); - - return BLE_ERR_SUCCESS; -} - -/** - * HCI LE extended advertising clear command - * - * @return int BLE error code - */ -int -ble_ll_adv_clear_all(void) -{ - int i; - - for (i = 0; i < BLE_ADV_INSTANCES; i++) { - if (g_ble_ll_adv_sm[i].adv_enabled) { - return BLE_ERR_CMD_DISALLOWED; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - if (g_ble_ll_adv_sm[i].periodic_adv_enabled) { - return BLE_ERR_CMD_DISALLOWED; - } -#endif - } - - ble_ll_adv_reset(); - - return BLE_ERR_SUCCESS; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) -static uint16_t -ble_ll_adv_sync_get_pdu_len(uint16_t data_len, uint16_t *data_offset, - uint16_t props) -{ - uint16_t rem_data_len = data_len - *data_offset; - uint8_t hdr_len = BLE_LL_EXT_ADV_HDR_LEN; - uint8_t ext_hdr = 0; - - /* TxPower if configured - * Note: TxPower shall not be present in chain PDU for SYNC - */ - if (*data_offset == 0 && - (props & BLE_HCI_LE_SET_PERIODIC_ADV_PROP_INC_TX_PWR)) { - ext_hdr |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT); - hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; - } - - /* if we have any fields in ext header we need to add flags, note that Aux - * PTR is handled later and it will account for flags if needed - * - * This could be handled inside TxPower but lets keep code consistent with - * how Aux calculate works and this also make it easier to add more fields - * into flags if needed in future - */ - if (ext_hdr) { - hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; - } - - /* AdvData always */ - data_len = min(BLE_LL_MAX_PAYLOAD_LEN - hdr_len, rem_data_len); - - /* AuxPtr if there are more AdvData remaining that we can fit here */ - if (rem_data_len > data_len) { - /* adjust for flags that needs to be added if AuxPtr is only field - * in Extended Header - */ - if (!ext_hdr) { - hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; - data_len -= BLE_LL_EXT_ADV_FLAGS_SIZE; - } - - hdr_len += BLE_LL_EXT_ADV_AUX_PTR_SIZE; - data_len -= BLE_LL_EXT_ADV_AUX_PTR_SIZE; - - /* PDU payload should be full if chained */ - BLE_LL_ASSERT(hdr_len + data_len == BLE_LL_MAX_PAYLOAD_LEN); - } - - *data_offset += data_len; - - return hdr_len + data_len; -} - -static bool -ble_ll_adv_periodic_check_data_itvl(uint16_t payload_len, uint16_t props, - uint16_t itvl, uint8_t phy) -{ - uint32_t max_usecs = 0; - uint32_t itvl_usecs; - uint16_t offset = 0; - uint16_t pdu_len; - - while (offset < payload_len) { - pdu_len = ble_ll_adv_sync_get_pdu_len(payload_len, &offset, props); - - max_usecs += ble_ll_pdu_tx_time_get(pdu_len, phy); - max_usecs += ble_ll_usecs_to_ticks_round_up(BLE_LL_MAFS + - MYNEWT_VAL(BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY)); - } - - itvl_usecs = (uint32_t)itvl * BLE_LL_ADV_PERIODIC_ITVL; - - return max_usecs < itvl_usecs; -} - -int -ble_ll_adv_periodic_set_param(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_periodic_adv_params_cp *cmd = (const void *) cmdbuf; - struct ble_ll_adv_sm *advsm; - uint16_t adv_itvl_min; - uint16_t adv_itvl_max; - uint16_t props; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - adv_itvl_min = le16toh(cmd->min_itvl); - adv_itvl_max = le16toh(cmd->max_itvl); - props = le16toh(cmd->props); - - advsm = ble_ll_adv_sm_find_configured(cmd->adv_handle); - if (!advsm) { - return BLE_ERR_UNK_ADV_INDENT; - } - - /* If the advertising set identified by the Advertising_Handle specified - * scannable, connectable, legacy, or anonymous advertising, the Controller - * shall return the error code Invalid HCI Command Parameters (0x12). - */ - if (advsm->props & (BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV | - BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE | - BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE | - BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* If the Host issues this command when periodic advertising is enabled for - * the specified advertising set, the Controller shall return the error code - * Command Disallowed (0x0C). - */ - if (advsm->periodic_adv_enabled) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* validate intervals */ - if ((adv_itvl_min < 0x0006) || (adv_itvl_max < 0x006) || - (adv_itvl_min > adv_itvl_max)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* validate properties */ - if (props & ~BLE_HCI_LE_SET_PERIODIC_ADV_PROP_MASK) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* If the advertising set already contains periodic advertising data and the - * length of the data is greater than the maximum that the Controller can - * transmit within a periodic advertising interval of - * Periodic_Advertising_Interval_Max, the Controller shall return the error - * code Packet Too Long (0x45). - */ - if (!ble_ll_adv_periodic_check_data_itvl(SYNC_DATA_LEN(advsm), props, - adv_itvl_max, advsm->sec_phy)) { - return BLE_ERR_PACKET_TOO_LONG; - } - - advsm->periodic_adv_itvl_min = adv_itvl_min; - advsm->periodic_adv_itvl_max = adv_itvl_max; - advsm->periodic_adv_props = props; - - ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_CONFIGURED); - - return BLE_ERR_SUCCESS; -} - -int -ble_ll_adv_periodic_set_data(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_periodic_adv_data_cp *cmd = (const void *) cmdbuf; - struct ble_ll_adv_sm *advsm; - uint16_t payload_total_len; - bool new_data = false; - - if (len < sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (cmd->adv_data_len > BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN || - cmd->adv_data_len != len - sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - advsm = ble_ll_adv_sm_find_configured(cmd->adv_handle); - if (!advsm) { - return BLE_ERR_UNK_ADV_INDENT; - } - - if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_CONFIGURED)) { - return BLE_ERR_CMD_DISALLOWED; - } - - switch (cmd->operation) { - case BLE_HCI_LE_SET_DATA_OPER_LAST: - case BLE_HCI_LE_SET_DATA_OPER_INT: - if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_DATA_INCOMPLETE)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (!advsm->periodic_adv_data || !cmd->adv_data_len) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (advsm->periodic_adv_enabled) { - return BLE_ERR_CMD_DISALLOWED; - } - break; - case BLE_HCI_LE_SET_DATA_OPER_FIRST: - if (advsm->periodic_adv_enabled) { - return BLE_ERR_CMD_DISALLOWED; - } - - if (!cmd->adv_data_len) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - new_data = true; - break; - case BLE_HCI_LE_SET_DATA_OPER_COMPLETE: - new_data = true; - break; - default: - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - payload_total_len = cmd->adv_data_len; - if (!new_data) { - payload_total_len += SYNC_DATA_LEN(advsm); - } - - /* If the combined length of the data is greater than the maximum that the - * Controller can transmit within the current periodic advertising interval - * (if periodic advertising is currently enabled) or the - * Periodic_Advertising_Interval_Max for the advertising set (if currently - * disabled), all the data shall be discarded and the Controller shall - * return the error code Packet Too Long (0x45). - */ - if (!ble_ll_adv_periodic_check_data_itvl(payload_total_len, - advsm->periodic_adv_props, - advsm->periodic_adv_itvl_max, - advsm->sec_phy)) { - return BLE_ERR_PACKET_TOO_LONG; - } - - if (advsm->periodic_adv_active) { - ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_NEW_DATA); - - ble_ll_adv_update_data_mbuf(&advsm->periodic_new_data, true, - BLE_ADV_DATA_MAX_LEN, - cmd->adv_data, cmd->adv_data_len); - if (!advsm->periodic_new_data) { - return BLE_ERR_MEM_CAPACITY; - } - - ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_NEW_DATA); - } else { - ble_ll_adv_update_data_mbuf(&advsm->periodic_adv_data, new_data, - BLE_ADV_DATA_MAX_LEN, cmd->adv_data, - cmd->adv_data_len); - if (!advsm->periodic_adv_data) { - return BLE_ERR_MEM_CAPACITY; - } - } - - /* set/clear incomplete data flag only on success */ - switch (cmd->operation) { - case BLE_HCI_LE_SET_DATA_OPER_LAST: - case BLE_HCI_LE_SET_DATA_OPER_COMPLETE: - ble_ll_adv_flags_clear(advsm, - BLE_LL_ADV_SM_FLAG_PERIODIC_DATA_INCOMPLETE); - break; - case BLE_HCI_LE_SET_DATA_OPER_INT: - case BLE_HCI_LE_SET_DATA_OPER_FIRST: - default: - ble_ll_adv_flags_set(advsm, - BLE_LL_ADV_SM_FLAG_PERIODIC_DATA_INCOMPLETE); - break; - } - - return BLE_ERR_SUCCESS; -} - -int -ble_ll_adv_periodic_enable(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_periodic_adv_enable_cp *cmd = (const void *)cmdbuf; - struct ble_ll_adv_sm *advsm; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - advsm = ble_ll_adv_sm_find_configured(cmd->adv_handle); - if (!advsm) { - return BLE_ERR_UNK_ADV_INDENT; - } - - if (cmd->enable) { - if (advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_DATA_INCOMPLETE) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* If Enable is set to 0x01 and the length of the periodic advertising - * data is greater than the maximum that the Controller can transmit - * within the chosen periodicadvertising interval, the Controller shall - * return the error code Packet Too Long (0x45). - */ - if (!ble_ll_adv_periodic_check_data_itvl(SYNC_DATA_LEN(advsm), - advsm->periodic_adv_props, - advsm->periodic_adv_itvl_max, - advsm->sec_phy)) { - return BLE_ERR_PACKET_TOO_LONG; - } - - /* If the advertising set is not currently enabled (see the - * LE_Set_Extended_Advertising_Enable command), the periodic advertising - * is not started until the advertising set is enabled. - */ - if (advsm->adv_enabled && !advsm->periodic_adv_active) { - /* Start the periodic advertising state machine */ - ble_ll_adv_sm_start_periodic(advsm); - } - } else { - /* Stop the periodic advertising state machine */ - ble_ll_adv_sm_stop_periodic(advsm); - } - - advsm->periodic_adv_enabled = cmd->enable; - - return BLE_ERR_SUCCESS; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -static int -ble_ll_adv_periodic_send_sync_ind(struct ble_ll_adv_sm *advsm, - struct ble_ll_conn_sm *connsm, - uint16_t service_data) -{ - struct os_mbuf *om; - uint8_t *sync_ind; - - om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN, - sizeof(struct ble_mbuf_hdr)); - if (!om) { - return BLE_ERR_MEM_CAPACITY; - } - - om->om_data[0] = BLE_LL_CTRL_PERIODIC_SYNC_IND; - - sync_ind = om->om_data + 1; - - /* ID (service_data), already in LE order */ - memcpy(sync_ind, &service_data, sizeof(service_data)); - - /* fill in syncinfo */ - ble_ll_adv_put_syncinfo(advsm, connsm, sync_ind + 20, sync_ind + 2); - - /* lastPaEventCounter */ - put_le16(sync_ind + 22, advsm->periodic_event_cntr_last_sent); - - /* SID, AType, SCA */ - sync_ind[24] = (advsm->adi >> 12); - sync_ind[24] |= !!(advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) << 4 ; - sync_ind[24] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5; - - /* PHY */ - sync_ind[25] = (0x01 << (advsm->sec_phy - 1)); - - /* AdvA */ - memcpy(sync_ind + 26, advsm->adva, BLE_DEV_ADDR_LEN); - - /* syncConnEventCount */ - put_le16(sync_ind + 32, connsm->event_cntr); - - ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, - BLE_LL_CTRL_PERIODIC_SYNC_IND_LEN + 1); - - return BLE_ERR_SUCCESS; -} - -int -ble_ll_adv_periodic_set_info_transfer(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_periodic_adv_set_info_transfer_cp *cmd = (const void *)cmdbuf; - struct ble_hci_le_periodic_adv_set_info_transfer_rp *rsp = (void *) rspbuf; - struct ble_ll_conn_sm *connsm; - struct ble_ll_adv_sm *advsm; - uint16_t handle; - int rc; - - if (len != sizeof(*cmd)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - advsm = ble_ll_adv_sm_find_configured(cmd->adv_handle); - if (!advsm) { - rc = BLE_ERR_UNK_ADV_INDENT; - goto done; - } - - if (!advsm->periodic_adv_active) { - rc = BLE_ERR_CMD_DISALLOWED; - goto done; - } - - handle = le16toh(cmd->conn_handle); - if (handle > 0xeff) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - connsm = ble_ll_conn_find_active_conn(handle); - if (!connsm) { - rc = BLE_ERR_UNK_CONN_ID; - goto done; - } - - /* TODO should not need to shift - * byte 3 (0 byte is conn_feature) , bit 1 - * - * Allow initiate LL procedure only if remote supports it. - */ - if (!(connsm->remote_features[2] & (BLE_LL_FEAT_SYNC_TRANS_RECV >> (8 * 3)))) { - rc = BLE_ERR_UNSUPP_REM_FEATURE; - goto done; - } - - rc = ble_ll_adv_periodic_send_sync_ind(advsm, connsm, cmd->service_data); - done: - rsp->conn_handle = cmd->conn_handle; - *rsplen = sizeof(*rsp); - return rc; -} -#endif -#endif -#endif - -/** - * Says whether the specified address is already connected or not. - * @param [in] addr The peer address. - * @param [in] addr_type Public address (0) or random address (1). - * @return Return 1 if already connected, 0 otherwise. - */ -static int -ble_ll_adv_already_connected(const uint8_t* addr, uint8_t addr_type) -{ - struct ble_ll_conn_sm *connsm; - - /* extracted from ble_ll_conn_slave_start function */ - SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) { - if (!memcmp(&connsm->peer_addr, addr, BLE_DEV_ADDR_LEN)) { - if (addr_type == BLE_ADDR_RANDOM) { - if (connsm->peer_addr_type & 1) { - return 1; - } - } else { - if ((connsm->peer_addr_type & 1) == 0) { - return 1; - } - } - } - } - - return 0; -} - -/** - * Called when the LL receives a scan request or connection request - * - * Context: Called from interrupt context. - * - * @param rxbuf - * - * @return -1: request not for us or is a connect request. - * 0: request (scan) is for us and we successfully went from rx to tx. - * > 0: PHY error attempting to go from rx to tx. - */ -static int -ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) -{ - int rc; - int resolved; - uint8_t chk_wl; - uint8_t txadd; - uint8_t peer_addr_type; - uint8_t *rxbuf; - uint8_t *adva; - uint8_t *peer; - struct ble_mbuf_hdr *ble_hdr; - struct ble_ll_adv_sm *advsm; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct aux_conn_rsp_data rsp_data; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - struct ble_ll_resolv_entry *rl; -#endif - - /* See if adva in the request (scan or connect) matches what we sent */ - advsm = g_ble_ll_cur_adv_sm; - rxbuf = rxpdu->om_data; - adva = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN; - if (memcmp(advsm->adva, adva, BLE_DEV_ADDR_LEN)) { - return -1; - } - - /* Set device match bit if we are whitelisting */ - if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { - chk_wl = advsm->adv_filter_policy & 1; - } else { - chk_wl = advsm->adv_filter_policy & 2; - } - - /* Get the peer address type */ - if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) { - txadd = BLE_ADDR_RANDOM; - } else { - txadd = BLE_ADDR_PUBLIC; - } - - ble_hdr = BLE_MBUF_HDR_PTR(rxpdu); - peer = rxbuf + BLE_LL_PDU_HDR_LEN; - peer_addr_type = txadd; - resolved = 0; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - rl = NULL; - if (ble_ll_resolv_enabled()) { - if (ble_ll_is_rpa(peer, txadd)) { - advsm->adv_rpa_index = ble_hw_resolv_list_match(); - if (advsm->adv_rpa_index >= 0) { - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_RESOLVED; - rl = &g_ble_ll_resolv_list[advsm->adv_rpa_index]; - if (chk_wl) { - peer = rl->rl_identity_addr; - peer_addr_type = rl->rl_addr_type; - resolved = 1; - } - } else { - if (chk_wl) { - return -1; - } - } - } else { - /* Verify privacy mode */ - rl = ble_ll_resolv_list_find(peer, peer_addr_type); - if (rl && (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && - rl->rl_has_peer) { - return -1; - } - } - } -#endif - - /* Set device match bit if we are whitelisting */ - if (chk_wl && !ble_ll_whitelist_match(peer, peer_addr_type, resolved)) { - return -1; - } - - /* - * We set the device match bit to tell the upper layer that we will - * accept the request - */ - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH; - - /* Setup to transmit the scan response if appropriate */ - rc = -1; - - if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { - /* PHY used for scan requests shall be the same as the PHY used for the - * PDU that they reply to so no need to change PHY mode. - */ - ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (advsm->flags & BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF) { - ble_ll_hci_ev_send_scan_req_recv(advsm->adv_instance, peer, - peer_addr_type); - } - - /* - * We need to store current rxed packet header temporarily so AuxPtr - * can be calculated (if necessary) relative to AUX_SCAN_RSP instead of - * AUX_ADV_IND. - */ - - advsm->rx_ble_hdr = ble_hdr; - rc = ble_phy_tx(ble_ll_adv_scan_rsp_pdu_make, advsm, - BLE_PHY_TRANSITION_NONE); - advsm->rx_ble_hdr = NULL; -#else - rc = ble_phy_tx(ble_ll_adv_scan_rsp_legacy_pdu_make, advsm, - BLE_PHY_TRANSITION_NONE); -#endif - - if (!rc) { - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_SCAN_RSP_TXD; - STATS_INC(ble_ll_stats, scan_rsp_txg); - } - } else if (pdu_type == BLE_ADV_PDU_TYPE_AUX_CONNECT_REQ) { - /* See if the device is already connected */ - if (ble_ll_adv_already_connected(peer, peer_addr_type)) { - return -1; - } - - /* - * Only accept connect requests from the desired address if we - * are doing directed advertising - */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { - if (memcmp(advsm->initiator_addr, peer, BLE_DEV_ADDR_LEN)) { - return -1; - } - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - return -1; - } - - /* use remote address used over the air */ - rsp_data.advsm = advsm; - rsp_data.peer = rxbuf + BLE_LL_PDU_HDR_LEN; - rsp_data.rxadd = rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK; - - ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm); - rc = ble_phy_tx(ble_ll_adv_aux_conn_rsp_pdu_make, &rsp_data, - BLE_PHY_TRANSITION_NONE); - if (!rc) { - ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD); - STATS_INC(ble_ll_stats, aux_conn_rsp_tx); - } -#endif - } - - return rc; -} - -/** - * Called when a connect request has been received. - * - * Context: Link Layer - * - * @param rxbuf - * @param flags - * - * @return 0: no connection started. 1: connection started - */ -static int -ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr, - struct ble_ll_adv_sm *advsm) -{ - int valid; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - uint8_t resolved; -#endif - uint8_t addr_type; - uint8_t *inita; - uint8_t *ident_addr; - - /* Don't create connection if AUX_CONNECT_RSP was not send */ - if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { - if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD)) { - return 0; - } - } - - /* Check filter policy. */ - valid = 0; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - resolved = BLE_MBUF_HDR_RESOLVED(hdr); -#endif - inita = rxbuf + BLE_LL_PDU_HDR_LEN; - if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_DEVMATCH) { - - valid = 1; - if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) { - addr_type = BLE_ADDR_RANDOM; - } else { - addr_type = BLE_ADDR_PUBLIC; - } - - /* - * Only accept connect requests from the desired address if we - * are doing directed advertising - */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { - ident_addr = inita; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (resolved) { - ident_addr = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_identity_addr; - addr_type = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_addr_type; - } -#endif - if ((addr_type != advsm->peer_addr_type) || - memcmp(advsm->peer_addr, ident_addr, BLE_DEV_ADDR_LEN)) { - valid = 0; - } - } - } - - if (valid) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (resolved) { - /* Retain the resolvable private address that we received. */ - memcpy(advsm->adv_rpa, inita, BLE_DEV_ADDR_LEN); - - /* Update resolving list with current peer RPA */ - ble_ll_resolv_set_peer_rpa(advsm->adv_rpa_index, inita); - - /* - * Overwrite received inita with identity address since that - * is used from now on. - */ - memcpy(inita, - g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_identity_addr, - BLE_DEV_ADDR_LEN); - - /* Peer address type is an identity address */ - addr_type = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_addr_type; - addr_type += 2; - } -#endif - - /* Try to start slave connection. If successful, stop advertising */ - valid = ble_ll_conn_slave_start(rxbuf, addr_type, hdr, - !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)); - if (valid) { - /* stop advertising only if not transmitting connection response */ - if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD)) { - ble_ll_adv_sm_stop(advsm); - } - } - } - - return valid; -} - -/** - * Called on phy rx pdu end when in advertising state. - * - * There are only two pdu types we care about in this state: scan requests - * and connection requests. When we receive a scan request we must determine if - * we need to send a scan response and that needs to be acted on within T_IFS. - * - * When we receive a connection request, we need to determine if we will allow - * this device to start a connection with us. However, no immediate response is - * sent so we handle this at the link layer task. - * - * Context: Interrupt - * - * @param pdu_type Type of pdu received. - * @param rxpdu Pointer to received PDU - * - * @return int - * < 0: Disable the phy after reception. - * == 0: Do not disable the PHY - * > 0: Do not disable PHY as that has already been done. - */ -int -ble_ll_adv_rx_isr_end(uint8_t pdu_type, struct os_mbuf *rxpdu, int crcok) -{ - int rc; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_mbuf_hdr *rxhdr; -#endif - - rc = -1; - if (rxpdu == NULL) { - ble_ll_adv_tx_done(g_ble_ll_cur_adv_sm); - } else { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - rxhdr = BLE_MBUF_HDR_PTR(rxpdu); - rxhdr->rxinfo.user_data = g_ble_ll_cur_adv_sm; - if (ble_ll_adv_active_chanset_is_sec(g_ble_ll_cur_adv_sm)) { - rxhdr->rxinfo.flags |= BLE_MBUF_HDR_F_EXT_ADV_SEC; - } else { - assert(ble_ll_adv_active_chanset_is_pri(g_ble_ll_cur_adv_sm)); - } -#endif - if (crcok) { - if ((pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) || - (pdu_type == BLE_ADV_PDU_TYPE_CONNECT_IND)) { - /* Process request */ - rc = ble_ll_adv_rx_req(pdu_type, rxpdu); - } - } - - if (rc) { - /* We no longer have a current state machine */ - g_ble_ll_cur_adv_sm = NULL; - } - } - - if (rc) { - ble_ll_state_set(BLE_LL_STATE_STANDBY); - } - - return rc; -} - -/** - * Process a received packet at the link layer task when in the advertising - * state - * - * Context: Link Layer - * - * - * @param ptype - * @param rxbuf - * @param hdr - * - * @return int - */ -void -ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, struct ble_mbuf_hdr *hdr) -{ - int adv_event_over; - struct ble_ll_adv_sm *advsm; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - advsm = (struct ble_ll_adv_sm *)hdr->rxinfo.user_data; -#else - advsm = &g_ble_ll_adv_sm[0]; -#endif - - /* - * It is possible that advertising was stopped and a packet plcaed on the - * LL receive packet queue. In this case, just ignore the received packet - * as the advertising state machine is no longer "valid" - */ - if (!advsm->adv_enabled) { - return; - } - - /* - * If we have received a scan request and we are transmitting a response - * or we have received a valid connect request, dont "end" the advertising - * event. In the case of a connect request we will stop advertising. In - * the case of the scan response transmission we will get a transmit - * end callback. - */ - adv_event_over = 1; - if (BLE_MBUF_HDR_CRC_OK(hdr)) { - if (ptype == BLE_ADV_PDU_TYPE_CONNECT_IND) { - if (ble_ll_adv_conn_req_rxd(rxbuf, hdr, advsm)) { - adv_event_over = 0; - } - } else { - if ((ptype == BLE_ADV_PDU_TYPE_SCAN_REQ) && - (hdr->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_RSP_TXD)) { - adv_event_over = 0; - } - } - } - - if (adv_event_over) { - ble_ll_adv_make_done(advsm, hdr); - } -} - -/** - * Called when a receive PDU has started and we are advertising. - * - * Context: interrupt - * - * @param pdu_type - * @param rxpdu - * - * @return int - * < 0: A frame we dont want to receive. - * = 0: Continue to receive frame. Dont go from rx to tx - * > 0: Continue to receive frame and go from rx to tx when done - */ -int -ble_ll_adv_rx_isr_start(uint8_t pdu_type) -{ - int rc; - struct ble_ll_adv_sm *advsm; - - /* Assume we will abort the frame */ - rc = -1; - - /* If we get a scan request we must tell the phy to go from rx to tx */ - advsm = g_ble_ll_cur_adv_sm; - if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { - /* Only accept scan requests if we are indirect adv or scan adv */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { - rc = 1; - } - } else { - /* Only accept connect requests if connectable advertising event */ - if (pdu_type == BLE_ADV_PDU_TYPE_CONNECT_IND) { - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { - /* Need transition to TX if extended adv */ - rc = !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY); - } - } - } - - /* - * If we abort the frame, we need to post the LL task to check if the - * advertising event is over. - */ - if (rc < 0) { - ble_ll_adv_tx_done(advsm); - } - - return rc; -} - -static void -ble_ll_adv_drop_event(struct ble_ll_adv_sm *advsm) -{ - STATS_INC(ble_ll_stats, adv_drop_event); - - ble_ll_sched_rmv_elem(&advsm->adv_sch); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - ble_ll_sched_rmv_elem(&advsm->aux[0].sch); - ble_ll_sched_rmv_elem(&advsm->aux[1].sch); - - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); - advsm->aux_active = 0; -#endif - - advsm->adv_chan = ble_ll_adv_final_chan(advsm); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); -} - -static void -ble_ll_adv_reschedule_event(struct ble_ll_adv_sm *advsm) -{ - int rc; - uint32_t start_time; - uint32_t max_delay_ticks; - - assert(advsm->adv_enabled); - - if (!advsm->adv_sch.enqueued) { - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { - max_delay_ticks = 0; - } else { - max_delay_ticks = - os_cputime_usecs_to_ticks(BLE_LL_ADV_DELAY_MS_MAX * 1000); - } - - rc = ble_ll_sched_adv_reschedule(&advsm->adv_sch, &start_time, - max_delay_ticks); - if (rc) { - ble_ll_adv_drop_event(advsm); - return; - } - - start_time += g_ble_ll_sched_offset_ticks; - advsm->adv_event_start_time = start_time; - advsm->adv_pdu_start_time = start_time; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) && - !advsm->aux_active) { - ble_ll_adv_aux_schedule(advsm); - } -#endif -} - -/** - * Called when an advertising event is over. - * - * Context: Link Layer task. - * - * @param arg Pointer to advertising state machine. - */ -static void -ble_ll_adv_done(struct ble_ll_adv_sm *advsm) - -{ - int rc; - int resched_pdu; - uint8_t mask; - uint8_t final_adv_chan; - int32_t delta_t; - uint32_t itvl; - uint32_t tick_itvl; - uint32_t start_time; - - assert(advsm->adv_enabled); - - ble_ll_rfmgmt_release(); - - ble_ll_adv_update_adv_scan_rsp_data(advsm); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - /* stop advertising this was due to transmitting connection response */ - if (advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD) { - ble_ll_adv_sm_stop(advsm); - return; - } - } -#endif - - /* Remove the element from the schedule if it is still there. */ - ble_ll_sched_rmv_elem(&advsm->adv_sch); - - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); - - /* - * Check if we have ended our advertising event. If our last advertising - * packet was sent on the last channel, it means we are done with this - * event. - */ - final_adv_chan = ble_ll_adv_final_chan(advsm); - - if (advsm->adv_chan == final_adv_chan) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (advsm->events_max) { - advsm->events++; - } -#endif - - ble_ll_scan_chk_resume(); - - /* This event is over. Set adv channel to first one */ - advsm->adv_chan = ble_ll_adv_first_chan(advsm); - - /* - * Calculate start time of next advertising event. NOTE: we do not - * add the random advDelay as the scheduling code will do that. - */ - itvl = advsm->adv_itvl_usecs; - tick_itvl = os_cputime_usecs_to_ticks(itvl); - advsm->adv_event_start_time += tick_itvl; - advsm->adv_pdu_start_time = advsm->adv_event_start_time; - - /* - * The scheduled time better be in the future! If it is not, we will - * just keep advancing until we the time is in the future - */ - start_time = advsm->adv_pdu_start_time - g_ble_ll_sched_offset_ticks; - - delta_t = (int32_t)(start_time - os_cputime_get32()); - if (delta_t < 0) { - /* - * NOTE: we just the same interval that we calculated earlier. - * No real need to keep recalculating a new interval. - */ - while (delta_t < 0) { - advsm->adv_event_start_time += tick_itvl; - advsm->adv_pdu_start_time = advsm->adv_event_start_time; - delta_t += (int32_t)tick_itvl; - } - } - resched_pdu = 0; - } else { - /* - * Move to next advertising channel. If not in the mask, just - * increment by 1. We can do this because we already checked if we - * just transmitted on the last advertising channel - */ - ++advsm->adv_chan; - mask = 1 << (advsm->adv_chan - BLE_PHY_ADV_CHAN_START); - if ((mask & advsm->adv_chanmask) == 0) { - ++advsm->adv_chan; - } - - /* - * We will transmit right away. Set next pdu start time to now - * plus a xcvr start delay just so we dont count late adv starts - */ - advsm->adv_pdu_start_time = os_cputime_get32() + - g_ble_ll_sched_offset_ticks; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* If we're past aux (unlikely, but can happen), just drop an event */ - if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) && - advsm->aux_active && - advsm->adv_pdu_start_time > AUX_CURRENT(advsm)->start_time) { - ble_ll_adv_drop_event(advsm); - return; - } -#endif - - resched_pdu = 1; - } - - /* check if advertising timed out */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (advsm->duration && - advsm->adv_pdu_start_time >= advsm->adv_end_time) { - /* Legacy PDUs need to be stop here. - * For ext adv it will be stopped when AUX is done (unless it was - * dropped so check if AUX is active here as well). - */ - if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) || - !advsm->aux_active) { - ble_ll_adv_sm_stop_timeout(advsm); - } - - return; - } -#else - if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) && - (advsm->adv_pdu_start_time >= advsm->adv_end_time)) { - ble_ll_adv_sm_stop_timeout(advsm); - return; - } -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (advsm->events_max && (advsm->events >= advsm->events_max)) { - /* Legacy PDUs need to be stop here. - * For ext adv it will be stopped when AUX is done (unless it was - * dropped so check if AUX is active here as well). - */ - if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) || - !advsm->aux_active) { - ble_ll_adv_sm_stop_limit_reached(advsm); - } - - return; - } -#endif - - /* We need to regenerate our RPA's if we have passed timeout */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - ble_ll_adv_chk_rpa_timeout(advsm); -#endif - - /* Schedule advertising transmit */ - ble_ll_adv_set_sched(advsm); - - if (!resched_pdu) { - ble_ll_adv_reschedule_event(advsm); - return; - } - - /* - * In the unlikely event we can't reschedule this, just post a done event - * and we will reschedule the next advertising PDU. - */ - rc = ble_ll_sched_adv_resched_pdu(&advsm->adv_sch); - if (rc) { - STATS_INC(ble_ll_stats, adv_resched_pdu_fail); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); - } -} - -static void -ble_ll_adv_event_done(struct ble_npl_event *ev) -{ - ble_ll_adv_done(ble_npl_event_get_arg(ev)); -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -/** - * Called when auxiliary packet is txd on secondary channel - * - * Context: Link Layer task. - * - * @param ev - */ -static void -ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm) -{ - struct ble_ll_adv_aux *aux; - struct ble_ll_adv_aux *aux_next; - - assert(advsm->adv_enabled); - assert(advsm->aux_active); - - aux = AUX_CURRENT(advsm); - aux_next = AUX_NEXT(advsm); - - /* We don't need RF anymore */ - ble_ll_rfmgmt_release(); - - if (advsm->aux_not_scanned) { - ble_ll_sched_rmv_elem(&aux_next->sch); - } - - /* Remove anything else scheduled for secondary channel */ - ble_ll_sched_rmv_elem(&aux->sch); - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); - - /* Stop advertising due to transmitting connection response */ - if (advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD) { - ble_ll_adv_sm_stop(advsm); - return; - } - - /* If we have next AUX scheduled, try to schedule another one */ - if (aux_next->sch.enqueued) { - advsm->aux_index ^= 1; - advsm->aux_first_pdu = 0; - ble_ll_adv_aux_schedule_next(advsm); - return; - } - - ble_ll_scan_chk_resume(); - - /* Check if advertising timed out */ - if (advsm->duration && (advsm->adv_pdu_start_time >= advsm->adv_end_time)) { - ble_ll_adv_sm_stop_timeout(advsm); - return; - } - - if (advsm->events_max && (advsm->events >= advsm->events_max)) { - ble_ll_adv_sm_stop_limit_reached(advsm); - return; - } - - advsm->aux_active = 0; - ble_ll_adv_update_adv_scan_rsp_data(advsm); - ble_ll_adv_reschedule_event(advsm); -} - -static void -ble_ll_adv_sec_event_done(struct ble_npl_event *ev) -{ - ble_ll_adv_sec_done(ble_npl_event_get_arg(ev)); -} -#endif - -static void -ble_ll_adv_make_done(struct ble_ll_adv_sm *advsm, struct ble_mbuf_hdr *hdr) -{ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (BLE_MBUF_HDR_EXT_ADV_SEC(hdr)) { - assert(!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)); - assert(ble_ll_adv_active_chanset_is_sec(advsm)); - ble_ll_adv_active_chanset_clear(advsm); - ble_ll_adv_sec_done(advsm); - } else { - assert(ble_ll_adv_active_chanset_is_pri(advsm)); - ble_ll_adv_active_chanset_clear(advsm); - ble_ll_adv_done(advsm); - } -#else - ble_ll_adv_active_chanset_clear(advsm); - ble_ll_adv_done(advsm); -#endif -} - -/** - * Checks if the controller can change the whitelist. If advertising is enabled - * and is using the whitelist the controller is not allowed to change the - * whitelist. - * - * @return int 0: not allowed to change whitelist; 1: change allowed. - */ -int -ble_ll_adv_can_chg_whitelist(void) -{ - struct ble_ll_adv_sm *advsm; - int rc; - int i; - - rc = 1; - for (i = 0; i < BLE_ADV_INSTANCES; ++i) { - advsm = &g_ble_ll_adv_sm[i]; - if (advsm->adv_enabled && - (advsm->adv_filter_policy != BLE_HCI_ADV_FILT_NONE)) { - rc = 0; - break; - } - } - - return rc; -} - -/** - * Sends the connection complete event when advertising a connection starts. - * - * @return uint8_t* Pointer to event buffer - */ -void -ble_ll_adv_send_conn_comp_ev(struct ble_ll_conn_sm *connsm, - struct ble_mbuf_hdr *rxhdr) -{ - uint8_t *evbuf; - struct ble_ll_adv_sm *advsm; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - advsm = (struct ble_ll_adv_sm *)rxhdr->rxinfo.user_data; -#else - advsm = &g_ble_ll_adv_sm[0]; -#endif - - evbuf = advsm->conn_comp_ev; - assert(evbuf != NULL); - advsm->conn_comp_ev = NULL; - - ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS, evbuf, advsm); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) - ble_ll_hci_ev_le_csa(connsm); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (ble_ll_hci_adv_mode_ext()) { - ble_ll_hci_ev_send_adv_set_terminated(0, advsm->adv_instance, - connsm->conn_handle, advsm->events); - } -#endif -} - -/** - * Returns the local resolvable private address currently being using by - * the advertiser - * - * @return uint8_t* - */ -uint8_t * -ble_ll_adv_get_local_rpa(struct ble_ll_adv_sm *advsm) -{ - uint8_t *rpa = NULL; - - if (advsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { - if ((advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) && - ble_ll_is_rpa(advsm->adva, 1)) { - rpa = advsm->adva; - } - } - - return rpa; -} - -/** - * Returns the peer resolvable private address of last device connecting to us - * - * @return uint8_t* - */ -uint8_t * -ble_ll_adv_get_peer_rpa(struct ble_ll_adv_sm *advsm) -{ - /* XXX: should this go into IRK list or connection? */ - return advsm->adv_rpa; -} - -/** - * Called when the LL wait for response timer expires while in the advertising - * state. Disables the phy and - * - */ -void -ble_ll_adv_wfr_timer_exp(void) -{ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - g_ble_ll_cur_adv_sm->aux_not_scanned = 1; -#endif - - ble_phy_disable(); - ble_ll_adv_tx_done(g_ble_ll_cur_adv_sm); -} - -/** - * Reset the advertising state machine. - * - * Context: Link Layer task - * - */ -void -ble_ll_adv_reset(void) -{ - int i; - struct ble_ll_adv_sm *advsm; - - for (i = 0; i < BLE_ADV_INSTANCES; ++i) { - advsm = &g_ble_ll_adv_sm[i]; - - /* Stop advertising state machine */ - ble_ll_adv_sm_stop(advsm); - - /* clear any data present */ - os_mbuf_free_chain(advsm->adv_data); - os_mbuf_free_chain(advsm->scan_rsp_data); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - /* Stop periodic advertising state machine */ - ble_ll_adv_sm_stop_periodic(advsm); - - /* clear any periodic data present */ - os_mbuf_free_chain(advsm->periodic_adv_data); -#endif - - /* re-initialize the advertiser state machine */ - ble_ll_adv_sm_init(advsm); - } -} - -/* Called to determine if advertising is enabled. - */ -uint8_t -ble_ll_adv_enabled(void) -{ - int i; - - for (i = 0; i < BLE_ADV_INSTANCES; i++) { - if (g_ble_ll_adv_sm[i].adv_enabled) { - return 1; - } - } - - return 0; -} - -static void -ble_ll_adv_sm_init(struct ble_ll_adv_sm *advsm) -{ - memset(advsm, 0, sizeof(struct ble_ll_adv_sm)); - - advsm->adv_itvl_min = BLE_HCI_ADV_ITVL_DEF; - advsm->adv_itvl_max = BLE_HCI_ADV_ITVL_DEF; - advsm->adv_chanmask = BLE_HCI_ADV_CHANMASK_DEF; - - /* Initialize advertising tx done event */ - ble_npl_event_init(&advsm->adv_txdone_ev, ble_ll_adv_event_done, advsm); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - ble_npl_event_init(&advsm->adv_sec_txdone_ev, ble_ll_adv_sec_event_done, advsm); -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - ble_npl_event_init(&advsm->adv_periodic_txdone_ev, - ble_ll_adv_periodic_event_done, advsm); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* Initialize aux schedulers */ - advsm->aux_active = 0; - advsm->aux[0].sch.cb_arg = advsm; - advsm->aux[0].sch.sched_cb = ble_ll_adv_secondary_tx_start_cb; - advsm->aux[0].sch.sched_type = BLE_LL_SCHED_TYPE_ADV; - advsm->aux[1].sch.cb_arg = advsm; - advsm->aux[1].sch.sched_cb = ble_ll_adv_secondary_tx_start_cb; - advsm->aux[1].sch.sched_type = BLE_LL_SCHED_TYPE_ADV; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - /* Initialize sync schedulers */ - advsm->periodic_sync_active = 0; - advsm->periodic_sync[0].sch.cb_arg = advsm; - advsm->periodic_sync[0].sch.sched_cb = ble_ll_adv_sync_tx_start_cb; - advsm->periodic_sync[0].sch.sched_type = BLE_LL_SCHED_TYPE_PERIODIC; - advsm->periodic_sync[1].sch.cb_arg = advsm; - advsm->periodic_sync[1].sch.sched_cb = ble_ll_adv_sync_tx_start_cb; - advsm->periodic_sync[1].sch.sched_type = BLE_LL_SCHED_TYPE_PERIODIC; -#endif -#endif - - /* Configure instances to be legacy on start */ - advsm->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE; - advsm->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY; -} - -/** - * Initialize the advertising functionality of a BLE device. This should - * be called once on initialization - */ -void -ble_ll_adv_init(void) -{ - int i; - - /* Set default advertising parameters */ - for (i = 0; i < BLE_ADV_INSTANCES; ++i) { - ble_ll_adv_sm_init(&g_ble_ll_adv_sm[i]); - } -} - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn.c deleted file mode 100644 index b3788de1d..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn.c +++ /dev/null @@ -1,4279 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/porting/nimble/include/os/os_cputime.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "nimble/nimble/include/nimble/ble_hci_trans.h" - -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) -#include "nimble/nimble/drivers/nrf51/include/ble/xcvr.h" -#elif defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) -#include "nimble/nimble/drivers/nrf52/include/ble/xcvr.h" -#endif - -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_whitelist.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_ctrl.h" -#include "../include/controller/ble_ll_resolv.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_trace.h" -#include "../include/controller/ble_ll_rfmgmt.h" -#include "../include/controller/ble_phy.h" -#include "../include/controller/ble_hw.h" -#include "../include/controller/ble_ll_utils.h" -#include "ble_ll_conn_priv.h" - -#if (BLETEST_THROUGHPUT_TEST == 1) -extern void bletest_completed_pkt(uint16_t handle); -#endif - -/* XXX TODO - * 1) I think if we are initiating and we already have a connection with - * a device that we will still try and connect to it. Fix this. - * -> This is true. There are a couple things to do - * i) When a connection create is issued, if we already are connected - * deny it. BLE ERROR = 0x0B (ACL connection exists). - * ii) If we receive an advertisement while initiating and want to send - * a connect request to the device, make sure we dont have it. - * iii) I think I need to do something like this: I am initiating and - * advertising. Suppose the device I want to connect to sends me a connect - * request because I am advertising? What happens to connection? Deal - * with this! - * - * 2) Make sure we check incoming data packets for size and all that. You - * know, supported octets and all that. For both rx and tx. - * - * 3) Make sure we are setting the schedule end time properly for both slave - * and master. We should just set this to the end of the connection event. - * We might want to guarantee a IFS time as well since the next event needs - * to be scheduled prior to the start of the event to account for the time it - * takes to get a frame ready (which is pretty much the IFS time). - * - * 4) looks like the current code will allow the 1st packet in a - * connection to extend past the end of the allocated connection end - * time. That is not good. Need to deal with that. Need to extend connection - * end time. - * - * 6) Use error code 0x3E correctly! Connection failed to establish. If you - * read the LE connection complete event, it says that if the connection - * fails to be established that the connection complete event gets sent to - * the host that issued the create connection. Need to resolve this. - * - * 7) How does peer address get set if we are using whitelist? Look at filter - * policy and make sure you are doing this correctly. - * - * 8) Right now I use a fixed definition for required slots. CHange this. - * - * 10) See what connection state machine elements are purely master and - * purely slave. We can make a union of them. - * - * 11) Not sure I am dealing with the connection terminate timeout perfectly. - * I may extend a connection event too long although if it is always in terms - * of connection events I am probably fine. Checking at end that the next - * connection event will occur past terminate timeould would be fine. - * - * 12) When a slave receives a data packet in a connection it has to send a - * response. Well, it should. If this packet will overrun the next scheduled - * event, what should we do? Transmit anyway? Not transmit? For now, we just - * transmit. - * - * 32kHz crystal - * 1) When scheduling, I need to make sure I have time between - * this one and the next. Should I deal with this in the sched. Or - * is this basically accounted for given a slot? I really just need to - * make sure everything is over N ticks before the next sched start! - * Just add to end time? - * - * 2) I think one way to handle the problem of losing up to a microsecond - * every time we call ble_ll_conn_next_event in a loop is to do everything by - * keeping track of last anchor point. Would need last anchor usecs too. I guess - * we could also keep last anchor usecs as a uint32 or something and when we - * do the next event keep track of the residual using a different ticks to - * usecs calculation. Not sure. - */ - -/* - * XXX: How should we deal with a late connection event? We need to determine - * what we want to do under the following cases: - * 1) The current connection event has not ended but a schedule item starts - */ - -/* This is a dummy structure we use for the empty PDU */ -struct ble_ll_empty_pdu -{ - struct os_mbuf om; - struct os_mbuf_pkthdr pkt_hdr; - struct ble_mbuf_hdr ble_hdr; -}; - -/* We cannot have more than 254 connections given our current implementation */ -#if (MYNEWT_VAL(BLE_MAX_CONNECTIONS) >= 255) - #error "Maximum # of connections is 254" -#endif - -/* Global connection complete event. Used when initiating */ -uint8_t *g_ble_ll_conn_comp_ev; - -/* Global LL connection parameters */ -struct ble_ll_conn_global_params g_ble_ll_conn_params; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -/* Global default sync transfer params */ -struct ble_ll_conn_sync_transfer_params g_ble_ll_conn_sync_transfer_params; -#endif - -/* Pointer to connection state machine we are trying to create */ -struct ble_ll_conn_sm *g_ble_ll_conn_create_sm; - -/* Pointer to current connection */ -struct ble_ll_conn_sm *g_ble_ll_conn_cur_sm; - -/* Connection state machine array */ -struct ble_ll_conn_sm g_ble_ll_conn_sm[MYNEWT_VAL(BLE_MAX_CONNECTIONS)]; - -/* List of active connections */ -struct ble_ll_conn_active_list g_ble_ll_conn_active_list; - -/* List of free connections */ -struct ble_ll_conn_free_list g_ble_ll_conn_free_list; - -STATS_SECT_START(ble_ll_conn_stats) - STATS_SECT_ENTRY(cant_set_sched) - STATS_SECT_ENTRY(conn_ev_late) - STATS_SECT_ENTRY(wfr_expirations) - STATS_SECT_ENTRY(handle_not_found) - STATS_SECT_ENTRY(no_conn_sm) - STATS_SECT_ENTRY(no_free_conn_sm) - STATS_SECT_ENTRY(rx_data_pdu_no_conn) - STATS_SECT_ENTRY(rx_data_pdu_bad_aa) - STATS_SECT_ENTRY(slave_rxd_bad_conn_req_params) - STATS_SECT_ENTRY(slave_ce_failures) - STATS_SECT_ENTRY(data_pdu_rx_dup) - STATS_SECT_ENTRY(data_pdu_txg) - STATS_SECT_ENTRY(data_pdu_txf) - STATS_SECT_ENTRY(conn_req_txd) - STATS_SECT_ENTRY(l2cap_enqueued) - STATS_SECT_ENTRY(rx_ctrl_pdus) - STATS_SECT_ENTRY(rx_l2cap_pdus) - STATS_SECT_ENTRY(rx_l2cap_bytes) - STATS_SECT_ENTRY(rx_malformed_ctrl_pdus) - STATS_SECT_ENTRY(rx_bad_llid) - STATS_SECT_ENTRY(tx_ctrl_pdus) - STATS_SECT_ENTRY(tx_ctrl_bytes) - STATS_SECT_ENTRY(tx_l2cap_pdus) - STATS_SECT_ENTRY(tx_l2cap_bytes) - STATS_SECT_ENTRY(tx_empty_pdus) - STATS_SECT_ENTRY(mic_failures) - STATS_SECT_ENTRY(sched_start_in_idle) - STATS_SECT_ENTRY(sched_end_in_idle) - STATS_SECT_ENTRY(conn_event_while_tmo) -STATS_SECT_END -STATS_SECT_DECL(ble_ll_conn_stats) ble_ll_conn_stats; - -STATS_NAME_START(ble_ll_conn_stats) - STATS_NAME(ble_ll_conn_stats, cant_set_sched) - STATS_NAME(ble_ll_conn_stats, conn_ev_late) - STATS_NAME(ble_ll_conn_stats, wfr_expirations) - STATS_NAME(ble_ll_conn_stats, handle_not_found) - STATS_NAME(ble_ll_conn_stats, no_conn_sm) - STATS_NAME(ble_ll_conn_stats, no_free_conn_sm) - STATS_NAME(ble_ll_conn_stats, rx_data_pdu_no_conn) - STATS_NAME(ble_ll_conn_stats, rx_data_pdu_bad_aa) - STATS_NAME(ble_ll_conn_stats, slave_rxd_bad_conn_req_params) - STATS_NAME(ble_ll_conn_stats, slave_ce_failures) - STATS_NAME(ble_ll_conn_stats, data_pdu_rx_dup) - STATS_NAME(ble_ll_conn_stats, data_pdu_txg) - STATS_NAME(ble_ll_conn_stats, data_pdu_txf) - STATS_NAME(ble_ll_conn_stats, conn_req_txd) - STATS_NAME(ble_ll_conn_stats, l2cap_enqueued) - STATS_NAME(ble_ll_conn_stats, rx_ctrl_pdus) - STATS_NAME(ble_ll_conn_stats, rx_l2cap_pdus) - STATS_NAME(ble_ll_conn_stats, rx_l2cap_bytes) - STATS_NAME(ble_ll_conn_stats, rx_malformed_ctrl_pdus) - STATS_NAME(ble_ll_conn_stats, rx_bad_llid) - STATS_NAME(ble_ll_conn_stats, tx_ctrl_pdus) - STATS_NAME(ble_ll_conn_stats, tx_ctrl_bytes) - STATS_NAME(ble_ll_conn_stats, tx_l2cap_pdus) - STATS_NAME(ble_ll_conn_stats, tx_l2cap_bytes) - STATS_NAME(ble_ll_conn_stats, tx_empty_pdus) - STATS_NAME(ble_ll_conn_stats, mic_failures) - STATS_NAME(ble_ll_conn_stats, sched_start_in_idle) - STATS_NAME(ble_ll_conn_stats, sched_end_in_idle) - STATS_NAME(ble_ll_conn_stats, conn_event_while_tmo) -STATS_NAME_END(ble_ll_conn_stats) - -static void ble_ll_conn_event_end(struct ble_npl_event *ev); - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) -/** - * Checks to see if we should start a PHY update procedure - * - * If current phy is not one of the preferred we need to start control - * procedure. - * - * XXX: we could also decide to change the PHY if RSSI is really good - * and we are currently at 1Mbps or lower data rate and we could use - * a higher data rate. - * - * @param connsm - * @return 0: success; -1: no phy update procedure started - */ -int -ble_ll_conn_chk_phy_upd_start(struct ble_ll_conn_sm *csm) -{ - int rc; - - /* If no host preferences or */ - if (((csm->phy_data.host_pref_tx_phys_mask == 0) && - (csm->phy_data.host_pref_rx_phys_mask == 0)) || - ((csm->phy_data.host_pref_tx_phys_mask & CONN_CUR_TX_PHY_MASK(csm)) && - (csm->phy_data.host_pref_rx_phys_mask & CONN_CUR_RX_PHY_MASK(csm)))) { - rc = -1; - } else { - csm->phy_data.req_pref_tx_phys_mask = csm->phy_data.host_pref_tx_phys_mask; - csm->phy_data.req_pref_rx_phys_mask = csm->phy_data.host_pref_rx_phys_mask; - ble_ll_ctrl_proc_start(csm, BLE_LL_CTRL_PROC_PHY_UPDATE); - rc = 0; - } - - return rc; -} -#endif - -static void -ble_ll_conn_calc_itvl_ticks(struct ble_ll_conn_sm *connsm) -{ - uint32_t ticks; - uint32_t usecs; - - /* - * Precalculate the number of ticks and remaining microseconds for - * the connection interval - */ - usecs = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS; - ticks = os_cputime_usecs_to_ticks(usecs); - connsm->conn_itvl_usecs = (uint8_t)(usecs - - os_cputime_ticks_to_usecs(ticks)); - if (connsm->conn_itvl_usecs == 31) { - connsm->conn_itvl_usecs = 0; - ++ticks; - } - connsm->conn_itvl_ticks = ticks; -} - -/** - * Get the event buffer allocated to send the connection complete event - * when we are initiating. - * - * @return uint8_t* - */ -static uint8_t * -ble_ll_init_get_conn_comp_ev(void) -{ - uint8_t *evbuf; - - evbuf = g_ble_ll_conn_comp_ev; - BLE_LL_ASSERT(evbuf != NULL); - g_ble_ll_conn_comp_ev = NULL; - - return evbuf; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/** - * Called to determine if the received PDU is an empty PDU or not. - */ -static int -ble_ll_conn_is_empty_pdu(uint8_t *rxbuf) -{ - int rc; - uint8_t llid; - - llid = rxbuf[0] & BLE_LL_DATA_HDR_LLID_MASK; - if ((llid == BLE_LL_LLID_DATA_FRAG) && (rxbuf[1] == 0)) { - rc = 1; - } else { - rc = 0; - } - return rc; -} -#endif - -/** - * Called to return the currently running connection state machine end time. - * Always called when interrupts are disabled. - * - * @return int 0: s1 is not least recently used. 1: s1 is least recently used - */ -int -ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2) -{ - int rc; - - /* Set time that we last serviced the schedule */ - if ((int32_t)(s1->last_scheduled - s2->last_scheduled) < 0) { - rc = 1; - } else { - rc = 0; - } - - return rc; -} - -/** - * Called to return the currently running connection state machine end time. - * Always called when interrupts are disabled. - * - * @return uint32_t - */ -uint32_t -ble_ll_conn_get_ce_end_time(void) -{ - uint32_t ce_end_time; - - if (g_ble_ll_conn_cur_sm) { - ce_end_time = g_ble_ll_conn_cur_sm->ce_end_time; - } else { - ce_end_time = os_cputime_get32(); - } - return ce_end_time; -} - -/** - * Called when connection state machine needs to halt. This function will: - * -> Disable the PHY, which will prevent any transmit/receive interrupts. - * -> Disable the wait for response timer, if running. - * -> Remove the connection state machine from the scheduler. - * -> Sets the Link Layer state to standby. - * -> Sets the current state machine to NULL. - * - * NOTE: the ordering of these function calls is important! We have to stop - * the PHY and remove the schedule item before we can set the state to - * standby and set the current state machine pointer to NULL. - */ -static void -ble_ll_conn_halt(void) -{ - ble_phy_disable(); - ble_ll_state_set(BLE_LL_STATE_STANDBY); - g_ble_ll_conn_cur_sm = NULL; -} - -/** - * Called when the current connection state machine is no longer being used. - */ -static void -ble_ll_conn_current_sm_over(struct ble_ll_conn_sm *connsm) -{ - - ble_ll_conn_halt(); - - /* - * NOTE: the connection state machine may be NULL if we are calling - * this when we are ending the connection. In that case, there is no - * need to post to the LL the connection event end event - */ - if (connsm) { - ble_ll_event_send(&connsm->conn_ev_end); - } -} - -/** - * Given a handle, find an active connection matching the handle - * - * @param handle - * - * @return struct ble_ll_conn_sm* - */ -struct ble_ll_conn_sm * -ble_ll_conn_find_active_conn(uint16_t handle) -{ - struct ble_ll_conn_sm *connsm; - - connsm = NULL; - if ((handle != 0) && (handle <= MYNEWT_VAL(BLE_MAX_CONNECTIONS))) { - connsm = &g_ble_ll_conn_sm[handle - 1]; - if (connsm->conn_state == BLE_LL_CONN_STATE_IDLE) { - connsm = NULL; - } - } - return connsm; -} - -/** - * Get a connection state machine. - */ -struct ble_ll_conn_sm * -ble_ll_conn_sm_get(void) -{ - struct ble_ll_conn_sm *connsm; - - connsm = STAILQ_FIRST(&g_ble_ll_conn_free_list); - if (connsm) { - STAILQ_REMOVE_HEAD(&g_ble_ll_conn_free_list, free_stqe); - } else { - STATS_INC(ble_ll_conn_stats, no_free_conn_sm); - } - - return connsm; -} - -static uint8_t -ble_ll_conn_calc_dci_csa1(struct ble_ll_conn_sm *conn) -{ - uint8_t curchan; - uint8_t remap_index; - uint8_t bitpos; - - /* Get next unmapped channel */ - curchan = conn->last_unmapped_chan + conn->hop_inc; - if (curchan > BLE_PHY_NUM_DATA_CHANS) { - curchan -= BLE_PHY_NUM_DATA_CHANS; - } - - /* Save unmapped channel */ - conn->last_unmapped_chan = curchan; - - /* Is this a valid channel? */ - bitpos = 1 << (curchan & 0x07); - if (conn->chanmap[curchan >> 3] & bitpos) { - return curchan; - } - - /* Calculate remap index */ - remap_index = curchan % conn->num_used_chans; - - return ble_ll_utils_remapped_channel(remap_index, conn->chanmap); -} - -/** - * Determine data channel index to be used for the upcoming/current - * connection event - * - * @param conn - * @param latency Used only for CSA #1 - * - * @return uint8_t - */ -uint8_t -ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn, uint16_t latency) -{ - uint8_t index; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) - if (CONN_F_CSA2_SUPP(conn)) { - return ble_ll_utils_calc_dci_csa2(conn->event_cntr, conn->channel_id, - conn->num_used_chans, conn->chanmap); - } -#endif - - index = conn->data_chan_index; - - while (latency > 0) { - index = ble_ll_conn_calc_dci_csa1(conn); - latency--; - } - - return index; -} - -/** - * Called when we are in the connection state and the wait for response timer - * fires off. - * - * Context: Interrupt - */ -void -ble_ll_conn_wfr_timer_exp(void) -{ - struct ble_ll_conn_sm *connsm; - - connsm = g_ble_ll_conn_cur_sm; - ble_ll_conn_current_sm_over(connsm); - STATS_INC(ble_ll_conn_stats, wfr_expirations); -} - -void -ble_ll_conn_reset_pending_aux_conn_rsp(void) -{ -#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - return; -#endif - struct ble_ll_conn_sm *connsm; - - connsm = g_ble_ll_conn_create_sm; - if (!connsm) { - return; - } - - if (CONN_F_AUX_CONN_REQ(connsm)) { - STATS_INC(ble_ll_stats, aux_conn_rsp_err); - CONN_F_CONN_REQ_TXD(connsm) = 0; - CONN_F_AUX_CONN_REQ(connsm) = 0; - ble_ll_sched_rmv_elem(&connsm->conn_sch); - return; - } - - return; -} - -bool -ble_ll_conn_init_pending_aux_conn_rsp(void) -{ -#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - return false; -#endif - struct ble_ll_conn_sm *connsm; - - connsm = g_ble_ll_conn_create_sm; - if (!connsm) { - return false; - } - - return CONN_F_AUX_CONN_REQ(connsm); -} - -void -ble_ll_conn_init_wfr_timer_exp(void) -{ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_ll_conn_sm *connsm; - - connsm = g_ble_ll_conn_create_sm; - if (!connsm) { - return; - } - - ble_ll_conn_reset_pending_aux_conn_rsp(); - connsm->inita_identity_used = 0; - - ble_ll_scan_interrupted(connsm->scansm); - -#endif -} -/** - * Callback for slave when it transmits a data pdu and the connection event - * ends after the transmission. - * - * Context: Interrupt - * - * @param sch - * - */ -static void -ble_ll_conn_wait_txend(void *arg) -{ - struct ble_ll_conn_sm *connsm; - - connsm = (struct ble_ll_conn_sm *)arg; - ble_ll_conn_current_sm_over(connsm); -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -static void -ble_ll_conn_start_rx_encrypt(void *arg) -{ - struct ble_ll_conn_sm *connsm; - - connsm = (struct ble_ll_conn_sm *)arg; - CONN_F_ENCRYPTED(connsm) = 1; - ble_phy_encrypt_enable(connsm->enc_data.rx_pkt_cntr, - connsm->enc_data.iv, - connsm->enc_data.enc_block.cipher_text, - !CONN_IS_MASTER(connsm)); -} - -static void -ble_ll_conn_start_rx_unencrypt(void *arg) -{ - struct ble_ll_conn_sm *connsm; - - connsm = (struct ble_ll_conn_sm *)arg; - CONN_F_ENCRYPTED(connsm) = 0; - ble_phy_encrypt_disable(); -} - -static void -ble_ll_conn_txend_encrypt(void *arg) -{ - struct ble_ll_conn_sm *connsm; - - connsm = (struct ble_ll_conn_sm *)arg; - CONN_F_ENCRYPTED(connsm) = 1; - ble_ll_conn_current_sm_over(connsm); -} - -static void -ble_ll_conn_rxend_unencrypt(void *arg) -{ - struct ble_ll_conn_sm *connsm; - - connsm = (struct ble_ll_conn_sm *)arg; - CONN_F_ENCRYPTED(connsm) = 0; - ble_ll_conn_current_sm_over(connsm); -} - -static void -ble_ll_conn_continue_rx_encrypt(void *arg) -{ - struct ble_ll_conn_sm *connsm; - - connsm = (struct ble_ll_conn_sm *)arg; - ble_phy_encrypt_set_pkt_cntr(connsm->enc_data.rx_pkt_cntr, - !CONN_IS_MASTER(connsm)); -} -#endif - -/** - * Returns the cputime of the next scheduled item on the scheduler list or - * when the current connection will start its next interval (whichever is - * earlier). This API is called when determining at what time we should end - * the current connection event. The current connection event must end before - * the next scheduled item. However, the current connection itself is not - * in the scheduler list! Thus, we need to calculate the time at which the - * next connection will start (the schedule start time; not the anchor point) - * and not overrun it. - * - * Context: Interrupt - * - * @param connsm - * - * @return uint32_t - */ -static uint32_t -ble_ll_conn_get_next_sched_time(struct ble_ll_conn_sm *connsm) -{ -#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) - uint32_t ce_end; - ce_end = connsm->ce_end_time; -#else - uint32_t ce_end; - uint32_t next_sched_time; - - /* Calculate time at which next connection event will start */ - /* NOTE: We dont care if this time is tick short. */ - ce_end = connsm->anchor_point + connsm->conn_itvl_ticks - - g_ble_ll_sched_offset_ticks; - if ((connsm->anchor_point_usecs + connsm->conn_itvl_usecs) >= 31) { - ++ce_end; - } - - if (ble_ll_sched_next_time(&next_sched_time)) { - if (CPUTIME_LT(next_sched_time, ce_end)) { - ce_end = next_sched_time; - } - } -#endif - - return ce_end; -} - -/** - * Called to check if certain connection state machine flags have been - * set. - * - * @param connsm - */ -static void -ble_ll_conn_chk_csm_flags(struct ble_ll_conn_sm *connsm) -{ - uint8_t update_status; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (connsm->csmflags.cfbit.send_ltk_req) { - /* - * Send Long term key request event to host. If masked, we need to - * send a REJECT_IND. - */ - if (ble_ll_hci_ev_ltk_req(connsm)) { - ble_ll_ctrl_reject_ind_send(connsm, BLE_LL_CTRL_ENC_REQ, - BLE_ERR_PINKEY_MISSING); - } - connsm->csmflags.cfbit.send_ltk_req = 0; - } -#endif - - /* - * There are two cases where this flag gets set: - * 1) A connection update procedure was started and the event counter - * has passed the instant. - * 2) We successfully sent the reject reason. - */ - if (connsm->csmflags.cfbit.host_expects_upd_event) { - update_status = BLE_ERR_SUCCESS; - if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE)) { - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE); - } else { - if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) { - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ); - update_status = connsm->reject_reason; - } - } - ble_ll_hci_ev_conn_update(connsm, update_status); - connsm->csmflags.cfbit.host_expects_upd_event = 0; - } - - /* Check if we need to send PHY update complete event */ -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - if (CONN_F_PHY_UPDATE_EVENT(connsm)) { - if (!ble_ll_hci_ev_phy_update(connsm, BLE_ERR_SUCCESS)) { - /* Sent event. Clear flag */ - CONN_F_PHY_UPDATE_EVENT(connsm) = 0; - } - } -#endif -} - -/** - * Called when we want to send a data channel pdu inside a connection event. - * - * Context: interrupt - * - * @param connsm - * - * @return int 0: success; otherwise failure to transmit - */ -static uint16_t -ble_ll_conn_adjust_pyld_len(struct ble_ll_conn_sm *connsm, uint16_t pyld_len) -{ - uint16_t phy_max_tx_octets; - uint16_t ret; - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - uint8_t phy_mode; - - if (connsm->phy_tx_transition) { - phy_mode = ble_ll_phy_to_phy_mode(connsm->phy_tx_transition, - connsm->phy_data.phy_options); - } else { - phy_mode = connsm->phy_data.tx_phy_mode; - } - - phy_max_tx_octets = ble_ll_pdu_max_tx_octets_get(connsm->eff_max_tx_time, - phy_mode); - -#else - phy_max_tx_octets = ble_ll_pdu_max_tx_octets_get(connsm->eff_max_tx_time, - BLE_PHY_MODE_1M); -#endif - - ret = pyld_len; - - if (ret > connsm->eff_max_tx_octets) { - ret = connsm->eff_max_tx_octets; - } - - if (ret > phy_max_tx_octets) { - ret = phy_max_tx_octets; - } - - return ret; -} - -static int -ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) -{ - int rc; - uint8_t md; - uint8_t hdr_byte; - uint8_t end_transition; - uint8_t cur_txlen; - uint8_t next_txlen; - uint8_t cur_offset; - uint16_t pktlen; - uint32_t next_event_time; - uint32_t ticks; - struct os_mbuf *m; - struct ble_mbuf_hdr *ble_hdr; - struct os_mbuf_pkthdr *pkthdr = NULL; - struct os_mbuf_pkthdr *nextpkthdr; - struct ble_ll_empty_pdu empty_pdu; - ble_phy_tx_end_func txend_func; - int tx_phy_mode; - uint8_t llid; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - int is_ctrl; - uint8_t opcode; -#endif - - /* For compiler warnings... */ - ble_hdr = NULL; - m = NULL; - md = 0; - hdr_byte = BLE_LL_LLID_DATA_FRAG; - - if (connsm->csmflags.cfbit.terminate_ind_rxd) { - /* We just received terminate indication. - * Just send empty packet as an ACK - */ - CONN_F_EMPTY_PDU_TXD(connsm) = 1; - goto conn_tx_pdu; - } - - /* - * We need to check if we are retrying a pdu or if there is a pdu on - * the transmit queue. - */ - pkthdr = STAILQ_FIRST(&connsm->conn_txq); - if (!connsm->cur_tx_pdu && !CONN_F_EMPTY_PDU_TXD(connsm) && !pkthdr) { - CONN_F_EMPTY_PDU_TXD(connsm) = 1; - goto conn_tx_pdu; - } - - /* - * If we dont have a pdu we have previously transmitted, take it off - * the connection transmit queue - */ - cur_offset = 0; - if (!connsm->cur_tx_pdu && !CONN_F_EMPTY_PDU_TXD(connsm)) { - /* Convert packet header to mbuf */ - m = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); - nextpkthdr = STAILQ_NEXT(pkthdr, omp_next); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - /* - * If we are encrypting, we are only allowed to send certain - * kinds of LL control PDU's. If none is enqueued, send empty pdu! - */ - if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) { - if (!ble_ll_ctrl_enc_allowed_pdu_tx(pkthdr)) { - CONN_F_EMPTY_PDU_TXD(connsm) = 1; - goto conn_tx_pdu; - } - - /* - * We will allow a next packet if it itself is allowed or we are - * a slave and we are sending the START_ENC_RSP. The master has - * to wait to receive the START_ENC_RSP from the slave before - * packets can be let go. - */ - if (nextpkthdr && !ble_ll_ctrl_enc_allowed_pdu_tx(nextpkthdr) - && ((connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) || - !ble_ll_ctrl_is_start_enc_rsp(m))) { - nextpkthdr = NULL; - } - } -#endif - /* Take packet off queue*/ - STAILQ_REMOVE_HEAD(&connsm->conn_txq, omp_next); - ble_hdr = BLE_MBUF_HDR_PTR(m); - - /* - * We dequeued new packet for transmission. - * If this is a data PDU we need to calculate payload length we can send - * over current PHY. Effectively, this determines fragmentation of packet - * into PDUs. - * If this is a control PDU we send complete PDU as only data PDU can be - * fragmented. We assume that checks (i.e. if remote supports such PDU) - * were already performed before putting packet on queue. - */ - llid = ble_hdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; - pktlen = pkthdr->omp_len; - if (llid == BLE_LL_LLID_CTRL) { - cur_txlen = pktlen; - } else { - cur_txlen = ble_ll_conn_adjust_pyld_len(connsm, pktlen); - } - ble_hdr->txinfo.pyld_len = cur_txlen; - - /* NOTE: header was set when first enqueued */ - hdr_byte = ble_hdr->txinfo.hdr_byte; - connsm->cur_tx_pdu = m; - } else { - nextpkthdr = pkthdr; - if (connsm->cur_tx_pdu) { - m = connsm->cur_tx_pdu; - ble_hdr = BLE_MBUF_HDR_PTR(m); - pktlen = OS_MBUF_PKTLEN(m); - cur_txlen = ble_hdr->txinfo.pyld_len; - cur_offset = ble_hdr->txinfo.offset; - if (cur_offset == 0) { - hdr_byte = ble_hdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; - } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) { - /* We will allow a next packet if it itself is allowed */ - pkthdr = OS_MBUF_PKTHDR(connsm->cur_tx_pdu); - if (nextpkthdr && !ble_ll_ctrl_enc_allowed_pdu_tx(nextpkthdr) - && ((connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) || - !ble_ll_ctrl_is_start_enc_rsp(connsm->cur_tx_pdu))) { - nextpkthdr = NULL; - } - } -#endif - } else { - /* Empty PDU here. NOTE: header byte gets set later */ - pktlen = 0; - cur_txlen = 0; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) { - /* We will allow a next packet if it itself is allowed */ - if (nextpkthdr && !ble_ll_ctrl_enc_allowed_pdu_tx(nextpkthdr)) { - nextpkthdr = NULL; - } - } -#endif - } - } - - /* - * Set the more data data flag if we have more data to send and we - * have not been asked to terminate - */ - if (nextpkthdr || ((cur_offset + cur_txlen) < pktlen)) { - /* Get next event time */ - next_event_time = ble_ll_conn_get_next_sched_time(connsm); - - /* XXX: TODO: need to check this with phy update procedure. There are - limitations if we have started update */ - - /* - * Dont bother to set the MD bit if we cannot do the following: - * -> wait IFS, send the current frame. - * -> wait IFS, receive a maximum size frame. - * -> wait IFS, send the next frame. - * -> wait IFS, receive a maximum size frame. - * - * For slave: - * -> wait IFS, send current frame. - * -> wait IFS, receive maximum size frame. - * -> wait IFS, send next frame. - */ - if ((cur_offset + cur_txlen) < pktlen) { - next_txlen = pktlen - (cur_offset + cur_txlen); - } else { - if (nextpkthdr->omp_len > connsm->eff_max_tx_octets) { - next_txlen = connsm->eff_max_tx_octets; - } else { - next_txlen = nextpkthdr->omp_len; - } - } - - /* - * XXX: this calculation is based on using the current time - * and assuming the transmission will occur an IFS time from - * now. This is not the most accurate especially if we have - * received a frame and we are replying to it. - */ -#if BLE_LL_BT5_PHY_SUPPORTED - tx_phy_mode = connsm->phy_data.tx_phy_mode; -#else - tx_phy_mode = BLE_PHY_MODE_1M; -#endif - - ticks = (BLE_LL_IFS * 3) + connsm->eff_max_rx_time + - ble_ll_pdu_tx_time_get(next_txlen, tx_phy_mode) + - ble_ll_pdu_tx_time_get(cur_txlen, tx_phy_mode); - - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - ticks += (BLE_LL_IFS + connsm->eff_max_rx_time); - } - - ticks = os_cputime_usecs_to_ticks(ticks); - if ((int32_t)((os_cputime_get32() + ticks) - next_event_time) < 0) { - md = 1; - } - } - - /* If we send an empty PDU we need to initialize the header */ -conn_tx_pdu: - if (CONN_F_EMPTY_PDU_TXD(connsm)) { - /* - * This looks strange, but we dont use the data pointer in the mbuf - * when we have an empty pdu. - */ - m = (struct os_mbuf *)&empty_pdu; - m->om_data = (uint8_t *)&empty_pdu; - m->om_data += BLE_MBUF_MEMBLOCK_OVERHEAD; - ble_hdr = &empty_pdu.ble_hdr; - ble_hdr->txinfo.flags = 0; - ble_hdr->txinfo.offset = 0; - ble_hdr->txinfo.pyld_len = 0; - } - - /* Set tx seqnum */ - if (connsm->tx_seqnum) { - hdr_byte |= BLE_LL_DATA_HDR_SN_MASK; - } - - /* If we have more data, set the bit */ - if (md) { - hdr_byte |= BLE_LL_DATA_HDR_MD_MASK; - } - - /* Set NESN (next expected sequence number) bit */ - if (connsm->next_exp_seqnum) { - hdr_byte |= BLE_LL_DATA_HDR_NESN_MASK; - } - - /* Set the header byte in the outgoing frame */ - ble_hdr->txinfo.hdr_byte = hdr_byte; - - /* - * If we are a slave, check to see if this transmission will end the - * connection event. We will end the connection event if we have - * received a valid frame with the more data bit set to 0 and we dont - * have more data. - * - * XXX: for a slave, we dont check to see if we can: - * -> wait IFS, rx frame from master (either big or small). - * -> wait IFS, send empty pdu or next pdu. - * - * We could do this. Now, we just keep going and hope that we dont - * overrun next scheduled item. - */ - if ((connsm->csmflags.cfbit.terminate_ind_rxd) || - ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && (md == 0) && - (connsm->cons_rxd_bad_crc == 0) && - ((connsm->last_rxd_hdr_byte & BLE_LL_DATA_HDR_MD_MASK) == 0) && - !ble_ll_ctrl_is_terminate_ind(hdr_byte, m->om_data[0]))) { - /* We will end the connection event */ - end_transition = BLE_PHY_TRANSITION_NONE; - txend_func = ble_ll_conn_wait_txend; - } else { - /* Wait for a response here */ - end_transition = BLE_PHY_TRANSITION_TX_RX; - txend_func = NULL; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - llid = ble_hdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; - if (llid == BLE_LL_LLID_CTRL) { - is_ctrl = 1; - opcode = m->om_data[0]; - } else { - is_ctrl = 0; - opcode = 0; - } - - if (is_ctrl && (opcode == BLE_LL_CTRL_START_ENC_RSP)) { - /* - * Both master and slave send the START_ENC_RSP encrypted and receive - * encrypted - */ - CONN_F_ENCRYPTED(connsm) = 1; - connsm->enc_data.tx_encrypted = 1; - ble_phy_encrypt_enable(connsm->enc_data.tx_pkt_cntr, - connsm->enc_data.iv, - connsm->enc_data.enc_block.cipher_text, - CONN_IS_MASTER(connsm)); - } else if (is_ctrl && (opcode == BLE_LL_CTRL_START_ENC_REQ)) { - /* - * Only the slave sends this and it gets sent unencrypted but - * we receive encrypted - */ - CONN_F_ENCRYPTED(connsm) = 0; - connsm->enc_data.enc_state = CONN_ENC_S_START_ENC_RSP_WAIT; - connsm->enc_data.tx_encrypted = 0; - ble_phy_encrypt_disable(); - if (txend_func == NULL) { - txend_func = ble_ll_conn_start_rx_encrypt; - } else { - txend_func = ble_ll_conn_txend_encrypt; - } - } else if (is_ctrl && (opcode == BLE_LL_CTRL_PAUSE_ENC_RSP)) { - /* - * The slave sends the PAUSE_ENC_RSP encrypted. The master sends - * it unencrypted (note that link was already set unencrypted). - */ - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - CONN_F_ENCRYPTED(connsm) = 1; - connsm->enc_data.tx_encrypted = 1; - ble_phy_encrypt_enable(connsm->enc_data.tx_pkt_cntr, - connsm->enc_data.iv, - connsm->enc_data.enc_block.cipher_text, - CONN_IS_MASTER(connsm)); - if (txend_func == NULL) { - txend_func = ble_ll_conn_start_rx_unencrypt; - } else { - txend_func = ble_ll_conn_rxend_unencrypt; - } - } else { - CONN_F_ENCRYPTED(connsm) = 0; - connsm->enc_data.enc_state = CONN_ENC_S_PAUSED; - connsm->enc_data.tx_encrypted = 0; - ble_phy_encrypt_disable(); - } - } else { - /* If encrypted set packet counter */ - if (CONN_F_ENCRYPTED(connsm)) { - connsm->enc_data.tx_encrypted = 1; - ble_phy_encrypt_set_pkt_cntr(connsm->enc_data.tx_pkt_cntr, - CONN_IS_MASTER(connsm)); - if (txend_func == NULL) { - txend_func = ble_ll_conn_continue_rx_encrypt; - } - } - } -#endif - - /* Set transmit end callback */ - ble_phy_set_txend_cb(txend_func, connsm); - rc = ble_phy_tx(ble_ll_tx_mbuf_pducb, m, end_transition); - if (!rc) { - /* Log transmit on connection state */ - cur_txlen = ble_hdr->txinfo.pyld_len; - ble_ll_trace_u32x2(BLE_LL_TRACE_ID_CONN_TX, cur_txlen, - ble_hdr->txinfo.offset); - - /* Set last transmitted MD bit */ - CONN_F_LAST_TXD_MD(connsm) = md; - - /* Increment packets transmitted */ - if (CONN_F_EMPTY_PDU_TXD(connsm)) { - if (connsm->csmflags.cfbit.terminate_ind_rxd) { - connsm->csmflags.cfbit.terminate_ind_rxd_acked = 1; - } - STATS_INC(ble_ll_conn_stats, tx_empty_pdus); - } else if ((hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) { - STATS_INC(ble_ll_conn_stats, tx_ctrl_pdus); - STATS_INCN(ble_ll_conn_stats, tx_ctrl_bytes, cur_txlen); - } else { - STATS_INC(ble_ll_conn_stats, tx_l2cap_pdus); - STATS_INCN(ble_ll_conn_stats, tx_l2cap_bytes, cur_txlen); - } - } - return rc; -} - -/** - * Schedule callback for start of connection event. - * - * Context: Interrupt - * - * @param sch - * - * @return int 0: scheduled item is still running. 1: schedule item is done. - */ -static int -ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch) -{ - int rc; - uint32_t usecs; - uint32_t start; - struct ble_ll_conn_sm *connsm; - - /* XXX: note that we can extend end time here if we want. Look at this */ - - /* Set current connection state machine */ - connsm = (struct ble_ll_conn_sm *)sch->cb_arg; - g_ble_ll_conn_cur_sm = connsm; - BLE_LL_ASSERT(connsm); - if (connsm->conn_state == BLE_LL_CONN_STATE_IDLE) { - /* That should not happen. If it does it means connection - * is already closed - */ - STATS_INC(ble_ll_conn_stats, sched_start_in_idle); - BLE_LL_ASSERT(0); - ble_ll_conn_current_sm_over(connsm); - return BLE_LL_SCHED_STATE_DONE; - } - - /* Log connection event start */ - ble_ll_trace_u32(BLE_LL_TRACE_ID_CONN_EV_START, connsm->conn_handle); - - /* Disable whitelisting as connections do not use it */ - ble_ll_whitelist_disable(); - - /* Set LL state */ - ble_ll_state_set(BLE_LL_STATE_CONNECTION); - - /* Set channel */ - ble_phy_setchan(connsm->data_chan_index, connsm->access_addr, - connsm->crcinit); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - ble_phy_resolv_list_disable(); -#endif - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_set(connsm->phy_data.tx_phy_mode, connsm->phy_data.rx_phy_mode); -#endif - - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - /* Set start time of transmission */ - start = sch->start_time + g_ble_ll_sched_offset_ticks; - rc = ble_phy_tx_set_start_time(start, sch->remainder); - if (!rc) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (CONN_F_ENCRYPTED(connsm)) { - ble_phy_encrypt_enable(connsm->enc_data.tx_pkt_cntr, - connsm->enc_data.iv, - connsm->enc_data.enc_block.cipher_text, - 1); - } else { - ble_phy_encrypt_disable(); - } -#endif - rc = ble_ll_conn_tx_pdu(connsm); - if (!rc) { - rc = BLE_LL_SCHED_STATE_RUNNING; - } else { - /* Inform LL task of connection event end */ - rc = BLE_LL_SCHED_STATE_DONE; - } - } else { - STATS_INC(ble_ll_conn_stats, conn_ev_late); - rc = BLE_LL_SCHED_STATE_DONE; - } - } else { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (CONN_F_ENCRYPTED(connsm)) { - ble_phy_encrypt_enable(connsm->enc_data.rx_pkt_cntr, - connsm->enc_data.iv, - connsm->enc_data.enc_block.cipher_text, - 1); - } else { - ble_phy_encrypt_disable(); - } -#endif - - /* XXX: what is this really for the slave? */ - start = sch->start_time + g_ble_ll_sched_offset_ticks; - rc = ble_phy_rx_set_start_time(start, sch->remainder); - if (rc) { - /* End the connection event as we have no more buffers */ - STATS_INC(ble_ll_conn_stats, slave_ce_failures); - rc = BLE_LL_SCHED_STATE_DONE; - } else { - /* - * Set flag that tells slave to set last anchor point if a packet - * has been received. - */ - connsm->csmflags.cfbit.slave_set_last_anchor = 1; - - /* - * Set the wait for response time. The anchor point is when we - * expect the master to start transmitting. Worst-case, we expect - * to hear a reply within the anchor point plus: - * -> current tx window size - * -> current window widening amount (includes +/- 16 usec jitter) - * -> Amount of time it takes to detect packet start. - * -> Some extra time (16 usec) to insure timing is OK - */ - - /* - * For the 32 kHz crystal, the amount of usecs we have to wait - * is not from the anchor point; we have to account for the time - * from when the receiver is enabled until the anchor point. The - * time we start before the anchor point is this: - * -> current window widening. - * -> up to one 32 kHz tick since we discard remainder. - * -> Up to one tick since the usecs to ticks calc can be off - * by up to one tick. - * NOTES: - * 1) the 61 we add is for the two ticks mentioned above. - * 2) The address rx time and jitter is accounted for in the - * phy function - */ - usecs = connsm->slave_cur_tx_win_usecs + 61 + - (2 * connsm->slave_cur_window_widening); - ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, usecs); - /* Set next wakeup time to connection event end time */ - rc = BLE_LL_SCHED_STATE_RUNNING; - } - } - - if (rc == BLE_LL_SCHED_STATE_DONE) { - ble_ll_event_send(&connsm->conn_ev_end); - ble_phy_disable(); - ble_ll_state_set(BLE_LL_STATE_STANDBY); - g_ble_ll_conn_cur_sm = NULL; - } - - /* Set time that we last serviced the schedule */ - connsm->last_scheduled = os_cputime_get32(); - return rc; -} - -/** - * Called to determine if the device is allowed to send the next pdu in the - * connection event. This will always return 'true' if we are a slave. If we - * are a master, we must be able to send the next fragment and get a minimum - * sized response from the slave. - * - * Context: Interrupt context (rx end isr). - * - * @param connsm - * @param begtime Time at which IFS before pdu transmission starts - * - * @return int 0: not allowed to send 1: allowed to send - */ -static int -ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime, - uint32_t add_usecs) -{ - int rc; - uint8_t rem_bytes; - uint32_t ticks; - uint32_t usecs; - uint32_t next_sched_time; - struct os_mbuf *txpdu; - struct os_mbuf_pkthdr *pkthdr; - struct ble_mbuf_hdr *txhdr; - uint32_t allowed_usecs; - int tx_phy_mode; - -#if BLE_LL_BT5_PHY_SUPPORTED - tx_phy_mode = connsm->phy_data.tx_phy_mode; -#else - tx_phy_mode = BLE_PHY_MODE_1M; -#endif - - rc = 1; - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - /* Get next scheduled item time */ - next_sched_time = ble_ll_conn_get_next_sched_time(connsm); - - txpdu = connsm->cur_tx_pdu; - if (!txpdu) { - pkthdr = STAILQ_FIRST(&connsm->conn_txq); - if (pkthdr) { - txpdu = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); - } - } else { - pkthdr = OS_MBUF_PKTHDR(txpdu); - } - - /* XXX: TODO: need to check this with phy update procedure. There are - limitations if we have started update */ - if (txpdu) { - txhdr = BLE_MBUF_HDR_PTR(txpdu); - rem_bytes = pkthdr->omp_len - txhdr->txinfo.offset; - if (rem_bytes > connsm->eff_max_tx_octets) { - rem_bytes = connsm->eff_max_tx_octets; - } - usecs = ble_ll_pdu_tx_time_get(rem_bytes, tx_phy_mode); - } else { - /* We will send empty pdu (just a LL header) */ - usecs = ble_ll_pdu_tx_time_get(0, tx_phy_mode); - } - usecs += (BLE_LL_IFS * 2) + connsm->eff_max_rx_time; - - ticks = (uint32_t)(next_sched_time - begtime); - allowed_usecs = os_cputime_ticks_to_usecs(ticks); - if ((usecs + add_usecs) >= allowed_usecs) { - rc = 0; - } - } - - return rc; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) -/** - * Callback for the Authenticated payload timer. This function is called - * when the authenticated payload timer expires. When the authenticated - * payload timeout expires, we should - * -> Send the authenticated payload timeout event. - * -> Start the LE ping procedure. - * -> Restart the timer. - * - * @param arg - */ -void -ble_ll_conn_auth_pyld_timer_cb(struct ble_npl_event *ev) -{ - struct ble_ll_conn_sm *connsm; - - connsm = (struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev); - ble_ll_auth_pyld_tmo_event_send(connsm); - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_LE_PING); - ble_ll_conn_auth_pyld_timer_start(connsm); -} - -void -ble_ll_conn_rd_features_timer_cb(struct ble_npl_event *ev) -{ - struct ble_ll_conn_sm *connsm; - - connsm = (struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev); - - if (!connsm->csmflags.cfbit.pending_hci_rd_features || - !connsm->csmflags.cfbit.rxd_features) { - return; - } - - ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS); - connsm->csmflags.cfbit.pending_hci_rd_features = 0; -} - -/** - * Start (or restart) the authenticated payload timer - * - * @param connsm - */ -void -ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm) -{ - int32_t tmo; - - /* Timeout in is in 10 msec units */ - tmo = (int32_t)BLE_LL_CONN_AUTH_PYLD_OS_TMO(connsm->auth_pyld_tmo); - ble_npl_callout_reset(&connsm->auth_pyld_timer, tmo); -} -#endif - -static void -ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm) -{ - - /* Set master role */ - connsm->conn_role = BLE_LL_CONN_ROLE_MASTER; - - /* Set default ce parameters */ - - /* - * XXX: for now, we need twice the transmit window as our calculations - * for the transmit window offset could be off. - */ - connsm->tx_win_size = BLE_LL_CONN_TX_WIN_MIN + 1; - connsm->tx_win_off = 0; - connsm->master_sca = MYNEWT_VAL(BLE_LL_MASTER_SCA); - - /* Hop increment is a random value between 5 and 16. */ - connsm->hop_inc = (rand() % 12) + 5; - - /* Set channel map to map requested by host */ - connsm->num_used_chans = g_ble_ll_conn_params.num_used_chans; - memcpy(connsm->chanmap, g_ble_ll_conn_params.master_chan_map, - BLE_LL_CONN_CHMAP_LEN); - - /* Calculate random access address and crc initialization value */ - connsm->access_addr = ble_ll_utils_calc_access_addr(); - connsm->crcinit = rand() & 0xffffff; - - /* Set initial schedule callback */ - connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb; -} -/** - * Called when a create connection command has been received. This initializes - * a connection state machine in the master role. - * - * NOTE: Must be called before the state machine is started - * - * @param connsm - * @param hcc - */ -void -ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm, - struct hci_create_conn *hcc) -{ - - ble_ll_conn_master_common_init(connsm); - - /* Set slave latency and supervision timeout */ - connsm->slave_latency = hcc->conn_latency; - connsm->supervision_tmo = hcc->supervision_timeout; - - /* Set own address type and peer address if needed */ - connsm->own_addr_type = hcc->own_addr_type; - if (hcc->filter_policy == 0) { - memcpy(&connsm->peer_addr, &hcc->peer_addr, BLE_DEV_ADDR_LEN); - connsm->peer_addr_type = hcc->peer_addr_type; - } - - /* XXX: for now, just make connection interval equal to max */ - connsm->conn_itvl = hcc->conn_itvl_max; - - /* Check the min/max CE lengths are less than connection interval */ - if (hcc->min_ce_len > (connsm->conn_itvl * 2)) { - connsm->min_ce_len = connsm->conn_itvl * 2; - } else { - connsm->min_ce_len = hcc->min_ce_len; - } - - if (hcc->max_ce_len > (connsm->conn_itvl * 2)) { - connsm->max_ce_len = connsm->conn_itvl * 2; - } else { - connsm->max_ce_len = hcc->max_ce_len; - } -} - -static void -ble_ll_update_max_tx_octets_phy_mode(struct ble_ll_conn_sm *connsm) -{ - uint32_t usecs; - - usecs = connsm->eff_max_tx_time; - - connsm->max_tx_octets_phy_mode[BLE_PHY_MODE_1M] = - ble_ll_pdu_max_tx_octets_get(usecs, BLE_PHY_MODE_1M); - connsm->max_tx_octets_phy_mode[BLE_PHY_MODE_2M] = - ble_ll_pdu_max_tx_octets_get(usecs, BLE_PHY_MODE_2M); - connsm->max_tx_octets_phy_mode[BLE_PHY_MODE_CODED_125KBPS] = - ble_ll_pdu_max_tx_octets_get(usecs, BLE_PHY_MODE_CODED_125KBPS); - connsm->max_tx_octets_phy_mode[BLE_PHY_MODE_CODED_500KBPS] = - ble_ll_pdu_max_tx_octets_get(usecs, BLE_PHY_MODE_CODED_500KBPS); -} - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - -static void -ble_ll_conn_set_phy(struct ble_ll_conn_sm *connsm, int tx_phy, int rx_phy) -{ - - struct ble_ll_conn_phy_data *phy_data = &connsm->phy_data; - - phy_data->rx_phy_mode = ble_ll_phy_to_phy_mode(rx_phy, - BLE_HCI_LE_PHY_CODED_ANY); - phy_data->cur_rx_phy = rx_phy; - - phy_data->tx_phy_mode = ble_ll_phy_to_phy_mode(tx_phy, - BLE_HCI_LE_PHY_CODED_ANY); - phy_data->cur_tx_phy = tx_phy; - -} - -static void -ble_ll_conn_init_phy(struct ble_ll_conn_sm *connsm, int phy) -{ - struct ble_ll_conn_global_params *conngp; - - /* Always initialize symmetric PHY - controller can change this later */ - ble_ll_conn_set_phy(connsm, phy, phy); - - /* Update data length management to match initial PHY */ - conngp = &g_ble_ll_conn_params; - connsm->max_tx_octets = conngp->conn_init_max_tx_octets; - connsm->max_rx_octets = conngp->supp_max_rx_octets; - if (phy == BLE_PHY_CODED) { - connsm->max_tx_time = conngp->conn_init_max_tx_time_coded; - connsm->max_rx_time = BLE_LL_CONN_SUPP_TIME_MAX_CODED; - connsm->rem_max_tx_time = BLE_LL_CONN_SUPP_TIME_MIN_CODED; - connsm->rem_max_rx_time = BLE_LL_CONN_SUPP_TIME_MIN_CODED; - /* Assume peer does support coded */ - connsm->remote_features[0] |= (BLE_LL_FEAT_LE_CODED_PHY >> 8); - } else { - connsm->max_tx_time = conngp->conn_init_max_tx_time_uncoded; - connsm->max_rx_time = BLE_LL_CONN_SUPP_TIME_MAX_UNCODED; - connsm->rem_max_tx_time = BLE_LL_CONN_SUPP_TIME_MIN_UNCODED; - connsm->rem_max_rx_time = BLE_LL_CONN_SUPP_TIME_MIN_UNCODED; - } - connsm->eff_max_tx_time = connsm->rem_max_tx_time; - connsm->eff_max_rx_time = connsm->rem_max_rx_time; - connsm->rem_max_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; - connsm->rem_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; - connsm->eff_max_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; - connsm->eff_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; - - ble_ll_update_max_tx_octets_phy_mode(connsm); -} - -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - -void -ble_ll_conn_ext_master_init(struct ble_ll_conn_sm *connsm, - struct hci_ext_create_conn *hcc) -{ - - ble_ll_conn_master_common_init(connsm); - - /* Set own address type and peer address if needed */ - connsm->own_addr_type = hcc->own_addr_type; - if (hcc->filter_policy == 0) { - memcpy(&connsm->peer_addr, &hcc->peer_addr, BLE_DEV_ADDR_LEN); - connsm->peer_addr_type = hcc->peer_addr_type; - } - - connsm->initial_params = *hcc; -} - -void -ble_ll_conn_ext_set_params(struct ble_ll_conn_sm *connsm, - struct hci_ext_conn_params *hcc_params, int phy) -{ - /* Set slave latency and supervision timeout */ - connsm->slave_latency = hcc_params->conn_latency; - connsm->supervision_tmo = hcc_params->supervision_timeout; - - /* XXX: for now, just make connection interval equal to max */ - connsm->conn_itvl = hcc_params->conn_itvl_max; - - - /* Check the min/max CE lengths are less than connection interval */ - if (hcc_params->min_ce_len > (connsm->conn_itvl * 2)) { - connsm->min_ce_len = connsm->conn_itvl * 2; - } else { - connsm->min_ce_len = hcc_params->min_ce_len; - } - - if (hcc_params->max_ce_len > (connsm->conn_itvl * 2)) { - connsm->max_ce_len = connsm->conn_itvl * 2; - } else { - connsm->max_ce_len = hcc_params->max_ce_len; - } - - ble_ll_conn_calc_itvl_ticks(connsm); - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_ll_conn_init_phy(connsm, phy); -#endif -} - - -#endif - -static void -ble_ll_conn_set_csa(struct ble_ll_conn_sm *connsm, bool chsel) -{ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) - if (chsel) { - CONN_F_CSA2_SUPP(connsm) = 1; - connsm->channel_id = ((connsm->access_addr & 0xffff0000) >> 16) ^ - (connsm->access_addr & 0x0000ffff); - - /* calculate the next data channel */ - connsm->data_chan_index = ble_ll_conn_calc_dci(connsm, 0); - return; - } -#endif - - connsm->last_unmapped_chan = 0; - - /* calculate the next data channel */ - connsm->data_chan_index = ble_ll_conn_calc_dci(connsm, 1); -} - -/** - * Create a new connection state machine. This is done once per - * connection when the HCI command "create connection" is issued to the - * controller or when a slave receives a connect request. - * - * Context: Link Layer task - * - * @param connsm - */ -void -ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm) -{ - struct ble_ll_conn_global_params *conn_params; - - /* Reset following elements */ - connsm->csmflags.conn_flags = 0; - connsm->event_cntr = 0; - connsm->conn_state = BLE_LL_CONN_STATE_IDLE; - connsm->disconnect_reason = 0; - connsm->rxd_disconnect_reason = 0; - connsm->conn_features = BLE_LL_CONN_INITIAL_FEATURES; - memset(connsm->remote_features, 0, sizeof(connsm->remote_features)); - connsm->vers_nr = 0; - connsm->comp_id = 0; - connsm->sub_vers_nr = 0; - connsm->reject_reason = BLE_ERR_SUCCESS; - connsm->conn_rssi = BLE_LL_CONN_UNKNOWN_RSSI; - connsm->rpa_index = -1; - connsm->inita_identity_used = 0; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - connsm->sync_transfer_sync_timeout = g_ble_ll_conn_sync_transfer_params.sync_timeout_us; - connsm->sync_transfer_mode = g_ble_ll_conn_sync_transfer_params.mode; - connsm->sync_transfer_skip = g_ble_ll_conn_sync_transfer_params.max_skip; -#endif - - /* XXX: TODO set these based on PHY that started connection */ -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - connsm->phy_data.cur_tx_phy = BLE_PHY_1M; - connsm->phy_data.cur_rx_phy = BLE_PHY_1M; - connsm->phy_data.tx_phy_mode = BLE_PHY_MODE_1M; - connsm->phy_data.rx_phy_mode = BLE_PHY_MODE_1M; - connsm->phy_data.req_pref_tx_phys_mask = 0; - connsm->phy_data.req_pref_rx_phys_mask = 0; - connsm->phy_data.host_pref_tx_phys_mask = g_ble_ll_data.ll_pref_tx_phys; - connsm->phy_data.host_pref_rx_phys_mask = g_ble_ll_data.ll_pref_rx_phys; - connsm->phy_data.phy_options = 0; - connsm->phy_tx_transition = 0; -#endif - - /* Reset current control procedure */ - connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE; - connsm->pending_ctrl_procs = 0; - - /* - * Set handle in connection update procedure to 0. If the handle - * is non-zero it means that the host initiated the connection - * parameter update request and the rest of the parameters are valid. - */ - connsm->conn_param_req.handle = 0; - - /* Connection end event */ - ble_npl_event_init(&connsm->conn_ev_end, ble_ll_conn_event_end, connsm); - - /* Initialize transmit queue and ack/flow control elements */ - STAILQ_INIT(&connsm->conn_txq); - connsm->cur_tx_pdu = NULL; - connsm->tx_seqnum = 0; - connsm->next_exp_seqnum = 0; - connsm->cons_rxd_bad_crc = 0; - connsm->last_rxd_sn = 1; - connsm->completed_pkts = 0; - - /* initialize data length mgmt */ - conn_params = &g_ble_ll_conn_params; - connsm->max_tx_octets = conn_params->conn_init_max_tx_octets; - connsm->max_rx_octets = conn_params->supp_max_rx_octets; - connsm->max_tx_time = conn_params->conn_init_max_tx_time; - connsm->max_rx_time = conn_params->supp_max_rx_time; - connsm->rem_max_tx_time = BLE_LL_CONN_SUPP_TIME_MIN; - connsm->rem_max_rx_time = BLE_LL_CONN_SUPP_TIME_MIN; - connsm->eff_max_tx_time = BLE_LL_CONN_SUPP_TIME_MIN; - connsm->eff_max_rx_time = BLE_LL_CONN_SUPP_TIME_MIN; - connsm->rem_max_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; - connsm->rem_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; - connsm->eff_max_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; - connsm->eff_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - connsm->host_req_max_tx_time = 0; -#endif - - ble_ll_update_max_tx_octets_phy_mode(connsm); - - /* Reset encryption data */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - memset(&connsm->enc_data, 0, sizeof(struct ble_ll_conn_enc_data)); - connsm->enc_data.enc_state = CONN_ENC_S_UNENCRYPTED; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) - connsm->auth_pyld_tmo = BLE_LL_CONN_DEF_AUTH_PYLD_TMO; - CONN_F_LE_PING_SUPP(connsm) = 1; - ble_npl_callout_init(&connsm->auth_pyld_timer, - &g_ble_ll_data.ll_evq, - ble_ll_conn_auth_pyld_timer_cb, - connsm); -#endif - - ble_ll_conn_calc_itvl_ticks(connsm); - - /* Add to list of active connections */ - SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle); -} - -void -ble_ll_conn_update_eff_data_len(struct ble_ll_conn_sm *connsm) -{ - int send_event; - uint16_t eff_time; - uint16_t eff_bytes; - - /* Assume no event sent */ - send_event = 0; - - /* See if effective times have changed */ - eff_time = min(connsm->rem_max_tx_time, connsm->max_rx_time); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - if (connsm->phy_data.cur_rx_phy == BLE_PHY_CODED) { - eff_time = max(eff_time, BLE_LL_CONN_SUPP_TIME_MIN_CODED); - } -#endif - if (eff_time != connsm->eff_max_rx_time) { - connsm->eff_max_rx_time = eff_time; - send_event = 1; - } - eff_time = min(connsm->rem_max_rx_time, connsm->max_tx_time); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - if (connsm->phy_data.cur_tx_phy == BLE_PHY_CODED) { - eff_time = max(eff_time, BLE_LL_CONN_SUPP_TIME_MIN_CODED); - } -#endif - if (eff_time != connsm->eff_max_tx_time) { - connsm->eff_max_tx_time = eff_time; - send_event = 1; - - ble_ll_update_max_tx_octets_phy_mode(connsm); - } - eff_bytes = min(connsm->rem_max_tx_octets, connsm->max_rx_octets); - if (eff_bytes != connsm->eff_max_rx_octets) { - connsm->eff_max_rx_octets = eff_bytes; - send_event = 1; - } - eff_bytes = min(connsm->rem_max_rx_octets, connsm->max_tx_octets); - if (eff_bytes != connsm->eff_max_tx_octets) { - connsm->eff_max_tx_octets = eff_bytes; - send_event = 1; - } - - if (send_event) { - ble_ll_hci_ev_datalen_chg(connsm); - } -} - -/** - * Called when a connection is terminated - * - * Context: Link Layer task. - * - * @param connsm - * @param ble_err - */ -void -ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err) -{ - struct os_mbuf *m; - struct os_mbuf_pkthdr *pkthdr; - os_sr_t sr; - - /* Remove scheduler events just in case */ - ble_ll_sched_rmv_elem(&connsm->conn_sch); - - /* In case of the supervision timeout we shall make sure - * that there is no ongoing connection event. It could happen - * because we scheduled connection event before checking connection timeout. - * If connection event managed to start, let us drop it. - */ - OS_ENTER_CRITICAL(sr); - if (g_ble_ll_conn_cur_sm == connsm) { - ble_ll_conn_halt(); - STATS_INC(ble_ll_conn_stats, conn_event_while_tmo); - } - OS_EXIT_CRITICAL(sr); - - /* Stop any control procedures that might be running */ - ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) - ble_npl_callout_stop(&connsm->auth_pyld_timer); -#endif - - /* Remove from the active connection list */ - SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle); - - /* Free the current transmit pdu if there is one. */ - if (connsm->cur_tx_pdu) { - os_mbuf_free_chain(connsm->cur_tx_pdu); - connsm->cur_tx_pdu = NULL; - } - - /* Free all packets on transmit queue */ - while (1) { - /* Get mbuf pointer from packet header pointer */ - pkthdr = STAILQ_FIRST(&connsm->conn_txq); - if (!pkthdr) { - break; - } - STAILQ_REMOVE_HEAD(&connsm->conn_txq, omp_next); - - m = (struct os_mbuf *)((uint8_t *)pkthdr - sizeof(struct os_mbuf)); - os_mbuf_free_chain(m); - } - - /* Make sure events off queue */ - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &connsm->conn_ev_end); - -#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) - /* Remove from occupied periods */ - OS_ENTER_CRITICAL(sr); - BLE_LL_ASSERT(g_ble_ll_sched_data.sch_num_occ_periods > 0); - BLE_LL_ASSERT(g_ble_ll_sched_data.sch_occ_period_mask & connsm->period_occ_mask); - --g_ble_ll_sched_data.sch_num_occ_periods; - g_ble_ll_sched_data.sch_occ_period_mask &= ~connsm->period_occ_mask; - OS_EXIT_CRITICAL(sr); -#endif - - /* Connection state machine is now idle */ - connsm->conn_state = BLE_LL_CONN_STATE_IDLE; - - /* - * If we have features and there's pending HCI command, send an event before - * disconnection event so it does make sense to host. - */ - if (connsm->csmflags.cfbit.pending_hci_rd_features && - connsm->csmflags.cfbit.rxd_features) { - ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS); - connsm->csmflags.cfbit.pending_hci_rd_features = 0; - } - - /* - * If there is still pending read features request HCI command, send an - * event to complete it. - */ - if (connsm->csmflags.cfbit.pending_hci_rd_features) { - ble_ll_hci_ev_rd_rem_used_feat(connsm, ble_err); - connsm->csmflags.cfbit.pending_hci_rd_features = 0; - } - - /* - * We need to send a disconnection complete event. Connection Complete for - * canceling connection creation is sent from LE Create Connection Cancel - * Command handler. - * - * If the ble error is "success" it means that the reset command was - * received and we should not send an event. - */ - if (ble_err && (ble_err != BLE_ERR_UNK_CONN_ID || - connsm->csmflags.cfbit.terminate_ind_rxd)) { - ble_ll_disconn_comp_event_send(connsm, ble_err); - } - - /* Put connection state machine back on free list */ - STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); - - /* Log connection end */ - ble_ll_trace_u32x3(BLE_LL_TRACE_ID_CONN_END, connsm->conn_handle, - connsm->event_cntr, (uint32_t)ble_err); -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -void -ble_ll_conn_get_anchor(struct ble_ll_conn_sm *connsm, uint16_t conn_event, - uint32_t *anchor, uint8_t *anchor_usecs) -{ - uint32_t ticks; - uint32_t itvl; - - itvl = (connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS); - - if ((int16_t)(conn_event - connsm->event_cntr) < 0) { - itvl *= connsm->event_cntr - conn_event; - ticks = os_cputime_usecs_to_ticks(itvl); - *anchor = connsm->anchor_point - ticks; - } else { - itvl *= conn_event - connsm->event_cntr; - ticks = os_cputime_usecs_to_ticks(itvl); - *anchor = connsm->anchor_point + ticks; - } - - *anchor_usecs = connsm->anchor_point_usecs; - *anchor_usecs += (itvl - os_cputime_ticks_to_usecs(ticks)); - if (*anchor_usecs >= 31) { - (*anchor)++; - *anchor_usecs -= 31; - } -} -#endif - -/** - * Called to move to the next connection event. - * - * Context: Link Layer task. - * - * @param connsm - * - * @return int - */ -static int -ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) -{ - uint16_t latency; - uint32_t itvl; - uint32_t cur_ww; - uint32_t max_ww; - struct ble_ll_conn_upd_req *upd; - uint32_t ticks; - uint32_t usecs; - - /* XXX: deal with connection request procedure here as well */ - ble_ll_conn_chk_csm_flags(connsm); - - /* If unable to start terminate procedure, start it now */ - if (connsm->disconnect_reason && !CONN_F_TERMINATE_STARTED(connsm)) { - ble_ll_ctrl_terminate_start(connsm); - } - - if (CONN_F_TERMINATE_STARTED(connsm) && (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE)) { - /* Some of the devices waits whole connection interval to ACK our - * TERMINATE_IND sent as a Slave. Since we are here it means we are still waiting for ACK. - * Make sure we catch it in next connection event. - */ - connsm->slave_latency = 0; - } - - /* - * XXX: TODO Probably want to add checks to see if we need to start - * a control procedure here as an instant may have prevented us from - * starting one. - */ - - /* - * XXX TODO: I think this is technically incorrect. We can allow slave - * latency if we are doing one of these updates as long as we - * know that the master has received the ACK to the PDU that set - * the instant - */ - /* Set event counter to the next connection event that we will tx/rx in */ - itvl = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS; - latency = 1; - if (connsm->csmflags.cfbit.allow_slave_latency && - !connsm->csmflags.cfbit.conn_update_sched && - !CONN_F_PHY_UPDATE_SCHED(connsm) && - !connsm->csmflags.cfbit.chanmap_update_scheduled) { - if (connsm->csmflags.cfbit.pkt_rxd) { - latency += connsm->slave_latency; - itvl = itvl * latency; - } - } - connsm->event_cntr += latency; - - /* Set next connection event start time */ - /* We can use pre-calculated values for one interval if latency is 1. */ - if (latency == 1) { - connsm->anchor_point += connsm->conn_itvl_ticks; - connsm->anchor_point_usecs += connsm->conn_itvl_usecs; - } else { - uint32_t ticks; - ticks = os_cputime_usecs_to_ticks(itvl); - connsm->anchor_point += ticks; - connsm->anchor_point_usecs += (itvl - os_cputime_ticks_to_usecs(ticks)); - } - if (connsm->anchor_point_usecs >= 31) { - ++connsm->anchor_point; - connsm->anchor_point_usecs -= 31; - } - - /* - * If a connection update has been scheduled and the event counter - * is now equal to the instant, we need to adjust the start of the - * connection by the the transmit window offset. We also copy in the - * update parameters as they now should take effect. - */ - if (connsm->csmflags.cfbit.conn_update_sched && - (connsm->event_cntr == connsm->conn_update_req.instant)) { - - /* Set flag so we send connection update event */ - upd = &connsm->conn_update_req; - if ((connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) || - ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && - IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) || - (connsm->conn_itvl != upd->interval) || - (connsm->slave_latency != upd->latency) || - (connsm->supervision_tmo != upd->timeout)) { - connsm->csmflags.cfbit.host_expects_upd_event = 1; - } - - connsm->supervision_tmo = upd->timeout; - connsm->slave_latency = upd->latency; - connsm->tx_win_size = upd->winsize; - connsm->slave_cur_tx_win_usecs = - connsm->tx_win_size * BLE_LL_CONN_TX_WIN_USECS; - connsm->tx_win_off = upd->winoffset; - connsm->conn_itvl = upd->interval; - ble_ll_conn_calc_itvl_ticks(connsm); - if (upd->winoffset != 0) { - usecs = upd->winoffset * BLE_LL_CONN_ITVL_USECS; - ticks = os_cputime_usecs_to_ticks(usecs); - connsm->anchor_point += ticks; - usecs = usecs - os_cputime_ticks_to_usecs(ticks); - connsm->anchor_point_usecs += usecs; - if (connsm->anchor_point_usecs >= 31) { - ++connsm->anchor_point; - connsm->anchor_point_usecs -= 31; - } - } - - /* Reset the starting point of the connection supervision timeout */ - connsm->last_rxd_pdu_cputime = connsm->anchor_point; - - /* Reset update scheduled flag */ - connsm->csmflags.cfbit.conn_update_sched = 0; - } - - /* - * If there is a channel map request pending and we have reached the - * instant, change to new channel map. Note there is a special case here. - * If we received a channel map update with an instant equal to the event - * counter, when we get here the event counter has already been - * incremented by 1. That is why we do a signed comparison and change to - * new channel map once the event counter equals or has passed channel - * map update instant. - */ - if (connsm->csmflags.cfbit.chanmap_update_scheduled && - ((int16_t)(connsm->chanmap_instant - connsm->event_cntr) <= 0)) { - - /* XXX: there is a chance that the control packet is still on - * the queue of the master. This means that we never successfully - * transmitted update request. Would end up killing connection - on slave side. Could ignore it or see if still enqueued. */ - connsm->num_used_chans = - ble_ll_utils_calc_num_used_chans(connsm->req_chanmap); - memcpy(connsm->chanmap, connsm->req_chanmap, BLE_LL_CONN_CHMAP_LEN); - - connsm->csmflags.cfbit.chanmap_update_scheduled = 0; - - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CHAN_MAP_UPD); - - /* XXX: host could have resent channel map command. Need to - check to make sure we dont have to restart! */ - } - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - if (CONN_F_PHY_UPDATE_SCHED(connsm) && - (connsm->event_cntr == connsm->phy_instant)) { - - /* Set cur phy to new phy */ - if (connsm->phy_data.new_tx_phy) { - connsm->phy_data.cur_tx_phy = connsm->phy_data.new_tx_phy; - connsm->phy_data.tx_phy_mode = - ble_ll_phy_to_phy_mode(connsm->phy_data.cur_tx_phy, - connsm->phy_data.phy_options); - } - - if (connsm->phy_data.new_rx_phy) { - connsm->phy_data.cur_rx_phy = connsm->phy_data.new_rx_phy; - connsm->phy_data.rx_phy_mode = - ble_ll_phy_to_phy_mode(connsm->phy_data.cur_rx_phy, - connsm->phy_data.phy_options); - } - - /* Clear flags and set flag to send event at next instant */ - CONN_F_PHY_UPDATE_SCHED(connsm) = 0; - CONN_F_PHY_UPDATE_EVENT(connsm) = 1; - - ble_ll_ctrl_phy_update_proc_complete(connsm); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - /* Recalculate effective connection parameters */ - ble_ll_conn_update_eff_data_len(connsm); - - /* - * If PHY in either direction was changed to coded, we assume that peer - * does support LE Coded PHY even if features were not exchanged yet. - * This means that MaxRxTime can be updated to supported max and we need - * initiate DLE to notify peer about the change. - */ - if (((connsm->phy_data.cur_tx_phy == BLE_PHY_CODED) || - (connsm->phy_data.cur_rx_phy == BLE_PHY_CODED)) && - !(connsm->remote_features[0] & (BLE_LL_FEAT_LE_CODED_PHY >> 8))) { - connsm->remote_features[0] |= (BLE_LL_FEAT_LE_CODED_PHY >> 8); - connsm->max_rx_time = BLE_LL_CONN_SUPP_TIME_MAX_CODED; - ble_ll_ctrl_initiate_dle(connsm); - } -#endif - } -#endif - - /* Calculate data channel index of next connection event */ - connsm->data_chan_index = ble_ll_conn_calc_dci(connsm, latency); - - /* - * If we are trying to terminate connection, check if next wake time is - * passed the termination timeout. If so, no need to continue with - * connection as we will time out anyway. - */ - if (CONN_F_TERMINATE_STARTED(connsm)) { - if ((int32_t)(connsm->terminate_timeout - connsm->anchor_point) <= 0) { - return -1; - } - } - - /* - * Calculate ce end time. For a slave, we need to add window widening and - * the transmit window if we still have one. - */ -#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) - itvl = g_ble_ll_sched_data.sch_ticks_per_period; -#else - itvl = MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT; -#endif - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - - cur_ww = ble_ll_utils_calc_window_widening(connsm->anchor_point, - connsm->last_anchor_point, - connsm->master_sca); - max_ww = (connsm->conn_itvl * (BLE_LL_CONN_ITVL_USECS/2)) - BLE_LL_IFS; - if (cur_ww >= max_ww) { - return -1; - } - cur_ww += BLE_LL_JITTER_USECS; - connsm->slave_cur_window_widening = cur_ww; - itvl += os_cputime_usecs_to_ticks(cur_ww + connsm->slave_cur_tx_win_usecs); - } - itvl -= g_ble_ll_sched_offset_ticks; - connsm->ce_end_time = connsm->anchor_point + itvl; - - return 0; -} - -/** - * Called when a connection has been created. This function will - * -> Set the connection state to created. - * -> Start the connection supervision timer - * -> Set the Link Layer state to connection. - * -> Send a connection complete event. - * - * See Section 4.5.2 Vol 6 Part B - * - * Context: Link Layer - * - * @param connsm - * - * @ return 0: connection NOT created. 1: connection created - */ -static int -ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr) -{ - int rc; - uint8_t *evbuf; - uint32_t endtime; - uint32_t usecs; - - /* XXX: TODO this assumes we received in 1M phy */ - - /* Set state to created */ - connsm->conn_state = BLE_LL_CONN_STATE_CREATED; - - /* Clear packet received flag */ - connsm->csmflags.cfbit.pkt_rxd = 0; - - /* Consider time created the last scheduled time */ - connsm->last_scheduled = os_cputime_get32(); - - /* - * Set the last rxd pdu time since this is where we want to start the - * supervision timer from. - */ - connsm->last_rxd_pdu_cputime = connsm->last_scheduled; - - /* - * Set first connection event time. If slave the endtime is the receive end - * time of the connect request. The actual connection starts 1.25 msecs plus - * the transmit window offset from the end of the connection request. - */ - rc = 1; - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - /* - * With a 32.768 kHz crystal we dont care about the remaining usecs - * when setting last anchor point. The only thing last anchor is used - * for is to calculate window widening. The effect of this is - * negligible. - */ - connsm->last_anchor_point = rxhdr->beg_cputime; - - usecs = rxhdr->rem_usecs + 1250 + - (connsm->tx_win_off * BLE_LL_CONN_TX_WIN_USECS) + - ble_ll_pdu_tx_time_get(BLE_CONNECT_REQ_LEN, - rxhdr->rxinfo.phy_mode); - - if (rxhdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) { - switch (rxhdr->rxinfo.phy) { - case BLE_PHY_1M: - case BLE_PHY_2M: - usecs += 1250; - break; - case BLE_PHY_CODED: - usecs += 2500; - break; - default: - BLE_LL_ASSERT(0); - break; - } - } - - /* Anchor point is cputime. */ - endtime = os_cputime_usecs_to_ticks(usecs); - connsm->anchor_point = rxhdr->beg_cputime + endtime; - connsm->anchor_point_usecs = usecs - os_cputime_ticks_to_usecs(endtime); - if (connsm->anchor_point_usecs == 31) { - ++connsm->anchor_point; - connsm->anchor_point_usecs = 0; - } - - connsm->slave_cur_tx_win_usecs = - connsm->tx_win_size * BLE_LL_CONN_TX_WIN_USECS; -#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) - connsm->ce_end_time = connsm->anchor_point + - g_ble_ll_sched_data.sch_ticks_per_period + - os_cputime_usecs_to_ticks(connsm->slave_cur_tx_win_usecs) + 1; - -#else - connsm->ce_end_time = connsm->anchor_point + - (MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT) - + os_cputime_usecs_to_ticks(connsm->slave_cur_tx_win_usecs) + 1; -#endif - connsm->slave_cur_window_widening = BLE_LL_JITTER_USECS; - - /* Start the scheduler for the first connection event */ - while (ble_ll_sched_slave_new(connsm)) { - if (ble_ll_conn_next_event(connsm)) { - STATS_INC(ble_ll_conn_stats, cant_set_sched); - rc = 0; - break; - } - } - } - - /* Send connection complete event to inform host of connection */ - if (rc) { -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - /* - * If we have default phy preferences and they are different than - * the current PHY's in use, start update procedure. - */ - /* - * XXX: should we attempt to start this without knowing if - * the other side can support it? - */ - if (!ble_ll_conn_chk_phy_upd_start(connsm)) { - CONN_F_CTRLR_PHY_UPDATE(connsm) = 1; - } -#endif - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - ble_ll_adv_send_conn_comp_ev(connsm, rxhdr); - } else { - evbuf = ble_ll_init_get_conn_comp_ev(); - ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS, evbuf, NULL); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) - ble_ll_hci_ev_le_csa(connsm); -#endif - - /* - * Initiate features exchange - * - * XXX we do this only as a master as it was observed that sending - * LL_SLAVE_FEATURE_REQ after connection breaks some recent iPhone - * models; for slave just assume master will initiate features xchg - * if it has some additional features to use. - */ - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG); - } - } - - return rc; -} - -/** - * Called upon end of connection event - * - * Context: Link-layer task - * - * @param void *arg Pointer to connection state machine - * - */ -static void -ble_ll_conn_event_end(struct ble_npl_event *ev) -{ - uint8_t ble_err; - uint32_t tmo; - struct ble_ll_conn_sm *connsm; - - ble_ll_rfmgmt_release(); - - /* Better be a connection state machine! */ - connsm = (struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev); - BLE_LL_ASSERT(connsm); - if (connsm->conn_state == BLE_LL_CONN_STATE_IDLE) { - /* That should not happen. If it does it means connection - * is already closed. - * Make sure LL state machine is in idle - */ - STATS_INC(ble_ll_conn_stats, sched_end_in_idle); - BLE_LL_ASSERT(0); - - /* Just in case */ - ble_ll_state_set(BLE_LL_STATE_STANDBY); - - ble_ll_scan_chk_resume(); - return; - } - - /* Log event end */ - ble_ll_trace_u32x2(BLE_LL_TRACE_ID_CONN_EV_END, connsm->conn_handle, - connsm->event_cntr); - - ble_ll_scan_chk_resume(); - - /* If we have transmitted the terminate IND successfully, we are done */ - if ((connsm->csmflags.cfbit.terminate_ind_txd) || - (connsm->csmflags.cfbit.terminate_ind_rxd && - connsm->csmflags.cfbit.terminate_ind_rxd_acked)) { - if (connsm->csmflags.cfbit.terminate_ind_txd) { - ble_err = BLE_ERR_CONN_TERM_LOCAL; - } else { - /* Make sure the disconnect reason is valid! */ - ble_err = connsm->rxd_disconnect_reason; - if (ble_err == 0) { - ble_err = BLE_ERR_REM_USER_CONN_TERM; - } - } - ble_ll_conn_end(connsm, ble_err); - return; - } - - /* Remove any connection end events that might be enqueued */ - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &connsm->conn_ev_end); - - /* - * If we have received a packet, we can set the current transmit window - * usecs to 0 since we dont need to listen in the transmit window. - */ - if (connsm->csmflags.cfbit.pkt_rxd) { - connsm->slave_cur_tx_win_usecs = 0; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) - /* - * If we are encrypted and have passed the authenticated payload timeout - * we need to send an event to tell the host. Unfortunately, I think we - * need one of these per connection and we have to set this timer - * fairly accurately. So we need to another event in the connection. - * This sucks. - * - * The way this works is that whenever the timer expires it just gets reset - * and we send the autheticated payload timeout event. Note that this timer - * should run even when encryption is paused. - * XXX: what should be here? Was there code here that got deleted? - */ -#endif - - /* Move to next connection event */ - if (ble_ll_conn_next_event(connsm)) { - ble_ll_conn_end(connsm, BLE_ERR_CONN_TERM_LOCAL); - return; - } - - /* Reset "per connection event" variables */ - connsm->cons_rxd_bad_crc = 0; - connsm->csmflags.cfbit.pkt_rxd = 0; - - /* See if we need to start any control procedures */ - ble_ll_ctrl_chk_proc_start(connsm); - - /* Set initial schedule callback */ - connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb; - - /* XXX: I think all this fine for when we do connection updates, but - we may want to force the first event to be scheduled. Not sure */ - /* Schedule the next connection event */ - while (ble_ll_sched_conn_reschedule(connsm)) { - if (ble_ll_conn_next_event(connsm)) { - ble_ll_conn_end(connsm, BLE_ERR_CONN_TERM_LOCAL); - return; - } - } - - /* - * This is definitely not perfect but hopefully will be fine in regards to - * the specification. We check the supervision timer at connection event - * end. If the next connection event is going to start past the supervision - * timeout we end the connection here. I guess this goes against the spec - * in two ways: - * 1) We are actually causing a supervision timeout before the time - * specified. However, this is really a moot point because the supervision - * timeout would have expired before we could possibly receive a packet. - * 2) We may end the supervision timeout a bit later than specified as - * we only check this at event end and a bad CRC could cause us to continue - * the connection event longer than the supervision timeout. Given that two - * bad CRC's consecutively ends the connection event, I dont regard this as - * a big deal but it could cause a slightly longer supervision timeout. - */ - if (connsm->conn_state == BLE_LL_CONN_STATE_CREATED) { - tmo = (uint32_t)connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS * 6UL; - ble_err = BLE_ERR_CONN_ESTABLISHMENT; - } else { - tmo = connsm->supervision_tmo * BLE_HCI_CONN_SPVN_TMO_UNITS * 1000UL; - ble_err = BLE_ERR_CONN_SPVN_TMO; - } - /* XXX: Convert to ticks to usecs calculation instead??? */ - tmo = os_cputime_usecs_to_ticks(tmo); - if ((int32_t)(connsm->anchor_point - connsm->last_rxd_pdu_cputime) >= tmo) { - ble_ll_conn_end(connsm, ble_err); - return; - } - - /* If we have completed packets, send an event */ - ble_ll_conn_num_comp_pkts_event_send(connsm); - - /* If we have features and there's pending HCI command, send an event */ - if (connsm->csmflags.cfbit.pending_hci_rd_features && - connsm->csmflags.cfbit.rxd_features) { - ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS); - connsm->csmflags.cfbit.pending_hci_rd_features = 0; - } -} - -/** - * Update the connection request PDU with the address type and address of - * advertiser we are going to send connect request to. - * - * @param m - * @param adva - * @param addr_type Address type of ADVA from received advertisement. - * @param inita - * @param inita_type Address type of INITA from received advertisement. - - * @param txoffset The tx window offset for this connection - */ -static void -ble_ll_conn_connect_ind_prepare(struct ble_ll_conn_sm *connsm, - struct ble_ll_scan_pdu_data *pdu_data, - uint8_t adva_type, uint8_t *adva, - uint8_t inita_type, uint8_t *inita, - int rpa_index, uint8_t channel) -{ - uint8_t hdr; - uint8_t *addr; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - int is_rpa; - struct ble_ll_resolv_entry *rl; -#endif - - hdr = BLE_ADV_PDU_TYPE_CONNECT_IND; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) - /* We need CSA2 bit only for legacy connect */ - if (channel >= BLE_PHY_NUM_DATA_CHANS) { - hdr |= BLE_ADV_PDU_HDR_CHSEL; - } -#endif - - if (adva_type) { - /* Set random address */ - hdr |= BLE_ADV_PDU_HDR_RXADD_MASK; - } - - if (inita) { - memcpy(pdu_data->inita, inita, BLE_DEV_ADDR_LEN); - if (inita_type) { - hdr |= BLE_ADV_PDU_HDR_TXADD_RAND; - } - } else { - /* Get pointer to our device address */ - connsm = g_ble_ll_conn_create_sm; - if ((connsm->own_addr_type & 1) == 0) { - addr = g_dev_addr; - } else { - hdr |= BLE_ADV_PDU_HDR_TXADD_RAND; - addr = g_random_addr; - } - - /* XXX: do this ahead of time? Calculate the local rpa I mean */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (connsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { - rl = NULL; - is_rpa = ble_ll_is_rpa(adva, adva_type); - if (is_rpa) { - if (rpa_index >= 0) { - rl = &g_ble_ll_resolv_list[rpa_index]; - } - } else { - /* we look for RL entry to generate local RPA regardless if - * resolving is enabled or not (as this is is for local RPA - * not peer RPA) - */ - rl = ble_ll_resolv_list_find(adva, adva_type); - } - - /* - * If peer in on resolving list, we use RPA generated with Local IRK - * from resolving list entry. In other case, we need to use our identity - * address (see Core 5.0, Vol 6, Part B, section 6.4). - */ - if (rl && rl->rl_has_local) { - hdr |= BLE_ADV_PDU_HDR_TXADD_RAND; - ble_ll_resolv_get_priv_addr(rl, 1, pdu_data->inita); - addr = NULL; - } - } -#endif - - if (addr) { - memcpy(pdu_data->inita, addr, BLE_DEV_ADDR_LEN); - /* Identity address used */ - connsm->inita_identity_used = 1; - } - } - - memcpy(pdu_data->adva, adva, BLE_DEV_ADDR_LEN); - - pdu_data->hdr_byte = hdr; -} - -/* Returns true if the address matches the connection peer address having in - * mind privacy mode - */ -static int -ble_ll_conn_is_peer_adv(uint8_t addr_type, uint8_t *adva, int index) -{ - int rc; - uint8_t *peer_addr = NULL; - struct ble_ll_conn_sm *connsm; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - struct ble_ll_resolv_entry *rl; -#endif - - /* XXX: Deal with different types of random addresses here! */ - connsm = g_ble_ll_conn_create_sm; - if (!connsm) { - return 0; - } - - switch (connsm->peer_addr_type) { - /* Fall-through intentional */ - case BLE_HCI_CONN_PEER_ADDR_PUBLIC: - case BLE_HCI_CONN_PEER_ADDR_RANDOM: -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (ble_ll_addr_is_id(adva, addr_type)) { - /* Peer uses its identity address. Let's verify privacy mode. - * - * Note: Core Spec 5.0 Vol 6, Part B - * If the Host has added the peer device to the resolving list - * with an all-zero peer IRK, the Controller shall only accept - * the peer's identity address. - */ - if (ble_ll_resolv_enabled()) { - rl = ble_ll_resolv_list_find(adva, addr_type); - if (rl && (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && - rl->rl_has_peer) { - return 0; - } - } - } - - /* Check if peer uses RPA. If so and it match, use it as controller - * supports privacy mode - */ - if ((index >= 0) && - (g_ble_ll_resolv_list[index].rl_addr_type == connsm->peer_addr_type)) { - peer_addr = g_ble_ll_resolv_list[index].rl_identity_addr; - } -#endif - /* - * If we are here it means we don't know the device, lets - * check if type is what we are looking for and later - * if address matches - */ - if ((connsm->peer_addr_type == addr_type) && !peer_addr) { - peer_addr = adva; - } - - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - case BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT: - if ((index < 0) || - (g_ble_ll_resolv_list[index].rl_addr_type != 0)) { - return 0; - } - peer_addr = g_ble_ll_resolv_list[index].rl_identity_addr; - break; - case BLE_HCI_CONN_PEER_ADDR_RANDOM_IDENT: - if ((index < 0) || - (g_ble_ll_resolv_list[index].rl_addr_type != 1)) { - return 0; - } - peer_addr = g_ble_ll_resolv_list[index].rl_identity_addr; - break; -#endif - default: - peer_addr = NULL; - break; - } - - rc = 0; - if (peer_addr) { - if (!memcmp(peer_addr, connsm->peer_addr, BLE_DEV_ADDR_LEN)) { - rc = 1; - } - } - - return rc; -} - -static void -ble_ll_conn_connect_ind_txend_to_standby(void *arg) -{ - ble_ll_state_set(BLE_LL_STATE_STANDBY); -} - -static void -ble_ll_conn_connect_ind_txend_to_init(void *arg) -{ - ble_ll_state_set(BLE_LL_STATE_INITIATING); -} - -static uint8_t -ble_ll_conn_connect_ind_tx_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) -{ - struct ble_ll_conn_sm *connsm; - struct ble_ll_scan_pdu_data *pdu_data; - - connsm = pducb_arg; - /* - * pdu_data was prepared just before starting TX and is expected to be - * still valid here - */ - pdu_data = ble_ll_scan_get_pdu_data(); - - memcpy(dptr, pdu_data->inita, BLE_DEV_ADDR_LEN); - memcpy(dptr + BLE_DEV_ADDR_LEN, pdu_data->adva, BLE_DEV_ADDR_LEN); - - dptr += 2 * BLE_DEV_ADDR_LEN; - - put_le32(dptr, connsm->access_addr); - dptr[4] = (uint8_t)connsm->crcinit; - dptr[5] = (uint8_t)(connsm->crcinit >> 8); - dptr[6] = (uint8_t)(connsm->crcinit >> 16); - dptr[7] = connsm->tx_win_size; - put_le16(dptr + 8, connsm->tx_win_off); - put_le16(dptr + 10, connsm->conn_itvl); - put_le16(dptr + 12, connsm->slave_latency); - put_le16(dptr + 14, connsm->supervision_tmo); - memcpy(dptr + 16, &connsm->chanmap, BLE_LL_CONN_CHMAP_LEN); - dptr[21] = connsm->hop_inc | (connsm->master_sca << 5); - - *hdr_byte = pdu_data->hdr_byte; - - return 34; -} - -/** - * Send a connection requestion to an advertiser - * - * Context: Interrupt - * - * @param addr_type Address type of advertiser - * @param adva Address of advertiser - */ -int -ble_ll_conn_connect_ind_send(struct ble_ll_conn_sm *connsm, uint8_t end_trans) -{ - int rc; - - if (end_trans == BLE_PHY_TRANSITION_NONE) { - ble_phy_set_txend_cb(ble_ll_conn_connect_ind_txend_to_standby, NULL); - } else { - ble_phy_set_txend_cb(ble_ll_conn_connect_ind_txend_to_init, NULL); - } - - rc = ble_phy_tx(ble_ll_conn_connect_ind_tx_pducb, connsm, end_trans); - - return rc; -} - -/** - * Called when a schedule item overlaps the currently running connection - * event. This generally should not happen, but if it does we stop the - * current connection event to let the schedule item run. - * - * NOTE: the phy has been disabled as well as the wfr timer before this is - * called. - */ -void -ble_ll_conn_event_halt(void) -{ - ble_ll_state_set(BLE_LL_STATE_STANDBY); - if (g_ble_ll_conn_cur_sm) { - g_ble_ll_conn_cur_sm->csmflags.cfbit.pkt_rxd = 0; - ble_ll_event_send(&g_ble_ll_conn_cur_sm->conn_ev_end); - g_ble_ll_conn_cur_sm = NULL; - } -} - -/** - * Process a received PDU while in the initiating state. - * - * Context: Link Layer task. - * - * @param pdu_type - * @param rxbuf - * @param ble_hdr - */ -void -ble_ll_init_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_mbuf_hdr *ble_hdr) -{ - uint8_t addr_type; - uint8_t *addr; - uint8_t *adv_addr; - uint8_t *inita; - uint8_t inita_type; - struct ble_ll_conn_sm *connsm; - int ext_adv_mode = -1; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_ll_aux_data *aux_data = NULL; - - if (ble_hdr->rxinfo.user_data) { - /* aux_data just a local helper, no need to ref - * as ble_hdr->rxinfo.user_data is unref in the end of this function - */ - aux_data = ble_hdr->rxinfo.user_data; - } -#endif - - /* Get the connection state machine we are trying to create */ - connsm = g_ble_ll_conn_create_sm; - if (!connsm) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (aux_data) { - ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data); - ble_hdr->rxinfo.user_data = NULL; - } -#endif - return; - } - - if (!BLE_MBUF_HDR_CRC_OK(ble_hdr)) { - goto scan_continue; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (BLE_MBUF_HDR_AUX_INVALID(ble_hdr)) { - goto scan_continue; - } - - if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND) { - if (BLE_MBUF_HDR_WAIT_AUX(ble_hdr)) { - /* Just continue scanning. We are waiting for AUX */ - if (!ble_ll_sched_aux_scan(ble_hdr, connsm->scansm, aux_data)) { - /* ref for aux ptr in the scheduler */ - ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data); - ble_hdr->rxinfo.user_data = NULL; - ble_ll_scan_chk_resume(); - return; - } - goto scan_continue; - } - } - - if (CONN_F_AUX_CONN_REQ(connsm)) { - if (pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) { - /* Wait for connection response, in this point of time aux is NULL */ - BLE_LL_ASSERT(ble_hdr->rxinfo.user_data == NULL); - return; - } - } -#endif - - /* If we have sent a connect request, we need to enter CONNECTION state */ - if (connsm && CONN_F_CONN_REQ_TXD(connsm)) { - /* Set address of advertiser to which we are connecting. */ - - if (ble_ll_scan_adv_decode_addr(pdu_type, rxbuf, ble_hdr, - &adv_addr, &addr_type, - &inita, &inita_type, &ext_adv_mode)) { - /* Something got wrong, keep trying to connect */ - goto scan_continue; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* - * Did we resolve this address? If so, set correct peer address - * and peer address type. - */ - if (connsm->rpa_index >= 0) { - addr_type = g_ble_ll_resolv_list[connsm->rpa_index].rl_addr_type + 2; - addr = g_ble_ll_resolv_list[connsm->rpa_index].rl_identity_addr; - } else { - addr = adv_addr; - } -#else - addr = adv_addr; -#endif - - if (connsm->rpa_index >= 0) { - connsm->peer_addr_type = addr_type; - memcpy(connsm->peer_addr, addr, BLE_DEV_ADDR_LEN); - - ble_ll_scan_set_peer_rpa(adv_addr); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* Update resolving list with current peer RPA */ - ble_ll_resolv_set_peer_rpa(connsm->rpa_index, rxbuf + BLE_LL_PDU_HDR_LEN); - if (ble_ll_is_rpa(inita, inita_type)) { - ble_ll_resolv_set_local_rpa(connsm->rpa_index, inita); - } - -#endif - } else if (ble_ll_scan_whitelist_enabled()) { - /* if WL is used we need to store peer addr also if it was not - * resolved - */ - connsm->peer_addr_type = addr_type; - memcpy(connsm->peer_addr, addr, BLE_DEV_ADDR_LEN); - } - - /* Connection has been created. Stop scanning */ - g_ble_ll_conn_create_sm = NULL; - ble_ll_scan_sm_stop(0); - - /* For AUX Connect CSA2 is mandatory. Otherwise we need to check bit - * mask - */ - if (ble_hdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) { - ble_ll_conn_set_csa(connsm, 1); - } else { - ble_ll_conn_set_csa(connsm, rxbuf[0] & BLE_ADV_PDU_HDR_CHSEL_MASK); - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - /* Lets take last used phy */ - ble_ll_conn_init_phy(connsm, ble_hdr->rxinfo.phy); -#endif - if (aux_data) { - ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data); - ble_hdr->rxinfo.user_data = NULL; - } -#endif - ble_ll_conn_created(connsm, NULL); - return; - } - -scan_continue: -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* Drop last reference and keep continue to connect */ - if (aux_data) { - ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data); - ble_hdr->rxinfo.user_data = NULL; - } -#endif - ble_ll_scan_chk_resume(); -} - -/** - * Called when a receive PDU has started and we are in the initiating state. - * - * Context: Interrupt - * - * @param pdu_type - * @param ble_hdr - * - * @return int - * 0: we will not attempt to reply to this frame - * 1: we may send a response to this frame. - */ -int -ble_ll_init_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *ble_hdr) -{ - struct ble_ll_conn_sm *connsm; - - connsm = g_ble_ll_conn_create_sm; - if (!connsm) { - return 0; - } - - if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) || - (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND || - pdu_type == BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP)) { - return 1; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND && - connsm->scansm->ext_scanning) { - if (connsm->scansm->cur_aux_data) { - STATS_INC(ble_ll_stats, aux_received); - } - - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_EXT_ADV; - return 1; - } -#endif - - return 0; -} - -/** - * Called when a receive PDU has ended and we are in the initiating state. - * - * Context: Interrupt - * - * @param rxpdu - * @param crcok - * @param ble_hdr - * - * @return int - * < 0: Disable the phy after reception. - * == 0: Success. Do not disable the PHY. - * > 0: Do not disable PHY as that has already been done. - */ -int -ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok, - struct ble_mbuf_hdr *ble_hdr) -{ - int rc; - int resolved; - int chk_wl; - int index; - uint8_t pdu_type; - uint8_t adv_addr_type; - uint8_t peer_addr_type; - uint8_t *adv_addr = NULL; - uint8_t *peer; - uint8_t *init_addr = NULL; - uint8_t init_addr_type; - uint8_t pyld_len; - uint8_t inita_is_rpa; - uint8_t conn_req_end_trans; - struct os_mbuf *rxpdu; - struct ble_ll_conn_sm *connsm; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - struct ble_ll_resolv_entry *rl; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_ll_scan_sm *scansm; - uint8_t phy; -#endif - int ext_adv_mode = -1; - - /* Get connection state machine to use if connection to be established */ - connsm = g_ble_ll_conn_create_sm; - /* This could happen if connection init was cancelled while isr end was - * already pending - */ - if (!connsm) { - ble_ll_state_set(BLE_LL_STATE_STANDBY); - return -1; - } - - rc = -1; - pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK; - pyld_len = rxbuf[1]; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - scansm = connsm->scansm; - if (scansm->cur_aux_data) { - ble_hdr->rxinfo.user_data = scansm->cur_aux_data; - scansm->cur_aux_data = NULL; - } -#endif - - if (!crcok) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* Invalid packet - make sure we do not wait for AUX_CONNECT_RSP */ - ble_ll_conn_reset_pending_aux_conn_rsp(); -#endif - - /* Ignore this packet */ - goto init_rx_isr_exit; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* If we sent AUX_CONNECT_REQ, we only expect AUX_CONNECT_RSP here */ - if (CONN_F_AUX_CONN_REQ(connsm)) { - if (pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) { - STATS_INC(ble_ll_stats, aux_conn_rsp_err); - CONN_F_CONN_REQ_TXD(connsm) = 0; - CONN_F_AUX_CONN_REQ(connsm) = 0; - ble_ll_sched_rmv_elem(&connsm->conn_sch); - } - goto init_rx_isr_exit; - } -#endif - - inita_is_rpa = 0; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND) { - if (!scansm->ext_scanning) { - goto init_rx_isr_exit; - } - - rc = ble_ll_scan_update_aux_data(ble_hdr, rxbuf, NULL); - if (rc < 0) { - /* No memory or broken packet */ - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_INVALID; - goto init_rx_isr_exit; - } - } -#endif - - /* Lets get addresses from advertising report*/ - if (ble_ll_scan_adv_decode_addr(pdu_type, rxbuf, ble_hdr, - &adv_addr, &adv_addr_type, - &init_addr, &init_addr_type, - &ext_adv_mode)) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_INVALID; -#endif - goto init_rx_isr_exit; - } - - switch (pdu_type) { - case BLE_ADV_PDU_TYPE_ADV_IND: - break; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - case BLE_ADV_PDU_TYPE_ADV_EXT_IND: - rc = -1; - - /* If this is not connectable adv mode, lets skip it */ - if (!(ext_adv_mode & BLE_LL_EXT_ADV_MODE_CONN)) { - goto init_rx_isr_exit; - } - - if (!adv_addr) { - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_PTR_WAIT; - goto init_rx_isr_exit; - } - - if (!init_addr) { - break; - } - /* if there is direct address lets fall down and check it.*/ - // no break -#endif - case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND: - inita_is_rpa = (uint8_t)ble_ll_is_rpa(init_addr, init_addr_type); - if (!inita_is_rpa) { - - /* Resolving will be done later. Check if identity InitA matches */ - if (!ble_ll_is_our_devaddr(init_addr, init_addr_type)) { - goto init_rx_isr_exit; - } - } -#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - else { - /* If privacy is off - reject RPA InitA*/ - goto init_rx_isr_exit; - } -#endif - - break; - default: - goto init_rx_isr_exit; - } - - /* Should we send a connect request? */ - index = -1; - peer = adv_addr; - peer_addr_type = adv_addr_type; - - resolved = 0; - chk_wl = ble_ll_scan_whitelist_enabled(); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (ble_ll_is_rpa(adv_addr, adv_addr_type) && ble_ll_resolv_enabled()) { - index = ble_hw_resolv_list_match(); - if (index >= 0) { - rl = &g_ble_ll_resolv_list[index]; - - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_RESOLVED; - connsm->rpa_index = index; - peer = rl->rl_identity_addr; - peer_addr_type = rl->rl_addr_type; - resolved = 1; - - /* Assure privacy */ - if ((rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && init_addr && - !inita_is_rpa && rl->rl_has_local) { - goto init_rx_isr_exit; - } - - /* - * If the InitA is a RPA, we must see if it resolves based on the - * identity address of the resolved ADVA. - */ - if (init_addr && inita_is_rpa) { - if (!ble_ll_resolv_rpa(init_addr, - g_ble_ll_resolv_list[index].rl_local_irk)) { - goto init_rx_isr_exit; - } - - /* Core Specification Vol 6, Part B, Section 6.4: - * "The Link Layer should not set the InitA field to the same - * value as the TargetA field in the received advertising PDU." - * - * We update the received PDU directly here, so ble_ll_init_rx_pkt_in - * can process it as is. - */ - memcpy(init_addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN); - } - - } else { - if (chk_wl) { - goto init_rx_isr_exit; - } - - /* Could not resolved InitA */ - if (init_addr && inita_is_rpa) { - goto init_rx_isr_exit; - } - } - } else if (init_addr) { - - /* If resolving is off and InitA is RPA we reject advertising */ - if (inita_is_rpa && !ble_ll_resolv_enabled()) { - goto init_rx_isr_exit; - } - - /* Let's see if we have IRK with that peer.*/ - rl = ble_ll_resolv_list_find(adv_addr, adv_addr_type); - - /* Lets make sure privacy mode is correct together with InitA in case it - * is identity address - */ - if (rl && !inita_is_rpa && - (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && - rl->rl_has_local) { - goto init_rx_isr_exit; - } - - /* - * If the InitA is a RPA, we must see if it resolves based on the - * identity address of the resolved ADVA. - */ - if (inita_is_rpa) { - if (!rl || !ble_ll_resolv_rpa(init_addr, rl->rl_local_irk)) { - goto init_rx_isr_exit; - } - - /* Core Specification Vol 6, Part B, Section 6.4: - * "The Link Layer should not set the InitA field to the same - * value as the TargetA field in the received advertising PDU." - * - * We update the received PDU directly here, so ble_ll_init_rx_pkt_in - * can process it as is. - */ - memcpy(init_addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN); - } - } -#endif - - /* Check filter policy */ - if (chk_wl) { - if (!ble_ll_whitelist_match(peer, peer_addr_type, resolved)) { - goto init_rx_isr_exit; - } - } else { - /* Must match the connection address */ - if (!ble_ll_conn_is_peer_adv(adv_addr_type, adv_addr, index)) { - goto init_rx_isr_exit; - } - } - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH; - - /* For CONNECT_IND we don't go into RX state */ - conn_req_end_trans = BLE_PHY_TRANSITION_NONE; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* Check if we should send AUX_CONNECT_REQ and wait for AUX_CONNECT_RSP */ - if (ble_hdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) { - conn_req_end_trans = BLE_PHY_TRANSITION_TX_RX; - } - - if (connsm->scansm->ext_scanning) { - phy = ble_hdr->rxinfo.phy; - - /* Update connection state machine with appropriate parameters for - * certain PHY - */ - ble_ll_conn_ext_set_params(connsm, - &connsm->initial_params.params[phy - 1], - phy); - - } -#endif - - /* Schedule new connection */ - if (ble_ll_sched_master_new(connsm, ble_hdr, pyld_len)) { - STATS_INC(ble_ll_conn_stats, cant_set_sched); - goto init_rx_isr_exit; - } - - /* Prepare data for connect request */ - ble_ll_conn_connect_ind_prepare(connsm, - ble_ll_scan_get_pdu_data(), - adv_addr_type, adv_addr, - init_addr_type, init_addr, - index, ble_hdr->rxinfo.channel); - - /* Setup to transmit the connect request */ - rc = ble_ll_conn_connect_ind_send(connsm, conn_req_end_trans); - if (rc) { - ble_ll_sched_rmv_elem(&connsm->conn_sch); - goto init_rx_isr_exit; - } - - if (init_addr && !inita_is_rpa) { - connsm->inita_identity_used = 1; - } - - CONN_F_CONN_REQ_TXD(connsm) = 1; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (ble_hdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) { - /* Lets wait for AUX_CONNECT_RSP */ - CONN_F_AUX_CONN_REQ(connsm) = 1; - /* Keep aux data until we get scan response */ - scansm->cur_aux_data = ble_hdr->rxinfo.user_data; - ble_hdr->rxinfo.user_data = NULL; - STATS_INC(ble_ll_stats, aux_conn_req_tx); - } -#endif - - STATS_INC(ble_ll_conn_stats, conn_req_txd); - -init_rx_isr_exit: - - /* - * We have to restart receive if we cant hand up pdu. We return 0 so that - * the phy does not get disabled. - */ - rxpdu = ble_ll_rxpdu_alloc(pyld_len + BLE_LL_PDU_HDR_LEN); - if (rxpdu == NULL) { - /* - * XXX: possible allocate the PDU when we start initiating? - * I cannot say I like this solution, but if we cannot allocate a PDU - * to hand up to the LL, we need to remove the connection we just - * scheduled since the connection state machine will not get processed - * by link layer properly. For now, just remove it from the scheduler - */ - if (CONN_F_CONN_REQ_TXD(connsm) == 1) { - CONN_F_CONN_REQ_TXD(connsm) = 0; - CONN_F_AUX_CONN_REQ(connsm) = 0; - ble_ll_sched_rmv_elem(&connsm->conn_sch); - } - ble_phy_restart_rx(); - rc = 0; - } else { - ble_phy_rxpdu_copy(rxbuf, rxpdu); - ble_ll_rx_pdu_in(rxpdu); - } - - if (rc) { - ble_ll_state_set(BLE_LL_STATE_STANDBY); - } - - return rc; -} - -/** - * Function called when a timeout has occurred for a connection. There are - * two types of timeouts: a connection supervision timeout and control - * procedure timeout. - * - * Context: Link Layer task - * - * @param connsm - * @param ble_err - */ -void -ble_ll_conn_timeout(struct ble_ll_conn_sm *connsm, uint8_t ble_err) -{ - int was_current; - os_sr_t sr; - - was_current = 0; - OS_ENTER_CRITICAL(sr); - if (g_ble_ll_conn_cur_sm == connsm) { - ble_ll_conn_current_sm_over(NULL); - was_current = 1; - } - OS_EXIT_CRITICAL(sr); - - /* Check if we need to resume scanning */ - if (was_current) { - ble_ll_scan_chk_resume(); - } - - ble_ll_conn_end(connsm, ble_err); -} - -/** - * Called when a data channel PDU has started that matches the access - * address of the current connection. Note that the CRC of the PDU has not - * been checked yet. - * - * Context: Interrupt - * - * @param rxhdr - */ -int -ble_ll_conn_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa) -{ - struct ble_ll_conn_sm *connsm; - - /* - * Disable wait for response timer since we receive a response. We dont - * care if this is the response we were waiting for or not; the code - * called at receive end will deal with ending the connection event - * if needed - */ - connsm = g_ble_ll_conn_cur_sm; - if (connsm) { - /* Double check access address. Better match connection state machine */ - if (aa != connsm->access_addr) { - STATS_INC(ble_ll_conn_stats, rx_data_pdu_bad_aa); - ble_ll_state_set(BLE_LL_STATE_STANDBY); - ble_ll_event_send(&connsm->conn_ev_end); - g_ble_ll_conn_cur_sm = NULL; - return -1; - } - - /* Set connection handle in mbuf header */ - rxhdr->rxinfo.handle = connsm->conn_handle; - - /* Set flag denoting we have received a packet in connection event */ - connsm->csmflags.cfbit.pkt_rxd = 1; - - /* Connection is established */ - connsm->conn_state = BLE_LL_CONN_STATE_ESTABLISHED; - - /* Set anchor point (and last) if 1st rxd frame in connection event */ - if (connsm->csmflags.cfbit.slave_set_last_anchor) { - connsm->csmflags.cfbit.slave_set_last_anchor = 0; - connsm->last_anchor_point = rxhdr->beg_cputime; - connsm->anchor_point = connsm->last_anchor_point; - connsm->anchor_point_usecs = rxhdr->rem_usecs; - } - } - return 1; -} - -/** - * Called from the Link Layer task when a data PDU has been received - * - * Context: Link layer task - * - * @param rxpdu Pointer to received pdu - * @param rxpdu Pointer to ble mbuf header of received pdu - */ -void -ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) -{ - uint8_t hdr_byte; - uint8_t rxd_sn; - uint8_t *rxbuf; - uint8_t llid; - uint16_t acl_len; - uint16_t acl_hdr; - struct ble_ll_conn_sm *connsm; - - if (BLE_MBUF_HDR_CRC_OK(hdr)) { - /* XXX: there is a chance that the connection was thrown away and - re-used before processing packets here. Fix this. */ - /* We better have a connection state machine */ - connsm = ble_ll_conn_find_active_conn(hdr->rxinfo.handle); - if (connsm) { - /* Check state machine */ - ble_ll_conn_chk_csm_flags(connsm); - - /* Validate rx data pdu */ - rxbuf = rxpdu->om_data; - hdr_byte = rxbuf[0]; - acl_len = rxbuf[1]; - llid = hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; - - /* - * Check that the LLID and payload length are reasonable. - * Empty payload is only allowed for LLID == 01b. - * */ - if ((llid == 0) || - ((acl_len == 0) && (llid != BLE_LL_LLID_DATA_FRAG))) { - STATS_INC(ble_ll_conn_stats, rx_bad_llid); - goto conn_rx_data_pdu_end; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - /* Check if PDU is allowed when encryption is started. If not, - * terminate connection. - * - * Reference: Core 5.0, Vol 6, Part B, 5.1.3.1 - */ - if ((connsm->enc_data.enc_state > CONN_ENC_S_PAUSE_ENC_RSP_WAIT) && - !ble_ll_ctrl_enc_allowed_pdu_rx(rxpdu)) { - ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC); - goto conn_rx_data_pdu_end; - } -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) - /* - * Reset authenticated payload timeout if valid MIC. NOTE: we dont - * check the MIC failure bit as that would have terminated the - * connection - */ - if ((connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) && - CONN_F_LE_PING_SUPP(connsm) && (acl_len != 0)) { - ble_ll_conn_auth_pyld_timer_start(connsm); - } -#endif - - /* Update RSSI */ - connsm->conn_rssi = hdr->rxinfo.rssi; - - /* - * If we are a slave, we can only start to use slave latency - * once we have received a NESN of 1 from the master - */ - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - if (hdr_byte & BLE_LL_DATA_HDR_NESN_MASK) { - connsm->csmflags.cfbit.allow_slave_latency = 1; - } - } - - /* - * Discard the received PDU if the sequence number is the same - * as the last received sequence number - */ - rxd_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK; - if (rxd_sn != connsm->last_rxd_sn) { - /* Update last rxd sn */ - connsm->last_rxd_sn = rxd_sn; - - /* No need to do anything if empty pdu */ - if ((llid == BLE_LL_LLID_DATA_FRAG) && (acl_len == 0)) { - goto conn_rx_data_pdu_end; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - /* - * XXX: should we check to see if we are in a state where we - * might expect to get an encrypted PDU? - */ - if (BLE_MBUF_HDR_MIC_FAILURE(hdr)) { - STATS_INC(ble_ll_conn_stats, mic_failures); - ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC); - goto conn_rx_data_pdu_end; - } -#endif - - if (llid == BLE_LL_LLID_CTRL) { - /* Process control frame */ - STATS_INC(ble_ll_conn_stats, rx_ctrl_pdus); - if (ble_ll_ctrl_rx_pdu(connsm, rxpdu)) { - STATS_INC(ble_ll_conn_stats, rx_malformed_ctrl_pdus); - } - } else { - /* Count # of received l2cap frames and byes */ - STATS_INC(ble_ll_conn_stats, rx_l2cap_pdus); - STATS_INCN(ble_ll_conn_stats, rx_l2cap_bytes, acl_len); - - /* NOTE: there should be at least two bytes available */ - BLE_LL_ASSERT(OS_MBUF_LEADINGSPACE(rxpdu) >= 2); - os_mbuf_prepend(rxpdu, 2); - rxbuf = rxpdu->om_data; - - acl_hdr = (llid << 12) | connsm->conn_handle; - put_le16(rxbuf, acl_hdr); - put_le16(rxbuf + 2, acl_len); - ble_hci_trans_ll_acl_tx(rxpdu); - } - - /* NOTE: we dont free the mbuf since we handed it off! */ - return; - } else { - STATS_INC(ble_ll_conn_stats, data_pdu_rx_dup); - } - } else { - STATS_INC(ble_ll_conn_stats, no_conn_sm); - } - } - - /* Free buffer */ -conn_rx_data_pdu_end: - os_mbuf_free_chain(rxpdu); -} - -/** - * Called when a packet has been received while in the connection state. - * - * Context: Interrupt - * - * @param rxpdu - * @param crcok - * - * @return int - * < 0: Disable the phy after reception. - * == 0: Success. Do not disable the PHY. - * > 0: Do not disable PHY as that has already been done. - */ -int -ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) -{ - int rc; - int is_ctrl; - uint8_t hdr_byte; - uint8_t hdr_sn; - uint8_t hdr_nesn; - uint8_t conn_sn; - uint8_t conn_nesn; - uint8_t reply; - uint8_t rem_bytes; - uint8_t opcode = 0; - uint8_t rx_pyld_len; - uint32_t begtime; - uint32_t add_usecs; - struct os_mbuf *txpdu; - struct ble_ll_conn_sm *connsm; - struct os_mbuf *rxpdu; - struct ble_mbuf_hdr *txhdr; - int rx_phy_mode; - - /* Retrieve the header and payload length */ - hdr_byte = rxbuf[0]; - rx_pyld_len = rxbuf[1]; - - /* - * We need to attempt to allocate a buffer here. The reason we do this - * now is that we should not ack the packet if we have no receive - * buffers available. We want to free up our transmit PDU if it was - * acked, but we should not ack the received frame if we cant hand it up. - * NOTE: we hand up empty pdu's to the LL task! - */ - rxpdu = ble_ll_rxpdu_alloc(rx_pyld_len + BLE_LL_PDU_HDR_LEN); - - /* - * We should have a current connection state machine. If we dont, we just - * hand the packet to the higher layer to count it. - */ - rc = -1; - connsm = g_ble_ll_conn_cur_sm; - if (!connsm) { - STATS_INC(ble_ll_conn_stats, rx_data_pdu_no_conn); - goto conn_exit; - } - - /* - * Calculate the end time of the received PDU. NOTE: this looks strange - * but for the 32768 crystal we add the time it takes to send the packet - * to the 'additional usecs' field to save some calculations. - */ - begtime = rxhdr->beg_cputime; -#if BLE_LL_BT5_PHY_SUPPORTED - rx_phy_mode = connsm->phy_data.rx_phy_mode; -#else - rx_phy_mode = BLE_PHY_MODE_1M; -#endif - add_usecs = rxhdr->rem_usecs + - ble_ll_pdu_tx_time_get(rx_pyld_len, rx_phy_mode); - - /* - * Check the packet CRC. A connection event can continue even if the - * received PDU does not pass the CRC check. If we receive two consecutive - * CRC errors we end the conection event. - */ - if (!BLE_MBUF_HDR_CRC_OK(rxhdr)) { - /* - * Increment # of consecutively received CRC errors. If more than - * one we will end the connection event. - */ - ++connsm->cons_rxd_bad_crc; - if (connsm->cons_rxd_bad_crc >= 2) { - reply = 0; - } else { - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - reply = CONN_F_LAST_TXD_MD(connsm); - } else { - /* A slave always responds with a packet */ - reply = 1; - } - } - } else { - /* Reset consecutively received bad crcs (since this one was good!) */ - connsm->cons_rxd_bad_crc = 0; - - /* Set last valid received pdu time (resets supervision timer) */ - connsm->last_rxd_pdu_cputime = begtime + - os_cputime_usecs_to_ticks(add_usecs); - - /* - * Check for valid LLID before proceeding. We have seen some weird - * things with the PHY where the CRC is OK but we dont have a valid - * LLID. This should really never happen but if it does we will just - * bail. An error stat will get incremented at the LL. - */ - if ((hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) == 0) { - goto conn_exit; - } - - /* Set last received header byte */ - connsm->last_rxd_hdr_byte = hdr_byte; - - is_ctrl = 0; - if ((hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) { - is_ctrl = 1; - opcode = rxbuf[2]; - } - - /* - * If SN bit from header does not match NESN in connection, this is - * a resent PDU and should be ignored. - */ - hdr_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK; - conn_nesn = connsm->next_exp_seqnum; - if (rxpdu && ((hdr_sn && conn_nesn) || (!hdr_sn && !conn_nesn))) { - connsm->next_exp_seqnum ^= 1; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (CONN_F_ENCRYPTED(connsm) && !ble_ll_conn_is_empty_pdu(rxbuf)) { - ++connsm->enc_data.rx_pkt_cntr; - } -#endif - } - - ble_ll_trace_u32x2(BLE_LL_TRACE_ID_CONN_RX, connsm->tx_seqnum, - !!(hdr_byte & BLE_LL_DATA_HDR_NESN_MASK)); - - /* - * Check NESN bit from header. If same as tx seq num, the transmission - * is acknowledged. Otherwise we need to resend this PDU. - */ - if (CONN_F_EMPTY_PDU_TXD(connsm) || connsm->cur_tx_pdu) { - hdr_nesn = hdr_byte & BLE_LL_DATA_HDR_NESN_MASK; - conn_sn = connsm->tx_seqnum; - if ((hdr_nesn && conn_sn) || (!hdr_nesn && !conn_sn)) { - /* We did not get an ACK. Must retry the PDU */ - STATS_INC(ble_ll_conn_stats, data_pdu_txf); - } else { - /* Transmit success */ - connsm->tx_seqnum ^= 1; - STATS_INC(ble_ll_conn_stats, data_pdu_txg); - - /* If we transmitted the empty pdu, clear flag */ - if (CONN_F_EMPTY_PDU_TXD(connsm)) { - CONN_F_EMPTY_PDU_TXD(connsm) = 0; - goto chk_rx_terminate_ind; - } - - /* - * Determine if we should remove packet from queue or if there - * are more fragments to send. - */ - txpdu = connsm->cur_tx_pdu; - if (txpdu) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (connsm->enc_data.tx_encrypted) { - ++connsm->enc_data.tx_pkt_cntr; - } -#endif - txhdr = BLE_MBUF_HDR_PTR(txpdu); - if ((txhdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) - == BLE_LL_LLID_CTRL) { - connsm->cur_tx_pdu = NULL; - /* Note: the mbuf is freed by this call */ - rc = ble_ll_ctrl_tx_done(txpdu, connsm); - if (rc) { - /* Means we transmitted a TERMINATE_IND */ - goto conn_exit; - } else { - goto chk_rx_terminate_ind; - } - } - - /* Increment offset based on number of bytes sent */ - txhdr->txinfo.offset += txhdr->txinfo.pyld_len; - if (txhdr->txinfo.offset >= OS_MBUF_PKTLEN(txpdu)) { - /* If l2cap pdu, increment # of completed packets */ - if (txhdr->txinfo.pyld_len != 0) { -#if (BLETEST_THROUGHPUT_TEST == 1) - bletest_completed_pkt(connsm->conn_handle); -#endif - ++connsm->completed_pkts; - if (connsm->completed_pkts > 2) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, - &g_ble_ll_data.ll_comp_pkt_ev); - } - } - os_mbuf_free_chain(txpdu); - connsm->cur_tx_pdu = NULL; - } else { - rem_bytes = OS_MBUF_PKTLEN(txpdu) - txhdr->txinfo.offset; - /* Adjust payload for max TX time and octets */ - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - if (is_ctrl && - (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && - (opcode == BLE_LL_CTRL_PHY_UPDATE_IND)) { - connsm->phy_tx_transition = - ble_ll_ctrl_phy_tx_transition_get(rxbuf[3]); - } -#endif - - rem_bytes = ble_ll_conn_adjust_pyld_len(connsm, rem_bytes); - txhdr->txinfo.pyld_len = rem_bytes; - } - } - } - } - - /* Should we continue connection event? */ - /* If this is a TERMINATE_IND, we have to reply */ -chk_rx_terminate_ind: - /* If we received a terminate IND, we must set some flags */ - if (is_ctrl && (opcode == BLE_LL_CTRL_TERMINATE_IND) - && (rx_pyld_len == (1 + BLE_LL_CTRL_TERMINATE_IND_LEN))) { - connsm->csmflags.cfbit.terminate_ind_rxd = 1; - connsm->rxd_disconnect_reason = rxbuf[3]; - } - - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - reply = CONN_F_LAST_TXD_MD(connsm) || (hdr_byte & BLE_LL_DATA_HDR_MD_MASK); - } else { - /* A slave always replies */ - reply = 1; - } - } - - /* If reply flag set, send data pdu and continue connection event */ - rc = -1; - if (rx_pyld_len && CONN_F_ENCRYPTED(connsm)) { - rx_pyld_len += BLE_LL_DATA_MIC_LEN; - } - if (reply && ble_ll_conn_can_send_next_pdu(connsm, begtime, add_usecs)) { - rc = ble_ll_conn_tx_pdu(connsm); - } - -conn_exit: - /* Copy the received pdu and hand it up */ - if (rxpdu) { - ble_phy_rxpdu_copy(rxbuf, rxpdu); - ble_ll_rx_pdu_in(rxpdu); - } - - /* Send link layer a connection end event if over */ - if (rc) { - ble_ll_conn_current_sm_over(connsm); - } - - return rc; -} - -/** - * Called to adjust payload length to fit into max effective octets and TX time - * on current PHY. - */ -/** - * Called to enqueue a packet on the transmit queue of a connection. Should - * only be called by the controller. - * - * Context: Link Layer - * - * - * @param connsm - * @param om - */ -void -ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om, - uint8_t hdr_byte, uint8_t length) -{ - os_sr_t sr; - struct os_mbuf_pkthdr *pkthdr; - struct ble_mbuf_hdr *ble_hdr; - int lifo; - - /* Set mbuf length and packet length if a control PDU */ - if (hdr_byte == BLE_LL_LLID_CTRL) { - om->om_len = length; - OS_MBUF_PKTHDR(om)->omp_len = length; - } - - /* Set BLE transmit header */ - ble_hdr = BLE_MBUF_HDR_PTR(om); - ble_hdr->txinfo.flags = 0; - ble_hdr->txinfo.offset = 0; - ble_hdr->txinfo.hdr_byte = hdr_byte; - - /* - * Initial payload length is calculate when packet is dequeued, there's no - * need to do this now. - */ - - lifo = 0; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) { - uint8_t llid; - - /* - * If this is one of the following types we need to insert it at - * head of queue. - */ - llid = ble_hdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; - if (llid == BLE_LL_LLID_CTRL) { - switch (om->om_data[0]) { - case BLE_LL_CTRL_TERMINATE_IND: - case BLE_LL_CTRL_REJECT_IND: - case BLE_LL_CTRL_REJECT_IND_EXT: - case BLE_LL_CTRL_START_ENC_REQ: - case BLE_LL_CTRL_START_ENC_RSP: - lifo = 1; - break; - case BLE_LL_CTRL_PAUSE_ENC_RSP: - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - lifo = 1; - } - break; - case BLE_LL_CTRL_ENC_REQ: - case BLE_LL_CTRL_ENC_RSP: - /* If encryption has been paused, we don't want to send any packets from the - * TX queue, as they would go unencrypted. - */ - if (connsm->enc_data.enc_state == CONN_ENC_S_PAUSED) { - lifo = 1; - } - break; - default: - break; - } - } - } -#endif - - /* Add to transmit queue for the connection */ - pkthdr = OS_MBUF_PKTHDR(om); - OS_ENTER_CRITICAL(sr); - if (lifo) { - STAILQ_INSERT_HEAD(&connsm->conn_txq, pkthdr, omp_next); - } else { - STAILQ_INSERT_TAIL(&connsm->conn_txq, pkthdr, omp_next); - } - OS_EXIT_CRITICAL(sr); -} - -/** - * Data packet from host. - * - * Context: Link Layer task - * - * @param om - * @param handle - * @param length - * - * @return int - */ -void -ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t length) -{ - uint8_t hdr_byte; - uint16_t conn_handle; - uint16_t pb; - struct ble_ll_conn_sm *connsm; - - /* See if we have an active matching connection handle */ - conn_handle = handle & 0x0FFF; - connsm = ble_ll_conn_find_active_conn(conn_handle); - if (connsm) { - /* Construct LL header in buffer (NOTE: pb already checked) */ - pb = handle & 0x3000; - if (pb == 0) { - hdr_byte = BLE_LL_LLID_DATA_START; - } else { - hdr_byte = BLE_LL_LLID_DATA_FRAG; - } - - /* Add to total l2cap pdus enqueue */ - STATS_INC(ble_ll_conn_stats, l2cap_enqueued); - - /* Clear flags field in BLE header */ - ble_ll_conn_enqueue_pkt(connsm, om, hdr_byte, length); - } else { - /* No connection found! */ - STATS_INC(ble_ll_conn_stats, handle_not_found); - os_mbuf_free_chain(om); - } -} - -/** - * Called to set the global channel mask that we use for all connections. - * - * @param num_used_chans - * @param chanmap - */ -void -ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, const uint8_t *chanmap) -{ - struct ble_ll_conn_sm *connsm; - struct ble_ll_conn_global_params *conn_params; - - /* Do nothing if same channel map */ - conn_params = &g_ble_ll_conn_params; - if (!memcmp(conn_params->master_chan_map, chanmap, BLE_LL_CONN_CHMAP_LEN)) { - return; - } - - /* Change channel map and cause channel map update procedure to start */ - conn_params->num_used_chans = num_used_chans; - memcpy(conn_params->master_chan_map, chanmap, BLE_LL_CONN_CHMAP_LEN); - - /* Perform channel map update */ - SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) { - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CHAN_MAP_UPD); - } - } -} - -/** - * Called when a device has received a connect request while advertising and - * the connect request has passed the advertising filter policy and is for - * us. This will start a connection in the slave role assuming that we dont - * already have a connection with this device and that the connect request - * parameters are valid. - * - * Context: Link Layer - * - * @param rxbuf Pointer to received Connect Request PDU - * - * @return 0: connection not started; 1 connecton started - */ -int -ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat, struct ble_mbuf_hdr *rxhdr, - bool force_csa2) -{ - int rc; - uint32_t temp; - uint32_t crcinit; - uint8_t *inita; - uint8_t *dptr; - struct ble_ll_conn_sm *connsm; - - /* Ignore the connection request if we are already connected*/ - inita = rxbuf + BLE_LL_PDU_HDR_LEN; - SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) { - if (!memcmp(&connsm->peer_addr, inita, BLE_DEV_ADDR_LEN)) { - if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) { - if (connsm->peer_addr_type & 1) { - return 0; - } - } else { - if ((connsm->peer_addr_type & 1) == 0) { - return 0; - } - } - } - } - - /* Allocate a connection. If none available, dont do anything */ - connsm = ble_ll_conn_sm_get(); - if (connsm == NULL) { - return 0; - } - - /* Set the pointer at the start of the connection data */ - dptr = rxbuf + BLE_LL_CONN_REQ_ADVA_OFF + BLE_DEV_ADDR_LEN; - - /* Set connection state machine information */ - connsm->access_addr = get_le32(dptr); - crcinit = dptr[6]; - crcinit = (crcinit << 8) | dptr[5]; - crcinit = (crcinit << 8) | dptr[4]; - connsm->crcinit = crcinit; - connsm->tx_win_size = dptr[7]; - connsm->tx_win_off = get_le16(dptr + 8); - connsm->conn_itvl = get_le16(dptr + 10); - connsm->slave_latency = get_le16(dptr + 12); - connsm->supervision_tmo = get_le16(dptr + 14); - memcpy(&connsm->chanmap, dptr + 16, BLE_LL_CONN_CHMAP_LEN); - connsm->hop_inc = dptr[21] & 0x1F; - connsm->master_sca = dptr[21] >> 5; - - /* Error check parameters */ - if ((connsm->tx_win_off > connsm->conn_itvl) || - (connsm->conn_itvl < BLE_HCI_CONN_ITVL_MIN) || - (connsm->conn_itvl > BLE_HCI_CONN_ITVL_MAX) || - (connsm->tx_win_size < BLE_LL_CONN_TX_WIN_MIN) || - (connsm->slave_latency > BLE_LL_CONN_SLAVE_LATENCY_MAX)) { - goto err_slave_start; - } - - /* Slave latency cannot cause a supervision timeout */ - temp = (connsm->slave_latency + 1) * (connsm->conn_itvl * 2) * - BLE_LL_CONN_ITVL_USECS; - if ((connsm->supervision_tmo * 10000) <= temp ) { - goto err_slave_start; - } - - /* - * The transmit window must be less than or equal to the lesser of 10 - * msecs or the connection interval minus 1.25 msecs. - */ - temp = connsm->conn_itvl - 1; - if (temp > 8) { - temp = 8; - } - if (connsm->tx_win_size > temp) { - goto err_slave_start; - } - - /* Set the address of device that we are connecting with */ - memcpy(&connsm->peer_addr, inita, BLE_DEV_ADDR_LEN); - connsm->peer_addr_type = pat; - - /* Calculate number of used channels; make sure it meets min requirement */ - connsm->num_used_chans = ble_ll_utils_calc_num_used_chans(connsm->chanmap); - if (connsm->num_used_chans < 2) { - goto err_slave_start; - } - - /* Start the connection state machine */ - connsm->conn_role = BLE_LL_CONN_ROLE_SLAVE; - ble_ll_conn_sm_new(connsm); - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - /* Use the same PHY as we received CONNECT_REQ on */ - ble_ll_conn_init_phy(connsm, rxhdr->rxinfo.phy); -#endif - - ble_ll_conn_set_csa(connsm, - force_csa2 || (rxbuf[0] & BLE_ADV_PDU_HDR_CHSEL_MASK)); - - /* Set initial schedule callback */ - connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb; - rc = ble_ll_conn_created(connsm, rxhdr); - if (!rc) { - SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle); - STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); - } - return rc; - -err_slave_start: - STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); - STATS_INC(ble_ll_conn_stats, slave_rxd_bad_conn_req_params); - return 0; -} - -#define MAX_TIME_UNCODED(_maxbytes) \ - ble_ll_pdu_tx_time_get(_maxbytes + BLE_LL_DATA_MIC_LEN, \ - BLE_PHY_MODE_1M); -#define MAX_TIME_CODED(_maxbytes) \ - ble_ll_pdu_tx_time_get(_maxbytes + BLE_LL_DATA_MIC_LEN, \ - BLE_PHY_MODE_CODED_125KBPS); - -/** - * Called to reset the connection module. When this function is called the - * scheduler has been stopped and the phy has been disabled. The LL should - * be in the standby state. - * - * Context: Link Layer task - */ -void -ble_ll_conn_module_reset(void) -{ - uint8_t max_phy_pyld; - uint16_t maxbytes; - struct ble_ll_conn_sm *connsm; - struct ble_ll_conn_global_params *conn_params; - - /* Kill the current one first (if one is running) */ - if (g_ble_ll_conn_cur_sm) { - connsm = g_ble_ll_conn_cur_sm; - g_ble_ll_conn_cur_sm = NULL; - ble_ll_conn_end(connsm, BLE_ERR_SUCCESS); - } - - /* Free the global connection complete event if there is one */ - if (g_ble_ll_conn_comp_ev) { - ble_hci_trans_buf_free(g_ble_ll_conn_comp_ev); - g_ble_ll_conn_comp_ev = NULL; - } - - /* Reset connection we are attempting to create */ - g_ble_ll_conn_create_sm = NULL; - - /* Now go through and end all the connections */ - while (1) { - connsm = SLIST_FIRST(&g_ble_ll_conn_active_list); - if (!connsm) { - break; - } - ble_ll_conn_end(connsm, BLE_ERR_SUCCESS); - } - - /* Get the maximum supported PHY PDU size from the PHY */ - max_phy_pyld = ble_phy_max_data_pdu_pyld(); - - /* Configure the global LL parameters */ - conn_params = &g_ble_ll_conn_params; - - maxbytes = min(MYNEWT_VAL(BLE_LL_SUPP_MAX_RX_BYTES), max_phy_pyld); - conn_params->supp_max_rx_octets = maxbytes; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - conn_params->supp_max_rx_time = MAX_TIME_CODED(maxbytes); -#else - conn_params->supp_max_rx_time = MAX_TIME_UNCODED(maxbytes); -#endif - - maxbytes = min(MYNEWT_VAL(BLE_LL_SUPP_MAX_TX_BYTES), max_phy_pyld); - conn_params->supp_max_tx_octets = maxbytes; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - conn_params->supp_max_tx_time = MAX_TIME_CODED(maxbytes); -#else - conn_params->supp_max_tx_time = MAX_TIME_UNCODED(maxbytes); -#endif - - maxbytes = min(MYNEWT_VAL(BLE_LL_CONN_INIT_MAX_TX_BYTES), max_phy_pyld); - conn_params->conn_init_max_tx_octets = maxbytes; - conn_params->conn_init_max_tx_time = MAX_TIME_UNCODED(maxbytes); - conn_params->conn_init_max_tx_time_uncoded = MAX_TIME_UNCODED(maxbytes); - conn_params->conn_init_max_tx_time_coded = MAX_TIME_CODED(maxbytes); - - conn_params->sugg_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; - conn_params->sugg_tx_time = BLE_LL_CONN_SUPP_TIME_MIN; - - /* Mask in all channels by default */ - conn_params->num_used_chans = BLE_PHY_NUM_DATA_CHANS; - memset(conn_params->master_chan_map, 0xff, BLE_LL_CONN_CHMAP_LEN - 1); - conn_params->master_chan_map[4] = 0x1f; - - /* Reset statistics */ - STATS_RESET(ble_ll_conn_stats); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - /* reset default sync transfer params */ - g_ble_ll_conn_sync_transfer_params.max_skip = 0; - g_ble_ll_conn_sync_transfer_params.mode = 0; - g_ble_ll_conn_sync_transfer_params.sync_timeout_us = 0; -#endif -} - -/* Initialize the connection module */ -void -ble_ll_conn_module_init(void) -{ - int rc; - uint16_t i; - struct ble_ll_conn_sm *connsm; - - /* Initialize list of active conections */ - SLIST_INIT(&g_ble_ll_conn_active_list); - STAILQ_INIT(&g_ble_ll_conn_free_list); - - /* - * Take all the connections off the free memory pool and add them to - * the free connection list, assigning handles in linear order. Note: - * the specification allows a handle of zero; we just avoid using it. - */ - connsm = &g_ble_ll_conn_sm[0]; - for (i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); ++i) { - - memset(connsm, 0, sizeof(struct ble_ll_conn_sm)); - connsm->conn_handle = i + 1; - STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); - - /* Initialize fixed schedule elements */ - connsm->conn_sch.sched_type = BLE_LL_SCHED_TYPE_CONN; - connsm->conn_sch.cb_arg = connsm; - ++connsm; - } - - /* Register connection statistics */ - rc = stats_init_and_reg(STATS_HDR(ble_ll_conn_stats), - STATS_SIZE_INIT_PARMS(ble_ll_conn_stats, STATS_SIZE_32), - STATS_NAME_INIT_PARMS(ble_ll_conn_stats), - "ble_ll_conn"); - BLE_LL_ASSERT(rc == 0); - - /* Call reset to finish reset of initialization */ - ble_ll_conn_module_reset(); -} - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_hci.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_hci.c deleted file mode 100644 index 19ceebf50..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_hci.c +++ /dev/null @@ -1,1898 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "nimble/nimble/include/nimble/ble_hci_trans.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_utils.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_conn.h" -#include "../include/controller/ble_ll_ctrl.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_adv.h" -#include "ble_ll_conn_priv.h" - -/* - * Used to limit the rate at which we send the number of completed packets - * event to the host. This is the os time at which we can send an event. - */ -static ble_npl_time_t g_ble_ll_last_num_comp_pkt_evt; -extern uint8_t *g_ble_ll_conn_comp_ev; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static const uint8_t ble_ll_valid_conn_phy_mask = (BLE_HCI_LE_PHY_1M_PREF_MASK -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - | BLE_HCI_LE_PHY_2M_PREF_MASK -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - | BLE_HCI_LE_PHY_CODED_PREF_MASK -#endif - ); -static const uint8_t ble_ll_conn_required_phy_mask = (BLE_HCI_LE_PHY_1M_PREF_MASK -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - | BLE_HCI_LE_PHY_CODED_PREF_MASK -#endif - ); -#endif - -/** - * Allocate an event to send a connection complete event when initiating - * - * @return int 0: success -1: failure - */ -static int -ble_ll_init_alloc_conn_comp_ev(void) -{ - int rc; - uint8_t *evbuf; - - rc = 0; - evbuf = g_ble_ll_conn_comp_ev; - if (evbuf == NULL) { - evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (!evbuf) { - rc = -1; - } else { - g_ble_ll_conn_comp_ev = evbuf; - } - } - - return rc; -} - -/** - * Called to check that the connection parameters are within range - * - * @param itvl_min - * @param itvl_max - * @param latency - * @param spvn_tmo - * - * @return int BLE_ERR_INV_HCI_CMD_PARMS if invalid parameters, 0 otherwise - */ -int -ble_ll_conn_hci_chk_conn_params(uint16_t itvl_min, uint16_t itvl_max, - uint16_t latency, uint16_t spvn_tmo) -{ - uint32_t spvn_tmo_usecs; - uint32_t min_spvn_tmo_usecs; - - if ((itvl_min > itvl_max) || - (itvl_min < BLE_HCI_CONN_ITVL_MIN) || - (itvl_max > BLE_HCI_CONN_ITVL_MAX) || - (latency > BLE_HCI_CONN_LATENCY_MAX) || - (spvn_tmo < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) || - (spvn_tmo > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* - * Supervision timeout (in msecs) must be more than: - * (1 + connLatency) * connIntervalMax * 1.25 msecs * 2. - */ - spvn_tmo_usecs = spvn_tmo; - spvn_tmo_usecs *= (BLE_HCI_CONN_SPVN_TMO_UNITS * 1000); - min_spvn_tmo_usecs = (uint32_t)itvl_max * 2 * BLE_LL_CONN_ITVL_USECS; - min_spvn_tmo_usecs *= (1 + latency); - if (spvn_tmo_usecs <= min_spvn_tmo_usecs) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return BLE_ERR_SUCCESS; -} - -/** - * Send a connection complete event - * - * @param status The BLE error code associated with the event - */ -void -ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, - uint8_t *evbuf, struct ble_ll_adv_sm *advsm) -{ - struct ble_hci_ev_le_subev_enh_conn_complete *enh_ev; - struct ble_hci_ev_le_subev_conn_complete *ev; - struct ble_hci_ev *hci_ev = (void *) evbuf; - uint8_t *rpa; - - BLE_LL_ASSERT(evbuf); - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE)) { - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*enh_ev); - enh_ev = (void *) hci_ev->data; - - memset(enh_ev, 0, sizeof(*enh_ev)); - - enh_ev->subev_code = BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE; - enh_ev->status = status; - - if (connsm) { - enh_ev->conn_handle = htole16(connsm->conn_handle); - enh_ev->role = connsm->conn_role - 1; - enh_ev->peer_addr_type = connsm->peer_addr_type; - memcpy(enh_ev->peer_addr, connsm->peer_addr, BLE_DEV_ADDR_LEN); - - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - if (connsm->inita_identity_used) { - /* We used identity address in CONNECT_IND which can be just - * fine if - * a) it was direct advertising we replied to and remote uses - * its identity address in device privacy mode or IRK is all - * zeros. - * b) peer uses RPA and this is first time we connect to him - */ - rpa = NULL; - } else if (connsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { - rpa = ble_ll_scan_get_local_rpa(); - } else { - rpa = NULL; - } - } else { - rpa = ble_ll_adv_get_local_rpa(advsm); - } - - if (rpa) { - memcpy(enh_ev->local_rpa, rpa, BLE_DEV_ADDR_LEN); - } - - /* We need to adjust peer type if device connected using RPA - * and was resolved since RPA needs to be added to HCI event. - */ - if (connsm->peer_addr_type < BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT - && (connsm->rpa_index > -1)) { - enh_ev->peer_addr_type += 2; - } - - if (enh_ev->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) { - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - rpa = ble_ll_scan_get_peer_rpa(); - } else { - rpa = ble_ll_adv_get_peer_rpa(advsm); - } - memcpy(enh_ev->peer_rpa, rpa, BLE_DEV_ADDR_LEN); - } - - enh_ev->conn_itvl = htole16(connsm->conn_itvl); - enh_ev->conn_latency = htole16(connsm->slave_latency); - enh_ev->supervision_timeout = htole16(connsm->supervision_tmo); - enh_ev->mca = connsm->master_sca; - } - - ble_ll_hci_event_send(hci_ev); - return; - } - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CONN_COMPLETE)) { - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - memset(ev, 0, sizeof(*ev)); - - ev->subev_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE; - ev->status = status; - - if (connsm) { - ev->conn_handle = htole16(connsm->conn_handle); - ev->role = connsm->conn_role - 1; - ev->peer_addr_type = connsm->peer_addr_type; - - if (ev->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) { - ev->peer_addr_type -= 2; - } - memcpy(ev->peer_addr, connsm->peer_addr, BLE_DEV_ADDR_LEN); - ev->conn_itvl = htole16(connsm->conn_itvl); - ev->conn_latency = htole16(connsm->slave_latency); - ev->supervision_timeout = htole16(connsm->supervision_tmo); - ev->mca = connsm->master_sca; - } - - ble_ll_hci_event_send(hci_ev); - return; - } - - ble_hci_trans_buf_free(evbuf); -} - -/** - * Called to create and send the number of completed packets event to the - * host. - */ -void -ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm) -{ - /** The maximum number of handles that will fit in an event buffer. */ - static const int max_handles = - (BLE_LL_MAX_EVT_LEN - sizeof(struct ble_hci_ev_num_comp_pkts) - 1) / 4; - struct ble_hci_ev_num_comp_pkts *ev; - struct ble_hci_ev *hci_ev; - int event_sent; - - if (connsm == NULL) { - goto skip_conn; - } - - /* - * At some periodic rate, make sure we go through all active connections - * and send the number of completed packet events. We do this mainly - * because the spec says we must update the host even though no packets - * have completed but there are data packets in the controller buffers - * (i.e. enqueued in a connection state machine). - */ - if ((ble_npl_stime_t)(ble_npl_time_get() - g_ble_ll_last_num_comp_pkt_evt) < - ble_npl_time_ms_to_ticks32(MYNEWT_VAL(BLE_LL_NUM_COMP_PKT_ITVL_MS))) { - /* - * If this connection has completed packets, send an event right away. - * We do this to increase throughput but we dont want to search the - * entire active list every time. - */ - if (connsm->completed_pkts) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_NUM_COMP_PKTS; - hci_ev->length = sizeof(*ev); - ev = (void *)hci_ev->data; - - ev->count = 1; - ev->completed[0].handle = htole16(connsm->conn_handle); - ev->completed[0].packets = htole16(connsm->completed_pkts); - hci_ev->length += sizeof(ev->completed[0]); - - connsm->completed_pkts = 0; - - ble_ll_hci_event_send(hci_ev); - } - } - return; - } - - /* Iterate through all the active, created connections */ -skip_conn: - hci_ev = NULL; - ev = NULL; - - event_sent = 0; - SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) { - /* - * Only look at connections that we have sent a connection complete - * event and that either has packets enqueued or has completed packets. - */ - if ((connsm->conn_state != BLE_LL_CONN_STATE_IDLE) && - (connsm->completed_pkts || !STAILQ_EMPTY(&connsm->conn_txq))) { - /* If no buffer, get one, If cant get one, leave. */ - if (!hci_ev) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (!hci_ev) { - break; - } - - hci_ev->opcode = BLE_HCI_EVCODE_NUM_COMP_PKTS; - hci_ev->length = sizeof(*ev); - ev = (void *)hci_ev->data; - - ev->count = 0; - } - - /* Add handle and complete packets */ - ev->completed[ev->count].handle = htole16(connsm->conn_handle); - ev->completed[ev->count].packets = htole16(connsm->completed_pkts); - hci_ev->length += sizeof(ev->completed[ev->count]); - ev->count++; - - connsm->completed_pkts = 0; - - /* Send now if the buffer is full. */ - if (ev->count == max_handles) { - ble_ll_hci_event_send(hci_ev); - hci_ev = NULL; - event_sent = 1; - } - } - } - - /* Send event if there is an event to send */ - if (hci_ev) { - ble_ll_hci_event_send(hci_ev); - event_sent = 1; - } - - if (event_sent) { - g_ble_ll_last_num_comp_pkt_evt = ble_npl_time_get(); - } -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) -/** - * Send a authenticated payload timeout event - * - * NOTE: we currently only send this event when we have a reason to send it; - * not when it fails. - * - * @param reason The BLE error code to send as a disconnect reason - */ -void -ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm) -{ - struct ble_hci_ev_auth_pyld_tmo *ev; - struct ble_hci_ev *hci_ev; - - if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_AUTH_PYLD_TMO)) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_AUTH_PYLD_TMO; - hci_ev->length = sizeof(*ev); - - ev = (void *) hci_ev->data; - ev->conn_handle = htole16(connsm->conn_handle); - - ble_ll_hci_event_send(hci_ev); - } - } -} -#endif - -/** - * Send a disconnection complete event. - * - * NOTE: we currently only send this event when we have a reason to send it; - * not when it fails. - * - * @param reason The BLE error code to send as a disconnect reason - */ -void -ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t reason) -{ - struct ble_hci_ev_disconn_cmp *ev; - struct ble_hci_ev *hci_ev; - - if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_DISCONN_CMP)) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_DISCONN_CMP; - hci_ev->length = sizeof(*ev); - - ev = (void *) hci_ev->data; - - ev->status = BLE_ERR_SUCCESS; - ev->conn_handle = htole16(connsm->conn_handle); - ev->reason = reason; - - ble_ll_hci_event_send(hci_ev); - } - } -} - -static int -ble_ll_conn_hci_chk_scan_params(uint16_t itvl, uint16_t window) -{ - /* Check interval and window */ - if ((itvl < BLE_HCI_SCAN_ITVL_MIN) || - (itvl > BLE_HCI_SCAN_ITVL_MAX) || - (window < BLE_HCI_SCAN_WINDOW_MIN) || - (window > BLE_HCI_SCAN_WINDOW_MAX) || - (itvl < window)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return 0; -} - -/** - * Process the HCI command to create a connection. - * - * Context: Link Layer task (HCI command processing) - * - * @param cmdbuf - * - * @return int - */ -int -ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_create_conn_cp *cmd = (const void *) cmdbuf; - struct ble_ll_conn_sm *connsm; - struct hci_create_conn hcc = { 0 }; - int rc; - - if (len < sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* If we are already creating a connection we should leave */ - if (g_ble_ll_conn_create_sm) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* If already enabled, we return an error */ - if (ble_ll_scan_enabled()) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* Retrieve command data */ - hcc.scan_itvl = le16toh(cmd->scan_itvl); - hcc.scan_window = le16toh(cmd->scan_window); - - rc = ble_ll_conn_hci_chk_scan_params(hcc.scan_itvl, hcc.scan_window); - if (rc) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check filter policy */ - hcc.filter_policy = cmd->filter_policy; - if (hcc.filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Get peer address type and address only if no whitelist used */ - if (hcc.filter_policy == 0) { - hcc.peer_addr_type = cmd->peer_addr_type; - if (hcc.peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - memcpy(&hcc.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); - } - - /* Get own address type (used in connection request) */ - hcc.own_addr_type = cmd->own_addr_type; - if (hcc.own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check connection interval, latency and supervision timeoout */ - hcc.conn_itvl_min = le16toh(cmd->min_conn_itvl); - hcc.conn_itvl_max = le16toh(cmd->max_conn_itvl); - hcc.conn_latency = le16toh(cmd->conn_latency); - hcc.supervision_timeout = le16toh(cmd->tmo); - rc = ble_ll_conn_hci_chk_conn_params(hcc.conn_itvl_min, - hcc.conn_itvl_max, - hcc.conn_latency, - hcc.supervision_timeout); - if (rc) { - return rc; - } - - /* Min/max connection event lengths */ - hcc.min_ce_len = le16toh(cmd->min_ce); - hcc.max_ce_len = le16toh(cmd->max_ce); - if (hcc.min_ce_len > hcc.max_ce_len) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Make sure we can allocate an event to send the connection complete */ - if (ble_ll_init_alloc_conn_comp_ev()) { - return BLE_ERR_MEM_CAPACITY; - } - - /* Make sure we can accept a connection! */ - connsm = ble_ll_conn_sm_get(); - if (connsm == NULL) { - return BLE_ERR_CONN_LIMIT; - } - - /* Initialize state machine in master role and start state machine */ - ble_ll_conn_master_init(connsm, &hcc); - ble_ll_conn_sm_new(connsm); - /* CSA will be selected when advertising is received */ - - /* Start scanning */ - rc = ble_ll_scan_initiator_start(&hcc, &connsm->scansm); - if (rc) { - SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle); - STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); - } else { - /* Set the connection state machine we are trying to create. */ - g_ble_ll_conn_create_sm = connsm; - } - - return rc; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static void -ble_ll_conn_hcc_params_set_fallback(struct hci_ext_create_conn *hcc, - const struct hci_ext_conn_params *fallback) -{ - BLE_LL_ASSERT(fallback); - - if (!(hcc->init_phy_mask & BLE_PHY_MASK_1M)) { - hcc->params[0] = *fallback; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - if (!(hcc->init_phy_mask & BLE_PHY_MASK_2M)) { - hcc->params[1] = *fallback; - } -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - if (!(hcc->init_phy_mask & BLE_PHY_MASK_CODED)) { - hcc->params[2] = *fallback; - } -#endif -} - -int -ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_ext_create_conn_cp *cmd = (const void *) cmdbuf; - const struct conn_params *params = cmd->conn_params; - const struct hci_ext_conn_params *fallback_params = NULL; - struct hci_ext_create_conn hcc = { 0 }; - struct ble_ll_conn_sm *connsm; - int rc; - - /* validate length */ - if (len < sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - len -= sizeof(*cmd); - - /* If we are already creating a connection we should leave */ - if (g_ble_ll_conn_create_sm) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* If already enabled, we return an error */ - if (ble_ll_scan_enabled()) { - return BLE_ERR_CMD_DISALLOWED; - } - - hcc.filter_policy = cmd->filter_policy; - if (hcc.filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - hcc.own_addr_type = cmd->own_addr_type; - if (hcc.own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Validate peer address type only if no whitelist used */ - if (hcc.filter_policy == 0) { - hcc.peer_addr_type = cmd->peer_addr_type; - - if (hcc.peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - memcpy(hcc.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); - } - - hcc.init_phy_mask = cmd->init_phy_mask; - if (hcc.init_phy_mask & ~ble_ll_valid_conn_phy_mask) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (!(hcc.init_phy_mask & ble_ll_conn_required_phy_mask)) { - /* At least one of those need to be set */ - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (hcc.init_phy_mask & BLE_PHY_MASK_1M) { - if (len < sizeof(*params)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - len -= sizeof(*params); - - hcc.params[0].scan_itvl = le16toh(params->scan_itvl); - hcc.params[0].scan_window = le16toh(params->scan_window); - - rc = ble_ll_conn_hci_chk_scan_params(hcc.params[0].scan_itvl, - hcc.params[0].scan_window); - if (rc) { - return rc; - } - - hcc.params[0].conn_itvl_min = le16toh(params->conn_min_itvl); - hcc.params[0].conn_itvl_max = le16toh(params->conn_min_itvl); - hcc.params[0].conn_latency = le16toh(params->conn_latency); - hcc.params[0].supervision_timeout = le16toh(params->supervision_timeout); - - rc = ble_ll_conn_hci_chk_conn_params(hcc.params[0].conn_itvl_min, - hcc.params[0].conn_itvl_max, - hcc.params[0].conn_latency, - hcc.params[0].supervision_timeout); - if (rc) { - return rc; - } - - /* Min/max connection event lengths */ - hcc.params[0].min_ce_len = le16toh(params->min_ce); - hcc.params[0].max_ce_len = le16toh(params->max_ce); - if (hcc.params[0].min_ce_len > hcc.params[0].max_ce_len) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - fallback_params = &hcc.params[0]; - params++; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - if (hcc.init_phy_mask & BLE_PHY_MASK_2M) { - if (len < sizeof(*params)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - len -= sizeof(*params); - - hcc.params[1].conn_itvl_min = le16toh(params->conn_min_itvl); - hcc.params[1].conn_itvl_max = le16toh(params->conn_min_itvl); - hcc.params[1].conn_latency = le16toh(params->conn_latency); - hcc.params[1].supervision_timeout = le16toh(params->supervision_timeout); - - rc = ble_ll_conn_hci_chk_conn_params(hcc.params[1].conn_itvl_min, - hcc.params[1].conn_itvl_max, - hcc.params[1].conn_latency, - hcc.params[1].supervision_timeout); - if (rc) { - return rc; - } - - /* Min/max connection event lengths */ - hcc.params[1].min_ce_len = le16toh(params->min_ce); - hcc.params[1].max_ce_len = le16toh(params->max_ce); - if (hcc.params[1].min_ce_len > hcc.params[1].max_ce_len) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - params++; - } -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - if (hcc.init_phy_mask & BLE_PHY_MASK_CODED) { - if (len < sizeof(*params)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - len -= sizeof(*params); - - hcc.params[2].scan_itvl = le16toh(params->scan_itvl); - hcc.params[2].scan_window = le16toh(params->scan_window); - - rc = ble_ll_conn_hci_chk_scan_params(hcc.params[2].scan_itvl, - hcc.params[2].scan_window); - if (rc) { - return rc; - } - - hcc.params[2].conn_itvl_min = le16toh(params->conn_min_itvl); - hcc.params[2].conn_itvl_max = le16toh(params->conn_min_itvl); - hcc.params[2].conn_latency = le16toh(params->conn_latency); - hcc.params[2].supervision_timeout = le16toh(params->supervision_timeout); - - rc = ble_ll_conn_hci_chk_conn_params(hcc.params[2].conn_itvl_min, - hcc.params[2].conn_itvl_max, - hcc.params[2].conn_latency, - hcc.params[2].supervision_timeout); - if (rc) { - return rc; - } - - /* Min/max connection event lengths */ - hcc.params[2].min_ce_len = le16toh(params->min_ce); - hcc.params[2].max_ce_len = le16toh(params->max_ce); - if (hcc.params[2].min_ce_len > hcc.params[2].max_ce_len) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (!fallback_params) { - fallback_params = &hcc.params[2]; - } - params++; - } -#endif - - /* Make sure we can allocate an event to send the connection complete */ - if (ble_ll_init_alloc_conn_comp_ev()) { - return BLE_ERR_MEM_CAPACITY; - } - - /* Make sure we can accept a connection! */ - connsm = ble_ll_conn_sm_get(); - if (connsm == NULL) { - return BLE_ERR_CONN_LIMIT; - } - - ble_ll_conn_hcc_params_set_fallback(&hcc, fallback_params); - - /* Initialize state machine in master role and start state machine */ - ble_ll_conn_ext_master_init(connsm, &hcc); - ble_ll_conn_sm_new(connsm); - - /* CSA will be selected when advertising is received */ - - /* Start scanning */ - rc = ble_ll_scan_ext_initiator_start(&hcc, &connsm->scansm); - if (rc) { - SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle); - STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); - } else { - /* Set the connection state machine we are trying to create. */ - g_ble_ll_conn_create_sm = connsm; - } - - return rc; -} -#endif - -static int -ble_ll_conn_process_conn_params(const struct ble_hci_le_rem_conn_param_rr_cp *cmd, - struct ble_ll_conn_sm *connsm) -{ - int rc; - struct hci_conn_update *hcu; - - /* Retrieve command data */ - hcu = &connsm->conn_param_req; - hcu->handle = connsm->conn_handle; - - BLE_LL_ASSERT(connsm->conn_handle == le16toh(cmd->conn_handle)); - - hcu->conn_itvl_min = le16toh(cmd->conn_itvl_min); - hcu->conn_itvl_max = le16toh(cmd->conn_itvl_max); - hcu->conn_latency = le16toh(cmd->conn_latency); - hcu->supervision_timeout = le16toh(cmd->supervision_timeout); - hcu->min_ce_len = le16toh(cmd->min_ce); - hcu->max_ce_len = le16toh(cmd->max_ce); - - /* Check that parameter values are in range */ - rc = ble_ll_conn_hci_chk_conn_params(hcu->conn_itvl_min, - hcu->conn_itvl_max, - hcu->conn_latency, - hcu->supervision_timeout); - - /* Check valid min/max ce length */ - if (rc || (hcu->min_ce_len > hcu->max_ce_len)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - return rc; -} - -/** - * Called when the host issues the read remote features command - * - * @param cmdbuf - * - * @return int - */ -int -ble_ll_conn_hci_read_rem_features(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_rd_rem_feat_cp *cmd = (const void *) cmdbuf; - struct ble_ll_conn_sm *connsm; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* If no connection handle exit with error */ - connsm = ble_ll_conn_find_active_conn(le16toh(cmd->conn_handle)); - if (!connsm) { - return BLE_ERR_UNK_CONN_ID; - } - - /* If already pending exit with error */ - if (connsm->csmflags.cfbit.pending_hci_rd_features) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* - * Start control procedure if we did not receive peer's features and did not - * start procedure already. - */ - if (!connsm->csmflags.cfbit.rxd_features && - !IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG)) { - if ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && - !(ble_ll_read_supp_features() & BLE_LL_FEAT_SLAVE_INIT)) { - return BLE_ERR_CMD_DISALLOWED; - } - - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG); - } - - connsm->csmflags.cfbit.pending_hci_rd_features = 1; - - return BLE_ERR_SUCCESS; -} - -/** - * Called to process a connection update command. - * - * @param cmdbuf - * - * @return int - */ -int -ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_conn_update_cp *cmd = (const void *) cmdbuf; - int rc; - uint8_t ctrl_proc; - uint16_t handle; - struct ble_ll_conn_sm *connsm; - struct hci_conn_update *hcu; - - /* - * XXX: must deal with slave not supporting this feature and using - * conn update! Right now, we only check if WE support the connection - * parameters request procedure. We dont check if the remote does. - * We should also be able to deal with sending the parameter request, - * getting an UNKOWN_RSP ctrl pdu and resorting to use normal - * connection update procedure. - */ - - /* If no connection handle exit with error */ - handle = le16toh(cmd->conn_handle); - connsm = ble_ll_conn_find_active_conn(handle); - if (!connsm) { - return BLE_ERR_UNK_CONN_ID; - } - - /* Better not have this procedure ongoing! */ - if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ) || - IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE)) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* See if this feature is supported on both sides */ - if ((connsm->conn_features & BLE_LL_FEAT_CONN_PARM_REQ) == 0) { - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - return BLE_ERR_UNSUPP_REM_FEATURE; - } - ctrl_proc = BLE_LL_CTRL_PROC_CONN_UPDATE; - } else { - ctrl_proc = BLE_LL_CTRL_PROC_CONN_PARAM_REQ; - } - - /* - * If we are a slave and the master has initiated the procedure already - * we should deny the slave request for now. If we are a master and the - * slave has initiated the procedure, we need to send a reject to the - * slave. - */ - if (connsm->csmflags.cfbit.awaiting_host_reply) { - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - return BLE_ERR_LMP_COLLISION; - } else { - connsm->csmflags.cfbit.awaiting_host_reply = 0; - - /* XXX: If this fails no reject ind will be sent! */ - ble_ll_ctrl_reject_ind_send(connsm, connsm->host_reply_opcode, - BLE_ERR_LMP_COLLISION); - } - } - - /* - * If we are a slave and the master has initiated the channel map - * update procedure we should deny the slave request for now. - */ - if (connsm->csmflags.cfbit.chanmap_update_scheduled) { - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - return BLE_ERR_DIFF_TRANS_COLL; - } - } - - /* Retrieve command data */ - hcu = &connsm->conn_param_req; - hcu->conn_itvl_min = le16toh(cmd->conn_itvl_min); - hcu->conn_itvl_max = le16toh(cmd->conn_itvl_max); - hcu->conn_latency = le16toh(cmd->conn_latency); - hcu->supervision_timeout = le16toh(cmd->supervision_timeout); - hcu->min_ce_len = le16toh(cmd->min_ce_len); - hcu->max_ce_len = le16toh(cmd->max_ce_len); - if (hcu->min_ce_len > hcu->max_ce_len) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check that parameter values are in range */ - rc = ble_ll_conn_hci_chk_conn_params(hcu->conn_itvl_min, - hcu->conn_itvl_max, - hcu->conn_latency, - hcu->supervision_timeout); - if (!rc) { - hcu->handle = handle; - - /* Start the control procedure */ - ble_ll_ctrl_proc_start(connsm, ctrl_proc); - } - - return rc; -} - -int -ble_ll_conn_hci_param_rr(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_rem_conn_param_rr_cp *cmd = (const void *) cmdbuf; - struct ble_hci_le_rem_conn_param_rr_rp *rsp = (void *) rspbuf; - int rc; - uint8_t *dptr; - uint8_t rsp_opcode; - uint16_t handle; - struct os_mbuf *om; - struct ble_ll_conn_sm *connsm; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - handle = le16toh(cmd->conn_handle); - - /* See if we support this feature */ - if ((ble_ll_read_supp_features() & BLE_LL_FEAT_CONN_PARM_REQ) == 0) { - rc = BLE_ERR_UNKNOWN_HCI_CMD; - goto done; - } - - /* If we dont have a handle we cant do anything */ - connsm = ble_ll_conn_find_active_conn(handle); - if (!connsm) { - rc = BLE_ERR_UNK_CONN_ID; - goto done; - } - - /* Make sure connection parameters are valid */ - rc = ble_ll_conn_process_conn_params(cmd, connsm); - - /* The connection should be awaiting a reply. If not, just discard */ - if (connsm->csmflags.cfbit.awaiting_host_reply) { - /* Get a control packet buffer */ - if (rc == BLE_ERR_SUCCESS) { - om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN, - sizeof(struct ble_mbuf_hdr)); - if (om) { - dptr = om->om_data; - rsp_opcode = ble_ll_ctrl_conn_param_reply(connsm, dptr, - &connsm->conn_cp); - dptr[0] = rsp_opcode; - len = g_ble_ll_ctrl_pkt_lengths[rsp_opcode] + 1; - ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, len); - } - } else { - /* XXX: check return code and deal */ - ble_ll_ctrl_reject_ind_send(connsm, connsm->host_reply_opcode, - BLE_ERR_CONN_PARMS); - } - connsm->csmflags.cfbit.awaiting_host_reply = 0; - - /* XXX: if we cant get a buffer, what do we do? We need to remember - * reason if it was a negative reply. We also would need to have - * some state to tell us this happened - */ - } - -done: - rsp->conn_handle = htole16(handle); - - *rsplen = sizeof(*rsp); - return rc; -} - -int -ble_ll_conn_hci_param_nrr(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_rem_conn_params_nrr_cp *cmd = (const void *) cmdbuf; - struct ble_hci_le_rem_conn_params_nrr_rp *rsp = (void *) rspbuf; - struct ble_ll_conn_sm *connsm; - uint16_t handle; - int rc; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - handle = le16toh(cmd->conn_handle); - - /* See if we support this feature */ - if ((ble_ll_read_supp_features() & BLE_LL_FEAT_CONN_PARM_REQ) == 0) { - rc = BLE_ERR_UNKNOWN_HCI_CMD; - goto done; - } - - /* If we dont have a handle we cant do anything */ - connsm = ble_ll_conn_find_active_conn(handle); - if (!connsm) { - rc = BLE_ERR_UNK_CONN_ID; - goto done; - } - - rc = BLE_ERR_SUCCESS; - - /* The connection should be awaiting a reply. If not, just discard */ - if (connsm->csmflags.cfbit.awaiting_host_reply) { - /* XXX: check return code and deal */ - ble_ll_ctrl_reject_ind_send(connsm, connsm->host_reply_opcode, - cmd->reason); - connsm->csmflags.cfbit.awaiting_host_reply = 0; - - /* XXX: if we cant get a buffer, what do we do? We need to remember - * reason if it was a negative reply. We also would need to have - * some state to tell us this happened - */ - } - -done: - rsp->conn_handle = htole16(handle); - - *rsplen = sizeof(*rsp); - return rc; -} - -/* this is called from same context after cmd complete is send so it is - * safe to use g_ble_ll_conn_comp_ev - */ -static void -ble_ll_conn_hci_cancel_conn_complete_event(void) -{ - BLE_LL_ASSERT(g_ble_ll_conn_comp_ev); - - ble_ll_conn_comp_event_send(NULL, BLE_ERR_UNK_CONN_ID, - g_ble_ll_conn_comp_ev, NULL); - g_ble_ll_conn_comp_ev = NULL; -} - -/** - * Called when HCI command to cancel a create connection command has been - * received. - * - * Context: Link Layer (HCI command parser) - * - * @return int - */ -int -ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb) -{ - int rc; - struct ble_ll_conn_sm *connsm; - os_sr_t sr; - - /* - * If we receive this command and we have not got a connection - * create command, we have to return disallowed. The spec does not say - * what happens if the connection has already been established. We - * return disallowed as well - */ - OS_ENTER_CRITICAL(sr); - connsm = g_ble_ll_conn_create_sm; - if (connsm && (connsm->conn_state == BLE_LL_CONN_STATE_IDLE)) { - /* stop scanning and end the connection event */ - g_ble_ll_conn_create_sm = NULL; - ble_ll_scan_sm_stop(1); - ble_ll_conn_end(connsm, BLE_ERR_UNK_CONN_ID); - - *post_cmd_cb = ble_ll_conn_hci_cancel_conn_complete_event; - - rc = BLE_ERR_SUCCESS; - } else { - /* If we are not attempting to create a connection*/ - rc = BLE_ERR_CMD_DISALLOWED; - } - OS_EXIT_CRITICAL(sr); - - return rc; -} - -/** - * Called to process a HCI disconnect command - * - * Context: Link Layer task (HCI command parser). - * - * @param cmdbuf - * - * @return int - */ -int -ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len) -{ - int rc; - uint16_t handle; - struct ble_ll_conn_sm *connsm; - const struct ble_hci_lc_disconnect_cp *cmd = (const void *) cmdbuf; - - if (len != sizeof (*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check for valid parameters */ - handle = le16toh(cmd->conn_handle); - - rc = BLE_ERR_INV_HCI_CMD_PARMS; - if (handle <= BLE_LL_CONN_MAX_CONN_HANDLE) { - /* Make sure reason is valid */ - switch (cmd->reason) { - case BLE_ERR_AUTH_FAIL: - case BLE_ERR_REM_USER_CONN_TERM: - case BLE_ERR_RD_CONN_TERM_RESRCS: - case BLE_ERR_RD_CONN_TERM_PWROFF: - case BLE_ERR_UNSUPP_REM_FEATURE: - case BLE_ERR_UNIT_KEY_PAIRING: - case BLE_ERR_CONN_PARMS: - connsm = ble_ll_conn_find_active_conn(handle); - if (connsm) { - /* Do not allow command if we are in process of disconnecting */ - if (connsm->disconnect_reason) { - rc = BLE_ERR_CMD_DISALLOWED; - } else { - /* This control procedure better not be pending! */ - BLE_LL_ASSERT(CONN_F_TERMINATE_STARTED(connsm) == 0); - - /* Record the disconnect reason */ - connsm->disconnect_reason = cmd->reason; - - /* Start this control procedure */ - ble_ll_ctrl_terminate_start(connsm); - - rc = BLE_ERR_SUCCESS; - } - } else { - rc = BLE_ERR_UNK_CONN_ID; - } - break; - default: - break; - } - } - - return rc; -} - -/** - * Called to process a HCI disconnect command - * - * Context: Link Layer task (HCI command parser). - * - * @param cmdbuf - * - * @return int - */ -int -ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len) -{ - struct ble_ll_conn_sm *connsm; - const struct ble_hci_rd_rem_ver_info_cp *cmd = (const void *) cmdbuf; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check for valid parameters */ - connsm = ble_ll_conn_find_active_conn(le16toh(cmd->conn_handle)); - if (!connsm) { - return BLE_ERR_UNK_CONN_ID; - } - - /* Return error if in progress */ - if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG)) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* - * Start this control procedure. If we have already done this control - * procedure we set the pending bit so that the host gets an event because - * it is obviously expecting one (or would not have sent the command). - * NOTE: we cant just send the event here. That would cause the event to - * be queued before the command status. - */ - if (!connsm->csmflags.cfbit.version_ind_sent) { - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG); - } else { - connsm->pending_ctrl_procs |= (1 << BLE_LL_CTRL_PROC_VERSION_XCHG); - } - - return BLE_ERR_SUCCESS; -} - -/** - * Called to read the RSSI for a given connection handle - * - * @param cmdbuf - * @param rspbuf - * @param rsplen - * - * @return int - */ -int -ble_ll_conn_hci_rd_rssi(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen) -{ - - const struct ble_hci_rd_rssi_cp *cmd = (const void *) cmdbuf; - struct ble_hci_rd_rssi_rp *rsp = (void *) rspbuf; - struct ble_ll_conn_sm *connsm; - int rc; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - rsp->handle = cmd->handle; - - connsm = ble_ll_conn_find_active_conn(le16toh(cmd->handle)); - if (!connsm) { - rsp->rssi = 127; - rc = BLE_ERR_UNK_CONN_ID; - } else { - rsp->rssi = connsm->conn_rssi; - rc = BLE_ERR_SUCCESS; - } - - *rsplen = sizeof(*rsp); - return rc; -} - -/** - * Called to read the current channel map of a connection - * - * @param cmdbuf - * @param rspbuf - * @param rsplen - * - * @return int - */ -int -ble_ll_conn_hci_rd_chan_map(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_rd_chan_map_cp *cmd = (const void *) cmdbuf; - struct ble_hci_le_rd_chan_map_rp *rsp = (void *) rspbuf; - struct ble_ll_conn_sm *connsm; - uint16_t handle; - int rc; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - handle = le16toh(cmd->conn_handle); - connsm = ble_ll_conn_find_active_conn(handle); - if (!connsm) { - rc = BLE_ERR_UNK_CONN_ID; - memset(rsp->chan_map, 0, sizeof(rsp->chan_map)); - } else { - if (connsm->csmflags.cfbit.chanmap_update_scheduled) { - memcpy(rsp->chan_map, connsm->req_chanmap, BLE_LL_CONN_CHMAP_LEN); - } else { - memcpy(rsp->chan_map, connsm->chanmap, BLE_LL_CONN_CHMAP_LEN); - } - rc = BLE_ERR_SUCCESS; - } - - rsp->conn_handle = htole16(handle); - - *rsplen = sizeof(*rsp); - return rc; -} - -/** - * Called when the host issues the LE command "set host channel classification" - * - * @param cmdbuf - * - * @return int - */ -int -ble_ll_conn_hci_set_chan_class(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_host_chan_class_cp *cmd = (const void *) cmdbuf; - uint8_t num_used_chans; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* - * The HCI command states that the host is allowed to mask in just one - * channel but the Link Layer needs minimum two channels to operate. So - * I will not allow this command if there are less than 2 channels masked. - */ - num_used_chans = ble_ll_utils_calc_num_used_chans(cmd->chan_map); - if ((num_used_chans < 2) || ((cmd->chan_map[4] & 0xe0) != 0)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Set the host channel mask */ - ble_ll_conn_set_global_chanmap(num_used_chans, cmd->chan_map); - return BLE_ERR_SUCCESS; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) -int -ble_ll_conn_hci_set_data_len(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_set_data_len_cp *cmd = (const void *) cmdbuf; - struct ble_hci_le_set_data_len_rp *rsp = (void *) rspbuf; - int rc; - uint16_t handle; - uint16_t txoctets; - uint16_t txtime; - struct ble_ll_conn_sm *connsm; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Find connection */ - handle = le16toh(cmd->conn_handle); - connsm = ble_ll_conn_find_active_conn(handle); - if (!connsm) { - rc = BLE_ERR_UNK_CONN_ID; - goto done; - } - - txoctets = le16toh(cmd->tx_octets); - txtime = le16toh(cmd->tx_time); - - /* Make sure it is valid */ - if (!ble_ll_chk_txrx_octets(txoctets) || - !ble_ll_chk_txrx_time(txtime)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - /* - * Keep original value requested by host since we may want to recalculate - * MaxTxTime after PHY changes between coded and uncoded. - */ - connsm->host_req_max_tx_time = txtime; - - /* If peer does not support coded, we cannot use value larger than 2120us */ - if (!(connsm->remote_features[0] & (BLE_LL_FEAT_LE_CODED_PHY >> 8))) { - txtime = min(txtime, BLE_LL_CONN_SUPP_TIME_MAX_UNCODED); - } -#endif - - rc = BLE_ERR_SUCCESS; - if (connsm->max_tx_time != txtime || - connsm->max_tx_octets != txoctets) { - - connsm->max_tx_time = txtime; - connsm->max_tx_octets = txoctets; - - ble_ll_ctrl_initiate_dle(connsm); - } - -done: - rsp->conn_handle = htole16(handle); - *rsplen = sizeof(*rsp); - return rc; -} -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/** - * LE start encrypt command - * - * @param cmdbuf - * - * @return int - */ -int -ble_ll_conn_hci_le_start_encrypt(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_start_encrypt_cp *cmd = (const void *) cmdbuf; - struct ble_ll_conn_sm *connsm; - int rc; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - connsm = ble_ll_conn_find_active_conn(le16toh(cmd->conn_handle)); - if (!connsm) { - rc = BLE_ERR_UNK_CONN_ID; - } else if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - rc = BLE_ERR_UNSPECIFIED; - } else if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_ENCRYPT) { - /* - * The specification does not say what to do here but the host should - * not be telling us to start encryption while we are in the process - * of honoring a previous start encrypt. - */ - rc = BLE_ERR_CMD_DISALLOWED; - } else { - /* Start the control procedure */ - connsm->enc_data.host_rand_num = le64toh(cmd->rand); - connsm->enc_data.enc_div = le16toh(cmd->div); - swap_buf(connsm->enc_data.enc_block.key, cmd->ltk, 16); - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_ENCRYPT); - rc = BLE_ERR_SUCCESS; - } - - return rc; -} - -/** - * Called to process the LE long term key reply. - * - * Context: Link Layer Task. - * - * @param cmdbuf - * @param rspbuf - * @param ocf - * - * @return int - */ -int -ble_ll_conn_hci_le_ltk_reply(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_lt_key_req_reply_cp *cmd = (const void *) cmdbuf; - struct ble_hci_le_lt_key_req_reply_rp *rsp = (void *) rspbuf; - struct ble_ll_conn_sm *connsm; - uint16_t handle; - int rc; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Find connection handle */ - handle = le16toh(cmd->conn_handle); - connsm = ble_ll_conn_find_active_conn(handle); - if (!connsm) { - rc = BLE_ERR_UNK_CONN_ID; - goto ltk_key_cmd_complete; - } - - /* Should never get this if we are a master! */ - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - rc = BLE_ERR_UNSPECIFIED; - goto ltk_key_cmd_complete; - } - - /* The connection should be awaiting a reply. If not, just discard */ - if (connsm->enc_data.enc_state != CONN_ENC_S_LTK_REQ_WAIT) { - rc = BLE_ERR_CMD_DISALLOWED; - goto ltk_key_cmd_complete; - } - - swap_buf(connsm->enc_data.enc_block.key, cmd->ltk, 16); - ble_ll_calc_session_key(connsm); - ble_ll_ctrl_start_enc_send(connsm); - rc = BLE_ERR_SUCCESS; - -ltk_key_cmd_complete: - rsp->conn_handle = htole16(handle); - - *rsplen = sizeof(*rsp); - return rc; -} - -/** - * Called to process the LE long term key negative reply. - * - * Context: Link Layer Task. - * - * @param cmdbuf - * @param rspbuf - * @param ocf - * - * @return int - */ -int -ble_ll_conn_hci_le_ltk_neg_reply(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_lt_key_req_neg_reply_cp *cmd = (const void *) cmdbuf; - struct ble_hci_le_lt_key_req_neg_reply_rp *rsp = (void *) rspbuf; - struct ble_ll_conn_sm *connsm; - uint16_t handle; - int rc; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Find connection handle */ - handle = le16toh(cmd->conn_handle); - connsm = ble_ll_conn_find_active_conn(handle); - if (!connsm) { - rc = BLE_ERR_UNK_CONN_ID; - goto ltk_key_cmd_complete; - } - - /* Should never get this if we are a master! */ - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - rc = BLE_ERR_UNSPECIFIED; - goto ltk_key_cmd_complete; - } - - /* The connection should be awaiting a reply. If not, just discard */ - if (connsm->enc_data.enc_state != CONN_ENC_S_LTK_REQ_WAIT) { - rc = BLE_ERR_CMD_DISALLOWED; - goto ltk_key_cmd_complete; - } - - /* We received a negative reply! Send REJECT_IND */ - ble_ll_ctrl_reject_ind_send(connsm, BLE_LL_CTRL_ENC_REQ, - BLE_ERR_PINKEY_MISSING); - connsm->enc_data.enc_state = CONN_ENC_S_LTK_NEG_REPLY; - - rc = BLE_ERR_SUCCESS; - -ltk_key_cmd_complete: - rsp->conn_handle = htole16(handle); - - *rsplen = sizeof(*rsp); - return rc; -} -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) -/** - * Read authenticated payload timeout (OGF=3, OCF==0x007B) - * - * @param cmdbuf - * @param rsplen - * - * @return int - */ -int -ble_ll_conn_hci_rd_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_cb_rd_auth_pyld_tmo_cp *cmd = (const void *) cmdbuf; - struct ble_hci_cb_rd_auth_pyld_tmo_rp *rsp = (void *) rspbuf; - struct ble_ll_conn_sm *connsm; - uint16_t handle; - int rc; - - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - handle = le16toh(cmd->conn_handle); - connsm = ble_ll_conn_find_active_conn(handle); - if (!connsm) { - rc = BLE_ERR_UNK_CONN_ID; - rsp->tmo = 0; - } else { - rc = BLE_ERR_SUCCESS; - rsp->tmo = htole16(connsm->auth_pyld_tmo); - } - - rsp->conn_handle = htole16(handle); - - *rsplen = sizeof(*rsp); - return rc; -} - -/** - * Write authenticated payload timeout (OGF=3, OCF=00x7C) - * - * @param cmdbuf - * @param rsplen - * - * @return int - */ -int -ble_ll_conn_hci_wr_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_cb_wr_auth_pyld_tmo_cp *cmd = (const void *) cmdbuf; - struct ble_hci_cb_wr_auth_pyld_tmo_rp *rsp = (void *) rspbuf; - struct ble_ll_conn_sm *connsm; - uint32_t min_tmo; - uint16_t handle; - uint16_t tmo; - int rc; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - rc = BLE_ERR_SUCCESS; - - handle = le16toh(cmd->conn_handle); - - connsm = ble_ll_conn_find_active_conn(handle); - if (!connsm) { - rc = BLE_ERR_UNK_CONN_ID; - } else { - /* - * The timeout is in units of 10 msecs. We need to make sure that the - * timeout is greater than or equal to connItvl * (1 + slaveLatency) - */ - tmo = le16toh(cmd->tmo); - min_tmo = (uint32_t)connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS; - min_tmo *= (connsm->slave_latency + 1); - min_tmo /= 10000; - - if (tmo < min_tmo) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - } else { - connsm->auth_pyld_tmo = tmo; - if (ble_npl_callout_is_active(&connsm->auth_pyld_timer)) { - ble_ll_conn_auth_pyld_timer_start(connsm); - } - } - } - - rsp->conn_handle = htole16(handle); - *rsplen = sizeof(*rsp); - return rc; -} -#endif - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) -/** - * Read current phy for connection (OGF=8, OCF==0x0030) - * - * @param cmdbuf - * @param rsplen - * - * @return int - */ -int -ble_ll_conn_hci_le_rd_phy(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_rd_phy_cp *cmd = (const void *) cmdbuf; - struct ble_hci_le_rd_phy_rp *rsp = (void *) rspbuf; - int rc; - uint16_t handle; - struct ble_ll_conn_sm *connsm; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - handle = le16toh(cmd->conn_handle); - connsm = ble_ll_conn_find_active_conn(handle); - if (!connsm) { - rsp->tx_phy = 0; - rsp->rx_phy = 0; - rc = BLE_ERR_UNK_CONN_ID; - } else { - rsp->tx_phy = connsm->phy_data.cur_tx_phy; - rsp->rx_phy = connsm->phy_data.cur_rx_phy; - rc = BLE_ERR_SUCCESS; - } - - rsp->conn_handle = htole16(handle); - - *rsplen = sizeof(*rsp); - return rc; -} - -/** - * Set PHY preferences for connection - * - * @param cmdbuf - * - * @return int - */ -int -ble_ll_conn_hci_le_set_phy(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_phy_cp *cmd = (const void *) cmdbuf; - int rc; - uint16_t phy_options; - uint8_t tx_phys; - uint8_t rx_phys; - uint16_t handle; - struct ble_ll_conn_sm *connsm; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - handle = le16toh(cmd->conn_handle); - connsm = ble_ll_conn_find_active_conn(handle); - if (!connsm) { - return BLE_ERR_UNK_CONN_ID; - } - - /* - * If host has requested a PHY update and we are not finished do - * not allow another one - */ - if (CONN_F_HOST_PHY_UPDATE(connsm)) { - return BLE_ERR_CMD_DISALLOWED; - } - - phy_options = le16toh(cmd->phy_options); - if (phy_options > BLE_HCI_LE_PHY_CODED_S8_PREF) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check valid parameters */ - rc = ble_ll_hci_chk_phy_masks(cmd->all_phys, cmd->tx_phys, cmd->rx_phys, - &tx_phys, &rx_phys); - if (rc) { - goto phy_cmd_param_err; - } - - connsm->phy_data.phy_options = phy_options & 0x03; - connsm->phy_data.host_pref_tx_phys_mask = tx_phys, - connsm->phy_data.host_pref_rx_phys_mask = rx_phys; - - /* - * The host preferences override the default phy preferences. Currently, - * the only reason the controller will initiate a procedure on its own - * is due to the fact that the host set default preferences. So if there - * is a pending control procedure and it has not yet started, we do not - * need to perform the default controller procedure. - */ - if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE)) { - if (connsm->cur_ctrl_proc != BLE_LL_CTRL_PROC_PHY_UPDATE) { - CONN_F_CTRLR_PHY_UPDATE(connsm) = 0; - } - CONN_F_HOST_PHY_UPDATE(connsm) = 1; - } else { - /* - * We could be doing a peer-initiated PHY update procedure. If this - * is the case the requested phy preferences will not both be 0. If - * we are not done with a peer-initiated procedure we just set the - * pending bit but do not start the control procedure. - */ - if (CONN_F_PEER_PHY_UPDATE(connsm)) { - connsm->pending_ctrl_procs |= (1 << BLE_LL_CTRL_PROC_PHY_UPDATE); - CONN_F_HOST_PHY_UPDATE(connsm) = 1; - } else { - /* Check if we should start phy update procedure */ - if (!ble_ll_conn_chk_phy_upd_start(connsm)) { - CONN_F_HOST_PHY_UPDATE(connsm) = 1; - } else { - /* - * Set flag to send a PHY update complete event. We set flag - * even if we do not do an update procedure since we have to - * inform the host even if we decide not to change anything. - */ - CONN_F_PHY_UPDATE_EVENT(connsm) = 1; - } - } - } - -phy_cmd_param_err: - return rc; -} -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -int -ble_ll_set_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_periodic_adv_sync_transfer_params_cp *cmd = (const void *)cmdbuf; - struct ble_hci_le_periodic_adv_sync_transfer_params_rp *rsp = (void *) rspbuf; - struct ble_ll_conn_sm *connsm; - uint16_t sync_timeout; - uint16_t skip; - int rc; - - if (len != sizeof(*cmd)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - if (cmd->mode > 0x02) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - skip = le16toh(cmd->skip); - if (skip > 0x01f3) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - sync_timeout = le16toh(cmd->sync_timeout); - if ((sync_timeout < 0x000a) || (sync_timeout > 0x4000)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - /* we don't support any CTE yet */ - if (cmd->sync_cte_type) { - rc = BLE_ERR_UNSUPPORTED; - goto done; - } - - connsm = ble_ll_conn_find_active_conn(le16toh(cmd->conn_handle)); - if (!connsm) { - rc = BLE_ERR_UNK_CONN_ID; - goto done; - } - - /* timeout in 10ms units */ - connsm->sync_transfer_sync_timeout = sync_timeout * 10000; - connsm->sync_transfer_mode = cmd->mode; - connsm->sync_transfer_skip = skip; - - rc = BLE_ERR_SUCCESS; - -done: - rsp->conn_handle = cmd->conn_handle; - *rsplen = sizeof(*rsp); - return rc; -} - -int -ble_ll_set_default_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_default_periodic_sync_transfer_params_cp *cmd = (const void *)cmdbuf; - uint16_t sync_timeout; - uint16_t skip; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (cmd->mode > 0x02) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - skip = le16toh(cmd->skip); - if (skip > 0x01f3) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - sync_timeout = le16toh(cmd->sync_timeout); - if ((sync_timeout < 0x000a) || (sync_timeout > 0x4000)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* we don't support any CTE yet */ - if (cmd->sync_cte_type) { - return BLE_ERR_UNSUPPORTED; - } - - /* timeout in 10ms units */ - g_ble_ll_conn_sync_transfer_params.sync_timeout_us = sync_timeout * 10000; - g_ble_ll_conn_sync_transfer_params.mode = cmd->mode; - g_ble_ll_conn_sync_transfer_params.max_skip = skip; - - return BLE_ERR_SUCCESS; -} -#endif -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_priv.h deleted file mode 100644 index e4ade10f9..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_priv.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_CONN_PRIV_ -#define H_BLE_LL_CONN_PRIV_ - -#include "../include/controller/ble_ll_conn.h" -#include "../include/controller/ble_ll_hci.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Definitions for min/max RX/TX time/bytes values allowed for connections. - * Source: Core 5.0 specification, Vol 6, Part B, section 4.5.10 - */ -#define BLE_LL_CONN_SUPP_TIME_MIN (328) /* usecs */ -#define BLE_LL_CONN_SUPP_TIME_MAX (17040) /* usecs */ -#define BLE_LL_CONN_SUPP_TIME_MIN_UNCODED (328) /* usecs */ -#define BLE_LL_CONN_SUPP_TIME_MAX_UNCODED (2120) /* usecs */ -#define BLE_LL_CONN_SUPP_TIME_MIN_CODED (2704) /* usecs */ -#define BLE_LL_CONN_SUPP_TIME_MAX_CODED (17040) /* usecs */ -#define BLE_LL_CONN_SUPP_BYTES_MIN (27) /* bytes */ -#define BLE_LL_CONN_SUPP_BYTES_MAX (251) /* bytes */ - -/* Connection event timing */ -#define BLE_LL_CONN_INITIAL_OFFSET (1250) -#define BLE_LL_CONN_ITVL_USECS (1250) -#define BLE_LL_CONN_TX_WIN_USECS (1250) -#define BLE_LL_CONN_TX_OFF_USECS (1250) -#define BLE_LL_CONN_CE_USECS (625) -#define BLE_LL_CONN_TX_WIN_MIN (1) /* in tx win units */ -#define BLE_LL_CONN_SLAVE_LATENCY_MAX (499) - -/* Connection handle range */ -#define BLE_LL_CONN_MAX_CONN_HANDLE (0x0EFF) - -/* Offset (in bytes) of advertising address in connect request */ -#define BLE_LL_CONN_REQ_ADVA_OFF (BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN) - -/* Default authenticated payload timeout (30 seconds; in 10 msecs increments) */ -#define BLE_LL_CONN_DEF_AUTH_PYLD_TMO (3000) -#define BLE_LL_CONN_AUTH_PYLD_OS_TMO(x) ble_npl_time_ms_to_ticks32((x) * 10) - -/* Global Link Layer connection parameters */ -struct ble_ll_conn_global_params -{ - uint8_t master_chan_map[BLE_LL_CONN_CHMAP_LEN]; - uint8_t num_used_chans; - uint8_t supp_max_tx_octets; - uint8_t supp_max_rx_octets; - uint8_t conn_init_max_tx_octets; - uint8_t sugg_tx_octets; - uint16_t sugg_tx_time; - uint16_t conn_init_max_tx_time; - uint16_t conn_init_max_tx_time_uncoded; - uint16_t conn_init_max_tx_time_coded; - uint16_t supp_max_tx_time; - uint16_t supp_max_rx_time; -}; -extern struct ble_ll_conn_global_params g_ble_ll_conn_params; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -struct ble_ll_conn_sync_transfer_params -{ - uint32_t sync_timeout_us; - uint16_t max_skip; - uint8_t mode; -}; -extern struct ble_ll_conn_sync_transfer_params g_ble_ll_conn_sync_transfer_params; -#endif - -/* Some data structures used by other LL routines */ -SLIST_HEAD(ble_ll_conn_active_list, ble_ll_conn_sm); -STAILQ_HEAD(ble_ll_conn_free_list, ble_ll_conn_sm); -extern struct ble_ll_conn_active_list g_ble_ll_conn_active_list; -extern struct ble_ll_conn_free_list g_ble_ll_conn_free_list; - -/* Pointer to connection state machine we are trying to create */ -extern struct ble_ll_conn_sm *g_ble_ll_conn_create_sm; - -/* Generic interface */ -struct ble_ll_len_req; -struct ble_mbuf_hdr; -struct ble_ll_adv_sm; - -struct hci_create_conn -{ - uint16_t scan_itvl; - uint16_t scan_window; - uint8_t filter_policy; - uint8_t peer_addr_type; - uint8_t peer_addr[BLE_DEV_ADDR_LEN]; - uint8_t own_addr_type; - uint16_t conn_itvl_min; - uint16_t conn_itvl_max; - uint16_t conn_latency; - uint16_t supervision_timeout; - uint16_t min_ce_len; - uint16_t max_ce_len; -}; - -void ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm); -void ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err); -void ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om, - uint8_t hdr_byte, uint8_t length); -struct ble_ll_conn_sm *ble_ll_conn_sm_get(void); -void ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm, - struct hci_create_conn *hcc); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -void ble_ll_conn_ext_master_init(struct ble_ll_conn_sm *connsm, - struct hci_ext_create_conn *hcc); - -void ble_ll_conn_ext_set_params(struct ble_ll_conn_sm *connsm, - struct hci_ext_conn_params *hcc_params, - int phy); -#endif - -struct ble_ll_conn_sm *ble_ll_conn_find_active_conn(uint16_t handle); -void ble_ll_conn_update_eff_data_len(struct ble_ll_conn_sm *connsm); - -/* Advertising interface */ -int ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat, - struct ble_mbuf_hdr *rxhdr, bool force_csa2); - -/* Link Layer interface */ -void ble_ll_conn_module_init(void); -void ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, const uint8_t *chanmap); -void ble_ll_conn_module_reset(void); -void ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t len); -int ble_ll_conn_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa); -int ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr); -void ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr); -void ble_ll_init_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_mbuf_hdr *ble_hdr); -int ble_ll_init_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *ble_hdr); -int ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok, - struct ble_mbuf_hdr *ble_hdr); -void ble_ll_conn_wfr_timer_exp(void); -void ble_ll_conn_init_wfr_timer_exp(void); -int ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2); -uint32_t ble_ll_conn_get_ce_end_time(void); -void ble_ll_conn_event_halt(void); -void ble_ll_conn_reset_pending_aux_conn_rsp(void); -bool ble_ll_conn_init_pending_aux_conn_rsp(void); -/* HCI */ -void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, - uint8_t reason); -void ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm); -int ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_conn_hci_set_chan_class(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_conn_hci_param_rr(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_conn_hci_param_nrr(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb); -void ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm); -void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, - uint8_t *evbuf, struct ble_ll_adv_sm *advsm); -void ble_ll_conn_timeout(struct ble_ll_conn_sm *connsm, uint8_t ble_err); -int ble_ll_conn_hci_chk_conn_params(uint16_t itvl_min, uint16_t itvl_max, - uint16_t latency, uint16_t spvn_tmo); -int ble_ll_conn_hci_read_rem_features(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_conn_hci_rd_rssi(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, - uint8_t *rsplen); -int ble_ll_conn_hci_rd_chan_map(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_conn_hci_set_data_len(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_conn_hci_le_start_encrypt(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_conn_hci_le_ltk_reply(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_conn_hci_le_ltk_neg_reply(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_conn_hci_wr_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_conn_hci_rd_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) -void ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm); -#else -#define ble_ll_conn_auth_pyld_timer_start(x) -#endif - -int ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg); -int ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg); - -int ble_ll_conn_hci_le_rd_phy(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rsp, uint8_t *rsplen); -int ble_ll_conn_hci_le_set_phy(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_conn_chk_phy_upd_start(struct ble_ll_conn_sm *connsm); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -int ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t cmdlen); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -int ble_ll_set_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_set_default_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_LL_CONN_PRIV_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_ctrl.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_ctrl.c deleted file mode 100644 index 1d5ed929b..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_ctrl.c +++ /dev/null @@ -1,2747 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_ctrl.h" -#include "../include/controller/ble_ll_trace.h" -#include "../include/controller/ble_hw.h" -#include "../include/controller/ble_ll_sync.h" -#include "ble_ll_conn_priv.h" - -/* To use spec sample data for testing */ -#undef BLE_LL_ENCRYPT_USE_TEST_DATA - -/* - * For console debug to show session key calculation. NOTE: if you define - * this the stack requirements for the LL task go up considerably. The - * default stack will not be enough and must be increased. - */ -#undef BLE_LL_ENCRYPT_DEBUG -#ifdef BLE_LL_ENCRYPT_DEBUG -#include "console/console.h" -#endif - -/* - * XXX: - * 1) Do I need to keep track of which procedures have already been done? - * Do I need to worry about repeating procedures? - * 2) Should we create pool of control pdu's?. Dont need more - * than the # of connections and can probably deal with quite a few less - * if we have lots of connections. - * 3) What about procedures that have been completed but try to restart? - * 4) NOTE: there is a supported features procedure. However, in the case - * of data length extension, if the receiving device does not understand - * the pdu or it does not support data length extension, the LL_UNKNOWN_RSP - * pdu is sent. That needs to be processed... - * 5) We are supposed to remember when we do the data length update proc if - * the device sent us an unknown rsp. We should not send it another len req. - * Implement this how? Through remote supported features? - * 8) How to count control pdus sent. DO we count enqueued + sent, or only - * sent (actually attempted to tx). Do we count failures? How? - */ - -/* - * XXX: I definitely have an issue with control procedures and connection - * param request procedure and connection update procedure. This was - * noted when receiving an unknown response. Right now, I am getting confused - * with connection parameter request and updates regarding which procedures - * are running. So I need to go look through all the code and see where I - * used the request procedure and the update procedure and make sure I am doing - * the correct thing. - */ - -/* - * This array contains the length of the CtrData field in LL control PDU's. - * Note that there is a one byte opcode which precedes this field in the LL - * control PDU, so total data channel payload length for the control pdu is - * one greater. - */ -const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES] = -{ - BLE_LL_CTRL_CONN_UPD_REQ_LEN, - BLE_LL_CTRL_CHAN_MAP_LEN, - BLE_LL_CTRL_TERMINATE_IND_LEN, - BLE_LL_CTRL_ENC_REQ_LEN, - BLE_LL_CTRL_ENC_RSP_LEN, - BLE_LL_CTRL_START_ENC_REQ_LEN, - BLE_LL_CTRL_START_ENC_RSP_LEN, - BLE_LL_CTRL_UNK_RSP_LEN, - BLE_LL_CTRL_FEATURE_LEN, - BLE_LL_CTRL_FEATURE_LEN, - BLE_LL_CTRL_PAUSE_ENC_REQ_LEN, - BLE_LL_CTRL_PAUSE_ENC_RSP_LEN, - BLE_LL_CTRL_VERSION_IND_LEN, - BLE_LL_CTRL_REJ_IND_LEN, - BLE_LL_CTRL_SLAVE_FEATURE_REQ_LEN, - BLE_LL_CTRL_CONN_PARAMS_LEN, - BLE_LL_CTRL_CONN_PARAMS_LEN, - BLE_LL_CTRL_REJECT_IND_EXT_LEN, - BLE_LL_CTRL_PING_LEN, - BLE_LL_CTRL_PING_LEN, - BLE_LL_CTRL_LENGTH_REQ_LEN, - BLE_LL_CTRL_LENGTH_REQ_LEN, - BLE_LL_CTRL_PHY_REQ_LEN, - BLE_LL_CTRL_PHY_RSP_LEN, - BLE_LL_CTRL_PHY_UPD_IND_LEN, - BLE_LL_CTRL_MIN_USED_CHAN_LEN, - BLE_LL_CTRL_CTE_REQ_LEN, - BLE_LL_CTRL_CTE_RSP_LEN, - BLE_LL_CTRL_PERIODIC_SYNC_IND_LEN, - BLE_LL_CTRL_CLOCK_ACCURACY_REQ_LEN, - BLE_LL_CTRL_CLOCK_ACCURACY_RSP_LEN, -}; - -/** - * Called to determine if a LL control procedure with an instant has - * been initiated. - * - * If the function returns a 0 it means no conflicting procedure has - * been initiated. Otherwise it returns the appropriate BLE error code to - * send. - * - * @param connsm Pointer to connection state machine. - * @param req_ctrl_proc The procedure that the peer is trying to initiate - * - * @return uint8_t - */ -uint8_t -ble_ll_ctrl_proc_with_instant_initiated(struct ble_ll_conn_sm *connsm, - uint8_t req_ctrl_proc) -{ - uint8_t err; - - switch (connsm->cur_ctrl_proc) { - case BLE_LL_CTRL_PROC_PHY_UPDATE: - case BLE_LL_CTRL_PROC_CONN_UPDATE: - case BLE_LL_CTRL_PROC_CONN_PARAM_REQ: - case BLE_LL_CTRL_PROC_CHAN_MAP_UPD: - if (req_ctrl_proc == connsm->cur_ctrl_proc) { - err = BLE_ERR_LMP_COLLISION; - } else if ((connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_CONN_UPDATE) && - (req_ctrl_proc == BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) { - err = BLE_ERR_LMP_COLLISION; - } else { - err = BLE_ERR_DIFF_TRANS_COLL; - } - break; - default: - err = 0; - } - - return err; -} - -/** - * Create a LL_REJECT_EXT_IND pdu. - * - * @param rej_opcode Opcode to be rejected. - * @param err: error response - * @param ctrdata: Pointer to where CtrData starts in pdu - */ -void -ble_ll_ctrl_rej_ext_ind_make(uint8_t rej_opcode, uint8_t err, uint8_t *ctrdata) -{ - ctrdata[0] = rej_opcode; - ctrdata[1] = err; -} - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) -/** - * Called to cancel a phy update procedure. - * - * @param connsm - * @param ble_err - */ -void -ble_ll_ctrl_phy_update_cancel(struct ble_ll_conn_sm *connsm, uint8_t ble_err) -{ - /* cancel any pending phy update procedures */ - CLR_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); - - /* Check if the host wants an event */ - if (CONN_F_HOST_PHY_UPDATE(connsm)) { - ble_ll_hci_ev_phy_update(connsm, ble_err); - CONN_F_HOST_PHY_UPDATE(connsm) = 0; - } - - /* Clear any bits for phy updates that might be in progress */ - CONN_F_CTRLR_PHY_UPDATE(connsm) = 0; -} -#endif - -static int -ble_ll_ctrl_len_proc(struct ble_ll_conn_sm *connsm, uint8_t *dptr) -{ - int rc; - struct ble_ll_len_req ctrl_req; - - /* Extract parameters and check if valid */ - ctrl_req.max_rx_bytes = get_le16(dptr); - ctrl_req.max_rx_time = get_le16(dptr + 2); - ctrl_req.max_tx_bytes = get_le16(dptr + 4); - ctrl_req.max_tx_time = get_le16(dptr + 6); - - if ((ctrl_req.max_rx_bytes < BLE_LL_CONN_SUPP_BYTES_MIN) || - (ctrl_req.max_rx_time < BLE_LL_CONN_SUPP_TIME_MIN) || - (ctrl_req.max_tx_bytes < BLE_LL_CONN_SUPP_BYTES_MIN) || - (ctrl_req.max_tx_time < BLE_LL_CONN_SUPP_TIME_MIN)) { - rc = 1; - } else { - /* Update parameters */ - connsm->rem_max_rx_time = ctrl_req.max_rx_time; - connsm->rem_max_tx_time = ctrl_req.max_tx_time; - connsm->rem_max_rx_octets = ctrl_req.max_rx_bytes; - connsm->rem_max_tx_octets = ctrl_req.max_tx_bytes; - - /* Recalculate effective connection parameters */ - ble_ll_conn_update_eff_data_len(connsm); - rc = 0; - } - - return rc; -} - -/** - * Process a received LL_PING_RSP control pdu. - * - * NOTE: we dont have to reset the callout since this packet will have had a - * valid MIC and that will restart the authenticated payload timer - * - * @param connsm - */ -static void -ble_ll_ctrl_rx_ping_rsp(struct ble_ll_conn_sm *connsm) -{ - /* Stop the control procedure */ - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_LE_PING); -} - -/** - * Called when we receive either a connection parameter request or response. - * - * @param connsm - * @param dptr - * @param rspbuf - * @param opcode - * - * @return int - */ -static int -ble_ll_ctrl_conn_param_pdu_proc(struct ble_ll_conn_sm *connsm, uint8_t *dptr, - uint8_t *rspbuf, uint8_t opcode) -{ - int rc; - int indicate; - uint8_t rsp_opcode; - uint8_t ble_err; - struct ble_ll_conn_params *req; - struct hci_conn_update *hcu; - - /* Extract parameters and check if valid */ - req = &connsm->conn_cp; - req->interval_min = get_le16(dptr); - req->interval_max = get_le16(dptr + 2); - req->latency = get_le16(dptr + 4); - req->timeout = get_le16(dptr + 6); - req->pref_periodicity = dptr[8]; - req->ref_conn_event_cnt = get_le16(dptr + 9); - req->offset0 = get_le16(dptr + 11); - req->offset1 = get_le16(dptr + 13); - req->offset2 = get_le16(dptr + 15); - req->offset3 = get_le16(dptr + 17); - req->offset4 = get_le16(dptr + 19); - req->offset5 = get_le16(dptr + 21); - - /* Check if parameters are valid */ - ble_err = BLE_ERR_SUCCESS; - rc = ble_ll_conn_hci_chk_conn_params(req->interval_min, - req->interval_max, - req->latency, - req->timeout); - if (rc) { - ble_err = BLE_ERR_INV_LMP_LL_PARM; - goto conn_param_pdu_exit; - } - - /* - * Check if there is a requested change to either the interval, timeout - * or latency. If not, this may just be an anchor point change and we do - * not have to notify the host. - * XXX: what if we dont like the parameters? When do we check that out? - */ - indicate = 1; - if (opcode == BLE_LL_CTRL_CONN_PARM_REQ) { - if ((connsm->conn_itvl >= req->interval_min) && - (connsm->conn_itvl <= req->interval_max) && - (connsm->supervision_tmo == req->timeout) && - (connsm->slave_latency == req->latency)) { - indicate = 0; - goto conn_parm_req_do_indicate; - } - } - - /* - * A change has been requested. Is it within the values specified by - * the host? Note that for a master we will not be processing a - * connect param request from a slave if we are currently trying to - * update the connection parameters. This means that the previous - * check is all we need for a master (when receiving a request). - */ - if ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) || - (opcode == BLE_LL_CTRL_CONN_PARM_RSP)) { - /* - * Not sure what to do about the slave. It is possible that the - * current connection parameters are not the same ones as the local host - * has provided? Not sure what to do here. Do we need to remember what - * host sent us? For now, I will assume that we need to remember what - * the host sent us and check it out. - */ - hcu = &connsm->conn_param_req; - if (hcu->handle != 0) { - if (!((req->interval_min < hcu->conn_itvl_min) || - (req->interval_min > hcu->conn_itvl_max) || - (req->interval_max < hcu->conn_itvl_min) || - (req->interval_max > hcu->conn_itvl_max) || - (req->latency != hcu->conn_latency) || - (req->timeout != hcu->supervision_timeout))) { - indicate = 0; - } - } - } - -conn_parm_req_do_indicate: - /* - * XXX: are the connection update parameters acceptable? If not, we will - * need to know before we indicate to the host that they are acceptable. - */ - if (indicate) { - /* If Host masked out Remote Connection Parameter Request Event, we need to - * send Reject back to the remote device - */ - if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ)){ - ble_err = BLE_ERR_UNSUPP_REM_FEATURE; - goto conn_param_pdu_exit; - } - - /* - * Send event to host. At this point we leave and wait to get - * an answer. - */ - ble_ll_hci_ev_rem_conn_parm_req(connsm, req); - connsm->host_reply_opcode = opcode; - connsm->csmflags.cfbit.awaiting_host_reply = 1; - rsp_opcode = 255; - } else { - /* Create reply to connection request */ - rsp_opcode = ble_ll_ctrl_conn_param_reply(connsm, rspbuf, req); - } - -conn_param_pdu_exit: - if (ble_err) { - rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; - rspbuf[1] = opcode; - rspbuf[2] = ble_err; - } - return rsp_opcode; -} - -/** - * Called to make a connection update request LL control PDU - * - * Context: Link Layer - * - * @param connsm - * @param rsp - */ -static void -ble_ll_ctrl_conn_upd_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld, - struct ble_ll_conn_params *cp) -{ - uint16_t instant; - uint32_t dt; - uint32_t num_old_ce; - uint32_t new_itvl_usecs; - uint32_t old_itvl_usecs; - struct hci_conn_update *hcu; - struct ble_ll_conn_upd_req *req; - - /* - * Set instant. We set the instant to the current event counter plus - * the amount of slave latency as the slave may not be listening - * at every connection interval and we are not sure when the connect - * request will actually get sent. We add one more event plus the - * minimum as per the spec of 6 connection events. - */ - instant = connsm->event_cntr + connsm->slave_latency + 6 + 1; - - /* - * XXX: This should change in the future, but for now we will just - * start the new instant at the same anchor using win offset 0. - */ - /* Copy parameters in connection update structure */ - hcu = &connsm->conn_param_req; - req = &connsm->conn_update_req; - if (cp) { - /* XXX: so we need to make the new anchor point some time away - * from txwinoffset by some amount of msecs. Not sure how to do - that here. We dont need to, but we should. */ - /* Calculate offset from requested offsets (if any) */ - if (cp->offset0 != 0xFFFF) { - new_itvl_usecs = cp->interval_max * BLE_LL_CONN_ITVL_USECS; - old_itvl_usecs = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS; - if ((int16_t)(cp->ref_conn_event_cnt - instant) >= 0) { - num_old_ce = cp->ref_conn_event_cnt - instant; - dt = old_itvl_usecs * num_old_ce; - dt += (cp->offset0 * BLE_LL_CONN_ITVL_USECS); - dt = dt % new_itvl_usecs; - } else { - num_old_ce = instant - cp->ref_conn_event_cnt; - dt = old_itvl_usecs * num_old_ce; - dt -= (cp->offset0 * BLE_LL_CONN_ITVL_USECS); - dt = dt % new_itvl_usecs; - dt = new_itvl_usecs - dt; - } - req->winoffset = dt / BLE_LL_CONN_TX_WIN_USECS; - } else { - req->winoffset = 0; - } - req->interval = cp->interval_max; - req->timeout = cp->timeout; - req->latency = cp->latency; - req->winsize = 1; - } else { - req->interval = hcu->conn_itvl_max; - req->timeout = hcu->supervision_timeout; - req->latency = hcu->conn_latency; - req->winoffset = 0; - req->winsize = connsm->tx_win_size; - } - req->instant = instant; - - /* XXX: make sure this works for the connection parameter request proc. */ - pyld[0] = req->winsize; - put_le16(pyld + 1, req->winoffset); - put_le16(pyld + 3, req->interval); - put_le16(pyld + 5, req->latency); - put_le16(pyld + 7, req->timeout); - put_le16(pyld + 9, instant); - - /* Set flag in state machine to denote we have scheduled an update */ - connsm->csmflags.cfbit.conn_update_sched = 1; -} - -/** - * Called to process and UNKNOWN_RSP LL control packet. - * - * Context: Link Layer Task - * - * @param dptr - */ -static int -ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t *rspdata) -{ - uint8_t ctrl_proc; - uint8_t opcode; - - /* Get opcode of unknown LL control frame */ - opcode = dptr[0]; - - /* Convert opcode to control procedure id */ - switch (opcode) { - case BLE_LL_CTRL_LENGTH_REQ: - ctrl_proc = BLE_LL_CTRL_PROC_DATA_LEN_UPD; - BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_DATA_LEN_EXT); - break; - case BLE_LL_CTRL_CONN_UPDATE_IND: - ctrl_proc = BLE_LL_CTRL_PROC_CONN_UPDATE; - break; - case BLE_LL_CTRL_SLAVE_FEATURE_REQ: - ctrl_proc = BLE_LL_CTRL_PROC_FEATURE_XCHG; - BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_SLAVE_INIT); - break; - case BLE_LL_CTRL_CONN_PARM_REQ: - BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_CONN_PARM_REQ); - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - ble_ll_ctrl_conn_upd_make(connsm, rspdata, NULL); - connsm->reject_reason = BLE_ERR_SUCCESS; - return BLE_LL_CTRL_CONN_UPDATE_IND; - } - /* note: fall-through intentional */ - case BLE_LL_CTRL_CONN_PARM_RSP: - ctrl_proc = BLE_LL_CTRL_PROC_CONN_PARAM_REQ; - break; - case BLE_LL_CTRL_PING_REQ: - /* LL can authenticate remote device even if remote device does not - * support LE Ping feature. - */ - ctrl_proc = BLE_LL_CTRL_PROC_LE_PING; - BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_LE_PING); - break; -#if (BLE_LL_BT5_PHY_SUPPORTED ==1) - case BLE_LL_CTRL_PHY_REQ: - ble_ll_ctrl_phy_update_cancel(connsm, BLE_ERR_UNSUPP_REM_FEATURE); - ctrl_proc = BLE_LL_CTRL_PROC_PHY_UPDATE; - break; -#endif - default: - ctrl_proc = BLE_LL_CTRL_PROC_NUM; - break; - } - - /* If we are running this one currently, stop it */ - if (connsm->cur_ctrl_proc == ctrl_proc) { - /* Stop the control procedure */ - ble_ll_ctrl_proc_stop(connsm, ctrl_proc); - if (ctrl_proc == BLE_LL_CTRL_PROC_CONN_PARAM_REQ) { - ble_ll_hci_ev_conn_update(connsm, BLE_ERR_UNSUPP_REM_FEATURE); - } else if (ctrl_proc == BLE_LL_CTRL_PROC_FEATURE_XCHG) { - if (connsm->csmflags.cfbit.pending_hci_rd_features) { - ble_ll_hci_ev_rd_rem_used_feat(connsm, - BLE_ERR_UNSUPP_REM_FEATURE); - } - connsm->csmflags.cfbit.pending_hci_rd_features = 0; - } - } - - return BLE_ERR_MAX; -} - -/** - * Callback when LL control procedure times out (for a given connection). If - * this is called, it means that we need to end the connection because it - * has not responded to a LL control request. - * - * Context: Link Layer - * - * @param arg Pointer to connection state machine. - */ -static void -ble_ll_ctrl_proc_rsp_timer_cb(struct ble_npl_event *ev) -{ - /* Control procedure has timed out. Kill the connection */ - ble_ll_conn_timeout((struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev), - BLE_ERR_LMP_LL_RSP_TMO); -} - -static void -ble_ll_ctrl_start_rsp_timer(struct ble_ll_conn_sm *connsm) -{ - ble_npl_callout_init(&connsm->ctrl_proc_rsp_timer, - &g_ble_ll_data.ll_evq, - ble_ll_ctrl_proc_rsp_timer_cb, - connsm); - - /* Re-start timer. Control procedure timeout is 40 seconds */ - ble_npl_callout_reset(&connsm->ctrl_proc_rsp_timer, - ble_npl_time_ms_to_ticks32(BLE_LL_CTRL_PROC_TIMEOUT_MS)); -} - -/** - * Convert a phy mask to a numeric phy value. - * - * NOTE: only one bit should be set here and there should be at least one. - * If this function returns a 0 it is an error! - * - * @param phy_mask Bitmask of phy - * - * @return uint8_t The numeric value associated with the phy mask - * - * BLE_HCI_LE_PHY_1M (1) - * BLE_HCI_LE_PHY_2M (2) - * BLE_HCI_LE_PHY_CODED (3) - */ -uint8_t -ble_ll_ctrl_phy_from_phy_mask(uint8_t phy_mask) -{ - uint8_t phy; - - /* - * NOTE: wipe out unsupported PHYs. There should not be an unsupported - * in this mask if the other side is working correctly. - */ -#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - phy_mask &= ~BLE_HCI_LE_PHY_2M_PREF_MASK; -#endif -#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - phy_mask &= ~BLE_HCI_LE_PHY_CODED_PREF_MASK; -#endif - - if (phy_mask & BLE_PHY_MASK_1M) { - phy = BLE_PHY_1M; - phy_mask &= ~BLE_PHY_MASK_1M; - } else if (phy_mask & BLE_PHY_MASK_2M) { - phy = BLE_PHY_2M; - phy_mask &= ~BLE_PHY_MASK_2M; - } else if (phy_mask & BLE_PHY_MASK_CODED) { - phy = BLE_PHY_CODED; - phy_mask &= ~BLE_PHY_MASK_CODED; - } else { - phy = 0; - } - - if (phy_mask != 0) { - phy = 0; - } - - return phy; -} - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) -uint8_t -ble_ll_ctrl_phy_tx_transition_get(uint8_t phy_mask) -{ - /* - * Evaluate PHYs in transition starting from the one with longest TX time - * so we select the one that allows shortest payload to be sent. This is - * to make sure we do not violate timing restriction on new PHY. - */ - if (phy_mask & BLE_PHY_MASK_CODED) { - return BLE_PHY_CODED; - } else if (phy_mask & BLE_PHY_MASK_1M) { - return BLE_PHY_1M; - } else if (phy_mask & BLE_PHY_MASK_2M) { - return BLE_PHY_2M; - } - - return 0; -} - -void -ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm) -{ - int chk_proc_stop; - int chk_host_phy; - - chk_proc_stop = 1; - chk_host_phy = 1; - - connsm->phy_tx_transition = 0; - - if (CONN_F_PEER_PHY_UPDATE(connsm)) { - CONN_F_PEER_PHY_UPDATE(connsm) = 0; - } else if (CONN_F_CTRLR_PHY_UPDATE(connsm)) { - CONN_F_CTRLR_PHY_UPDATE(connsm) = 0; - } else { - /* Must be a host-initiated update */ - CONN_F_HOST_PHY_UPDATE(connsm) = 0; - chk_host_phy = 0; - if (CONN_F_PHY_UPDATE_EVENT(connsm) == 0) { - ble_ll_hci_ev_phy_update(connsm, BLE_ERR_SUCCESS); - } - } - - /* Must check if we need to start host procedure */ - if (chk_host_phy) { - if (CONN_F_HOST_PHY_UPDATE(connsm)) { - if (ble_ll_conn_chk_phy_upd_start(connsm)) { - CONN_F_HOST_PHY_UPDATE(connsm) = 0; - } else { - chk_proc_stop = 0; - } - } - } - - if (chk_proc_stop) { - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); - } -} - -/** - * - * There is probably a better way for the controller to choose which PHY use. - * There are no BER metrics and RSSI does not give you S/N so for now we will - * choose this heirarchy: - * -> if 2Mbps available, use it. - * -> If 1Mbps available, use it. - * -> otherwise use coded phy. - * - * @param prefs The mask of preferred phys - * @return uint8_t The phy to use (not a mask) - */ -static uint8_t -ble_ll_ctrl_find_new_phy(uint8_t phy_mask_prefs) -{ - uint8_t new_phy; - - new_phy = phy_mask_prefs; - if (new_phy) { - if (new_phy & BLE_PHY_MASK_2M) { - new_phy = BLE_PHY_2M; - } else if (new_phy & BLE_PHY_MASK_1M) { - new_phy = BLE_PHY_1M; - } else { - new_phy = BLE_PHY_CODED; - } - } - - return new_phy; -} - -/** - * Create a LL_PHY_UPDATE_IND pdu - * - * @param connsm Pointer to connection state machine - * @param dptr Pointer to PHY_REQ or PHY_RSP data. - * @param ctrdata: Pointer to where CtrData of UPDATE_IND pdu starts - * @param slave_req flag denoting if slave requested this. 0: no 1:yes - */ -static void -ble_ll_ctrl_phy_update_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr, - uint8_t *ctrdata, int slave_req) -{ - uint8_t m_to_s; - uint8_t s_to_m; - uint8_t tx_phys; - uint8_t rx_phys; - uint16_t instant; - uint8_t is_slave_sym = 0; - - /* Get preferences from PDU */ - tx_phys = dptr[0]; - rx_phys = dptr[1]; - - /* If we are master, check if slave requested symmetric PHY */ - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - is_slave_sym = tx_phys == rx_phys; - is_slave_sym &= __builtin_popcount(tx_phys) == 1; - } - - /* Get m_to_s and s_to_m masks */ - if (slave_req) { - m_to_s = connsm->phy_data.host_pref_tx_phys_mask & rx_phys; - s_to_m = connsm->phy_data.host_pref_rx_phys_mask & tx_phys; - } else { - m_to_s = connsm->phy_data.req_pref_tx_phys_mask & rx_phys; - s_to_m = connsm->phy_data.req_pref_rx_phys_mask & tx_phys; - } - - if (is_slave_sym) { - /* - * If either s_to_m or m_to_s is 0, it means for at least one direction - * requested PHY is not our preferred one so make sure we keep current - * PHY in both directions - * - * Core 5.2, Vol 6, PartB, 5.1.10 - * If the slave specified a single PHY in both the TX_PHYS and - * RX_PHYS fields and both fields are the same, the master shall - * either select the PHY specified by the slave for both directions - * or shall leave both directions unchanged. - */ - if ((s_to_m == 0) || (m_to_s == 0)) { - s_to_m = 0; - m_to_s = 0; - } else { - BLE_LL_ASSERT(s_to_m == m_to_s); - } - } - - /* Calculate new PHYs to use */ - m_to_s = ble_ll_ctrl_find_new_phy(m_to_s); - s_to_m = ble_ll_ctrl_find_new_phy(s_to_m); - - /* Make sure we do not indicate PHY change if the same as current one */ - if (m_to_s == connsm->phy_data.cur_tx_phy) { - m_to_s = 0; - } - if (s_to_m == connsm->phy_data.cur_rx_phy) { - s_to_m = 0; - } - - /* At this point, m_to_s and s_to_m are not masks; they are numeric */ - - /* - * If not changing we still send update ind. Check if hosts expects - * the event and if so send it. Stop control procedure if it is the - * one running. - */ - if ((m_to_s == 0) && (s_to_m == 0)) { - if (CONN_F_PEER_PHY_UPDATE(connsm)) { - CONN_F_PEER_PHY_UPDATE(connsm) = 0; - } else if (CONN_F_CTRLR_PHY_UPDATE(connsm)) { - CONN_F_CTRLR_PHY_UPDATE(connsm) = 0; - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); - } else { - ble_ll_hci_ev_phy_update(connsm, BLE_ERR_SUCCESS); - CONN_F_HOST_PHY_UPDATE(connsm) = 0; - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); - } - instant = 0; - } else { - /* Determine instant we will use. 6 more is minimum */ - instant = connsm->event_cntr + connsm->slave_latency + 6 + 1; - connsm->phy_instant = instant; - CONN_F_PHY_UPDATE_SCHED(connsm) = 1; - - /* Set new phys to use when instant occurs */ - connsm->phy_data.new_tx_phy = m_to_s; - connsm->phy_data.new_rx_phy = s_to_m; - - /* Convert m_to_s and s_to_m to masks */ - if (m_to_s) { - m_to_s = 1 << (m_to_s - 1); - } - - if (s_to_m) { - s_to_m = 1 << (s_to_m - 1); - } - } - - ctrdata[0] = m_to_s; - ctrdata[1] = s_to_m; - put_le16(ctrdata + 2, instant); -} - -/** - * Create a LL_PHY_REQ or LL_PHY_RSP pdu - * - * @param connsm Pointer to connection state machine - * @param ctrdata: Pointer to where CtrData starts in pdu - */ -static void -ble_ll_ctrl_phy_req_rsp_make(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata) -{ - /* If no preference we use current phy */ - if (connsm->phy_data.host_pref_tx_phys_mask == 0) { - ctrdata[0] = CONN_CUR_TX_PHY_MASK(connsm); - } else { - ctrdata[0] = connsm->phy_data.host_pref_tx_phys_mask; - } - if (connsm->phy_data.host_pref_rx_phys_mask == 0) { - ctrdata[1] = CONN_CUR_RX_PHY_MASK(connsm); - } else { - ctrdata[1] = connsm->phy_data.host_pref_rx_phys_mask; - } -} - -static uint8_t -ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req, - uint8_t *rsp) -{ - uint8_t rsp_opcode; - uint8_t err; - - /* - * XXX: TODO if we have an instant in progress we should end connection. - * At least it seems that is the case. Need to figure out more from - * the spec here. - */ - - /* Check if we have already initiated a procedure with an instant */ - err = ble_ll_ctrl_proc_with_instant_initiated(connsm, - BLE_LL_CTRL_PROC_PHY_UPDATE); - - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - if (err) { - ble_ll_ctrl_rej_ext_ind_make(BLE_LL_CTRL_PHY_REQ, err, rsp); - rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; - } else { - /* - * NOTE: do not change order of these two lines as the call to - * make the LL_PHY_UPDATE_IND pdu might clear the flag. - */ - CONN_F_PEER_PHY_UPDATE(connsm) = 1; - ble_ll_ctrl_phy_update_ind_make(connsm, req, rsp, 1); - rsp_opcode = BLE_LL_CTRL_PHY_UPDATE_IND; - } - } else { - /* XXX: deal with other control procedures that we need to stop */ - if (err) { - if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) { - ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer); - connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE; - } - - /* If there is a PHY update procedure pending cancel it */ - ble_ll_ctrl_phy_update_cancel(connsm, err); - - /* XXX: ? Should not be any phy update events */ - CONN_F_PHY_UPDATE_EVENT(connsm) = 0; - } - - /* XXX: TODO: if we started another procedure with an instant - * why are we doing this? Need to look into this.*/ - - /* Respond to master's phy update procedure */ - CONN_F_PEER_PHY_UPDATE(connsm) = 1; - ble_ll_ctrl_phy_req_rsp_make(connsm, rsp); - rsp_opcode = BLE_LL_CTRL_PHY_RSP; - - connsm->phy_tx_transition = ble_ll_ctrl_phy_tx_transition_get(req[1] | rsp[0]); - - /* Start response timer */ - connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_PHY_UPDATE; - ble_ll_ctrl_start_rsp_timer(connsm); - } - return rsp_opcode; -} - -/** - * Process a received LL_PHY_RSP pdu - * - * @param connsm - * @param dptr Pointer to LL_PHY_RSP ctrdata - * @param rsp Pointer to CtrData of PHY_UPDATE_IND. - * - * @return uint8_t - */ -static uint8_t -ble_ll_ctrl_rx_phy_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, - uint8_t *rsp) -{ - uint8_t rsp_opcode; - - rsp_opcode = BLE_ERR_MAX; - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) { - ble_ll_ctrl_phy_update_ind_make(connsm, dptr, rsp, 0); - ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer); - rsp_opcode = BLE_LL_CTRL_PHY_UPDATE_IND; - } - - /* - * If not in the process of doing this control procedure something - * is wrong. End connection? Assert? - * - * XXX: TODO count some stat? - */ - } else { - rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP; - } - - /* NOTE: slave should never receive one of these */ - - return rsp_opcode; -} - -/** - * Called when a LL_PHY_UPDATE_IND pdu is received - * - * NOTE: slave is the only device that should receive this. - * - * @param connsm - * @param dptr - * - * @return uint8_t - */ -static uint8_t -ble_ll_ctrl_rx_phy_update_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr) -{ - int no_change; - uint8_t new_m_to_s_mask; - uint8_t new_s_to_m_mask; - uint8_t new_tx_phy; - uint8_t new_rx_phy; - uint16_t instant; - uint16_t delta; - - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - return BLE_LL_CTRL_UNKNOWN_RSP; - } - - /* - * Reception stops the procedure response timer but does not - * complete the procedure - */ - if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) { - ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer); - } - - /* - * XXX: Should we check to see if we are expecting to receive one - * of these, and if not, kill connection? Meaning we better be - * doing either a PEER, CTRLR, or HOST phy update. - */ - /* get the new phy masks and see if we need to change */ - new_m_to_s_mask = dptr[0]; - new_s_to_m_mask = dptr[1]; - instant = get_le16(dptr + 2); - - if ((new_m_to_s_mask == 0) && (new_s_to_m_mask == 0)) { - /* No change in phy */ - no_change = 1; - } else { - no_change = 0; - /* - * NOTE: from the slaves perspective, the m to s phy is the one - * that the slave will receive on; s to m is the one it will - * transmit on - */ - new_rx_phy = ble_ll_ctrl_phy_from_phy_mask(new_m_to_s_mask); - new_tx_phy = ble_ll_ctrl_phy_from_phy_mask(new_s_to_m_mask); - - if ((new_tx_phy == 0) && (new_rx_phy == 0)) { - /* XXX: this is an error! What to do??? */ - no_change = 1; - } - - if ((new_tx_phy == connsm->phy_data.cur_tx_phy) && - (new_rx_phy == connsm->phy_data.cur_rx_phy)) { - no_change = 1; - } - } - - if (!no_change) { - /* If instant is in the past, we have to end the connection */ - delta = (instant - connsm->event_cntr) & 0xFFFF; - if (delta >= 32767) { - ble_ll_conn_timeout(connsm, BLE_ERR_INSTANT_PASSED); - } else { - connsm->phy_data.new_tx_phy = new_tx_phy; - connsm->phy_data.new_rx_phy = new_rx_phy; - connsm->phy_instant = instant; - CONN_F_PHY_UPDATE_SCHED(connsm) = 1; - } - return BLE_ERR_MAX; - } - - ble_ll_ctrl_phy_update_proc_complete(connsm); - - return BLE_ERR_MAX; -} -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -/** - * Called when a BLE_LL_CTRL_PERIODIC_SYNC_IND PDU is received - * - * @param connsm - * @param dptr - * - * @return uint8_t - */ -static uint8_t -ble_ll_ctrl_rx_periodic_sync_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr) -{ - if (connsm->sync_transfer_mode) { - ble_ll_sync_periodic_ind(connsm, dptr, connsm->sync_transfer_mode == 1, - connsm->sync_transfer_skip, - connsm->sync_transfer_sync_timeout); - } - - return BLE_ERR_MAX; -} -#endif - -/** - * Create a link layer length request or length response PDU. - * - * NOTE: this function does not set the LL data pdu header nor does it - * set the opcode in the buffer. - * - * @param connsm - * @param dptr: Pointer to where control pdu payload starts - */ -static void -ble_ll_ctrl_datalen_upd_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr) -{ - put_le16(dptr + 1, connsm->max_rx_octets); - put_le16(dptr + 3, connsm->max_rx_time); - put_le16(dptr + 5, connsm->max_tx_octets); - put_le16(dptr + 7, connsm->max_tx_time); -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -void -ble_ll_calc_session_key(struct ble_ll_conn_sm *connsm) -{ -#ifdef BLE_LL_ENCRYPT_DEBUG - int cnt; -#endif - - /* XXX: possibly have some way out of this if this locks up */ - while (1) { - if (!ble_hw_encrypt_block(&connsm->enc_data.enc_block)) { - break; - } - } - -#ifdef BLE_LL_ENCRYPT_DEBUG - console_printf("Calculating Session Key for handle=%u", - connsm->conn_handle); - - console_printf("\nLTK:"); - for (cnt = 0; cnt < 16; ++cnt) { - console_printf("%02x", connsm->enc_data.enc_block.key[cnt]); - } - console_printf("\nSKD:"); - for (cnt = 0; cnt < 16; ++cnt) { - console_printf("%02x", connsm->enc_data.enc_block.plain_text[cnt]); - } - console_printf("\nSession Key:"); - for (cnt = 0; cnt < 16; ++cnt) { - console_printf("%02x", connsm->enc_data.enc_block.cipher_text[cnt]); - } - console_printf("\nIV:"); - for (cnt = 0; cnt < 8; ++ cnt) { - console_printf("%02x", connsm->enc_data.iv[cnt]); - } - console_printf("\n"); -#endif -} - -/** - * Called to determine if this is a control PDU we are allowed to send. This - * is called when a link is being encrypted, as only certain control PDU's - * area lowed to be sent. - * - * XXX: the current code may actually allow some control pdu's to be sent - * in states where they shouldnt. I dont expect those states to occur so I - * dont try to check for them but we could do more... for example there are - * different PDUs allowed for master/slave and TX/RX - * - * @param llid - * @param opcode - * @param len - * - * @return int - */ -static int -ble_ll_ctrl_enc_allowed_pdu(uint8_t llid, uint8_t len, uint8_t opcode) -{ - int allowed; - - allowed = 0; - - switch (llid) { - case BLE_LL_LLID_CTRL: - switch (opcode) { - case BLE_LL_CTRL_REJECT_IND: - case BLE_LL_CTRL_REJECT_IND_EXT: - case BLE_LL_CTRL_START_ENC_RSP: - case BLE_LL_CTRL_START_ENC_REQ: - case BLE_LL_CTRL_ENC_REQ: - case BLE_LL_CTRL_ENC_RSP: - case BLE_LL_CTRL_PAUSE_ENC_REQ: - case BLE_LL_CTRL_PAUSE_ENC_RSP: - case BLE_LL_CTRL_TERMINATE_IND: - allowed = 1; - break; - } - break; - case BLE_LL_LLID_DATA_FRAG: - if (len == 0) { - /* Empty PDUs are allowed */ - allowed = 1; - } - break; - } - - return allowed; -} - -int -ble_ll_ctrl_enc_allowed_pdu_rx(struct os_mbuf *rxpdu) -{ - uint8_t llid; - uint8_t len; - uint8_t opcode; - - llid = rxpdu->om_data[0] & BLE_LL_DATA_HDR_LLID_MASK; - len = rxpdu->om_data[1]; - if (llid == BLE_LL_LLID_CTRL) { - opcode = rxpdu->om_data[2]; - } else { - opcode = 0; - } - - return ble_ll_ctrl_enc_allowed_pdu(llid, len, opcode); -} - -int -ble_ll_ctrl_enc_allowed_pdu_tx(struct os_mbuf_pkthdr *pkthdr) -{ - struct os_mbuf *m; - struct ble_mbuf_hdr *ble_hdr; - uint8_t llid; - uint8_t len; - uint8_t opcode; - - m = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); - ble_hdr = BLE_MBUF_HDR_PTR(m); - - llid = ble_hdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; - len = ble_hdr->txinfo.pyld_len; - if (llid == BLE_LL_LLID_CTRL) { - opcode = m->om_data[0]; - } else { - opcode = 0; - } - - return ble_ll_ctrl_enc_allowed_pdu(llid, len, opcode); -} - -int -ble_ll_ctrl_is_start_enc_rsp(struct os_mbuf *txpdu) -{ - int is_start_enc_rsp; - uint8_t opcode; - uint8_t llid; - struct ble_mbuf_hdr *ble_hdr; - - is_start_enc_rsp = 0; - ble_hdr = BLE_MBUF_HDR_PTR(txpdu); - - llid = ble_hdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; - if (llid == BLE_LL_LLID_CTRL) { - opcode = txpdu->om_data[0]; - if (opcode == BLE_LL_CTRL_START_ENC_RSP) { - is_start_enc_rsp = 1; - } - } - - return is_start_enc_rsp; -} - -/** - * Called to create and send a LL_START_ENC_REQ - * - * @param connsm - * @param err - * - * @return int - */ -int -ble_ll_ctrl_start_enc_send(struct ble_ll_conn_sm *connsm) -{ - int rc; - struct os_mbuf *om; - - om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN, - sizeof(struct ble_mbuf_hdr)); - if (om) { - om->om_data[0] = BLE_LL_CTRL_START_ENC_REQ; - ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, 1); - - /* Wait for LL_START_ENC_RSP. If there is already procedure in progress, - * LL response timer is already running. - */ - if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_IDLE) { - connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_ENCRYPT; - ble_ll_ctrl_start_rsp_timer(connsm); - } - - rc = 0; - } else { - rc = -1; - } - return rc; -} - -/** - * Create a link layer control "encrypt request" PDU. - * - * The LL_ENC_REQ PDU format is: - * Rand (8) - * EDIV (2) - * SKDm (8) - * IVm (4) - * - * The random number and encrypted diversifier come from the host command. - * Controller generates master portion of SDK and IV. - * - * NOTE: this function does not set the LL data pdu header nor does it - * set the opcode in the buffer. - * - * @param connsm - * @param dptr: Pointer to where control pdu payload starts - */ -static void -ble_ll_ctrl_enc_req_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr) -{ - put_le64(dptr, connsm->enc_data.host_rand_num); - put_le16(dptr + 8, connsm->enc_data.enc_div); - -#ifdef BLE_LL_ENCRYPT_USE_TEST_DATA - /* IV stored LSB to MSB, IVm is LSB, IVs is MSB */ - put_le64(dptr + 10, g_bletest_SKDm); - swap_buf(connsm->enc_data.enc_block.plain_text + 8, dptr + 10, 8); - put_le32(dptr + 18, g_bletest_IVm); - memcpy(connsm->enc_data.iv, dptr + 18, 4); - return; -#endif - - ble_ll_rand_data_get(connsm->enc_data.enc_block.plain_text + 8, 8); - swap_buf(dptr + 10, connsm->enc_data.enc_block.plain_text + 8, 8); - ble_ll_rand_data_get(connsm->enc_data.iv, 4); - memcpy(dptr + 18, connsm->enc_data.iv, 4); -} - -/** - * Called when LL_ENC_RSP is received by the master. - * - * Context: Link Layer Task. - * - * Format of the LL_ENC_RSP is: - * SKDs (8) - * IVs (4) - * - * The master now has the long term key (from the start encrypt command) - * and the SKD (stored in the plain text encryption block). From this the - * sessionKey is generated. - * - * @param connsm - * @param dptr - */ -static void -ble_ll_ctrl_rx_enc_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr) -{ - /* Calculate session key now that we have received the ENC_RSP */ - if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_ENCRYPT) { - /* In case we were already encrypted we need to reset packet counters */ - connsm->enc_data.rx_pkt_cntr = 0; - connsm->enc_data.tx_pkt_cntr = 0; - connsm->enc_data.tx_encrypted = 0; - - swap_buf(connsm->enc_data.enc_block.plain_text, dptr, 8); - memcpy(connsm->enc_data.iv + 4, dptr + 8, 4); - ble_ll_calc_session_key(connsm); - connsm->enc_data.enc_state = CONN_ENC_S_START_ENC_REQ_WAIT; - } -} - -/** - * Called when we have received a LL control encryption request PDU. This - * should only be received by a slave. - * - * The LL_ENC_REQ PDU format is: - * Rand (8) - * EDIV (2) - * SKDm (8) - * IVm (4) - * - * This function returns the response opcode. Typically this will be ENC_RSP - * but it could be a reject ind. Note that the caller of this function - * will send the REJECT_IND_EXT if supported by remote. - * - * NOTE: if this is received by a master we will silently discard the PDU - * (denoted by return BLE_ERR_MAX). - * - * @param connsm - * @param dptr Pointer to start of encrypt request data. - * @param rspbuf - */ -static uint8_t -ble_ll_ctrl_rx_enc_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, - uint8_t *rspdata) -{ - if (connsm->conn_role != BLE_LL_CONN_ROLE_SLAVE) { - return BLE_LL_CTRL_UNKNOWN_RSP; - } - - connsm->enc_data.enc_state = CONN_ENC_S_LTK_REQ_WAIT; - - /* In case we were already encrypted we need to reset packet counters */ - connsm->enc_data.rx_pkt_cntr = 0; - connsm->enc_data.tx_pkt_cntr = 0; - connsm->enc_data.tx_encrypted = 0; - - /* Extract information from request */ - connsm->enc_data.host_rand_num = get_le64(dptr); - connsm->enc_data.enc_div = get_le16(dptr + 8); - -#if BLE_LL_ENCRYPT_USE_TEST_DATA - swap_buf(connsm->enc_data.enc_block.plain_text + 8, dptr + 10, 8); - memcpy(connsm->enc_data.iv, dptr + 18, 4); - - put_le64(rspdata, g_bletest_SKDs); - swap_buf(connsm->enc_data.enc_block.plain_text, rspdata, 8); - put_le32(rspdata + 8, g_bletest_IVs); - memcpy(connsm->enc_data.iv + 4, rspdata + 8, 4); - return BLE_LL_CTRL_ENC_RSP; -#endif - - swap_buf(connsm->enc_data.enc_block.plain_text + 8, dptr + 10, 8); - memcpy(connsm->enc_data.iv, dptr + 18, 4); - - /* Create the ENC_RSP. Concatenate our SKD and IV */ - ble_ll_rand_data_get(connsm->enc_data.enc_block.plain_text, 8); - swap_buf(rspdata, connsm->enc_data.enc_block.plain_text, 8); - ble_ll_rand_data_get(connsm->enc_data.iv + 4, 4); - memcpy(rspdata + 8, connsm->enc_data.iv + 4, 4); - - return BLE_LL_CTRL_ENC_RSP; -} - -static uint8_t -ble_ll_ctrl_rx_start_enc_req(struct ble_ll_conn_sm *connsm) -{ - int rc; - - /* Only master should receive start enc request */ - rc = BLE_ERR_MAX; - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - /* We only want to send a START_ENC_RSP if we havent yet */ - if (connsm->enc_data.enc_state == CONN_ENC_S_START_ENC_REQ_WAIT) { - connsm->enc_data.enc_state = CONN_ENC_S_START_ENC_RSP_WAIT; - rc = BLE_LL_CTRL_START_ENC_RSP; - } - } else { - rc = BLE_LL_CTRL_UNKNOWN_RSP; - } - return rc; -} - -static uint8_t -ble_ll_ctrl_rx_pause_enc_req(struct ble_ll_conn_sm *connsm) -{ - int rc; - - /* - * The spec does not say what to do here, but if we receive a pause - * encryption request and we are not encrypted, what do we do? We - * ignore it... - */ - rc = BLE_ERR_MAX; - if ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && - (connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED)) { - rc = BLE_LL_CTRL_PAUSE_ENC_RSP; - } else { - rc = BLE_LL_CTRL_UNKNOWN_RSP; - } - - return rc; -} - -/** - * Called when a LL control pdu with opcode PAUSE_ENC_RSP is received. - * - * - * @param connsm - * - * @return uint8_t - */ -static uint8_t -ble_ll_ctrl_rx_pause_enc_rsp(struct ble_ll_conn_sm *connsm) -{ - int rc; - - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - rc = BLE_LL_CTRL_PAUSE_ENC_RSP; - } else if (connsm->enc_data.enc_state == CONN_ENC_S_PAUSE_ENC_RSP_WAIT) { - /* Master sends back unencrypted LL_PAUSE_ENC_RSP. - * From this moment encryption is paused. - */ - rc = BLE_ERR_MAX; - connsm->enc_data.enc_state = CONN_ENC_S_PAUSED; - } else { - rc = BLE_LL_CTRL_UNKNOWN_RSP; - } - - return rc; -} - -/** - * Called when we have received a LL_CTRL_START_ENC_RSP. - * - * Context: Link-layer task - * - * @param connsm - * - * @return uint8_t - */ -static uint8_t -ble_ll_ctrl_rx_start_enc_rsp(struct ble_ll_conn_sm *connsm) -{ - int rc; - - /* Not in proper state. Discard */ - if (connsm->enc_data.enc_state != CONN_ENC_S_START_ENC_RSP_WAIT) { - return BLE_ERR_MAX; - } - - /* If master, we are done. Stop control procedure and sent event to host */ - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_ENCRYPT); - - /* We are encrypted */ - connsm->enc_data.enc_state = CONN_ENC_S_ENCRYPTED; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) - ble_ll_conn_auth_pyld_timer_start(connsm); -#endif - rc = BLE_ERR_MAX; - } else { - /* Procedure has completed but slave needs to send START_ENC_RSP */ - rc = BLE_LL_CTRL_START_ENC_RSP; - - /* Stop timer if it was started when sending START_ENC_REQ */ - if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_ENCRYPT) { - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_ENCRYPT); - } - } - - /* - * XXX: for now, a Slave sends this event when it receivest the - * START_ENC_RSP from the master. It might be technically incorrect - * to send it before we transmit our own START_ENC_RSP. - */ - ble_ll_hci_ev_encrypt_chg(connsm, BLE_ERR_SUCCESS); - - return rc; -} - -#endif - -/** - * Called to make a connection parameter request or response control pdu. - * - * @param connsm - * @param dptr Pointer to start of data. NOTE: the opcode is not part - * of the data. - */ -static void -ble_ll_ctrl_conn_param_pdu_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr, - struct ble_ll_conn_params *req) -{ - uint16_t offset; - struct hci_conn_update *hcu; - - /* If we were passed in a request, we use the parameters from the request */ - if (req) { - put_le16(dptr, req->interval_min); - put_le16(dptr + 2, req->interval_max); - put_le16(dptr + 4, req->latency); - put_le16(dptr + 6, req->timeout); - } else { - hcu = &connsm->conn_param_req; - /* The host should have provided the parameters! */ - BLE_LL_ASSERT(hcu->handle != 0); - put_le16(dptr, hcu->conn_itvl_min); - put_le16(dptr + 2, hcu->conn_itvl_max); - put_le16(dptr + 4, hcu->conn_latency); - put_le16(dptr + 6, hcu->supervision_timeout); - } - - /* XXX: NOTE: if interval min and interval max are != to each - * other this value should be set to non-zero. I think this - * applies only when an offset field is set. See section 5.1.7.1 pg 103 - * Vol 6 Part B. - */ - /* XXX: for now, set periodicity to 0 */ - dptr[8] = 0; - - /* XXX: deal with reference event count. what to put here? */ - put_le16(dptr + 9, connsm->event_cntr); - - /* XXX: For now, dont use offsets */ - offset = 0xFFFF; - put_le16(dptr + 11, offset); - put_le16(dptr + 13, offset); - put_le16(dptr + 15, offset); - put_le16(dptr + 17, offset); - put_le16(dptr + 19, offset); - put_le16(dptr + 21, offset); -} - -static void -ble_ll_ctrl_version_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld) -{ - /* Set flag to denote we have sent/received this */ - connsm->csmflags.cfbit.version_ind_sent = 1; - - /* Fill out response */ - pyld[0] = BLE_HCI_VER_BCS; - put_le16(pyld + 1, MYNEWT_VAL(BLE_LL_MFRG_ID)); - put_le16(pyld + 3, BLE_LL_SUB_VERS_NR); -} - -/** - * Called to make a LL control channel map request PDU. - * - * @param connsm Pointer to connection state machine - * @param pyld Pointer to payload of LL control PDU - */ -static void -ble_ll_ctrl_chanmap_req_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld) -{ - /* Copy channel map that host desires into request */ - memcpy(pyld, g_ble_ll_conn_params.master_chan_map, BLE_LL_CONN_CHMAP_LEN); - memcpy(connsm->req_chanmap, pyld, BLE_LL_CONN_CHMAP_LEN); - - /* Place instant into request */ - connsm->chanmap_instant = connsm->event_cntr + connsm->slave_latency + 6 + 1; - put_le16(pyld + BLE_LL_CONN_CHMAP_LEN, connsm->chanmap_instant); - - /* Set scheduled flag */ - connsm->csmflags.cfbit.chanmap_update_scheduled = 1; -} - -/** - * Called to respond to a LL control PDU connection parameter request or - * response. - * - * @param connsm - * @param rsp - * @param req - * - * @return uint8_t - */ -uint8_t -ble_ll_ctrl_conn_param_reply(struct ble_ll_conn_sm *connsm, uint8_t *rsp, - struct ble_ll_conn_params *req) -{ - uint8_t rsp_opcode; - - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - /* Create a connection parameter response */ - ble_ll_ctrl_conn_param_pdu_make(connsm, rsp + 1, req); - rsp_opcode = BLE_LL_CTRL_CONN_PARM_RSP; - } else { - /* Create a connection update pdu */ - ble_ll_ctrl_conn_upd_make(connsm, rsp + 1, req); - rsp_opcode = BLE_LL_CTRL_CONN_UPDATE_IND; - } - - return rsp_opcode; -} - -/** - * Called when we have received a LL_REJECT_IND or LL_REJECT_IND_EXT link - * layer control Data Channel pdu. - * - * @param connsm - * @param dptr - * @param opcode - */ -static int -ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr, - uint8_t opcode, uint8_t *rspdata) -{ - uint8_t ble_error; - uint8_t rsp_opcode = BLE_ERR_MAX; - - /* Get error out of received PDU */ - if (opcode == BLE_LL_CTRL_REJECT_IND) { - ble_error = dptr[0]; - } else { - ble_error = dptr[1]; - } - - /* XXX: should I check to make sure the rejected opcode is sane - if we receive ind ext? */ - switch (connsm->cur_ctrl_proc) { - case BLE_LL_CTRL_PROC_CONN_PARAM_REQ: - if (opcode == BLE_LL_CTRL_REJECT_IND_EXT) { - /* As a master we should send connection update indication in this point */ - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - rsp_opcode = BLE_LL_CTRL_CONN_UPDATE_IND; - ble_ll_ctrl_conn_upd_make(connsm, rspdata, NULL); - connsm->reject_reason = BLE_ERR_SUCCESS; - } else { - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ); - ble_ll_hci_ev_conn_update(connsm, ble_error); - } - } - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - case BLE_LL_CTRL_PROC_ENCRYPT: - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_ENCRYPT); - ble_ll_hci_ev_encrypt_chg(connsm, ble_error); - connsm->enc_data.enc_state = CONN_ENC_S_UNENCRYPTED; - break; -#endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - case BLE_LL_CTRL_PROC_PHY_UPDATE: - ble_ll_ctrl_phy_update_cancel(connsm, ble_error); - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); - break; -#endif - case BLE_LL_CTRL_PROC_DATA_LEN_UPD: - /* That should not happen according to Bluetooth 5.0 Vol6 Part B, 5.1.9 - * However we need this workaround as there are devices on the market - * which do send LL_REJECT on LL_LENGTH_REQ when collision happens - */ - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD); - break; - default: - break; - } - - return rsp_opcode; -} - -/** - * Called when we receive a connection update event - * - * @param connsm - * @param dptr - * - * @return int - */ -static int -ble_ll_ctrl_rx_conn_update(struct ble_ll_conn_sm *connsm, uint8_t *dptr) -{ - uint8_t rsp_opcode; - uint16_t conn_events; - struct ble_ll_conn_upd_req *reqdata; - - /* Only a slave should receive this */ - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - return BLE_LL_CTRL_UNKNOWN_RSP; - } - - /* Retrieve parameters */ - reqdata = &connsm->conn_update_req; - reqdata->winsize = dptr[0]; - reqdata->winoffset = get_le16(dptr + 1); - reqdata->interval = get_le16(dptr + 3); - reqdata->latency = get_le16(dptr + 5); - reqdata->timeout = get_le16(dptr + 7); - reqdata->instant = get_le16(dptr + 9); - - /* XXX: validate them at some point. If they dont check out, we - return the unknown response */ - rsp_opcode = BLE_ERR_MAX; - - /* If instant is in the past, we have to end the connection */ - conn_events = (reqdata->instant - connsm->event_cntr) & 0xFFFF; - if (conn_events >= 32767) { - ble_ll_conn_timeout(connsm, BLE_ERR_INSTANT_PASSED); - } else { - connsm->csmflags.cfbit.conn_update_sched = 1; - - /* - * Errata says that receiving a connection update when the event - * counter is equal to the instant means wesimply ignore the window - * offset and window size. Anchor point has already been set based on - * first packet received in connection event. Given that we increment - * the event counter BEFORE checking to see if the instant is equal to - * the event counter what we do here is increment the instant and set - * the window offset and size to 0. - */ - if (conn_events == 0) { - reqdata->winoffset = 0; - reqdata->winsize = 0; - reqdata->instant += 1; - } - } - - return rsp_opcode; -} - -void -ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm) -{ - if (!(connsm->conn_features & BLE_LL_FEAT_DATA_LEN_EXT)) { - return; - } - - /* - * Section 4.5.10 Vol 6 PART B. If the max tx/rx time or octets - * exceeds the minimum, data length procedure needs to occur - */ - if ((connsm->max_tx_octets <= BLE_LL_CONN_SUPP_BYTES_MIN) && - (connsm->max_rx_octets <= BLE_LL_CONN_SUPP_BYTES_MIN) && - (connsm->max_tx_time <= BLE_LL_CONN_SUPP_TIME_MIN) && - (connsm->max_rx_time <= BLE_LL_CONN_SUPP_TIME_MIN)) { - return; - } - - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD); -} - -static void -ble_ll_ctrl_update_features(struct ble_ll_conn_sm *connsm, uint8_t *feat) -{ - connsm->conn_features = feat[0]; - memcpy(connsm->remote_features, feat + 1, 7); - - /* If we received peer's features for the 1st time, we should try DLE */ - if (!connsm->csmflags.cfbit.rxd_features) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - /* - * If connection was established on uncoded PHY, by default we use - * MaxTxTime and MaxRxTime applicable for that PHY since we are not - * allowed to indicate longer supported time if peer does not support - * LE Coded PHY. However, once we know that peer does support it we can - * update those values to ones applicable for coded PHY. - */ - if (connsm->remote_features[0] & (BLE_LL_FEAT_LE_CODED_PHY >> 8)) { - if (connsm->host_req_max_tx_time) { - connsm->max_tx_time = max(connsm->max_tx_time, - connsm->host_req_max_tx_time); - } else { - connsm->max_tx_time = g_ble_ll_conn_params.conn_init_max_tx_time_coded; - } - connsm->max_rx_time = BLE_LL_CONN_SUPP_TIME_MAX_CODED; - } -#endif - - connsm->csmflags.cfbit.pending_initiate_dle = 1; - connsm->csmflags.cfbit.rxd_features = 1; - } -} - -/** - * Called when we receive a feature request or a slave initiated feature - * request. - * - * - * @param connsm - * @param dptr - * @param rspbuf - * @param opcode - * @param new_features - * - * @return int - */ -static int -ble_ll_ctrl_rx_feature_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, - uint8_t *rspbuf, uint8_t opcode) -{ - uint8_t rsp_opcode; - uint64_t our_feat; - - /* - * Only accept slave feature requests if we are a master and feature - * requests if we are a slave. - */ - if (opcode == BLE_LL_CTRL_SLAVE_FEATURE_REQ) { - if (connsm->conn_role != BLE_LL_CONN_ROLE_MASTER) { - return BLE_LL_CTRL_UNKNOWN_RSP; - } - } else { - /* XXX: not sure this is correct but do it anyway */ - if (connsm->conn_role != BLE_LL_CONN_ROLE_SLAVE) { - return BLE_LL_CTRL_UNKNOWN_RSP; - } - } - - our_feat = ble_ll_read_supp_features(); - - rsp_opcode = BLE_LL_CTRL_FEATURE_RSP; - - ble_ll_ctrl_update_features(connsm, dptr); - - /* - * 1st octet of features should be common features of local and remote - * controller - we call this 'connection features' - * remaining octets are features of controller which sends PDU, in this case - * it's our controller - * - * See: Vol 6, Part B, section 2.4.2.10 - */ - connsm->conn_features &= our_feat; - - put_le64(rspbuf + 1, our_feat); - rspbuf[1] = connsm->conn_features; - - return rsp_opcode; -} - -/** - * Called when we receive a feature response - * - * @param connsm - * @param dptr - * @param new_features - * - */ -static void -ble_ll_ctrl_rx_feature_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr) -{ - ble_ll_ctrl_update_features(connsm, dptr); - - /* Stop the control procedure */ - if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG)) { - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG); - } - - /* Send event to host if pending features read */ - if (connsm->csmflags.cfbit.pending_hci_rd_features) { - ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS); - connsm->csmflags.cfbit.pending_hci_rd_features = 0; - } -} - -/** - * - * - * Context: Link Layer task - * - * @param connsm - * @param dptr - * @param rspbuf - * - * @return int - */ -static int -ble_ll_ctrl_rx_conn_param_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, - uint8_t *rspbuf) -{ - uint8_t rsp_opcode; - - /* - * This is not in the specification per se but it simplifies the - * implementation. If we get a connection parameter request and we - * are awaiting a reply from the host, simply ignore the request. This - * might not be a good idea if the parameters are different, but oh - * well. This is not expected to happen anyway. A return of BLE_ERR_MAX - * means that we will simply discard the connection parameter request - */ - if (connsm->csmflags.cfbit.awaiting_host_reply) { - return BLE_ERR_MAX; - } - - /* XXX: remember to deal with this on the master: if the slave has - * initiated a procedure we may have received its connection parameter - * update request and have signaled the host with an event. If that - * is the case, we will need to drop the host command when we get it - and also clear any applicable states. */ - - /* XXX: Read 5.3 again. There are multiple control procedures that might - * be pending (a connection update) that will cause collisions and the - behavior below. */ - /* - * Check for procedure collision (Vol 6 PartB 5.3). If we are a slave - * and we receive a request we "consider the slave initiated - * procedure as complete". This means send a connection update complete - * event (with error). - * - * If a master, we send reject with a - * transaction collision error code. - */ - if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) { - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ); - ble_ll_hci_ev_conn_update(connsm, BLE_ERR_LMP_COLLISION); - } else { - /* The master sends reject ind ext w/error code 0x23 */ - rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; - rspbuf[1] = BLE_LL_CTRL_CONN_PARM_REQ; - rspbuf[2] = BLE_ERR_LMP_COLLISION; - return rsp_opcode; - } - } - - /* - * If we are a master and we currently performing a channel map - * update procedure we need to return an error - */ - if ((connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) && - (connsm->csmflags.cfbit.chanmap_update_scheduled)) { - rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; - rspbuf[1] = BLE_LL_CTRL_CONN_PARM_REQ; - rspbuf[2] = BLE_ERR_DIFF_TRANS_COLL; - return rsp_opcode; - } - - /* Process the received connection parameter request */ - rsp_opcode = ble_ll_ctrl_conn_param_pdu_proc(connsm, dptr, rspbuf, - BLE_LL_CTRL_CONN_PARM_REQ); - return rsp_opcode; -} - -static int -ble_ll_ctrl_rx_conn_param_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, - uint8_t *rspbuf) -{ - uint8_t rsp_opcode; - - /* A slave should never receive this response */ - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - return BLE_LL_CTRL_UNKNOWN_RSP; - } - - /* - * This case should never happen! It means that the slave initiated a - * procedure and the master initiated one as well. If we do get in this - * state just clear the awaiting reply. The slave will hopefully stop its - * procedure when we reply. - */ - if (connsm->csmflags.cfbit.awaiting_host_reply) { - connsm->csmflags.cfbit.awaiting_host_reply = 0; - } - - /* If we receive a response and no procedure is pending, just leave */ - if (!IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) { - return BLE_ERR_MAX; - } - - /* Process the received connection parameter response */ - rsp_opcode = ble_ll_ctrl_conn_param_pdu_proc(connsm, dptr, rspbuf, - BLE_LL_CTRL_CONN_PARM_RSP); - return rsp_opcode; -} - -/** - * Called to process the LL control PDU VERSION_IND - * - * Context: Link Layer task - * - * @param connsm - * @param dptr - * @param rspbuf - * - * @return int - */ -static int -ble_ll_ctrl_rx_version_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr, - uint8_t *rspbuf) -{ - uint8_t rsp_opcode; - - /* Process the packet */ - connsm->vers_nr = dptr[0]; - connsm->comp_id = get_le16(dptr + 1); - connsm->sub_vers_nr = get_le16(dptr + 3); - connsm->csmflags.cfbit.rxd_version_ind = 1; - - rsp_opcode = BLE_ERR_MAX; - if (!connsm->csmflags.cfbit.version_ind_sent) { - rsp_opcode = BLE_LL_CTRL_VERSION_IND; - ble_ll_ctrl_version_ind_make(connsm, rspbuf); - } - - /* Stop the control procedure */ - if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG)) { - ble_ll_hci_ev_rd_rem_ver(connsm, BLE_ERR_SUCCESS); - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG); - } - return rsp_opcode; -} - -/** - * Called to process a received channel map request control pdu. - * - * Context: Link Layer task - * - * @param connsm - * @param dptr - */ -static int -ble_ll_ctrl_rx_chanmap_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr) -{ - uint16_t instant; - uint16_t conn_events; - - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - return BLE_LL_CTRL_UNKNOWN_RSP; - } - - /* If instant is in the past, we have to end the connection */ - instant = get_le16(dptr + BLE_LL_CONN_CHMAP_LEN); - conn_events = (instant - connsm->event_cntr) & 0xFFFF; - if (conn_events >= 32767) { - ble_ll_conn_timeout(connsm, BLE_ERR_INSTANT_PASSED); - } else { - connsm->chanmap_instant = instant; - memcpy(connsm->req_chanmap, dptr, BLE_LL_CONN_CHMAP_LEN); - connsm->csmflags.cfbit.chanmap_update_scheduled = 1; - } - - return BLE_ERR_MAX; -} - -/** - * Initiate LL control procedure. - * - * This function is called to obtain a mbuf to send a LL control PDU. The data - * channel PDU header is not part of the mbuf data; it is part of the BLE - * header (which is part of the mbuf). - * - * Context: LL task. - * - * @param connsm - * @param ctrl_proc - */ -static struct os_mbuf * -ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc) -{ - uint8_t len; - uint8_t opcode; - uint8_t *dptr; - uint8_t *ctrdata; - struct os_mbuf *om; - - /* Get an mbuf for the control pdu */ - om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN, sizeof(struct ble_mbuf_hdr)); - - if (om) { - /* The control data starts after the opcode (1 byte) */ - dptr = om->om_data; - ctrdata = dptr + 1; - - switch (ctrl_proc) { - case BLE_LL_CTRL_PROC_CONN_UPDATE: - opcode = BLE_LL_CTRL_CONN_UPDATE_IND; - ble_ll_ctrl_conn_upd_make(connsm, ctrdata, NULL); - break; - case BLE_LL_CTRL_PROC_CHAN_MAP_UPD: - opcode = BLE_LL_CTRL_CHANNEL_MAP_REQ; - ble_ll_ctrl_chanmap_req_make(connsm, ctrdata); - break; - case BLE_LL_CTRL_PROC_FEATURE_XCHG: - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - opcode = BLE_LL_CTRL_FEATURE_REQ; - } else { - opcode = BLE_LL_CTRL_SLAVE_FEATURE_REQ; - } - put_le64(ctrdata, ble_ll_read_supp_features()); - break; - case BLE_LL_CTRL_PROC_VERSION_XCHG: - opcode = BLE_LL_CTRL_VERSION_IND; - ble_ll_ctrl_version_ind_make(connsm, ctrdata); - break; - case BLE_LL_CTRL_PROC_TERMINATE: - opcode = BLE_LL_CTRL_TERMINATE_IND; - ctrdata[0] = connsm->disconnect_reason; - break; - case BLE_LL_CTRL_PROC_CONN_PARAM_REQ: - opcode = BLE_LL_CTRL_CONN_PARM_REQ; - ble_ll_ctrl_conn_param_pdu_make(connsm, ctrdata, NULL); - break; - case BLE_LL_CTRL_PROC_LE_PING: - opcode = BLE_LL_CTRL_PING_REQ; - break; - case BLE_LL_CTRL_PROC_DATA_LEN_UPD: - opcode = BLE_LL_CTRL_LENGTH_REQ; - ble_ll_ctrl_datalen_upd_make(connsm, dptr); - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - /* XXX: deal with already encrypted connection.*/ - case BLE_LL_CTRL_PROC_ENCRYPT: - /* If we are already encrypted we do pause procedure */ - if (connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) { - opcode = BLE_LL_CTRL_PAUSE_ENC_REQ; - } else { - opcode = BLE_LL_CTRL_ENC_REQ; - ble_ll_ctrl_enc_req_make(connsm, ctrdata); - } - break; -#endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - case BLE_LL_CTRL_PROC_PHY_UPDATE: - opcode = BLE_LL_CTRL_PHY_REQ; - ble_ll_ctrl_phy_req_rsp_make(connsm, ctrdata); - break; -#endif - default: - BLE_LL_ASSERT(0); - break; - } - - /* Set llid, length and opcode */ - dptr[0] = opcode; - len = g_ble_ll_ctrl_pkt_lengths[opcode] + 1; - - /* Add packet to transmit queue of connection */ - ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, len); - } - - return om; -} - -/** - * Called to determine if the pdu is a TERMINATE_IND - * - * @param hdr - * @param opcode - * - * @return int - */ -int -ble_ll_ctrl_is_terminate_ind(uint8_t hdr, uint8_t opcode) -{ - int rc; - - rc = 0; - if ((hdr & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) { - if (opcode == BLE_LL_CTRL_TERMINATE_IND) { - rc = 1; - } - } - return rc; -} - -/** - * Stops the LL control procedure indicated by 'ctrl_proc'. - * - * Context: Link Layer task - * - * @param connsm - * @param ctrl_proc - */ -void -ble_ll_ctrl_proc_stop(struct ble_ll_conn_sm *connsm, int ctrl_proc) -{ - if (connsm->cur_ctrl_proc == ctrl_proc) { - ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer); - connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE; - } - CLR_PENDING_CTRL_PROC(connsm, ctrl_proc); - - /* If there are others, start them */ - ble_ll_ctrl_chk_proc_start(connsm); -} - -/** - * Called to start the terminate procedure. - * - * Context: Link Layer task. - * - * @param connsm - */ -void -ble_ll_ctrl_terminate_start(struct ble_ll_conn_sm *connsm) -{ - int ctrl_proc; - uint32_t usecs; - struct os_mbuf *om; - - BLE_LL_ASSERT(connsm->disconnect_reason != 0); - - ctrl_proc = BLE_LL_CTRL_PROC_TERMINATE; - om = ble_ll_ctrl_proc_init(connsm, ctrl_proc); - if (om) { - CONN_F_TERMINATE_STARTED(connsm) = 1; - - /* Set terminate "timeout" */ - usecs = connsm->supervision_tmo * BLE_HCI_CONN_SPVN_TMO_UNITS * 1000; - connsm->terminate_timeout = os_cputime_get32() + - os_cputime_usecs_to_ticks(usecs); - } -} - -/** - * Called to start a LL control procedure except for the terminate procedure. We - * always set the control procedure pending bit even if the control procedure - * has been initiated. - * - * Context: Link Layer task. - * - * @param connsm Pointer to connection state machine. - */ -void -ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc) -{ - struct os_mbuf *om; - - BLE_LL_ASSERT(ctrl_proc != BLE_LL_CTRL_PROC_TERMINATE); - - om = NULL; - if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_IDLE) { - /* Initiate the control procedure. */ - om = ble_ll_ctrl_proc_init(connsm, ctrl_proc); - if (om) { - /* Set the current control procedure */ - connsm->cur_ctrl_proc = ctrl_proc; - - /* Initialize the procedure response timeout */ - if (ctrl_proc != BLE_LL_CTRL_PROC_CHAN_MAP_UPD) { - ble_ll_ctrl_start_rsp_timer(connsm); - } - } - } - - /* Set bitmask denoting control procedure is pending */ - connsm->pending_ctrl_procs |= (1 << ctrl_proc); -} - -/** - * Called to determine if we need to start a LL control procedure for the given - * connection. - * - * Context: Link Layer - * - * @param connsm Pointer to connection state machine. - */ -void -ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm) -{ - int i; - - /* XXX: TODO new rules! Cannot start certain control procedures if other - * ones are peer initiated. We need to wait. Deal with this. - */ - - /* - * If we are terminating, dont start any new procedures but start - * terminate if needed - */ - if (connsm->disconnect_reason) { - if (!CONN_F_TERMINATE_STARTED(connsm)) { - /* - * If the terminate procedure has not started it means we were not - * able to start it right away (no control pdu was available). - * Start it now. No need to start any other procedures. - */ - ble_ll_ctrl_terminate_start(connsm); - } - return; - } - - /* If there is a running procedure or no pending, do nothing */ - if ((connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_IDLE) && - (connsm->pending_ctrl_procs != 0)) { - /* - * The specification says there is no priority to control procedures - * so just start from the first one for now. - */ - for (i = 0; i < BLE_LL_CTRL_PROC_NUM; ++i) { - if (IS_PENDING_CTRL_PROC(connsm, i)) { - /* - * The version exchange is a special case. If we have already - * received the information dont start it. - */ - if ((i == BLE_LL_CTRL_PROC_VERSION_XCHG) && - (connsm->csmflags.cfbit.rxd_version_ind)) { - ble_ll_hci_ev_rd_rem_ver(connsm, BLE_ERR_SUCCESS); - CLR_PENDING_CTRL_PROC(connsm, i); - } else { - ble_ll_ctrl_proc_start(connsm, i); - break; - } - } - } - } -} - -/** - * Called when the Link Layer receives a LL control PDU. - * - * NOTE: this function uses the received PDU for the response in some cases. If - * the received PDU is not used it needs to be freed here. - * - * XXX: may want to check, for both master and slave, whether the control - * pdu should be received by that role. Might make for less code... - * Context: Link Layer - * - * @param om - * @param connsm - */ -int -ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om) -{ - uint32_t features; - uint32_t feature; - uint8_t len; - uint8_t opcode; - uint8_t rsp_opcode; - uint8_t *dptr; - uint8_t *rspbuf; - uint8_t *rspdata; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - int restart_encryption; -#endif - int rc = 0; - - /* XXX: where do we validate length received and packet header length? - * do this in LL task when received. Someplace!!! What I mean - * is we should validate the over the air length with the mbuf length. - Should the PHY do that???? */ - - /* - * dptr points to om_data pointer. The first byte of om_data is the - * first byte of the Data Channel PDU header. Get length from header and - * opcode from LL control PDU. - */ - dptr = om->om_data; - len = dptr[1]; - opcode = dptr[2]; - - /* - * rspbuf points to first byte of response. The response buffer does not - * contain the Data Channel PDU. Thus, the first byte of rspbuf is the - * LL control PDU payload (the opcode of the control PDU). rspdata - * points to CtrData in the control PDU. - */ - rspbuf = dptr; - rspdata = rspbuf + 1; - - /* Move data pointer to start of control data (2 byte PDU hdr + opcode) */ - dptr += (BLE_LL_PDU_HDR_LEN + 1); - - /* - * Subtract the opcode from the length. Note that if the length was zero, - * which would be an error, we will fail the check against the length - * of the control packet. - */ - --len; - - ble_ll_trace_u32x2(BLE_LL_TRACE_ID_CTRL_RX, opcode, len); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - restart_encryption = 0; -#endif - - /* If opcode comes from reserved value or CtrlData fields is invalid - * we shall respond with LL_UNKNOWN_RSP - */ - if ((opcode >= BLE_LL_CTRL_OPCODES) || - (len != g_ble_ll_ctrl_pkt_lengths[opcode])) { - rc = -1; - rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP; - goto ll_ctrl_send_rsp; - } - - /* Check if the feature is supported. */ - switch (opcode) { - case BLE_LL_CTRL_LENGTH_REQ: - feature = BLE_LL_FEAT_DATA_LEN_EXT; - break; - case BLE_LL_CTRL_SLAVE_FEATURE_REQ: - feature = BLE_LL_FEAT_SLAVE_INIT; - break; - case BLE_LL_CTRL_CONN_PARM_REQ: - case BLE_LL_CTRL_CONN_PARM_RSP: - feature = BLE_LL_FEAT_CONN_PARM_REQ; - break; - case BLE_LL_CTRL_ENC_REQ: - case BLE_LL_CTRL_START_ENC_REQ: - case BLE_LL_CTRL_PAUSE_ENC_REQ: - feature = BLE_LL_FEAT_LE_ENCRYPTION; - break; - case BLE_LL_CTRL_PING_REQ: - feature = BLE_LL_FEAT_LE_PING; - break; - case BLE_LL_CTRL_PHY_REQ: - feature = BLE_LL_FEAT_LE_2M_PHY | BLE_LL_FEAT_LE_CODED_PHY; - break; - case BLE_LL_CTRL_MIN_USED_CHAN_IND: - feature = BLE_LL_FEAT_MIN_USED_CHAN; - break; - case BLE_LL_CTRL_PERIODIC_SYNC_IND: - feature = BLE_LL_FEAT_SYNC_TRANS_RECV; - break; - default: - feature = 0; - break; - } - - if (feature) { - features = ble_ll_read_supp_features(); - if ((features & feature) == 0) { - if (opcode == BLE_LL_CTRL_ENC_REQ) { - if (connsm->conn_features & BLE_LL_FEAT_EXTENDED_REJ) { - rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; - rspbuf[1] = opcode; - rspbuf[2] = BLE_ERR_UNSUPP_REM_FEATURE; - - } else { - rsp_opcode = BLE_LL_CTRL_REJECT_IND; - rspbuf[1] = BLE_ERR_UNSUPP_REM_FEATURE; - } - } else { - /* Construct unknown rsp pdu */ - rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP; - } - goto ll_ctrl_send_rsp; - } - } - - /* Process opcode */ - rsp_opcode = BLE_ERR_MAX; - switch (opcode) { - case BLE_LL_CTRL_CONN_UPDATE_IND: - rsp_opcode = ble_ll_ctrl_rx_conn_update(connsm, dptr); - break; - case BLE_LL_CTRL_CHANNEL_MAP_REQ: - rsp_opcode = ble_ll_ctrl_rx_chanmap_req(connsm, dptr); - break; - case BLE_LL_CTRL_LENGTH_REQ: - /* Extract parameters and check if valid */ - if (ble_ll_ctrl_len_proc(connsm, dptr)) { - rc = -1; - rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP; - goto ll_ctrl_send_rsp; - } - - /* - * If we have not started this procedure ourselves and it is - * pending, no need to perform it. - */ - if ((connsm->cur_ctrl_proc != BLE_LL_CTRL_PROC_DATA_LEN_UPD) && - IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD)) { - CLR_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD); - } - - /* Send a response */ - rsp_opcode = BLE_LL_CTRL_LENGTH_RSP; - ble_ll_ctrl_datalen_upd_make(connsm, rspbuf); - break; - case BLE_LL_CTRL_LENGTH_RSP: - /* According to specification, process this only if we asked for it. */ - if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_DATA_LEN_UPD) { - /* - * Process the received data. If received data is invalid, we'll - * reply with LL_UNKNOWN_RSP as per spec, but we still need to stop - * control procedure to avoid timeout. - */ - if (ble_ll_ctrl_len_proc(connsm, dptr)) { - rc = -1; - rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP; - } - - /* Stop the control procedure */ - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD); - } - break; - case BLE_LL_CTRL_UNKNOWN_RSP: - rsp_opcode = ble_ll_ctrl_proc_unk_rsp(connsm, dptr, rspdata); - break; - case BLE_LL_CTRL_FEATURE_REQ: - rsp_opcode = ble_ll_ctrl_rx_feature_req(connsm, dptr, rspbuf, opcode); - break; - /* XXX: check to see if ctrl procedure was running? Do we care? */ - case BLE_LL_CTRL_FEATURE_RSP: - ble_ll_ctrl_rx_feature_rsp(connsm, dptr); - break; - case BLE_LL_CTRL_VERSION_IND: - rsp_opcode = ble_ll_ctrl_rx_version_ind(connsm, dptr, rspdata); - break; - case BLE_LL_CTRL_SLAVE_FEATURE_REQ: - rsp_opcode = ble_ll_ctrl_rx_feature_req(connsm, dptr, rspbuf, opcode); - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - case BLE_LL_CTRL_ENC_REQ: - rsp_opcode = ble_ll_ctrl_rx_enc_req(connsm, dptr, rspdata); - break; - case BLE_LL_CTRL_ENC_RSP: - ble_ll_ctrl_rx_enc_rsp(connsm, dptr); - break; - case BLE_LL_CTRL_START_ENC_REQ: - rsp_opcode = ble_ll_ctrl_rx_start_enc_req(connsm); - break; - case BLE_LL_CTRL_START_ENC_RSP: - rsp_opcode = ble_ll_ctrl_rx_start_enc_rsp(connsm); - break; - case BLE_LL_CTRL_PAUSE_ENC_REQ: - rsp_opcode = ble_ll_ctrl_rx_pause_enc_req(connsm); - break; - case BLE_LL_CTRL_PAUSE_ENC_RSP: - rsp_opcode = ble_ll_ctrl_rx_pause_enc_rsp(connsm); - if (rsp_opcode == BLE_LL_CTRL_PAUSE_ENC_RSP) { - restart_encryption = 1; - } - break; -#endif - case BLE_LL_CTRL_PING_REQ: - rsp_opcode = BLE_LL_CTRL_PING_RSP; - break; - case BLE_LL_CTRL_PING_RSP: - ble_ll_ctrl_rx_ping_rsp(connsm); - break; - case BLE_LL_CTRL_CONN_PARM_REQ: - rsp_opcode = ble_ll_ctrl_rx_conn_param_req(connsm, dptr, rspbuf); - break; - case BLE_LL_CTRL_CONN_PARM_RSP: - rsp_opcode = ble_ll_ctrl_rx_conn_param_rsp(connsm, dptr, rspbuf); - break; - /* Fall-through intentional... */ - case BLE_LL_CTRL_REJECT_IND: - case BLE_LL_CTRL_REJECT_IND_EXT: - /* Sometimes reject triggers sending other LL CTRL msg */ - rsp_opcode = ble_ll_ctrl_rx_reject_ind(connsm, dptr, opcode, rspdata); - break; -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - case BLE_LL_CTRL_PHY_REQ: - rsp_opcode = ble_ll_ctrl_rx_phy_req(connsm, dptr, rspdata); - break; - case BLE_LL_CTRL_PHY_RSP: - rsp_opcode = ble_ll_ctrl_rx_phy_rsp(connsm, dptr, rspdata); - break; - case BLE_LL_CTRL_PHY_UPDATE_IND: - rsp_opcode = ble_ll_ctrl_rx_phy_update_ind(connsm, dptr); - break; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - case BLE_LL_CTRL_PERIODIC_SYNC_IND: - rsp_opcode = ble_ll_ctrl_rx_periodic_sync_ind(connsm, dptr); - break; -#endif - default: - /* Nothing to do here */ - break; - } - - /* Free mbuf or send response */ -ll_ctrl_send_rsp: - if (rsp_opcode == BLE_ERR_MAX) { - os_mbuf_free_chain(om); - } else { - /* - * Write the response opcode into the buffer. If this is an unknown - * response, put opcode of unknown pdu into buffer. - */ - rspbuf[0] = rsp_opcode; - if (rsp_opcode == BLE_LL_CTRL_UNKNOWN_RSP) { - rspbuf[1] = opcode; - } - len = g_ble_ll_ctrl_pkt_lengths[rsp_opcode] + 1; - ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, len); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (restart_encryption) { - /* XXX: what happens if this fails? Meaning we cant allocate - mbuf? */ - ble_ll_ctrl_proc_init(connsm, BLE_LL_CTRL_PROC_ENCRYPT); - } -#endif - } - - if (connsm->csmflags.cfbit.pending_initiate_dle) { - connsm->csmflags.cfbit.pending_initiate_dle = 0; - ble_ll_ctrl_initiate_dle(connsm); - } - - return rc; -} - -/** - * Called to create and send a REJECT_IND_EXT control PDU or a REJECT_IND - * - * @param connsm - * @param rej_opcode - * @param err - * - * @return int - */ -int -ble_ll_ctrl_reject_ind_send(struct ble_ll_conn_sm *connsm, uint8_t rej_opcode, - uint8_t err) -{ - int rc; - uint8_t len; - uint8_t opcode; - uint8_t *rspbuf; - struct os_mbuf *om; - - om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN, - sizeof(struct ble_mbuf_hdr)); - if (om) { - rspbuf = om->om_data; - opcode = BLE_LL_CTRL_REJECT_IND_EXT; - if (rej_opcode == BLE_LL_CTRL_ENC_REQ) { - if ((connsm->conn_features & BLE_LL_FEAT_EXTENDED_REJ) == 0) { - opcode = BLE_LL_CTRL_REJECT_IND; - } - } - rspbuf[0] = opcode; - if (opcode == BLE_LL_CTRL_REJECT_IND) { - rspbuf[1] = err; - len = BLE_LL_CTRL_REJ_IND_LEN + 1; - } else { - rspbuf[1] = rej_opcode; - rspbuf[2] = err; - len = BLE_LL_CTRL_REJECT_IND_EXT_LEN + 1; - } - ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, len); - rc = 0; - } else { - rc = 1; - } - return rc; -} - -/** - * Called when a Link Layer Control pdu has been transmitted successfully. - * This is called when we have a received a PDU during the ISR. - * - * Context: ISR - * - * @param txpdu - * - * @return int - */ -int -ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) -{ - int rc; - uint8_t opcode; - - rc = 0; - opcode = txpdu->om_data[0]; - switch (opcode) { - case BLE_LL_CTRL_TERMINATE_IND: - connsm->csmflags.cfbit.terminate_ind_txd = 1; - rc = -1; - break; - case BLE_LL_CTRL_REJECT_IND_EXT: - if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_CONN_PARAM_REQ) { - /* If rejecting opcode is BLE_LL_CTRL_PROC_CONN_PARAM_REQ and - * reason is LMP collision that means we are master on the link and - * peer wanted to start procedure which we already started. - * Let's wait for response and do not close procedure. */ - if (txpdu->om_data[1] == BLE_LL_CTRL_CONN_PARM_REQ && - txpdu->om_data[2] != BLE_ERR_LMP_COLLISION) { - connsm->reject_reason = txpdu->om_data[2]; - connsm->csmflags.cfbit.host_expects_upd_event = 1; - } - } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) { - connsm->enc_data.enc_state = CONN_ENC_S_UNENCRYPTED; - } -#endif - break; - case BLE_LL_CTRL_REJECT_IND: -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - connsm->enc_data.enc_state = CONN_ENC_S_UNENCRYPTED; -#endif - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - case BLE_LL_CTRL_PAUSE_ENC_REQ: - /* note: fall-through intentional */ - case BLE_LL_CTRL_ENC_REQ: - connsm->enc_data.enc_state = CONN_ENC_S_ENC_RSP_WAIT; - break; - case BLE_LL_CTRL_ENC_RSP: - connsm->csmflags.cfbit.send_ltk_req = 1; - break; - case BLE_LL_CTRL_START_ENC_RSP: - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - connsm->enc_data.enc_state = CONN_ENC_S_ENCRYPTED; - if (CONN_F_LE_PING_SUPP(connsm)) { - ble_ll_conn_auth_pyld_timer_start(connsm); - } - } - break; - case BLE_LL_CTRL_PAUSE_ENC_RSP: - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - connsm->enc_data.enc_state = CONN_ENC_S_PAUSE_ENC_RSP_WAIT; - } - break; -#endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - case BLE_LL_CTRL_PHY_REQ: - connsm->phy_tx_transition = - ble_ll_ctrl_phy_tx_transition_get(connsm->phy_data.req_pref_tx_phys_mask); - break; - case BLE_LL_CTRL_PHY_UPDATE_IND: - connsm->phy_tx_transition = - ble_ll_ctrl_phy_tx_transition_get(txpdu->om_data[2]); - break; -#endif - default: - break; - } - - os_mbuf_free_chain(txpdu); - return rc; -} -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_dtm.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_dtm.c deleted file mode 100644 index baf8c2570..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_dtm.c +++ /dev/null @@ -1,728 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/sysinit/sysinit.h" - -#if MYNEWT_VAL(BLE_LL_DTM) - -#include -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/porting/nimble/include/stats/stats.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_phy.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_rfmgmt.h" -#include "ble_ll_dtm_priv.h" - -STATS_SECT_START(ble_ll_dtm_stats) - STATS_SECT_ENTRY(rx_count) - STATS_SECT_ENTRY(tx_failed) - STATS_SECT_ENTRY(rx_failed) -STATS_SECT_END -STATS_SECT_DECL(ble_ll_dtm_stats) ble_ll_dtm_stats; - -STATS_NAME_START(ble_ll_dtm_stats) - STATS_NAME(ble_ll_dtm_stats, rx_count) - STATS_NAME(ble_ll_dtm_stats, tx_failed) - STATS_NAME(ble_ll_dtm_stats, rx_failed) -STATS_NAME_END(ble_phy_stats) - -struct dtm_ctx { - uint8_t payload_packet; - uint8_t itvl_rem_usec; - uint16_t num_of_packets; - uint32_t itvl_ticks; -#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) - uint16_t num_of_packets_max; -#endif - int active; - uint8_t rf_channel; - uint8_t phy_mode; - struct os_mbuf *om; - struct ble_npl_event evt; - struct ble_ll_sched_item sch; - uint32_t pdu_start_ticks; - uint8_t pdu_start_usecs; -}; - -static struct dtm_ctx g_ble_ll_dtm_ctx; - -static const uint8_t g_ble_ll_dtm_prbs9_data[] = -{ - 0xff, 0xc1, 0xfb, 0xe8, 0x4c, 0x90, 0x72, 0x8b, - 0xe7, 0xb3, 0x51, 0x89, 0x63, 0xab, 0x23, 0x23, - 0x02, 0x84, 0x18, 0x72, 0xaa, 0x61, 0x2f, 0x3b, - 0x51, 0xa8, 0xe5, 0x37, 0x49, 0xfb, 0xc9, 0xca, - 0x0c, 0x18, 0x53, 0x2c, 0xfd, 0x45, 0xe3, 0x9a, - 0xe6, 0xf1, 0x5d, 0xb0, 0xb6, 0x1b, 0xb4, 0xbe, - 0x2a, 0x50, 0xea, 0xe9, 0x0e, 0x9c, 0x4b, 0x5e, - 0x57, 0x24, 0xcc, 0xa1, 0xb7, 0x59, 0xb8, 0x87, - 0xff, 0xe0, 0x7d, 0x74, 0x26, 0x48, 0xb9, 0xc5, - 0xf3, 0xd9, 0xa8, 0xc4, 0xb1, 0xd5, 0x91, 0x11, - 0x01, 0x42, 0x0c, 0x39, 0xd5, 0xb0, 0x97, 0x9d, - 0x28, 0xd4, 0xf2, 0x9b, 0xa4, 0xfd, 0x64, 0x65, - 0x06, 0x8c, 0x29, 0x96, 0xfe, 0xa2, 0x71, 0x4d, - 0xf3, 0xf8, 0x2e, 0x58, 0xdb, 0x0d, 0x5a, 0x5f, - 0x15, 0x28, 0xf5, 0x74, 0x07, 0xce, 0x25, 0xaf, - 0x2b, 0x12, 0xe6, 0xd0, 0xdb, 0x2c, 0xdc, 0xc3, - 0x7f, 0xf0, 0x3e, 0x3a, 0x13, 0xa4, 0xdc, 0xe2, - 0xf9, 0x6c, 0x54, 0xe2, 0xd8, 0xea, 0xc8, 0x88, - 0x00, 0x21, 0x86, 0x9c, 0x6a, 0xd8, 0xcb, 0x4e, - 0x14, 0x6a, 0xf9, 0x4d, 0xd2, 0x7e, 0xb2, 0x32, - 0x03, 0xc6, 0x14, 0x4b, 0x7f, 0xd1, 0xb8, 0xa6, - 0x79, 0x7c, 0x17, 0xac, 0xed, 0x06, 0xad, 0xaf, - 0x0a, 0x94, 0x7a, 0xba, 0x03, 0xe7, 0x92, 0xd7, - 0x15, 0x09, 0x73, 0xe8, 0x6d, 0x16, 0xee, 0xe1, - 0x3f, 0x78, 0x1f, 0x9d, 0x09, 0x52, 0x6e, 0xf1, - 0x7c, 0x36, 0x2a, 0x71, 0x6c, 0x75, 0x64, 0x44, - 0x80, 0x10, 0x43, 0x4e, 0x35, 0xec, 0x65, 0x27, - 0x0a, 0xb5, 0xfc, 0x26, 0x69, 0x3f, 0x59, 0x99, - 0x01, 0x63, 0x8a, 0xa5, 0xbf, 0x68, 0x5c, 0xd3, - 0x3c, 0xbe, 0x0b, 0xd6, 0x76, 0x83, 0xd6, 0x57, - 0x05, 0x4a, 0x3d, 0xdd, 0x81, 0x73, 0xc9, 0xeb, - 0x8a, 0x84, 0x39, 0xf4, 0x36, 0x0b, 0xf7 -}; - -static const uint8_t g_ble_ll_dtm_prbs15_data[] = -{ - 0xff, 0x7f, 0xf0, 0x3e, 0x3a, 0x13, 0xa4, 0xdc, - 0xe2, 0xf9, 0x6c, 0x54, 0xe2, 0xd8, 0xea, 0xc8, - 0x88, 0x00, 0x21, 0x86, 0x9c, 0x6a, 0xd8, 0xcb, - 0x4e, 0x14, 0x6a, 0xf9, 0x4d, 0xd2, 0x7e, 0xb2, - 0x32, 0x03, 0xc6, 0x14, 0x4b, 0x7f, 0xd1, 0xb8, - 0xa6, 0x79, 0x7c, 0x17, 0xac, 0xed, 0x06, 0xad, - 0xaf, 0x0a, 0x94, 0x7a, 0xba, 0x03, 0xe7, 0x92, - 0xd7, 0x15, 0x09, 0x73, 0xe8, 0x6d, 0x16, 0xee, - 0xe1, 0x3f, 0x78, 0x1f, 0x9d, 0x09, 0x52, 0x6e, - 0xf1, 0x7c, 0x36, 0x2a, 0x71, 0x6c, 0x75, 0x64, - 0x44, 0x80, 0x10, 0x43, 0x4e, 0x35, 0xec, 0x65, - 0x27, 0x0a, 0xb5, 0xfc, 0x26, 0x69, 0x3f, 0x59, - 0x99, 0x01, 0x63, 0x8a, 0xa5, 0xbf, 0x68, 0x5c, - 0xd3, 0x3c, 0xbe, 0x0b, 0xd6, 0x76, 0x83, 0xd6, - 0x57, 0x05, 0x4a, 0x3d, 0xdd, 0x81, 0x73, 0xc9, - 0xeb, 0x8a, 0x84, 0x39, 0xf4, 0x36, 0x0b, 0xf7, - 0xf0, 0x1f, 0xbc, 0x8f, 0xce, 0x04, 0x29, 0xb7, - 0x78, 0x3e, 0x1b, 0x95, 0x38, 0xb6, 0x3a, 0x32, - 0x22, 0x40, 0x88, 0x21, 0xa7, 0x1a, 0xf6, 0xb2, - 0x13, 0x85, 0x5a, 0x7e, 0x93, 0xb4, 0x9f, 0xac, - 0xcc, 0x80, 0x31, 0xc5, 0xd2, 0x5f, 0x34, 0xae, - 0x69, 0x1e, 0xdf, 0x05, 0x6b, 0xbb, 0x41, 0xeb, - 0xab, 0x02, 0xa5, 0x9e, 0xee, 0xc0, 0xb9, 0xe4, - 0x75, 0x45, 0xc2, 0x1c, 0x7a, 0x9b, 0x85, 0x7b, - 0xf8, 0x0f, 0xde, 0x47, 0x67, 0x82, 0x94, 0x5b, - 0x3c, 0x9f, 0x8d, 0x4a, 0x1c, 0x5b, 0x1d, 0x19, - 0x11, 0x20, 0xc4, 0x90, 0x53, 0x0d, 0x7b, 0xd9, - 0x89, 0x42, 0x2d, 0xbf, 0x49, 0xda, 0x4f, 0x56, - 0x66, 0xc0, 0x98, 0x62, 0xe9, 0x2f, 0x1a, 0xd7, - 0x34, 0x8f, 0xef, 0x82, 0xb5, 0xdd, 0xa0, 0xf5, - 0x55, 0x81, 0x52, 0x4f, 0x77, 0xe0, 0x5c, 0xf2, - 0xba, 0x22, 0x61, 0x0e, 0xbd, 0xcd, 0xc2 -}; - -static const uint8_t channel_rf_to_index[] = { - 37, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 38, 11 ,12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 39 -}; - -#define BLE_DTM_SYNC_WORD (0x71764129) -#define BLE_DTM_CRC (0x555555) - -static void ble_ll_dtm_ctx_free(struct dtm_ctx * ctx); - -static void -ble_ll_dtm_set_next(struct dtm_ctx *ctx) -{ - struct ble_ll_sched_item *sch = &ctx->sch; - - ctx->pdu_start_ticks += ctx->itvl_ticks; - ctx->pdu_start_usecs += ctx->itvl_rem_usec; - if (ctx->pdu_start_usecs >= 31) { - ctx->pdu_start_ticks++; - ctx->pdu_start_usecs -= 31; - } - - sch->start_time = ctx->pdu_start_ticks; - sch->remainder = ctx->pdu_start_usecs; - - sch->start_time -= g_ble_ll_sched_offset_ticks; -} - -static void -ble_ll_dtm_ev_tx_resched_cb(struct ble_npl_event *evt) { - /* It is called in LL context */ - struct dtm_ctx *ctx = ble_npl_event_get_arg(evt); - int rc; - os_sr_t sr; - - OS_ENTER_CRITICAL(sr); - if (!ctx->active || !ctx->om) { - OS_EXIT_CRITICAL(sr); - return; - } - OS_EXIT_CRITICAL(sr); - -#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) - if (g_ble_ll_dtm_ctx.num_of_packets_max && - (g_ble_ll_dtm_ctx.num_of_packets == g_ble_ll_dtm_ctx.num_of_packets_max)) { - /* - * XXX do not send more packets, but also do not stop DTM - it shall be - * stopped as usual by HCI command since there is no standard way to - * signal end of test to host. - */ - return; - } -#endif - - ble_ll_dtm_set_next(ctx); - rc = ble_ll_sched_dtm(&ctx->sch); - BLE_LL_ASSERT(rc == 0); -} - -static int ble_ll_dtm_rx_start(void); - -static void -ble_ll_dtm_ev_rx_restart_cb(struct ble_npl_event *evt) { - if (ble_ll_dtm_rx_start() != 0) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt); - STATS_INC(ble_ll_dtm_stats, rx_failed); - } -} - -static void -ble_ll_dtm_tx_done(void *arg) -{ - struct dtm_ctx *ctx; - - ctx = arg; - if (!ctx->active) { - return; - } - - g_ble_ll_dtm_ctx.num_of_packets++; - - /* Reschedule event in LL context */ - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &ctx->evt); - - ble_ll_state_set(BLE_LL_STATE_STANDBY); -} - -static int -ble_ll_dtm_tx_sched_cb(struct ble_ll_sched_item *sch) -{ - struct dtm_ctx *ctx = sch->cb_arg; - int rc; - - if (!ctx->active) { - return BLE_LL_SCHED_STATE_DONE; - } - - rc = ble_phy_setchan(channel_rf_to_index[ctx->rf_channel], - BLE_DTM_SYNC_WORD, BLE_DTM_CRC); - if (rc != 0) { - BLE_LL_ASSERT(0); - return BLE_LL_SCHED_STATE_DONE; - } - -#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)) - ble_phy_mode_set(ctx->phy_mode, ctx->phy_mode); -#endif - ble_phy_set_txend_cb(ble_ll_dtm_tx_done, ctx); - ble_phy_txpwr_set(0); - - sch->start_time += g_ble_ll_sched_offset_ticks; - - rc = ble_phy_tx_set_start_time(sch->start_time, sch->remainder); - if (rc) { - goto resched; - } - - rc = ble_phy_tx(ble_ll_tx_mbuf_pducb, ctx->om, BLE_PHY_TRANSITION_NONE); - if (rc) { - goto resched; - } - - ble_ll_state_set(BLE_LL_STATE_DTM); - - return BLE_LL_SCHED_STATE_DONE; - -resched: - /* Reschedule from LL task if late for this PDU */ - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &ctx->evt); - - STATS_INC(ble_ll_dtm_stats, tx_failed); - - return BLE_LL_SCHED_STATE_DONE; -} - -static void -ble_ll_dtm_calculate_itvl(struct dtm_ctx *ctx, uint8_t len, - uint16_t cmd_interval, int phy_mode) -{ - uint32_t l; - uint32_t itvl_usec; - uint32_t itvl_ticks; - - /* Calculate interval as per spec Bluetooth 5.0 Vol 6. Part F, 4.1.6 */ - l = ble_ll_pdu_tx_time_get(len + BLE_LL_PDU_HDR_LEN, phy_mode); - itvl_usec = ((l + 249 + 624) / 625) * 625; - -#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) - if (cmd_interval > itvl_usec) { - itvl_usec = cmd_interval; - } -#endif - - itvl_ticks = os_cputime_usecs_to_ticks(itvl_usec); - ctx->itvl_rem_usec = (itvl_usec - os_cputime_ticks_to_usecs(itvl_ticks)); - if (ctx->itvl_rem_usec == 31) { - ctx->itvl_rem_usec = 0; - ++itvl_ticks; - } - ctx->itvl_ticks = itvl_ticks; -} - -static int -ble_ll_dtm_tx_create_ctx(uint8_t packet_payload, uint8_t len, - uint8_t rf_channel, uint8_t phy_mode, - uint16_t cmd_interval, uint16_t cmd_pkt_count) -{ - int rc = 0; - uint8_t byte_pattern; - struct ble_mbuf_hdr *ble_hdr; - struct os_mbuf *m; - struct dtm_ctx *ctx = &g_ble_ll_dtm_ctx; - struct ble_ll_sched_item *sch = &ctx->sch; - - /* MSYS is big enough to get continues memory */ - m = os_msys_get_pkthdr(len, sizeof(struct ble_mbuf_hdr)); - ctx->om = m; - BLE_LL_ASSERT(g_ble_ll_dtm_ctx.om); - - ctx->phy_mode = phy_mode; - ctx->rf_channel = rf_channel; - ctx->num_of_packets = 0; -#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) - ctx->num_of_packets_max = cmd_pkt_count; -#endif - - /* Set BLE transmit header */ - ble_hdr = BLE_MBUF_HDR_PTR(m); - ble_hdr->txinfo.flags = 0; - ble_hdr->txinfo.offset = 0; - ble_hdr->txinfo.pyld_len = len; - ble_hdr->txinfo.hdr_byte = packet_payload; - - switch(packet_payload) { - case 0x00: - if (os_mbuf_copyinto(m, 0, &g_ble_ll_dtm_prbs9_data, len)) { - return 1; - } - goto schedule; - case 0x01: - byte_pattern = 0x0F; - break; - case 0x02: - byte_pattern = 0x55; - break; - case 0x03: - if (os_mbuf_copyinto(m, 0, &g_ble_ll_dtm_prbs15_data, len)) { - return 1; - } - goto schedule; - case 0x04: - byte_pattern = 0xFF; - break; - case 0x05: - byte_pattern = 0x00; - break; - case 0x06: - byte_pattern = 0xF0; - break; - case 0x07: - byte_pattern = 0xAA; - break; - default: - return 1; - } - - for (rc = 0; rc < len; rc++) { - if (os_mbuf_copyinto(m, rc, &byte_pattern, 1)) { - return 1; - } - } - -schedule: - ble_phy_enable_dtm(); - - sch->sched_cb = ble_ll_dtm_tx_sched_cb; - sch->cb_arg = ctx; - sch->sched_type = BLE_LL_SCHED_TYPE_DTM; - - /* Prepare os_event */ - ble_npl_event_init(&ctx->evt, ble_ll_dtm_ev_tx_resched_cb, ctx); - - ble_ll_dtm_calculate_itvl(ctx, len, cmd_interval, phy_mode); - - ctx->pdu_start_ticks = ble_ll_rfmgmt_enable_now(); - ctx->pdu_start_usecs = 0; - ble_ll_dtm_set_next(ctx); - - /* Set some start point for TX packets */ - rc = ble_ll_sched_dtm(sch); - BLE_LL_ASSERT(rc == 0); - - g_ble_ll_dtm_ctx.active = 1; - return 0; -} - -static int -ble_ll_dtm_rx_start(void) -{ - os_sr_t sr; - int rc; - - rc = ble_phy_setchan(channel_rf_to_index[g_ble_ll_dtm_ctx.rf_channel], - BLE_DTM_SYNC_WORD, BLE_DTM_CRC); - if (rc) { - return rc; - } - -#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)) - ble_phy_mode_set(g_ble_ll_dtm_ctx.phy_mode, g_ble_ll_dtm_ctx.phy_mode); -#endif - - OS_ENTER_CRITICAL(sr); - rc = ble_phy_rx_set_start_time(os_cputime_get32(), 0); - OS_EXIT_CRITICAL(sr); - if (rc && rc != BLE_PHY_ERR_RX_LATE) { - return rc; - } - - ble_ll_state_set(BLE_LL_STATE_DTM); - - return 0; -} - -static int -ble_ll_dtm_rx_sched_cb(struct ble_ll_sched_item *sch) -{ - if (ble_ll_dtm_rx_start() != 0) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt); - STATS_INC(ble_ll_dtm_stats, rx_failed); - } - - return BLE_LL_SCHED_STATE_DONE; -} - -static int -ble_ll_dtm_rx_create_ctx(uint8_t rf_channel, uint8_t phy_mode) -{ - struct ble_ll_sched_item *sch = &g_ble_ll_dtm_ctx.sch; - int rc; - - g_ble_ll_dtm_ctx.phy_mode = phy_mode; - g_ble_ll_dtm_ctx.rf_channel = rf_channel; - - STATS_CLEAR(ble_ll_dtm_stats, rx_count); - - ble_npl_event_init(&g_ble_ll_dtm_ctx.evt, ble_ll_dtm_ev_rx_restart_cb, - NULL); - - sch->sched_cb = ble_ll_dtm_rx_sched_cb; - sch->cb_arg = &g_ble_ll_dtm_ctx; - sch->sched_type = BLE_LL_SCHED_TYPE_DTM; - sch->start_time = ble_ll_rfmgmt_enable_now(); - - rc = ble_ll_sched_dtm(sch); - BLE_LL_ASSERT(rc == 0); - - ble_phy_enable_dtm(); - - g_ble_ll_dtm_ctx.active = 1; - return 0; -} - -static void -ble_ll_dtm_ctx_free(struct dtm_ctx * ctx) -{ - os_sr_t sr; - - OS_ENTER_CRITICAL(sr); - if (!ctx->active) { - OS_EXIT_CRITICAL(sr); - return; - } - - ble_ll_sched_rmv_elem(&ctx->sch); - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt); - - ble_phy_disable(); - ble_phy_disable_dtm(); - ble_ll_state_set(BLE_LL_STATE_STANDBY); - ble_ll_rfmgmt_release(); - - os_mbuf_free_chain(ctx->om); - memset(ctx, 0, sizeof(*ctx)); - OS_EXIT_CRITICAL(sr); -} - -static int -ble_ll_dtm_tx_test(uint8_t tx_chan, uint8_t len, uint8_t packet_payload, - uint8_t hci_phy, uint16_t interval, uint16_t pkt_count) -{ - uint8_t phy_mode; - - if (g_ble_ll_dtm_ctx.active) { - return BLE_ERR_CTLR_BUSY; - } - - switch (hci_phy) { - case BLE_HCI_LE_PHY_1M: - phy_mode = BLE_PHY_MODE_1M; - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - case BLE_HCI_LE_PHY_2M: - phy_mode = BLE_PHY_MODE_2M; - break; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - case BLE_HCI_LE_PHY_CODED_S8: - phy_mode = BLE_PHY_MODE_CODED_125KBPS; - break; - case BLE_HCI_LE_PHY_CODED_S2: - phy_mode = BLE_PHY_MODE_CODED_500KBPS; - break; -#endif - default: - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (tx_chan > 0x27 || packet_payload > 0x07) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (ble_ll_dtm_tx_create_ctx(packet_payload, len, tx_chan, phy_mode, - interval, pkt_count)) { - return BLE_ERR_UNSPECIFIED; - } - - return BLE_ERR_SUCCESS; -} - -#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) -static int -ble_ll_hci_dtm_tx_test_ext(const uint8_t *cmdbuf) -{ - const struct ble_hci_le_tx_test_ext_cp *cmd = (const void *) cmdbuf; - - return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload, - BLE_HCI_LE_PHY_1M, le16toh(cmd->interval), - le16toh(cmd->pkt_count)); -} - -static int -ble_ll_hci_dtm_tx_test_v2_ext(const uint8_t *cmdbuf) -{ - const struct ble_hci_le_tx_test_v2_ext_cp *cmd = (const void *) cmdbuf; - - return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload, - cmd->phy, le16toh(cmd->interval), - le16toh(cmd->pkt_count)); -} -#endif - -int -ble_ll_hci_dtm_tx_test(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_tx_test_cp *cmd = (const void *) cmdbuf; - -#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) - if (len == sizeof(struct ble_hci_le_tx_test_ext_cp)) { - return ble_ll_hci_dtm_tx_test_ext(cmdbuf); - } -#endif - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload, - BLE_HCI_LE_PHY_1M, 0, 0); -} - -int -ble_ll_hci_dtm_tx_test_v2(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_tx_test_v2_cp *cmd = (const void *) cmdbuf; - -#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) - if (len == sizeof(struct ble_hci_le_tx_test_v2_ext_cp)) { - return ble_ll_hci_dtm_tx_test_v2_ext(cmdbuf); - } -#endif - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload, - cmd->phy, 0, 0); -} - -static int -ble_ll_dtm_rx_test(uint8_t rx_chan, uint8_t hci_phy) -{ - uint8_t phy_mode; - - if (g_ble_ll_dtm_ctx.active) { - return BLE_ERR_CTLR_BUSY; - } - - switch (hci_phy) { - case BLE_HCI_LE_PHY_1M: - phy_mode = BLE_PHY_MODE_1M; - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - case BLE_HCI_LE_PHY_2M: - phy_mode = BLE_PHY_MODE_2M; - break; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - case BLE_HCI_LE_PHY_CODED: - phy_mode = BLE_PHY_MODE_CODED_500KBPS; - break; -#endif - default: - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (rx_chan > 0x27) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (ble_ll_dtm_rx_create_ctx(rx_chan, phy_mode)) { - return BLE_ERR_UNSPECIFIED; - } - - return BLE_ERR_SUCCESS; -} - -int ble_ll_hci_dtm_rx_test(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_rx_test_cp *cmd = (const void *) cmdbuf; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return ble_ll_dtm_rx_test(cmd->rx_chan, BLE_HCI_LE_PHY_1M); -} - -int ble_ll_hci_dtm_rx_test_v2(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_rx_test_v2_cp *cmd = (const void *) cmdbuf; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* TODO ignoring modulation index */ - - return ble_ll_dtm_rx_test(cmd->rx_chan, cmd->phy); -} - -int ble_ll_dtm_end_test(uint8_t *rsp, uint8_t *rsplen) -{ - put_le16(rsp, g_ble_ll_dtm_ctx. num_of_packets); - *rsplen = 2; - - ble_ll_dtm_ctx_free(&g_ble_ll_dtm_ctx); - return BLE_ERR_SUCCESS; -} - -int ble_ll_dtm_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa) -{ - return 0; -} - -void -ble_ll_dtm_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) -{ - if (BLE_MBUF_HDR_CRC_OK(hdr)) { - /* XXX Compare data. */ - g_ble_ll_dtm_ctx.num_of_packets++; - STATS_INC(ble_ll_dtm_stats, rx_count); - } - - if (ble_ll_dtm_rx_start() != 0) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt); - STATS_INC(ble_ll_dtm_stats, rx_failed); - } -} - -int -ble_ll_dtm_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) -{ - struct os_mbuf *rxpdu; - - if (!g_ble_ll_dtm_ctx.active) { - return -1; - } - - rxpdu = ble_ll_rxpdu_alloc(rxbuf[1] + BLE_LL_PDU_HDR_LEN); - - /* Copy the received pdu and hand it up */ - if (rxpdu) { - ble_phy_rxpdu_copy(rxbuf, rxpdu); - ble_ll_rx_pdu_in(rxpdu); - } - - return 0; -} - -void -ble_ll_dtm_wfr_timer_exp(void) -{ - /* Should not be needed */ - BLE_LL_ASSERT(0); -} - - -void -ble_ll_dtm_reset(void) -{ - ble_ll_dtm_ctx_free(&g_ble_ll_dtm_ctx); -} - -void -ble_ll_dtm_init(void) -{ - int rc; - - rc = stats_init_and_reg(STATS_HDR(ble_ll_dtm_stats), - STATS_SIZE_INIT_PARMS(ble_ll_dtm_stats, STATS_SIZE_32), - STATS_NAME_INIT_PARMS(ble_ll_dtm_stats), - "ble_ll_dtm"); - SYSINIT_PANIC_ASSERT(rc == 0); -} -#endif -#endif \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_dtm_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_dtm_priv.h deleted file mode 100644 index e04af07be..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_dtm_priv.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_TEST_PRIV_ -#define H_BLE_LL_TEST_PRIV_ - -#include -#include -#include "nimble/ble.h" - -int ble_ll_hci_dtm_tx_test(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_hci_dtm_tx_test_v2(const uint8_t *cmdbuf, uint8_t len); - -int ble_ll_hci_dtm_rx_test(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_hci_dtm_rx_test_v2(const uint8_t *cmdbuf, uint8_t len); - -int ble_ll_dtm_end_test(uint8_t *rsp, uint8_t *rsplen); - -int ble_ll_dtm_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa); -int ble_ll_dtm_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr); -void ble_ll_dtm_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr); -void ble_ll_dtm_wfr_timer_exp(void); -void ble_ll_dtm_reset(void); -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci.c deleted file mode 100644 index d83af2c01..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci.c +++ /dev/null @@ -1,1519 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "nimble/nimble/include/nimble/ble_hci_trans.h" -#include "../include/controller/ble_hw.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_whitelist.h" -#include "../include/controller/ble_ll_resolv.h" -#include "../include/controller/ble_ll_sync.h" -#include "ble_ll_priv.h" -#include "ble_ll_conn_priv.h" - -#if MYNEWT_VAL(BLE_LL_DTM) -#include "ble_ll_dtm_priv.h" -#endif - -static void ble_ll_hci_cmd_proc(struct ble_npl_event *ev); - -/* OS event to enqueue command */ -static struct ble_npl_event g_ble_ll_hci_cmd_ev; - -/* LE event mask */ -static uint64_t g_ble_ll_hci_le_event_mask; -static uint64_t g_ble_ll_hci_event_mask; -static uint64_t g_ble_ll_hci_event_mask2; - -static int16_t rx_path_pwr_compensation; -static int16_t tx_path_pwr_compensation; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static enum { - ADV_MODE_ANY, - ADV_MODE_LEGACY, - ADV_MODE_EXT, -} hci_adv_mode; - -bool ble_ll_hci_adv_mode_ext(void) -{ - return hci_adv_mode == ADV_MODE_EXT; -} -#else -bool -ble_ll_hci_adv_mode_ext(void) -{ - return false; -} -#endif - -/** - * ll hci get num cmd pkts - * - * Returns the number of command packets that the host is allowed to send - * to the controller. - * - * @return uint8_t - */ -static uint8_t -ble_ll_hci_get_num_cmd_pkts(void) -{ - return BLE_LL_CFG_NUM_HCI_CMD_PKTS; -} - -/** - * Send an event to the host. - * - * @param evbuf Pointer to event buffer to send - * - * @return int 0: success; -1 otherwise. - */ -int -ble_ll_hci_event_send(struct ble_hci_ev *hci_ev) -{ - int rc; - - BLE_LL_DEBUG_GPIO(HCI_EV, 1); - - BLE_LL_ASSERT(sizeof(*hci_ev) + hci_ev->length <= BLE_LL_MAX_EVT_LEN); - - /* Count number of events sent */ - STATS_INC(ble_ll_stats, hci_events_sent); - - /* Send the event to the host */ - rc = ble_hci_trans_ll_evt_tx((uint8_t *)hci_ev); - - BLE_LL_DEBUG_GPIO(HCI_EV, 0); - - return rc; -} - -/** - * Created and sends a command complete event with the no-op opcode to the - * host. - */ -void -ble_ll_hci_send_noop(void) -{ - struct ble_hci_ev_command_complete_nop *ev; - struct ble_hci_ev *hci_ev; - - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - /* Create a command complete event with a NO-OP opcode */ - hci_ev->opcode = BLE_HCI_EVCODE_COMMAND_COMPLETE; - - hci_ev->length = sizeof(*ev); - ev = (void *)hci_ev->data; - - ev->num_packets = ble_ll_hci_get_num_cmd_pkts(); - ev->opcode = BLE_HCI_OPCODE_NOP; - - ble_ll_hci_event_send(hci_ev); - } -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/** - * LE encrypt command - * - * @param cmdbuf - * @param rspbuf - * @param rsplen - * - * @return int - */ -static int -ble_ll_hci_le_encrypt(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, - uint8_t *rsplen) -{ - const struct ble_hci_le_encrypt_cp *cmd = (const void *) cmdbuf; - struct ble_hci_le_encrypt_rp *rsp = (void *)rspbuf; - struct ble_encryption_block ecb; - int rc; - - /* Call the link layer to encrypt the data */ - swap_buf(ecb.key, cmd->key, BLE_ENC_BLOCK_SIZE); - swap_buf(ecb.plain_text, cmd->data, BLE_ENC_BLOCK_SIZE); - rc = ble_hw_encrypt_block(&ecb); - if (!rc) { - swap_buf(rsp->data, ecb.cipher_text, BLE_ENC_BLOCK_SIZE); - *rsplen = sizeof(*rsp); - rc = BLE_ERR_SUCCESS; - } else { - rc = BLE_ERR_CTLR_BUSY; - } - - return rc; -} -#endif - -/** - * LE rand command - * - * @param cmdbuf - * @param rspbuf - * @param rsplen - * - * @return int - */ -static int -ble_ll_hci_le_rand(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_le_rand_rp *rsp = (void *) rspbuf; - - ble_ll_rand_data_get((uint8_t *)&rsp->random_number, - sizeof(rsp->random_number)); - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} - -/** - * Read local version - * - * @param rspbuf - * @param rsplen - * - * @return int - */ -static int -ble_ll_hci_rd_local_version(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_ip_rd_local_ver_rp *rsp = (void *) rspbuf; - - rsp->hci_ver = BLE_HCI_VER_BCS; - rsp->hci_rev = 0; - rsp->lmp_ver = BLE_LMP_VER_BCS; - rsp->manufacturer = htole16(MYNEWT_VAL(BLE_LL_MFRG_ID)); - rsp->lmp_subver = 0; - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} - -/** - * Read local supported features - * - * @param rspbuf - * @param rsplen - * - * @return int - */ -static int -ble_ll_hci_rd_local_supp_feat(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_ip_rd_loc_supp_feat_rp *rsp = (void *) rspbuf; - - /* - * The only two bits we set here currently are (5th byte): - * BR/EDR not supported (bit 5) - * LE supported (controller) (bit 6) - */ - rsp->features = htole64(0x0000006000000000); - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} - -/** - * Read local supported commands - * - * @param rspbuf - * @param rsplen - * - * @return int - */ -static int -ble_ll_hci_rd_local_supp_cmd(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_ip_rd_loc_supp_cmd_rp *rsp = (void *) rspbuf; - - memset(rsp->commands, 0, sizeof(rsp->commands)); - memcpy(rsp->commands, g_ble_ll_supp_cmds, sizeof(g_ble_ll_supp_cmds)); - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} - -/** - * Called to read the public device address of the device - * - * - * @param rspbuf - * @param rsplen - * - * @return int - */ -static int -ble_ll_hci_rd_bd_addr(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_ip_rd_bd_addr_rp *rsp = (void *) rspbuf; - - memcpy(rsp->addr, g_dev_addr, BLE_DEV_ADDR_LEN); - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} - -/** - * ll hci set le event mask - * - * Called when the LL controller receives a set LE event mask command. - * - * Context: Link Layer task (HCI command parser) - * - * @param cmdbuf Pointer to command buf. - * - * @return int BLE_ERR_SUCCESS. Does not return any errors. - */ -static int -ble_ll_hci_set_le_event_mask(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_event_mask_cp *cmd = (const void *) cmdbuf; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - g_ble_ll_hci_le_event_mask = le64toh(cmd->event_mask); - - return BLE_ERR_SUCCESS; -} - -/** - * HCI read buffer size command. Returns the ACL data packet length and - * num data packets. - * - * @param rspbuf Pointer to response buffer - * @param rsplen Length of response buffer - * - * @return int BLE error code - */ -static int -ble_ll_hci_le_read_bufsize(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_le_rd_buf_size_rp *rp = (void *) rspbuf; - - rp->data_len = htole16(g_ble_ll_data.ll_acl_pkt_size); - rp->data_packets = g_ble_ll_data.ll_num_acl_pkts; - - *rsplen = sizeof(*rp); - return BLE_ERR_SUCCESS; -} - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) -/** - * Checks the preferred phy masks for validity and places the preferred masks - * in the input phy masks - - * @return int BLE_ERR_SUCCESS or BLE_ERR_INV_HCI_CMD_PARMS or BLE_ERR_UNSUPPORTED - */ -int -ble_ll_hci_chk_phy_masks(uint8_t all_phys, uint8_t tx_phys, uint8_t rx_phys, - uint8_t *txphy, uint8_t *rxphy) -{ - /* Check for RFU */ - if ((tx_phys & ~BLE_HCI_LE_PHY_PREF_MASK_ALL) || - (rx_phys & ~BLE_HCI_LE_PHY_PREF_MASK_ALL)) { - return BLE_ERR_UNSUPPORTED; - } - - if ((!(all_phys & BLE_HCI_LE_PHY_NO_TX_PREF_MASK) && (tx_phys == 0)) || - (!(all_phys & BLE_HCI_LE_PHY_NO_RX_PREF_MASK) && (rx_phys == 0))) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* If phy not supported, return error */ -#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - if((tx_phys & BLE_HCI_LE_PHY_2M_PREF_MASK) || - (rx_phys & BLE_HCI_LE_PHY_2M_PREF_MASK)) { - return BLE_ERR_UNSUPPORTED; - } -#endif -#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - if ((tx_phys & BLE_HCI_LE_PHY_CODED_PREF_MASK) || - (rx_phys & BLE_HCI_LE_PHY_CODED_PREF_MASK)) { - return BLE_ERR_UNSUPPORTED; - } -#endif - /* Set the default PHY preferences */ - if (all_phys & BLE_HCI_LE_PHY_NO_TX_PREF_MASK) { - tx_phys = BLE_HCI_LE_PHY_PREF_MASK_ALL; - } - *txphy = tx_phys; - - if (all_phys & BLE_HCI_LE_PHY_NO_RX_PREF_MASK) { - rx_phys = BLE_HCI_LE_PHY_PREF_MASK_ALL; - } - *rxphy = rx_phys; - - return BLE_ERR_SUCCESS; -} - -/** - * Set PHY preferences for connection - * - * @param cmdbuf - * - * @return int - */ -static int -ble_ll_hci_le_set_def_phy(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_default_phy_cp *cmd = (const void *) cmdbuf; - int rc; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - rc = ble_ll_hci_chk_phy_masks(cmd->all_phys, cmd->tx_phys, cmd->rx_phys, - &g_ble_ll_data.ll_pref_tx_phys, - &g_ble_ll_data.ll_pref_rx_phys); - return rc; -} -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) -/** - * HCI write suggested default data length command. - * - * This command is used by the host to change the initial max tx octets/time - * for all connections. Note that if the controller does not support the - * requested times no error is returned; the controller simply ignores the - * request (but remembers what the host requested for the read suggested - * default data length command). The spec allows for the controller to - * disregard the host. - * - * @param rspbuf Pointer to response buffer - * @param rsplen Length of response buffer - * - * @return int BLE error code - */ -static int -ble_ll_hci_le_wr_sugg_data_len(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_wr_sugg_def_data_len_cp *cmd = (const void*) cmdbuf; - uint16_t tx_oct; - uint16_t tx_time; - int rc; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Get suggested octets and time */ - tx_oct = le16toh(cmd->max_tx_octets); - tx_time = le16toh(cmd->max_tx_time); - - /* If valid, write into suggested and change connection initial times */ - if (ble_ll_chk_txrx_octets(tx_oct) && ble_ll_chk_txrx_time(tx_time)) { - g_ble_ll_conn_params.sugg_tx_octets = (uint8_t)tx_oct; - g_ble_ll_conn_params.sugg_tx_time = tx_time; - - /* - * We can disregard host suggestion, but we are a nice controller so - * let's use host suggestion, unless they exceed max supported values - * in which case we just use our max. - */ - g_ble_ll_conn_params.conn_init_max_tx_octets = - min(tx_oct, g_ble_ll_conn_params.supp_max_tx_octets); - g_ble_ll_conn_params.conn_init_max_tx_time = - min(tx_time, g_ble_ll_conn_params.supp_max_tx_time); - - /* - * Use the same for coded and uncoded defaults. These are used when PHY - * parameters are initialized and we want to use values overridden by - * host. Make sure we do not exceed max supported time on uncoded. - */ - g_ble_ll_conn_params.conn_init_max_tx_time_uncoded = - min(BLE_LL_CONN_SUPP_TIME_MAX_UNCODED, - g_ble_ll_conn_params.conn_init_max_tx_time); - g_ble_ll_conn_params.conn_init_max_tx_time_coded = - g_ble_ll_conn_params.conn_init_max_tx_time; - - rc = BLE_ERR_SUCCESS; - } else { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - } - - return rc; -} - -/** - * HCI read suggested default data length command. Returns the controllers - * initial max tx octet/time. - * - * @param rspbuf Pointer to response buffer - * @param rsplen Length of response buffer - * - * @return int BLE error code - */ -static int -ble_ll_hci_le_rd_sugg_data_len(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_le_rd_sugg_def_data_len_rp *rsp = (void *) rspbuf; - - /* Place the data packet length and number of packets in the buffer */ - rsp->max_tx_octets = htole16(g_ble_ll_conn_params.sugg_tx_octets); - rsp->max_tx_time = htole16(g_ble_ll_conn_params.sugg_tx_time); - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} - -/** - * HCI read maximum data length command. Returns the controllers max supported - * rx/tx octets/times. - * - * @param rspbuf Pointer to response buffer - * @param rsplen Length of response buffer - * - * @return int BLE error code - */ -static int -ble_ll_hci_le_rd_max_data_len(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_le_rd_max_data_len_rp *rsp = (void *)rspbuf; - - /* Place the data packet length and number of packets in the buffer */ - rsp->max_tx_octests = htole16(g_ble_ll_conn_params.supp_max_tx_octets); - rsp->max_tx_time = htole16(g_ble_ll_conn_params.supp_max_tx_time); - rsp->max_rx_octests = htole16(g_ble_ll_conn_params.supp_max_rx_octets); - rsp->max_rx_time = htole16(g_ble_ll_conn_params.supp_max_rx_time); - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} -#endif - -/** - * HCI read local supported features command. Returns the features - * supported by the controller. - * - * @param rspbuf Pointer to response buffer - * @param rsplen Length of response buffer - * - * @return int BLE error code - */ -static int -ble_ll_hci_le_read_local_features(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_le_rd_loc_supp_feat_rp *rsp = (void *) rspbuf; - - rsp->features = htole64(ble_ll_read_supp_features()); - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} - -/** - * HCI read local supported states command. Returns the states - * supported by the controller. - * - * @param rspbuf Pointer to response buffer - * @param rsplen Length of response buffer - * - * @return int BLE error code - */ -static int -ble_ll_hci_le_read_supp_states(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_le_rd_supp_states_rp *rsp = (void *) rspbuf; - - /* Add list of supported states. */ - rsp->states = htole64(ble_ll_read_supp_states()); - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} - - -/** - * Checks to see if a LE event has been disabled by the host. - * - * @param subev Sub-event code of the LE Meta event. Note that this can - * be a value from 1 to 64, inclusive. - * - * @return uint8_t 0: event is not enabled; otherwise event is enabled. - */ -bool -ble_ll_hci_is_le_event_enabled(unsigned int subev) -{ - /* The LE meta event must be enabled for any LE event to be enabled */ - if (g_ble_ll_hci_event_mask & (1ull << (BLE_HCI_EVCODE_LE_META - 1))) { - return g_ble_ll_hci_le_event_mask & (1ull << (subev - 1)); - } - - return false; -} - -/** - * Checks to see if an event has been disabled by the host. - * - * NOTE: there are two "pages" of event masks; the first page is for event - * codes between 0 and 63 and the second page is for event codes 64 and - * greater. - * - * @param evcode This is the event code for the event. - * - * @return uint8_t 0: event is not enabled; otherwise event is enabled. - */ -bool -ble_ll_hci_is_event_enabled(unsigned int evcode) -{ - if (evcode >= 64) { - return g_ble_ll_hci_event_mask2 & (1ull << (evcode - 64)); - } - - return g_ble_ll_hci_event_mask & (1ull << (evcode - 1)); -} - -/** - * Called to determine if the reply to the command should be a command complete - * event or a command status event. - * - * @param ocf - * - * @return int 0: return command complete; 1: return command status event - */ -static int -ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf) -{ - int rc; - - switch (ocf) { - case BLE_HCI_OCF_LE_RD_REM_FEAT: - case BLE_HCI_OCF_LE_CREATE_CONN: - case BLE_HCI_OCF_LE_EXT_CREATE_CONN: - case BLE_HCI_OCF_LE_CONN_UPDATE: - case BLE_HCI_OCF_LE_START_ENCRYPT: - case BLE_HCI_OCF_LE_RD_P256_PUBKEY: - case BLE_HCI_OCF_LE_GEN_DHKEY: - case BLE_HCI_OCF_LE_SET_PHY: - case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC: - rc = 1; - break; - default: - rc = 0; - break; - } - return rc; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -/** HCI LE read maximum advertising data length command. Returns the controllers -* max supported advertising data length; -* -* @param rspbuf Pointer to response buffer -* @param rsplen Length of response buffer -* -* @return int BLE error code -*/ -static int -ble_ll_adv_rd_max_adv_data_len(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_le_rd_max_adv_data_len_rp *rsp = (void *) rspbuf; - - rsp->max_adv_data_len = htole16(BLE_ADV_DATA_MAX_LEN); - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} - -/** - * HCI LE read number of supported advertising sets - * - * @param rspbuf Pointer to response buffer - * @param rsplen Length of response buffer - * - * @return int BLE error code - */ -static int -ble_ll_adv_rd_sup_adv_sets(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_le_rd_num_of_adv_sets_rp *rsp = (void *)rspbuf; - - rsp->num_sets = BLE_ADV_INSTANCES; - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} - -static bool -ble_ll_is_valid_adv_mode(uint8_t ocf) -{ - /* - * If, since the last power-on or reset, the Host has ever issued a legacy - * advertising command and then issues an extended advertising command, or - * has ever issued an extended advertising command and then issues a legacy - * advertising command, the Controller shall return the error code Command - * Disallowed (0x0C). - */ - - switch(ocf) { - case BLE_HCI_OCF_LE_CREATE_CONN: - case BLE_HCI_OCF_LE_SET_ADV_PARAMS: - case BLE_HCI_OCF_LE_SET_ADV_ENABLE: - case BLE_HCI_OCF_LE_SET_ADV_DATA: - case BLE_HCI_OCF_LE_SET_SCAN_PARAMS: - case BLE_HCI_OCF_LE_SET_SCAN_ENABLE: - case BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA: - case BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR: - if (hci_adv_mode == ADV_MODE_EXT) { - return false; - } - - hci_adv_mode = ADV_MODE_LEGACY; - break; - case BLE_HCI_OCF_LE_EXT_CREATE_CONN: - case BLE_HCI_OCF_LE_SET_EXT_ADV_DATA: - case BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE: - case BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM: - case BLE_HCI_OCF_LE_SET_EXT_SCAN_ENABLE: - case BLE_HCI_OCF_LE_SET_EXT_SCAN_PARAM: - case BLE_HCI_OCF_LE_SET_EXT_SCAN_RSP_DATA: - case BLE_HCI_OCF_LE_RD_MAX_ADV_DATA_LEN: - case BLE_HCI_OCF_LE_RD_NUM_OF_ADV_SETS: - case BLE_HCI_OCF_LE_REMOVE_ADV_SET: - case BLE_HCI_OCF_LE_CLEAR_ADV_SETS: - case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS: - case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA: - case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE: - case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC: - case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL: - case BLE_HCI_OCF_LE_PERIODIC_ADV_TERM_SYNC: - case BLE_HCI_OCF_LE_ADD_DEV_TO_PERIODIC_ADV_LIST: - case BLE_HCI_OCF_LE_REM_DEV_FROM_PERIODIC_ADV_LIST: - case BLE_HCI_OCF_LE_CLEAR_PERIODIC_ADV_LIST: - case BLE_HCI_OCF_LE_RD_PERIODIC_ADV_LIST_SIZE: -#if MYNEWT_VAL(BLE_VERSION) >= 51 - case BLE_HCI_OCF_LE_PERIODIC_ADV_RECEIVE_ENABLE: -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - case BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER: - case BLE_HCI_OCF_LE_PERIODIC_ADV_SET_INFO_TRANSFER: - case BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER_PARAMS: - case BLE_HCI_OCF_LE_SET_DEFAULT_SYNC_TRANSFER_PARAMS: -#endif - if (hci_adv_mode == ADV_MODE_LEGACY) { - return false; - } - - hci_adv_mode = ADV_MODE_EXT; - break; - default: - break; - } - - return true; -} -#endif - -static int -ble_ll_read_tx_power(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_le_rd_transmit_power_rp *rsp = (void *) rspbuf; - - rsp->min_tx_power = ble_phy_txpower_round(-127); - rsp->max_tx_power = ble_phy_txpower_round(126); - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} - -static int -ble_ll_read_rf_path_compensation(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_le_rd_rf_path_compensation_rp *rsp = (void *) rspbuf; - - rsp->rx_path_compensation = htole16(rx_path_pwr_compensation); - rsp->tx_path_compensation = htole16(tx_path_pwr_compensation); - - *rsplen = sizeof(*rsp);; - return BLE_ERR_SUCCESS; -} - -static int -ble_ll_write_rf_path_compensation(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_wr_rf_path_compensation_cp *cmd = (const void *)cmdbuf; - int16_t rx; - int16_t tx; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - tx = le16toh(cmd->tx_path_compensation); - rx = le16toh(cmd->rx_path_compensation); - - if ((tx < -1280) || (tx > 1280) || (rx < -1280) || (rx > 1280)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - tx_path_pwr_compensation = tx; - rx_path_pwr_compensation = rx; - - ble_phy_set_rx_pwr_compensation(rx_path_pwr_compensation / 10); - - return BLE_ERR_SUCCESS; -} - -int8_t -ble_ll_get_tx_pwr_compensation(void) -{ - return tx_path_pwr_compensation / 10; -} - -/** - * Process a LE command sent from the host to the controller. The HCI command - * has a 3 byte command header followed by data. The header is: - * -> opcode (2 bytes) - * -> Length of parameters (1 byte; does include command header bytes). - * - * @param cmdbuf Pointer to command buffer. Points to start of command header. - * @param ocf Opcode command field. - * @param *rsplen Pointer to length of response - * - * @return int This function returns a BLE error code. If a command status - * event should be returned as opposed to command complete, - * 256 gets added to the return value. - */ -static int -ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, - uint8_t *rspbuf, uint8_t *rsplen, - ble_ll_hci_post_cmd_complete_cb *cb) -{ - int rc; - - /* Assume error; if all pass rc gets set to 0 */ - rc = BLE_ERR_INV_HCI_CMD_PARMS; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (!ble_ll_is_valid_adv_mode(ocf)) { - rc = BLE_ERR_CMD_DISALLOWED; - - /* - * This code is here because we add 256 to the return code to denote - * that the reply to this command should be command status (as opposed to - * command complete). - * - * For unknown HCI command let us return always command status as per - * specification Bluetooth 5, Vol. 2, Chapter 4.4 - */ - if (ble_ll_hci_le_cmd_send_cmd_status(ocf)) { - rc += (BLE_ERR_MAX + 1); - } - - return rc; - } -#endif - - switch (ocf) { - case BLE_HCI_OCF_LE_SET_EVENT_MASK: - rc = ble_ll_hci_set_le_event_mask(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_RD_BUF_SIZE: - if (len == 0) { - rc = ble_ll_hci_le_read_bufsize(rspbuf, rsplen); - } - break; - case BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT: - if (len == 0) { - rc = ble_ll_hci_le_read_local_features(rspbuf, rsplen); - } - break; - case BLE_HCI_OCF_LE_SET_RAND_ADDR: -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - rc = ble_ll_set_random_addr(cmdbuf, len, hci_adv_mode == ADV_MODE_EXT); -#else - rc = ble_ll_set_random_addr(cmdbuf, len, false); -#endif - break; - case BLE_HCI_OCF_LE_SET_ADV_PARAMS: - rc = ble_ll_adv_set_adv_params(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR: - if (len == 0) { - rc = ble_ll_adv_read_txpwr(rspbuf, rsplen); - } - break; - case BLE_HCI_OCF_LE_SET_ADV_DATA: - rc = ble_ll_hci_set_adv_data(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA: - rc = ble_ll_hci_set_scan_rsp_data(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_SET_ADV_ENABLE: - rc = ble_ll_hci_adv_set_enable(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_SET_SCAN_PARAMS: - rc = ble_ll_scan_set_scan_params(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_SET_SCAN_ENABLE: - rc = ble_ll_hci_scan_set_enable(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_CREATE_CONN: - rc = ble_ll_conn_create(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_CREATE_CONN_CANCEL: - if (len == 0) { - rc = ble_ll_conn_create_cancel(cb); - } - break; - case BLE_HCI_OCF_LE_RD_WHITE_LIST_SIZE: - if (len == 0) { - rc = ble_ll_whitelist_read_size(rspbuf, rsplen); - } - break; - case BLE_HCI_OCF_LE_CLEAR_WHITE_LIST: - if (len == 0) { - rc = ble_ll_whitelist_clear(); - } - break; - case BLE_HCI_OCF_LE_ADD_WHITE_LIST: - rc = ble_ll_whitelist_add(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_RMV_WHITE_LIST: - rc = ble_ll_whitelist_rmv(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_CONN_UPDATE: - rc = ble_ll_conn_hci_update(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS: - rc = ble_ll_conn_hci_set_chan_class(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_RD_CHAN_MAP: - rc = ble_ll_conn_hci_rd_chan_map(cmdbuf, len, rspbuf, rsplen); - break; - case BLE_HCI_OCF_LE_RD_REM_FEAT: - rc = ble_ll_conn_hci_read_rem_features(cmdbuf, len); - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - case BLE_HCI_OCF_LE_ENCRYPT: - rc = ble_ll_hci_le_encrypt(cmdbuf, len, rspbuf, rsplen); - break; -#endif - case BLE_HCI_OCF_LE_RAND: - if (len == 0) { - rc = ble_ll_hci_le_rand(rspbuf, rsplen); - } - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - case BLE_HCI_OCF_LE_START_ENCRYPT: - rc = ble_ll_conn_hci_le_start_encrypt(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY: - rc = ble_ll_conn_hci_le_ltk_reply(cmdbuf, len, rspbuf, rsplen); - break; - case BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY: - rc = ble_ll_conn_hci_le_ltk_neg_reply(cmdbuf, len, rspbuf, rsplen); - break; -#endif - case BLE_HCI_OCF_LE_RD_SUPP_STATES : - if (len == 0) { - rc = ble_ll_hci_le_read_supp_states(rspbuf, rsplen); - } - break; -#if MYNEWT_VAL(BLE_LL_DTM) - case BLE_HCI_OCF_LE_TX_TEST: - rc = ble_ll_hci_dtm_tx_test(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_RX_TEST: - rc = ble_ll_hci_dtm_rx_test(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_TEST_END: - if (len == 0) { - rc = ble_ll_dtm_end_test(rspbuf, rsplen); - } - break; -#endif - case BLE_HCI_OCF_LE_REM_CONN_PARAM_RR: - rc = ble_ll_conn_hci_param_rr(cmdbuf, len, rspbuf, rsplen); - break; - case BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR: - rc = ble_ll_conn_hci_param_nrr(cmdbuf, len, rspbuf, rsplen); - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) - case BLE_HCI_OCF_LE_SET_DATA_LEN: - rc = ble_ll_conn_hci_set_data_len(cmdbuf, len, rspbuf, rsplen); - break; - case BLE_HCI_OCF_LE_RD_SUGG_DEF_DATA_LEN: - if (len == 0) { - rc = ble_ll_hci_le_rd_sugg_data_len(rspbuf, rsplen); - } - break; - case BLE_HCI_OCF_LE_WR_SUGG_DEF_DATA_LEN: - rc = ble_ll_hci_le_wr_sugg_data_len(cmdbuf, len); - break; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - case BLE_HCI_OCF_LE_ADD_RESOLV_LIST: - rc = ble_ll_resolv_list_add(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_RMV_RESOLV_LIST: - rc = ble_ll_resolv_list_rmv(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_CLR_RESOLV_LIST: - if (len == 0) { - rc = ble_ll_resolv_list_clr(); - } - break; - case BLE_HCI_OCF_LE_RD_RESOLV_LIST_SIZE: - if (len == 0) { - rc = ble_ll_resolv_list_read_size(rspbuf, rsplen); - } - break; - case BLE_HCI_OCF_LE_RD_PEER_RESOLV_ADDR: - rc = ble_ll_resolv_peer_addr_rd(cmdbuf, len, rspbuf, rsplen); - break; - case BLE_HCI_OCF_LE_RD_LOCAL_RESOLV_ADDR: - rc = ble_ll_resolv_local_addr_rd(cmdbuf, len, rspbuf, rsplen); - break; - case BLE_HCI_OCF_LE_SET_ADDR_RES_EN: - rc = ble_ll_resolv_enable_cmd(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_SET_RPA_TMO: - rc = ble_ll_resolv_set_rpa_tmo(cmdbuf, len); - break; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) - case BLE_HCI_OCF_LE_RD_MAX_DATA_LEN: - if (len == 0) { - rc = ble_ll_hci_le_rd_max_data_len(rspbuf, rsplen); - } - break; -#endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - case BLE_HCI_OCF_LE_RD_PHY: - rc = ble_ll_conn_hci_le_rd_phy(cmdbuf, len, rspbuf, rsplen); - break; - case BLE_HCI_OCF_LE_SET_DEFAULT_PHY: - rc = ble_ll_hci_le_set_def_phy(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_SET_PHY: - rc = ble_ll_conn_hci_le_set_phy(cmdbuf, len); - break; -#endif -#if MYNEWT_VAL(BLE_LL_DTM) - case BLE_HCI_OCF_LE_RX_TEST_V2: - rc = ble_ll_hci_dtm_rx_test_v2(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_TX_TEST_V2: - rc = ble_ll_hci_dtm_tx_test_v2(cmdbuf, len); - break; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - case BLE_HCI_OCF_LE_SET_ADV_SET_RND_ADDR: - rc = ble_ll_adv_hci_set_random_addr(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM: - rc = ble_ll_adv_ext_set_param(cmdbuf, len, rspbuf, rsplen); - break; - case BLE_HCI_OCF_LE_SET_EXT_ADV_DATA: - rc = ble_ll_adv_ext_set_adv_data(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_SET_EXT_SCAN_RSP_DATA: - rc = ble_ll_adv_ext_set_scan_rsp(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE: - rc = ble_ll_adv_ext_set_enable(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_RD_MAX_ADV_DATA_LEN: - if (len == 0) { - rc = ble_ll_adv_rd_max_adv_data_len(rspbuf, rsplen); - } - break; - case BLE_HCI_OCF_LE_RD_NUM_OF_ADV_SETS: - if (len == 0) { - rc = ble_ll_adv_rd_sup_adv_sets(rspbuf, rsplen); - } - break; - case BLE_HCI_OCF_LE_REMOVE_ADV_SET: - rc = ble_ll_adv_remove(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_CLEAR_ADV_SETS: - if (len == 0) { - rc = ble_ll_adv_clear_all(); - } - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS: - rc = ble_ll_adv_periodic_set_param(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA: - rc = ble_ll_adv_periodic_set_data(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE: - rc = ble_ll_adv_periodic_enable(cmdbuf, len); - break; -#endif -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - case BLE_HCI_OCF_LE_SET_EXT_SCAN_PARAM: - rc = ble_ll_set_ext_scan_params(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_SET_EXT_SCAN_ENABLE: - rc = ble_ll_hci_ext_scan_set_enable(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_EXT_CREATE_CONN: - rc = ble_ll_ext_conn_create(cmdbuf, len); - break; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC: - rc = ble_ll_sync_create(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL: - if (len == 0) { - rc = ble_ll_sync_cancel(cb); - } - break; - case BLE_HCI_OCF_LE_PERIODIC_ADV_TERM_SYNC: - rc = ble_ll_sync_terminate(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_ADD_DEV_TO_PERIODIC_ADV_LIST: - rc = ble_ll_sync_list_add(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_REM_DEV_FROM_PERIODIC_ADV_LIST: - rc = ble_ll_sync_list_remove(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_CLEAR_PERIODIC_ADV_LIST: - if (len == 0) { - rc = ble_ll_sync_list_clear(); - } - break; - case BLE_HCI_OCF_LE_RD_PERIODIC_ADV_LIST_SIZE: - if (len == 0) { - rc = ble_ll_sync_list_size(rspbuf, rsplen); - } - break; -#if MYNEWT_VAL(BLE_VERSION) >= 51 - case BLE_HCI_OCF_LE_PERIODIC_ADV_RECEIVE_ENABLE: - rc = ble_ll_sync_receive_enable(cmdbuf, len); - break; -#endif -#endif - case BLE_HCI_OCF_LE_RD_TRANSMIT_POWER: - rc = ble_ll_read_tx_power(rspbuf, rsplen); - break; - case BLE_HCI_OCF_LE_RD_RF_PATH_COMPENSATION: - rc = ble_ll_read_rf_path_compensation(rspbuf, rsplen); - break; - case BLE_HCI_OCF_LE_WR_RF_PATH_COMPENSATION: - rc = ble_ll_write_rf_path_compensation(cmdbuf, len); - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - case BLE_HCI_OCF_LE_SET_PRIVACY_MODE: - rc = ble_ll_resolve_set_priv_mode(cmdbuf, len); - break; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - case BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER: - rc = ble_ll_sync_transfer(cmdbuf, len, rspbuf, rsplen); - break; - case BLE_HCI_OCF_LE_PERIODIC_ADV_SET_INFO_TRANSFER: - rc = ble_ll_adv_periodic_set_info_transfer(cmdbuf, len, rspbuf, rsplen); - break; - case BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER_PARAMS: - rc = ble_ll_set_sync_transfer_params(cmdbuf, len, rspbuf, rsplen); - break; - case BLE_HCI_OCF_LE_SET_DEFAULT_SYNC_TRANSFER_PARAMS: - rc = ble_ll_set_default_sync_transfer_params(cmdbuf, len); - break; -#endif -#if MYNEWT_VAL(BLE_VERSION) >= 52 - case BLE_HCI_OCF_LE_SET_HOST_FEAT: - rc = ble_ll_set_host_feat(cmdbuf, len); - break; -#endif - default: - rc = BLE_ERR_UNKNOWN_HCI_CMD; - break; - } - - /* - * This code is here because we add 256 to the return code to denote - * that the reply to this command should be command status (as opposed to - * command complete). - * - * For unknown HCI command let us return always command status as per - * specification Bluetooth 5, Vol. 2, Chapter 4.4 - */ - if (ble_ll_hci_le_cmd_send_cmd_status(ocf) || rc == BLE_ERR_UNKNOWN_HCI_CMD) { - rc += (BLE_ERR_MAX + 1); - } - - return rc; -} - -/** - * Process a link control command sent from the host to the controller. The HCI - * command has a 3 byte command header followed by data. The header is: - * -> opcode (2 bytes) - * -> Length of parameters (1 byte; does include command header bytes). - * - * @param cmdbuf Pointer to command buffer. Points to start of command header. - * @param ocf Opcode command field. - * - * @return int This function returns a BLE error code. If a command status - * event should be returned as opposed to command complete, - * 256 gets added to the return value. - */ -static int -ble_ll_hci_link_ctrl_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf) -{ - int rc; - - switch (ocf) { - case BLE_HCI_OCF_DISCONNECT_CMD: - rc = ble_ll_conn_hci_disconnect_cmd(cmdbuf, len); - /* Send command status instead of command complete */ - rc += (BLE_ERR_MAX + 1); - break; - - case BLE_HCI_OCF_RD_REM_VER_INFO: - rc = ble_ll_conn_hci_rd_rem_ver_cmd(cmdbuf, len); - /* Send command status instead of command complete */ - rc += (BLE_ERR_MAX + 1); - break; - - default: - rc = BLE_ERR_UNKNOWN_HCI_CMD; - break; - } - - return rc; -} - -static int -ble_ll_hci_cb_set_event_mask(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_cb_set_event_mask_cp *cmd = (const void *) cmdbuf; - - if (len != sizeof (*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - g_ble_ll_hci_event_mask = le64toh(cmd->event_mask); - - return BLE_ERR_SUCCESS; -} - -static int -ble_ll_hci_cb_set_event_mask2(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_cb_set_event_mask2_cp *cmd = (const void *) cmdbuf; - - if (len != sizeof (*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - g_ble_ll_hci_event_mask2 = le64toh(cmd->event_mask2); - - return BLE_ERR_SUCCESS; -} - -static int -ble_ll_hci_ctlr_bb_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, - uint8_t *rspbuf, uint8_t *rsplen) -{ - int rc; - - /* Assume error; if all pass rc gets set to 0 */ - rc = BLE_ERR_INV_HCI_CMD_PARMS; - - switch (ocf) { - case BLE_HCI_OCF_CB_SET_EVENT_MASK: - rc = ble_ll_hci_cb_set_event_mask(cmdbuf, len); - break; - case BLE_HCI_OCF_CB_RESET: - if (len == 0) { - rc = ble_ll_reset(); - } - break; - case BLE_HCI_OCF_CB_SET_EVENT_MASK2: - rc = ble_ll_hci_cb_set_event_mask2(cmdbuf, len); - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) - case BLE_HCI_OCF_CB_RD_AUTH_PYLD_TMO: - rc = ble_ll_conn_hci_rd_auth_pyld_tmo(cmdbuf, len, rspbuf, rsplen); - break; - case BLE_HCI_OCF_CB_WR_AUTH_PYLD_TMO: - rc = ble_ll_conn_hci_wr_auth_pyld_tmo(cmdbuf, len, rspbuf, rsplen); - break; -#endif - default: - rc = BLE_ERR_UNKNOWN_HCI_CMD; - break; - } - - return rc; -} - -static int -ble_ll_hci_info_params_cmd_proc(const uint8_t *cmdbuf, uint8_t len, - uint16_t ocf, uint8_t *rspbuf, uint8_t *rsplen) -{ - int rc; - - /* Assume error; if all pass rc gets set to 0 */ - rc = BLE_ERR_INV_HCI_CMD_PARMS; - - switch (ocf) { - case BLE_HCI_OCF_IP_RD_LOCAL_VER: - if (len == 0) { - rc = ble_ll_hci_rd_local_version(rspbuf, rsplen); - } - break; - case BLE_HCI_OCF_IP_RD_LOC_SUPP_CMD: - if (len == 0) { - rc = ble_ll_hci_rd_local_supp_cmd(rspbuf, rsplen); - } - break; - case BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT: - if (len == 0) { - rc = ble_ll_hci_rd_local_supp_feat(rspbuf, rsplen); - } - break; - case BLE_HCI_OCF_IP_RD_BD_ADDR: - if (len == 0) { - rc = ble_ll_hci_rd_bd_addr(rspbuf, rsplen); - } - break; - default: - rc = BLE_ERR_UNKNOWN_HCI_CMD; - break; - } - - return rc; -} - -static int -ble_ll_hci_status_params_cmd_proc(const uint8_t *cmdbuf, uint8_t len, - uint16_t ocf, uint8_t *rspbuf, - uint8_t *rsplen) -{ - int rc; - - switch (ocf) { - case BLE_HCI_OCF_RD_RSSI: - rc = ble_ll_conn_hci_rd_rssi(cmdbuf, len, rspbuf, rsplen); - break; - default: - rc = BLE_ERR_UNKNOWN_HCI_CMD; - break; - } - - return rc; -} - -/** - * Called to process an HCI command from the host. - * - * @param ev Pointer to os event containing a pointer to command buffer - */ -static void -ble_ll_hci_cmd_proc(struct ble_npl_event *ev) -{ - int rc; - uint8_t ogf; - uint8_t rsplen; - struct ble_hci_cmd *cmd; - uint16_t opcode; - uint16_t ocf; - ble_ll_hci_post_cmd_complete_cb post_cb = NULL; - struct ble_hci_ev *hci_ev; - struct ble_hci_ev_command_status *cmd_status; - struct ble_hci_ev_command_complete *cmd_complete; - uint8_t *rspbuf; - - BLE_LL_DEBUG_GPIO(HCI_CMD, 1); - - /* The command buffer is the event argument */ - cmd = ble_npl_event_get_arg(ev); - BLE_LL_ASSERT(cmd != NULL); - - /* Get the opcode from the command buffer */ - opcode = le16toh(cmd->opcode); - ocf = BLE_HCI_OCF(opcode); - ogf = BLE_HCI_OGF(opcode); - - /* - * The command response pointer points into the same buffer as the - * command data itself. That is fine, as each command reads all the data - * before crafting a response. - * Also reuse cmd buffer for complete event - */ - hci_ev = (struct ble_hci_ev *) cmd; - rspbuf = hci_ev->data + sizeof(*cmd_complete); - - /* Assume response length is zero */ - rsplen = 0; - - switch (ogf) { - case BLE_HCI_OGF_LINK_CTRL: - rc = ble_ll_hci_link_ctrl_cmd_proc(cmd->data, cmd->length, ocf); - break; - case BLE_HCI_OGF_CTLR_BASEBAND: - rc = ble_ll_hci_ctlr_bb_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen); - break; - case BLE_HCI_OGF_INFO_PARAMS: - rc = ble_ll_hci_info_params_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen); - break; - case BLE_HCI_OGF_STATUS_PARAMS: - rc = ble_ll_hci_status_params_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen); - break; - case BLE_HCI_OGF_LE: - rc = ble_ll_hci_le_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen, &post_cb); - break; - default: - /* XXX: Need to support other OGF. For now, return unsupported */ - rc = BLE_ERR_UNKNOWN_HCI_CMD; - break; - } - - /* If no response is generated, we free the buffers */ - BLE_LL_ASSERT(rc >= 0); - if (rc <= BLE_ERR_MAX) { - /* Create a command complete event with status from command */ - hci_ev->opcode = BLE_HCI_EVCODE_COMMAND_COMPLETE; - hci_ev->length = sizeof(*cmd_complete) + rsplen; - - cmd_complete = (void *) hci_ev->data; - cmd_complete->num_packets = ble_ll_hci_get_num_cmd_pkts(); - cmd_complete->opcode = htole16(opcode); - cmd_complete->status = (uint8_t) rc; - } else { - /* Create a command status event */ - rc -= (BLE_ERR_MAX + 1); - - hci_ev->opcode = BLE_HCI_EVCODE_COMMAND_STATUS; - hci_ev->length = sizeof(*cmd_status); - - cmd_status = (void *) hci_ev->data; - cmd_status->status = (uint8_t)rc; - cmd_status->num_packets = ble_ll_hci_get_num_cmd_pkts(); - cmd_status->opcode = htole16(opcode); - } - - /* Count commands and those in error */ - if (rc) { - STATS_INC(ble_ll_stats, hci_cmd_errs); - } else { - STATS_INC(ble_ll_stats, hci_cmds); - } - - /* Send the event (events cannot be masked) */ - ble_ll_hci_event_send(hci_ev); - - /* Call post callback if set by command handler */ - if (post_cb) { - post_cb(); - } - - BLE_LL_DEBUG_GPIO(HCI_CMD, 0); -} - -/** - * Sends an HCI command to the controller. On success, the supplied buffer is - * relinquished to the controller task. On failure, the caller must free the - * buffer. - * - * @param cmd A flat buffer containing the HCI command to - * send. - * - * @return 0 on success; - * BLE_ERR_MEM_CAPACITY on HCI buffer exhaustion. - */ -int -ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg) -{ - struct ble_npl_event *ev; - - /* Get an event structure off the queue */ - ev = &g_ble_ll_hci_cmd_ev; - if (ble_npl_event_is_queued(ev)) { - return BLE_ERR_MEM_CAPACITY; - } - - /* Fill out the event and post to Link Layer */ - ble_npl_event_set_arg(ev, cmd); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, ev); - - return 0; -} - -/* Send ACL data from host to contoller */ -int -ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg) -{ - ble_ll_acl_data_in(om); - return 0; -} - -/** - * Initalize the LL HCI. - * - * NOTE: This function is called by the HCI RESET command so if any code - * is added here it must be OK to be executed when the reset command is used. - */ -void -ble_ll_hci_init(void) -{ - BLE_LL_DEBUG_GPIO_INIT(HCI_CMD); - BLE_LL_DEBUG_GPIO_INIT(HCI_EV); - - /* Set event callback for command processing */ - ble_npl_event_init(&g_ble_ll_hci_cmd_ev, ble_ll_hci_cmd_proc, NULL); - - /* Set defaults for LE events: Vol 2 Part E 7.8.1 */ - g_ble_ll_hci_le_event_mask = 0x1f; - - /* Set defaults for controller/baseband events: Vol 2 Part E 7.3.1 */ - g_ble_ll_hci_event_mask = 0x1fffffffffff; - - - /* Set page 2 to 0 */ - g_ble_ll_hci_event_mask2 = 0; - - /* reset RF path compensation values */ - rx_path_pwr_compensation = 0; - tx_path_pwr_compensation = 0; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* after reset both legacy and extended advertising commands are allowed */ - hci_adv_mode = ADV_MODE_ANY; -#endif -} - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci_ev.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci_ev.c deleted file mode 100644 index b78b919ef..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci_ev.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "nimble/nimble/include/nimble/ble_hci_trans.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_ctrl.h" -#include "ble_ll_conn_priv.h" - -#if (BLETEST_CONCURRENT_CONN_TEST == 1) -extern void bletest_ltk_req_reply(uint16_t handle); -#endif - -/** - * Send a data length change event for a connection to the host. - * - * @param connsm Pointer to connection state machine - */ -void -ble_ll_hci_ev_datalen_chg(struct ble_ll_conn_sm *connsm) -{ - struct ble_hci_ev_le_subev_data_len_chg *ev; - struct ble_hci_ev *hci_ev; - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_DATA_LEN_CHG)) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_DATA_LEN_CHG; - ev->conn_handle = htole16(connsm->conn_handle); - - ev->max_tx_octets = htole16(connsm->eff_max_tx_octets); - ev->max_tx_time = htole16(connsm->eff_max_tx_time); - ev->max_rx_octets = htole16(connsm->eff_max_rx_octets); - ev->max_rx_time = htole16(connsm->eff_max_rx_time); - - ble_ll_hci_event_send(hci_ev); - } - } -} - -/** - * Send a connection parameter request event for a connection to the host. - * - * @param connsm Pointer to connection state machine - */ -void -ble_ll_hci_ev_rem_conn_parm_req(struct ble_ll_conn_sm *connsm, - struct ble_ll_conn_params *cp) -{ - struct ble_hci_ev_le_subev_rem_conn_param_req *ev; - struct ble_hci_ev *hci_ev; - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ)) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ; - ev->conn_handle = htole16(connsm->conn_handle); - ev->min_interval = htole16(cp->interval_min); - ev->max_interval = htole16(cp->interval_max); - ev->latency = htole16(cp->latency); - ev->timeout = htole16(cp->timeout); - - ble_ll_hci_event_send(hci_ev); - } - } -} - -/** - * Send a connection update event. - * - * @param connsm Pointer to connection state machine - * @param status The error code. - */ -void -ble_ll_hci_ev_conn_update(struct ble_ll_conn_sm *connsm, uint8_t status) -{ - struct ble_hci_ev_le_subev_conn_upd_complete *ev; - struct ble_hci_ev *hci_ev; - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE)) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE; - ev->status = status; - ev->conn_handle = htole16(connsm->conn_handle); - ev->conn_itvl = htole16(connsm->conn_itvl); - ev->conn_latency = htole16(connsm->slave_latency); - ev->supervision_timeout = htole16(connsm->supervision_tmo); - - ble_ll_hci_event_send(hci_ev); - } - } -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -void -ble_ll_hci_ev_encrypt_chg(struct ble_ll_conn_sm *connsm, uint8_t status) -{ - struct ble_hci_ev_enc_key_refresh *ev_key_refresh; - struct ble_hci_ev_enrypt_chg *ev_enc_chf; - struct ble_hci_ev *hci_ev; - - if (CONN_F_ENC_CHANGE_SENT(connsm) == 0) { - if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_ENCRYPT_CHG)) { - hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_ENCRYPT_CHG; - hci_ev->length = sizeof(*ev_enc_chf); - ev_enc_chf = (void *) hci_ev->data; - - ev_enc_chf->status = status; - ev_enc_chf->connection_handle = htole16(connsm->conn_handle); - ev_enc_chf->enabled = (status == BLE_ERR_SUCCESS) ? 0x01 : 0x00; - - ble_ll_hci_event_send(hci_ev); - } - } - - CONN_F_ENC_CHANGE_SENT(connsm) = 1; - return; - } - - if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_ENC_KEY_REFRESH)) { - hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_ENC_KEY_REFRESH; - hci_ev->length = sizeof(*ev_key_refresh); - ev_key_refresh = (void *) hci_ev->data; - - ev_key_refresh->status = status; - ev_key_refresh->conn_handle = htole16(connsm->conn_handle); - - ble_ll_hci_event_send(hci_ev); - } - } -} - -/** - * Send a long term key request event for a connection to the host. - * - * @param connsm Pointer to connection state machine - */ -int -ble_ll_hci_ev_ltk_req(struct ble_ll_conn_sm *connsm) -{ - struct ble_hci_ev_le_subev_lt_key_req *ev; - struct ble_hci_ev *hci_ev; - int rc; - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_LT_KEY_REQ)) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_LT_KEY_REQ; - ev->conn_handle = htole16(connsm->conn_handle); - ev->rand = htole64(connsm->enc_data.host_rand_num); - ev->div = htole16(connsm->enc_data.enc_div); - - ble_ll_hci_event_send(hci_ev); - } - rc = 0; - } else { - rc = -1; - } - -#if (BLETEST_CONCURRENT_CONN_TEST == 1) - if (rc == 0) { - bletest_ltk_req_reply(connsm->conn_handle); - } -#endif - return rc; -} -#endif - -void -ble_ll_hci_ev_rd_rem_used_feat(struct ble_ll_conn_sm *connsm, uint8_t status) -{ - struct ble_hci_ev_le_subev_rd_rem_used_feat *ev; - struct ble_hci_ev *hci_ev; - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT)) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT; - ev->status = status; - ev->conn_handle = htole16(connsm->conn_handle); - ev->features[0] = connsm->conn_features; - memcpy(ev->features + 1, connsm->remote_features, 7); - - ble_ll_hci_event_send(hci_ev); - } - } -} - -void -ble_ll_hci_ev_rd_rem_ver(struct ble_ll_conn_sm *connsm, uint8_t status) -{ - struct ble_hci_ev_rd_rem_ver_info_cmp *ev; - struct ble_hci_ev *hci_ev; - - if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_RD_REM_VER_INFO_CMP)) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_RD_REM_VER_INFO_CMP; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->status = status; - ev->conn_handle = htole16(connsm->conn_handle); - ev->version = connsm->vers_nr; - ev->manufacturer = htole16(connsm->comp_id); - ev->subversion = htole16(connsm->sub_vers_nr); - - ble_ll_hci_event_send(hci_ev); - } - } -} - -/** - * Send a HW error to the host. - * - * @param hw_err - * - * @return int 0: event masked or event sent, -1 otherwise - */ -int -ble_ll_hci_ev_hw_err(uint8_t hw_err) -{ - struct ble_hci_ev_hw_error *ev; - struct ble_hci_ev *hci_ev; - int rc; - - rc = 0; - if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_HW_ERROR)) { - hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_HW_ERROR; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->hw_code = hw_err; - - ble_ll_hci_event_send(hci_ev); - } else { - rc = -1; - } - } - return rc; -} - -void -ble_ll_hci_ev_databuf_overflow(void) -{ - struct ble_hci_ev_data_buf_overflow *ev; - struct ble_hci_ev *hci_ev; - - if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_DATA_BUF_OVERFLOW)) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_DATA_BUF_OVERFLOW; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->link_type = BLE_HCI_EVENT_ACL_BUF_OVERFLOW; - - ble_ll_hci_event_send(hci_ev); - } - } -} - -/** - * Send a LE Channel Selection Algorithm event. - * - * @param connsm Pointer to connection state machine - */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) -void -ble_ll_hci_ev_le_csa(struct ble_ll_conn_sm *connsm) -{ - struct ble_hci_ev_le_subev_chan_sel_alg *ev; - struct ble_hci_ev *hci_ev; - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CHAN_SEL_ALG)) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_CHAN_SEL_ALG; - ev->conn_handle = htole16(connsm->conn_handle); - ev->csa = connsm->csmflags.cfbit.csa2_supp ? 0x01 : 0x00; - - ble_ll_hci_event_send(hci_ev); - } - } -} -#endif - -/** - * Sends the LE Scan Request Received event - * - */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -void -ble_ll_hci_ev_send_scan_req_recv(uint8_t adv_handle, const uint8_t *peer, - uint8_t peer_addr_type) -{ - struct ble_hci_ev_le_subev_scan_req_rcvd *ev; - struct ble_hci_ev *hci_ev; - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD)) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD; - ev->adv_handle = adv_handle; - ev->peer_addr_type = peer_addr_type; - memcpy(ev->peer_addr, peer, BLE_DEV_ADDR_LEN); - - ble_ll_hci_event_send(hci_ev); - } - } -} -#endif - -/** - * Sends the LE Scan Timeout Event - * - */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -void -ble_ll_hci_ev_send_scan_timeout(void) -{ - struct ble_hci_ev_le_subev_scan_timeout *ev; - struct ble_hci_ev *hci_ev; - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_SCAN_TIMEOUT)) { - hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_SCAN_TIMEOUT; - - ble_ll_hci_event_send(hci_ev); - } - } -} -#endif - -/** - * Sends the LE Advertising Set Terminated event - * - */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -void -ble_ll_hci_ev_send_adv_set_terminated(uint8_t status, uint8_t adv_handle, - uint16_t conn_handle, uint8_t events) -{ - struct ble_hci_ev_le_subev_adv_set_terminated *ev; - struct ble_hci_ev *hci_ev; - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED)) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED; - ev->status = status; - ev->adv_handle = adv_handle; - ev->conn_handle = htole16(conn_handle); - ev->num_events = events; - - ble_ll_hci_event_send(hci_ev); - } - } -} -#endif - -/** - * Send a PHY update complete event - * - * @param connsm Pointer to connection state machine - * @param status error status of event - */ -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) -int -ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status) -{ - struct ble_hci_ev_le_subev_phy_update_complete *ev; - struct ble_hci_ev *hci_ev; - int rc; - - rc = 0; - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE)) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE; - ev->status = status; - ev->conn_handle = htole16(connsm->conn_handle); - ev->tx_phy = connsm->phy_data.cur_tx_phy; - ev->rx_phy = connsm->phy_data.cur_rx_phy; - - ble_ll_hci_event_send(hci_ev); - } else { - rc = BLE_ERR_MEM_CAPACITY; - } - } - return rc; -} -#endif - -void -ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line) -{ - struct ble_hci_ev_vendor_debug *ev; - struct ble_hci_ev *hci_ev; - unsigned int str_len; - bool skip = true; - uint8_t digit; - int max_len; - int i; - - /* 6 is for line number ":00000" , we assume files have no more than 64k of - * lines - */ - max_len = BLE_HCI_MAX_DATA_LEN - sizeof(*ev) - 6; - - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_VENDOR_DEBUG; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - /* Debug id for future use */ - ev->id = 0x00; - - /* snprintf would be nicer but this is heavy on flash - * len = snprintf((char *) ev->data, max_len, "%s:%u", file, line); - * if (len < 0) { - * len = 0; - * } else if (len > max_len) { - * len = max_len; - * } - * - * hci_ev->length += len; - */ - str_len = strlen(file); - if (str_len > max_len) { - str_len = max_len; - } - - memcpy(ev->data, file, str_len); - ev->data[str_len++] = ':'; - - for (i = 100000; i >= 10; i /= 10) { - digit = (line % i) / (i/10); - - if (!digit && skip) { - continue; - } - - skip = false; - ev->data[str_len++] = '0' + digit; - } - - hci_ev->length += str_len; - - ble_ll_hci_event_send(hci_ev); - } -} - -#endif \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_priv.h deleted file mode 100644 index 900950ef6..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_priv.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_PRIV_ -#define H_BLE_LL_PRIV_ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef MYNEWT - -#include "syscfg/syscfg.h" -#include "hal/hal_gpio.h" - -#define BLE_LL_DEBUG_GPIO_INIT(_name) \ - if (MYNEWT_VAL(BLE_LL_DEBUG_GPIO_ ## _name) >= 0) { \ - hal_gpio_init_out(MYNEWT_VAL(BLE_LL_DEBUG_GPIO_ ## _name), 0); \ - } - -#define BLE_LL_DEBUG_GPIO(_name, _val) \ - if (MYNEWT_VAL(BLE_LL_DEBUG_GPIO_ ## _name) >= 0) { \ - hal_gpio_write(MYNEWT_VAL(BLE_LL_DEBUG_GPIO_ ## _name), !!(_val)); \ - } - -#else -#define BLE_LL_DEBUG_GPIO_INIT(_name) (void)(0) -#define BLE_LL_DEBUG_GPIO(_name, _val) (void)(0) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_LL_PRIV_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rand.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rand.c deleted file mode 100644 index dd89e04b0..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rand.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "../include/controller/ble_hw.h" -#include "../include/controller/ble_ll.h" -#if MYNEWT_VAL(TRNG) -#include "trng/trng.h" -#endif - -#if MYNEWT_VAL(TRNG) -static struct trng_dev *g_trng; -#else -/* This is a simple circular buffer for holding N samples of random data */ -struct ble_ll_rnum_data -{ - uint8_t *rnd_in; - uint8_t *rnd_out; - volatile uint8_t rnd_size; -}; - -struct ble_ll_rnum_data g_ble_ll_rnum_data; -uint8_t g_ble_ll_rnum_buf[MYNEWT_VAL(BLE_LL_RNG_BUFSIZE)]; - -#define IS_RNUM_BUF_END(x) \ - (x == &g_ble_ll_rnum_buf[MYNEWT_VAL(BLE_LL_RNG_BUFSIZE) - 1]) - -void -ble_ll_rand_sample(uint8_t rnum) -{ - os_sr_t sr; - - OS_ENTER_CRITICAL(sr); - if (g_ble_ll_rnum_data.rnd_size < MYNEWT_VAL(BLE_LL_RNG_BUFSIZE)) { - ++g_ble_ll_rnum_data.rnd_size; - g_ble_ll_rnum_data.rnd_in[0] = rnum; - if (IS_RNUM_BUF_END(g_ble_ll_rnum_data.rnd_in)) { - g_ble_ll_rnum_data.rnd_in = g_ble_ll_rnum_buf; - } else { - ++g_ble_ll_rnum_data.rnd_in; - } - } else { - /* Stop generating random numbers as we are full */ - ble_hw_rng_stop(); - } - OS_EXIT_CRITICAL(sr); -} -#endif - -/* Get 'len' bytes of random data */ -int -ble_ll_rand_data_get(uint8_t *buf, uint8_t len) -{ -#if MYNEWT_VAL(TRNG) - size_t num; - - while (len) { - num = trng_read(g_trng, buf, len); - buf += num; - len -= num; - } -#else - uint8_t rnums; - os_sr_t sr; - - while (len != 0) { - OS_ENTER_CRITICAL(sr); - rnums = g_ble_ll_rnum_data.rnd_size; - if (rnums > len) { - rnums = len; - } - len -= rnums; - g_ble_ll_rnum_data.rnd_size -= rnums; - while (rnums) { - buf[0] = g_ble_ll_rnum_data.rnd_out[0]; - if (IS_RNUM_BUF_END(g_ble_ll_rnum_data.rnd_out)) { - g_ble_ll_rnum_data.rnd_out = g_ble_ll_rnum_buf; - } else { - ++g_ble_ll_rnum_data.rnd_out; - } - ++buf; - --rnums; - } - OS_EXIT_CRITICAL(sr); - - /* Make sure rng is started! */ - ble_hw_rng_start(); - - /* Wait till bytes are in buffer. */ - if (len) { - while ((g_ble_ll_rnum_data.rnd_size < len) && - (g_ble_ll_rnum_data.rnd_size < MYNEWT_VAL(BLE_LL_RNG_BUFSIZE))) { - /* Spin here */ - } - } - } -#endif - return BLE_ERR_SUCCESS; -} - -/** - * Called to obtain a "prand" as defined in core V4.2 Vol 6 Part B 1.3.2.2 - * - * @param prand - */ -void -ble_ll_rand_prand_get(uint8_t *prand) -{ - uint16_t sum; - - while (1) { - /* Get 24 bits of random data */ - ble_ll_rand_data_get(prand, 3); - - /* Prand cannot be all zeros or 1's. */ - sum = prand[0] + prand[1] + prand[2]; - if ((sum != 0) && (sum != (3 * 0xff))) { - break; - } - } - - /* Upper two bits must be 01 */ - prand[2] &= ~0xc0; - prand[2] |= 0x40; -} - -/** - * Start the generation of random numbers - * - * @return int - */ -int -ble_ll_rand_start(void) -{ -#if MYNEWT_VAL(TRNG) - /* Nothing to do - this is handled by driver */ -#else - /* Start the generation of numbers if we are not full */ - if (g_ble_ll_rnum_data.rnd_size < MYNEWT_VAL(BLE_LL_RNG_BUFSIZE)) { - ble_hw_rng_start(); - } -#endif - return 0; -} - -/** - * Initialize LL random number generation. Should be called only once on - * initialization. - * - * @return int - */ -int -ble_ll_rand_init(void) -{ -#if MYNEWT_VAL(TRNG) - g_trng = (struct trng_dev *) os_dev_open("trng", OS_TIMEOUT_NEVER, NULL); -#else - g_ble_ll_rnum_data.rnd_in = g_ble_ll_rnum_buf; - g_ble_ll_rnum_data.rnd_out = g_ble_ll_rnum_buf; - ble_hw_rng_init(ble_ll_rand_sample, 1); -#endif - return 0; -} - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_resolv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_resolv.c deleted file mode 100644 index 231ecad23..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_resolv.c +++ /dev/null @@ -1,755 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_resolv.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_sync.h" -#include "../include/controller/ble_hw.h" -#include "ble_ll_conn_priv.h" - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -struct ble_ll_resolv_data -{ - uint8_t addr_res_enabled; - uint8_t rl_size; - uint8_t rl_cnt_hw; - uint8_t rl_cnt; - ble_npl_time_t rpa_tmo; - struct ble_npl_callout rpa_timer; -}; -struct ble_ll_resolv_data g_ble_ll_resolv_data; - -__attribute__((aligned(4))) -struct ble_ll_resolv_entry g_ble_ll_resolv_list[MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)]; - -static int -ble_ll_is_controller_busy(void) -{ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - if (ble_ll_sync_enabled()) { - return 1; - } -#endif - - return ble_ll_adv_enabled() || ble_ll_scan_enabled() || - g_ble_ll_conn_create_sm; -} -/** - * Called to determine if a change is allowed to the resolving list at this - * time. We are not allowed to modify the resolving list if address translation - * is enabled and we are either scanning, advertising, or attempting to create - * a connection. - * - * @return int 0: not allowed. 1: allowed. - */ -static int -ble_ll_resolv_list_chg_allowed(void) -{ - int rc; - - if (g_ble_ll_resolv_data.addr_res_enabled && - ble_ll_is_controller_busy()) { - rc = 0; - } else { - rc = 1; - } - return rc; -} - - -/** - * Called to generate a resolvable private address in rl structure - * - * @param rl - * @param local - */ -static void -ble_ll_resolv_gen_priv_addr(struct ble_ll_resolv_entry *rl, int local) -{ - uint8_t *irk; - uint8_t *prand; - struct ble_encryption_block ecb; - uint8_t *addr; - - BLE_LL_ASSERT(rl != NULL); - - if (local) { - addr = rl->rl_local_rpa; - irk = rl->rl_local_irk; - } else { - addr = rl->rl_peer_rpa; - irk = rl->rl_peer_irk; - } - - /* Get prand */ - prand = addr + 3; - ble_ll_rand_prand_get(prand); - - /* Calculate hash, hash = ah(local IRK, prand) */ - memcpy(ecb.key, irk, 16); - memset(ecb.plain_text, 0, 13); - ecb.plain_text[13] = prand[2]; - ecb.plain_text[14] = prand[1]; - ecb.plain_text[15] = prand[0]; - - /* Calculate hash */ - ble_hw_encrypt_block(&ecb); - - addr[0] = ecb.cipher_text[15]; - addr[1] = ecb.cipher_text[14]; - addr[2] = ecb.cipher_text[13]; -} - -/** - * Called when the Resolvable private address timer expires. This timer - * is used to regenerate local and peers RPA's in the resolving list. - */ -static void -ble_ll_resolv_rpa_timer_cb(struct ble_npl_event *ev) -{ - int i; - os_sr_t sr; - struct ble_ll_resolv_entry *rl; - - rl = &g_ble_ll_resolv_list[0]; - for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) { - if (rl->rl_has_local) { - OS_ENTER_CRITICAL(sr); - ble_ll_resolv_gen_priv_addr(rl, 1); - OS_EXIT_CRITICAL(sr); - } - - if (rl->rl_has_peer) { - OS_ENTER_CRITICAL(sr); - ble_ll_resolv_gen_priv_addr(rl, 0); - OS_EXIT_CRITICAL(sr); - } - ++rl; - } - - ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer, - g_ble_ll_resolv_data.rpa_tmo); - - ble_ll_adv_rpa_timeout(); -} - -/** - * Called to determine if the IRK is all zero. - * - * @param irk - * - * @return int 0: IRK is zero . 1: IRK has non-zero value. - */ -static int -ble_ll_resolv_irk_nonzero(const uint8_t *irk) -{ - int i; - int rc; - - rc = 0; - for (i = 0; i < 16; ++i) { - if (*irk != 0) { - rc = 1; - break; - } - ++irk; - } - - return rc; -} - -/** - * Clear the resolving list - * - * @return int 0: success, BLE error code otherwise - */ -int -ble_ll_resolv_list_clr(void) -{ - /* Check proper state */ - if (!ble_ll_resolv_list_chg_allowed()) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* Sets total on list to 0. Clears HW resolve list */ - g_ble_ll_resolv_data.rl_cnt_hw = 0; - g_ble_ll_resolv_data.rl_cnt = 0; - ble_hw_resolv_list_clear(); - - /* stop RPA timer when clearing RL */ - ble_npl_callout_stop(&g_ble_ll_resolv_data.rpa_timer); - - return BLE_ERR_SUCCESS; -} - -/** - * Read the size of the resolving list. This is the total number of resolving - * list entries allowed by the controller. - * - * @param rspbuf Pointer to response buffer - * - * @return int 0: success. - */ -int -ble_ll_resolv_list_read_size(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_le_rd_resolv_list_size_rp *rsp = (void *) rspbuf; - - rsp->size = g_ble_ll_resolv_data.rl_size; - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} - -/** - * Used to determine if the device is on the resolving list. - * - * @param addr - * @param addr_type Public address (0) or random address (1) - * - * @return int 0: device is not on resolving list; otherwise the return value - * is the 'position' of the device in the resolving list (the index of the - * element plus 1). - */ -static int -ble_ll_is_on_resolv_list(const uint8_t *addr, uint8_t addr_type) -{ - int i; - struct ble_ll_resolv_entry *rl; - - rl = &g_ble_ll_resolv_list[0]; - for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) { - if ((rl->rl_addr_type == addr_type) && - (!memcmp(&rl->rl_identity_addr[0], addr, BLE_DEV_ADDR_LEN))) { - return i + 1; - } - ++rl; - } - - return 0; -} - -/** - * Used to determine if the device is on the resolving list. - * - * @param addr - * @param addr_type Public address (0) or random address (1) - * - * @return Pointer to resolving list entry or NULL if no entry found. - */ -struct ble_ll_resolv_entry * -ble_ll_resolv_list_find(const uint8_t *addr, uint8_t addr_type) -{ - int i; - struct ble_ll_resolv_entry *rl; - - rl = &g_ble_ll_resolv_list[0]; - for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) { - if ((rl->rl_addr_type == addr_type) && - (!memcmp(&rl->rl_identity_addr[0], addr, BLE_DEV_ADDR_LEN))) { - return rl; - } - ++rl; - } - - return NULL; -} - -/** - * Add a device to the resolving list - * - * @return int - */ -int -ble_ll_resolv_list_add(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_add_resolv_list_cp *cmd = (const void *) cmdbuf; - struct ble_ll_resolv_entry *rl; - int rc = BLE_ERR_SUCCESS; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Must be in proper state */ - if (!ble_ll_resolv_list_chg_allowed()) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* Check if we have any open entries */ - if (g_ble_ll_resolv_data.rl_cnt >= g_ble_ll_resolv_data.rl_size) { - return BLE_ERR_MEM_CAPACITY; - } - - /* spec is not clear on how to handle this but make sure host is aware - * that new keys are not used in that case - */ - if (ble_ll_is_on_resolv_list(cmd->peer_id_addr, cmd->peer_addr_type)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* we keep this sorted in a way that entries with peer_irk are first */ - if (ble_ll_resolv_irk_nonzero(cmd->peer_irk)) { - memmove(&g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt_hw + 1], - &g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt_hw], - (g_ble_ll_resolv_data.rl_cnt - g_ble_ll_resolv_data.rl_cnt_hw) * - sizeof(g_ble_ll_resolv_list[0])); - rl = &g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt_hw]; - } else { - rl = &g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt]; - } - - memset (rl, 0, sizeof(*rl)); - rl->rl_addr_type = cmd->peer_addr_type; - memcpy(rl->rl_identity_addr, cmd->peer_id_addr, BLE_DEV_ADDR_LEN); - - if (ble_ll_resolv_irk_nonzero(cmd->peer_irk)) { - swap_buf(rl->rl_peer_irk, cmd->peer_irk, 16); - rl->rl_has_peer = 1; - - /* generate peer RPA now, those will be updated by timer when - * resolution is enabled - */ - ble_ll_resolv_gen_priv_addr(rl, 0); - } - - if (ble_ll_resolv_irk_nonzero(cmd->local_irk)) { - swap_buf(rl->rl_local_irk, cmd->local_irk, 16); - rl->rl_has_local = 1; - - /* generate local RPA now, those will be updated by timer when - * resolution is enabled - */ - ble_ll_resolv_gen_priv_addr(rl, 1); - } - - /* By default use privacy network mode */ - rl->rl_priv_mode = BLE_HCI_PRIVACY_NETWORK; - - /* Add peers IRKs to HW resolving list. Should always succeed since we - * already checked if there is room for it. - */ - if (rl->rl_has_peer) { - rc = ble_hw_resolv_list_add(rl->rl_peer_irk); - BLE_LL_ASSERT(rc == BLE_ERR_SUCCESS); - g_ble_ll_resolv_data.rl_cnt_hw++; - } - - g_ble_ll_resolv_data.rl_cnt++; - - /* start RPA timer if this was first element added to RL */ - if (g_ble_ll_resolv_data.rl_cnt == 1) { - ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer, - g_ble_ll_resolv_data.rpa_tmo); - } - - return rc; -} - -/** - * Remove a device from the resolving list - * - * @param cmdbuf - * - * @return int 0: success, BLE error code otherwise - */ -int -ble_ll_resolv_list_rmv(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_rmv_resolve_list_cp *cmd = (const void *) cmdbuf; - int position; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Must be in proper state */ - if (!ble_ll_resolv_list_chg_allowed()) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* Remove from IRK records */ - position = ble_ll_is_on_resolv_list(cmd->peer_id_addr, cmd->peer_addr_type); - if (position) { - BLE_LL_ASSERT(position <= g_ble_ll_resolv_data.rl_cnt); - - memmove(&g_ble_ll_resolv_list[position - 1], - &g_ble_ll_resolv_list[position], - (g_ble_ll_resolv_data.rl_cnt - position) * - sizeof(g_ble_ll_resolv_list[0])); - g_ble_ll_resolv_data.rl_cnt--; - - /* Remove from HW list */ - if (position <= g_ble_ll_resolv_data.rl_cnt_hw) { - ble_hw_resolv_list_rmv(position - 1); - g_ble_ll_resolv_data.rl_cnt_hw--; - } - - /* stop RPA timer if list is empty */ - if (g_ble_ll_resolv_data.rl_cnt == 0) { - ble_npl_callout_stop(&g_ble_ll_resolv_data.rpa_timer); - } - - return BLE_ERR_SUCCESS; - } - - return BLE_ERR_UNK_CONN_ID; -} - -/** - * Called to enable or disable address resolution in the controller - * - * @param cmdbuf - * - * @return int - */ -int -ble_ll_resolv_enable_cmd(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_addr_res_en_cp *cmd = (const void *) cmdbuf; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (ble_ll_is_controller_busy()) { - return BLE_ERR_CMD_DISALLOWED; - - } - - if (cmd->enable > 1) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - g_ble_ll_resolv_data.addr_res_enabled = cmd->enable; - - return BLE_ERR_SUCCESS; -} - -int -ble_ll_resolv_peer_addr_rd(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_rd_peer_recolv_addr_cp *cmd = (const void *) cmdbuf; - struct ble_hci_le_rd_peer_recolv_addr_rp *rsp = (void *) rspbuf; - struct ble_ll_resolv_entry *rl; - int rc; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - rl = ble_ll_resolv_list_find(cmd->peer_id_addr, cmd->peer_addr_type); - if (rl) { - memcpy(rsp->rpa, rl->rl_peer_rpa, BLE_DEV_ADDR_LEN); - rc = BLE_ERR_SUCCESS; - } else { - memset(rsp->rpa, 0, BLE_DEV_ADDR_LEN); - rc = BLE_ERR_UNK_CONN_ID; - } - - *rsplen = sizeof(*rsp); - return rc; -} - -int -ble_ll_resolv_local_addr_rd(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_rd_local_recolv_addr_cp *cmd = (const void *) cmdbuf; - struct ble_hci_le_rd_local_recolv_addr_rp *rsp = (void *) rspbuf; - struct ble_ll_resolv_entry *rl; - int rc; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - rl = ble_ll_resolv_list_find(cmd->peer_id_addr, cmd->peer_addr_type); - if (rl) { - memcpy(rsp->rpa, rl->rl_local_rpa, BLE_DEV_ADDR_LEN); - rc = BLE_ERR_SUCCESS; - } else { - memset(rsp->rpa, 0, BLE_DEV_ADDR_LEN); - rc = BLE_ERR_UNK_CONN_ID; - } - - *rsplen = sizeof(*rsp); - return rc; -} - -/** - * Set the resolvable private address timeout. - * - * @param cmdbuf - * - * @return int - */ -int -ble_ll_resolv_set_rpa_tmo(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_rpa_tmo_cp *cmd = (const void *)cmdbuf; - uint16_t tmo_secs; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - tmo_secs = le16toh(cmd->rpa_timeout); - if (!((tmo_secs > 0) && (tmo_secs <= 0xA1B8))) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - g_ble_ll_resolv_data.rpa_tmo = ble_npl_time_ms_to_ticks32(tmo_secs * 1000); - - /* restart timer if there is something on RL */ - if (g_ble_ll_resolv_data.rl_cnt) { - ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer, - g_ble_ll_resolv_data.rpa_tmo); - } - - return BLE_ERR_SUCCESS; -} - -int -ble_ll_resolve_set_priv_mode(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_privacy_mode_cp *cmd = (const void *) cmdbuf; - struct ble_ll_resolv_entry *rl; - - if (ble_ll_is_controller_busy()) { - return BLE_ERR_CMD_DISALLOWED; - } - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - rl = ble_ll_resolv_list_find(cmd->peer_id_addr, cmd->peer_id_addr_type); - if (!rl) { - return BLE_ERR_UNK_CONN_ID; - } - - if (cmd->mode > BLE_HCI_PRIVACY_DEVICE) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - rl->rl_priv_mode = cmd->mode; - - return BLE_ERR_SUCCESS; -} - -/** - * Returns the Resolvable Private address timeout, in os ticks - * - * - * @return uint32_t - */ -uint32_t -ble_ll_resolv_get_rpa_tmo(void) -{ - return g_ble_ll_resolv_data.rpa_tmo; -} - -void -ble_ll_resolv_get_priv_addr(struct ble_ll_resolv_entry *rl, int local, - uint8_t *addr) -{ - os_sr_t sr; - - BLE_LL_ASSERT(rl != NULL); - BLE_LL_ASSERT(addr != NULL); - - OS_ENTER_CRITICAL(sr); - if (local) { - BLE_LL_ASSERT(rl->rl_has_local); - memcpy(addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN); - } else { - BLE_LL_ASSERT(rl->rl_has_peer); - memcpy(addr, rl->rl_peer_rpa, BLE_DEV_ADDR_LEN); - } - - OS_EXIT_CRITICAL(sr); -} - -void -ble_ll_resolv_set_peer_rpa(int index, uint8_t *rpa) -{ - os_sr_t sr; - struct ble_ll_resolv_entry *rl; - - OS_ENTER_CRITICAL(sr); - rl = &g_ble_ll_resolv_list[index]; - memcpy(rl->rl_peer_rpa, rpa, BLE_DEV_ADDR_LEN); - OS_EXIT_CRITICAL(sr); -} - -void -ble_ll_resolv_set_local_rpa(int index, uint8_t *rpa) -{ - os_sr_t sr; - struct ble_ll_resolv_entry *rl; - - OS_ENTER_CRITICAL(sr); - rl = &g_ble_ll_resolv_list[index]; - memcpy(rl->rl_local_rpa, rpa, BLE_DEV_ADDR_LEN); - OS_EXIT_CRITICAL(sr); -} - -/** - * Generate a resolvable private address. - * - * @param addr - * @param addr_type - * @param rpa - * - * @return int - */ -int -ble_ll_resolv_gen_rpa(uint8_t *addr, uint8_t addr_type, uint8_t *rpa, int local) -{ - struct ble_ll_resolv_entry *rl; - - rl = ble_ll_resolv_list_find(addr, addr_type); - if (rl) { - if ((local && rl->rl_has_local) || (!local && rl->rl_has_peer)) { - ble_ll_resolv_get_priv_addr(rl, local, rpa); - return 1; - } - } - - return 0; -} - -/** - * Resolve a Resolvable Private Address - * - * @param rpa - * @param index - * - * @return int - */ -int -ble_ll_resolv_rpa(const uint8_t *rpa, const uint8_t *irk) -{ - int rc; - const uint32_t *irk32; - uint32_t *key32; - uint32_t *pt32; - struct ble_encryption_block ecb; - - irk32 = (const uint32_t *)irk; - key32 = (uint32_t *)&ecb.key[0]; - - key32[0] = irk32[0]; - key32[1] = irk32[1]; - key32[2] = irk32[2]; - key32[3] = irk32[3]; - - pt32 = (uint32_t *)&ecb.plain_text[0]; - pt32[0] = 0; - pt32[1] = 0; - pt32[2] = 0; - pt32[3] = 0; - - ecb.plain_text[15] = rpa[3]; - ecb.plain_text[14] = rpa[4]; - ecb.plain_text[13] = rpa[5]; - - ble_hw_encrypt_block(&ecb); - if ((ecb.cipher_text[15] == rpa[0]) && (ecb.cipher_text[14] == rpa[1]) && - (ecb.cipher_text[13] == rpa[2])) { - rc = 1; - } else { - rc = 0; - } - - return rc; -} - -int -ble_ll_resolv_peer_rpa_any(const uint8_t *rpa) -{ - int i; - - for (i = 0; i < g_ble_ll_resolv_data.rl_cnt_hw; i++) { - if (ble_ll_resolv_rpa(rpa, g_ble_ll_resolv_list[i].rl_peer_irk)) { - return i; - } - } - - return -1; -} - -/** - * Returns whether or not address resolution is enabled. - * - * @return uint8_t - */ -uint8_t -ble_ll_resolv_enabled(void) -{ - return g_ble_ll_resolv_data.addr_res_enabled; -} - -/** - * Called to reset private address resolution module. - */ -void -ble_ll_resolv_list_reset(void) -{ - g_ble_ll_resolv_data.addr_res_enabled = 0; - ble_npl_callout_stop(&g_ble_ll_resolv_data.rpa_timer); - ble_ll_resolv_list_clr(); - ble_ll_resolv_init(); -} - -void -ble_ll_resolv_init(void) -{ - uint8_t hw_size; - - /* Default is 15 minutes */ - g_ble_ll_resolv_data.rpa_tmo = ble_npl_time_ms_to_ticks32(15 * 60 * 1000); - - hw_size = ble_hw_resolv_list_size(); - if (hw_size > MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)) { - hw_size = MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE); - } - g_ble_ll_resolv_data.rl_size = hw_size; - - ble_npl_callout_init(&g_ble_ll_resolv_data.rpa_timer, - &g_ble_ll_data.ll_evq, - ble_ll_resolv_rpa_timer_cb, - NULL); -} - -#endif /* if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) */ -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rfmgmt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rfmgmt.c deleted file mode 100644 index 444019cc0..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rfmgmt.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os_cputime.h" -#include "../include/controller/ble_phy.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_rfmgmt.h" - -#if MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME) > 0 - -enum ble_ll_rfmgmt_state { - RFMGMT_STATE_OFF = 0, - RFMGMT_STATE_ENABLING = 1, - RFMGMT_STATE_ENABLED = 2, -}; - -struct ble_ll_rfmgmt_data { - enum ble_ll_rfmgmt_state state; - uint16_t ticks_to_enabled; - - struct hal_timer timer; - bool timer_scheduled; - uint32_t timer_scheduled_at; - - bool enable_scan; - bool enable_sched; - uint32_t enable_scan_at; - uint32_t enable_sched_at; - - uint32_t enabled_at; - - struct ble_npl_event release_ev; -}; - -static struct ble_ll_rfmgmt_data g_ble_ll_rfmgmt_data; - -static void -ble_ll_rfmgmt_enable(void) -{ - OS_ASSERT_CRITICAL(); - - if (g_ble_ll_rfmgmt_data.state == RFMGMT_STATE_OFF) { - g_ble_ll_rfmgmt_data.state = RFMGMT_STATE_ENABLING; - g_ble_ll_rfmgmt_data.enabled_at = os_cputime_get32(); - ble_phy_rfclk_enable(); - } -} - -static void -ble_ll_rfmgmt_disable(void) -{ - OS_ASSERT_CRITICAL(); - - if (g_ble_ll_rfmgmt_data.state != RFMGMT_STATE_OFF) { - ble_phy_rfclk_disable(); - g_ble_ll_rfmgmt_data.state = RFMGMT_STATE_OFF; - } -} - -static void -ble_ll_rfmgmt_timer_reschedule(void) -{ - struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; - uint32_t enable_at; - - /* Figure out when we need to enable RF */ - if (rfmgmt->enable_scan && rfmgmt->enable_sched) { - if (CPUTIME_LT(rfmgmt->enable_scan_at, rfmgmt->enable_sched_at)) { - enable_at = rfmgmt->enable_scan_at; - } else { - enable_at = rfmgmt->enable_sched_at; - } - } else if (rfmgmt->enable_scan) { - enable_at = rfmgmt->enable_scan_at; - } else if (rfmgmt->enable_sched) { - enable_at = rfmgmt->enable_sched_at; - } else { - rfmgmt->timer_scheduled = false; - os_cputime_timer_stop(&rfmgmt->timer); - return; - } - - if (rfmgmt->timer_scheduled) { - /* - * If there is timer already scheduled at the same time we do not need - * to do anything. Otherwise we need to stop timer and schedule it again - * regardless if it's earlier or later to make sure it fires at the time - * something expects it. - */ - - if (rfmgmt->timer_scheduled_at == enable_at) { - return; - } - - rfmgmt->timer_scheduled = false; - os_cputime_timer_stop(&rfmgmt->timer); - } - - /* - * In case timer was requested to be enabled before current time, just make - * sure it's enabled and assume caller can deal with this. This will happen - * if something is scheduled "now" since "enable_at" is in the past, but in - * such case it's absolutely harmless since we already have clock enabled - * and this will do nothing. - */ - if (CPUTIME_LEQ(enable_at, os_cputime_get32())) { - ble_ll_rfmgmt_enable(); - return; - } - - rfmgmt->timer_scheduled = true; - rfmgmt->timer_scheduled_at = enable_at; - os_cputime_timer_start(&rfmgmt->timer, enable_at); -} - -static void -ble_ll_rfmgmt_timer_exp(void *arg) -{ - g_ble_ll_rfmgmt_data.timer_scheduled = false; - ble_ll_rfmgmt_enable(); -} - -static void -ble_ll_rfmgmt_release_ev(struct ble_npl_event *ev) -{ - struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; - uint32_t now; - bool can_disable; - uint8_t lls; - os_sr_t sr; - - OS_ENTER_CRITICAL(sr); - - now = os_cputime_get32(); - - can_disable = true; - lls = ble_ll_state_get(); - - if (rfmgmt->enable_scan && CPUTIME_GEQ(now, rfmgmt->enable_scan_at)) { - /* Blocked by scan */ - can_disable = false; - } else if (rfmgmt->enable_sched && CPUTIME_GEQ(now, rfmgmt->enable_sched_at)) { - /* Blocked by scheduler item */ - can_disable = false; - } else if (lls != BLE_LL_STATE_STANDBY) { - /* Blocked by LL state */ - can_disable = false; - } - - if (can_disable) { - ble_ll_rfmgmt_disable(); - } - - OS_EXIT_CRITICAL(sr); -} - -static uint32_t -ble_ll_rfmgmt_ticks_to_enabled(void) -{ - struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; - uint32_t rem_ticks; - uint32_t now; - - switch (rfmgmt->state) { - case RFMGMT_STATE_OFF: - rem_ticks = rfmgmt->ticks_to_enabled; - break; - case RFMGMT_STATE_ENABLING: - now = os_cputime_get32(); - if (CPUTIME_LT(now, rfmgmt->enabled_at + rfmgmt->ticks_to_enabled)) { - rem_ticks = rfmgmt->enabled_at + rfmgmt->ticks_to_enabled - now; - break; - } - rfmgmt->state = RFMGMT_STATE_ENABLED; - /* no break */ - case RFMGMT_STATE_ENABLED: - rem_ticks = 0; - break; - default: - BLE_LL_ASSERT(0); - rem_ticks = 0; - break; - } - - return rem_ticks; -} - -void -ble_ll_rfmgmt_init(void) -{ - struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; - - rfmgmt->state = RFMGMT_STATE_OFF; - - rfmgmt->ticks_to_enabled = - ble_ll_usecs_to_ticks_round_up(MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME)); - - rfmgmt->timer_scheduled = false; - os_cputime_timer_init(&rfmgmt->timer, ble_ll_rfmgmt_timer_exp, NULL); - - ble_npl_event_init(&rfmgmt->release_ev, ble_ll_rfmgmt_release_ev, NULL); -} - -void -ble_ll_rfmgmt_reset(void) -{ - struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; - - rfmgmt->timer_scheduled = false; - rfmgmt->timer_scheduled_at = 0; - os_cputime_timer_stop(&rfmgmt->timer); - - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev); - - ble_ll_rfmgmt_disable(); - - rfmgmt->enable_scan = false; - rfmgmt->enable_scan_at = 0; - rfmgmt->enable_sched = false; - rfmgmt->enable_sched_at = 0; - - rfmgmt->enabled_at = 0; -} - -void -ble_ll_rfmgmt_scan_changed(bool enabled, uint32_t next_window) -{ - struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; - os_sr_t sr; - - OS_ENTER_CRITICAL(sr); - - rfmgmt->enable_scan = enabled; - rfmgmt->enable_scan_at = next_window - rfmgmt->ticks_to_enabled; - - ble_ll_rfmgmt_timer_reschedule(); - - OS_EXIT_CRITICAL(sr); -} - -void -ble_ll_rfmgmt_sched_changed(struct ble_ll_sched_item *first) -{ - struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; - os_sr_t sr; - - OS_ENTER_CRITICAL(sr); - - rfmgmt->enable_sched = (first != NULL); - if (first) { - rfmgmt->enable_sched_at = first->start_time - rfmgmt->ticks_to_enabled; - } - - ble_ll_rfmgmt_timer_reschedule(); - - OS_EXIT_CRITICAL(sr); -} - -void -ble_ll_rfmgmt_release(void) -{ - struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; - os_sr_t sr; - - OS_ENTER_CRITICAL(sr); - - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev); - - if (g_ble_ll_rfmgmt_data.state != RFMGMT_STATE_OFF) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev); - } - - OS_EXIT_CRITICAL(sr); -} - -uint32_t -ble_ll_rfmgmt_enable_now(void) -{ - struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; - uint32_t enabled_at; - os_sr_t sr; - - OS_ENTER_CRITICAL(sr); - - ble_ll_rfmgmt_enable(); - - if (rfmgmt->state == RFMGMT_STATE_ENABLED) { - enabled_at = os_cputime_get32(); - } else { - enabled_at = rfmgmt->enabled_at + rfmgmt->ticks_to_enabled + 1; - } - - OS_EXIT_CRITICAL(sr); - - return enabled_at; -} - -bool -ble_ll_rfmgmt_is_enabled(void) -{ - bool ret; - - OS_ASSERT_CRITICAL(); - - ret = ble_ll_rfmgmt_ticks_to_enabled() == 0; - - return ret; -} - -#else - -void -ble_ll_rfmgmt_init(void) -{ - static bool enabled = false; - - if (!enabled) { - ble_phy_rfclk_enable(); - } - - enabled = true; -} - -#endif -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_scan.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_scan.c deleted file mode 100644 index 03a683a76..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_scan.c +++ /dev/null @@ -1,3981 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef ESP_PLATFORM - -#include -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/porting/nimble/include/os/os_cputime.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "nimble/nimble/include/nimble/ble_hci_trans.h" -#include "../include/controller/ble_phy.h" -#include "../include/controller/ble_hw.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_whitelist.h" -#include "../include/controller/ble_ll_resolv.h" -#include "../include/controller/ble_ll_rfmgmt.h" -#include "../include/controller/ble_ll_trace.h" -#include "../include/controller/ble_ll_sync.h" -#include "ble_ll_conn_priv.h" - -/* - * XXX: - * 1) I think I can guarantee that we dont process things out of order if - * I send an event when a scan request is sent. The scan_rsp_pending flag - * code might be made simpler. - * - * 2) Interleave sending scan requests to different advertisers? I guess I need - * a list of advertisers to which I sent a scan request and have yet to - * receive a scan response from? Implement this. - */ - -/* Dont allow more than 255 of these entries */ -#if MYNEWT_VAL(BLE_LL_NUM_SCAN_RSP_ADVS) > 255 - #error "Cannot have more than 255 scan response entries!" -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) -#define SCAN_VALID_PHY_MASK (BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_CODED_PREF_MASK) -#else -#define SCAN_VALID_PHY_MASK (BLE_HCI_LE_PHY_1M_PREF_MASK) -#endif - -/* The scanning parameters set by host */ -static struct ble_ll_scan_params g_ble_ll_scan_params[BLE_LL_SCAN_PHY_NUMBER]; - -/* The scanning state machine global object */ -static struct ble_ll_scan_sm g_ble_ll_scan_sm; - -struct ble_ll_ext_adv_hdr -{ - uint8_t mode; - uint8_t hdr_len; - uint8_t hdr[0]; -}; - -struct ble_ll_scan_addr_data { - bool adva_present; - uint8_t adva_type; - uint8_t *adva; - uint8_t targeta_type; - uint8_t *targeta; - uint8_t adv_addr_type; - uint8_t *adv_addr; - struct ble_ll_resolv_entry *rl; -}; - -/* - * Structure used to store advertisers. This is used to limit sending scan - * requests to the same advertiser and also to filter duplicate events sent - * to the host. - */ -struct ble_ll_scan_advertisers -{ - uint16_t sc_adv_flags; - uint16_t adi; - struct ble_dev_addr adv_addr; -}; - -#define BLE_LL_SC_ADV_F_RANDOM_ADDR (0x01) -#define BLE_LL_SC_ADV_F_SCAN_RSP_RXD (0x02) -#define BLE_LL_SC_ADV_F_DIRECT_RPT_SENT (0x04) -#define BLE_LL_SC_ADV_F_ADV_RPT_SENT (0x08) -#define BLE_LL_SC_ADV_F_SCAN_RSP_SENT (0x10) - -/* Contains list of advertisers that we have heard scan responses from */ -static uint8_t g_ble_ll_scan_num_rsp_advs; -struct ble_ll_scan_advertisers -g_ble_ll_scan_rsp_advs[MYNEWT_VAL(BLE_LL_NUM_SCAN_RSP_ADVS)]; - -/* Duplicates filtering data */ -#define BLE_LL_SCAN_ENTRY_TYPE_LEGACY(addr_type) \ - ((addr_type) & 1) -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#define BLE_LL_SCAN_ENTRY_TYPE_EXT(addr_type, has_aux, is_anon, adi) \ - (((adi >> 8) & 0xF0) | (1 << 3) | (is_anon << 2) | (has_aux << 1) | ((addr_type) & 1)) -#endif - -#define BLE_LL_SCAN_DUP_F_ADV_REPORT_SENT (0x01) -#define BLE_LL_SCAN_DUP_F_DIR_ADV_REPORT_SENT (0x02) -#define BLE_LL_SCAN_DUP_F_SCAN_RSP_SENT (0x04) - -struct ble_ll_scan_dup_entry { - uint8_t type; /* entry type, see BLE_LL_SCAN_ENTRY_TYPE_* */ - uint8_t addr[6]; - uint8_t flags; /* use BLE_LL_SCAN_DUP_F_xxx */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - uint16_t adi; -#endif - TAILQ_ENTRY(ble_ll_scan_dup_entry) link; -}; - -static os_membuf_t g_scan_dup_mem[ OS_MEMPOOL_SIZE( - MYNEWT_VAL(BLE_LL_NUM_SCAN_DUP_ADVS), - sizeof(struct ble_ll_scan_dup_entry)) ]; -static struct os_mempool g_scan_dup_pool; -static TAILQ_HEAD(ble_ll_scan_dup_list, ble_ll_scan_dup_entry) g_scan_dup_list; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#if MYNEWT_VAL(BLE_LL_EXT_ADV_AUX_PTR_CNT) != 0 -static os_membuf_t ext_scan_aux_mem[ OS_MEMPOOL_SIZE( - MYNEWT_VAL(BLE_LL_EXT_ADV_AUX_PTR_CNT), - sizeof (struct ble_ll_aux_data)) -]; -#else -#define ext_scan_aux_mem NULL -#endif - -static struct os_mempool ext_scan_aux_pool; - -static int ble_ll_scan_start(struct ble_ll_scan_sm *scansm, - struct ble_ll_sched_item *sch); - -static void -ble_ll_aux_scan_drop_event_cb(struct ble_npl_event *ev) -{ - struct ble_ll_aux_data *aux_data = ble_npl_event_get_arg(ev); - - ble_ll_scan_end_adv_evt(aux_data); - ble_ll_scan_aux_data_unref(aux_data); -} - -static void -ble_ll_aux_scan_drop(struct ble_ll_aux_data *aux_data) -{ - BLE_LL_ASSERT(aux_data); - - STATS_INC(ble_ll_stats, aux_scan_drop); - - ble_npl_event_init(&aux_data->ev, ble_ll_aux_scan_drop_event_cb, aux_data); - ble_ll_event_send(&aux_data->ev); -} - -static int -ble_ll_aux_scan_cb(struct ble_ll_sched_item *sch) -{ - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - uint8_t lls = ble_ll_state_get(); - uint32_t wfr_usec; - - STATS_INC(ble_ll_stats, aux_sched_cb); - - /* Drop the scheduled item if scan was disable or there is aux or scan - * response pending - */ - if (!scansm->scan_enabled || scansm->cur_aux_data || - scansm->scan_rsp_pending) { - ble_ll_aux_scan_drop(sch->cb_arg); - sch->cb_arg = NULL; - goto done; - } - - /* Check if there is no aux connect sent. If so drop the sched item */ - if (lls == BLE_LL_STATE_INITIATING && ble_ll_conn_init_pending_aux_conn_rsp()) { - ble_ll_aux_scan_drop(sch->cb_arg); - sch->cb_arg = NULL; - goto done; - } - - /* This function is called only when scanner is running. This can happen - * in 3 states: - * BLE_LL_STATE_SCANNING - * BLE_LL_STATE_INITIATING - * BLE_LL_STATE_STANDBY - */ - if (lls != BLE_LL_STATE_STANDBY) { - ble_phy_disable(); - ble_ll_state_set(BLE_LL_STATE_STANDBY); - } - - /* When doing RX for AUX pkt, cur_aux_data keeps valid aux data */ - scansm->cur_aux_data = sch->cb_arg; - sch->cb_arg = NULL; - BLE_LL_ASSERT(scansm->cur_aux_data != NULL); - scansm->cur_aux_data->scanning = 1; - - if (ble_ll_scan_start(scansm, sch)) { - ble_ll_scan_interrupted(scansm); - goto done; - } - - STATS_INC(ble_ll_stats, aux_fired_for_read); - - wfr_usec = scansm->cur_aux_data->offset_units ? 300 : 30; - ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, wfr_usec); - -done: - - return BLE_LL_SCHED_STATE_DONE; -} - -static int -ble_ll_scan_ext_adv_init(struct ble_ll_aux_data **aux_data) -{ - struct ble_ll_aux_data *e; - - e = os_memblock_get(&ext_scan_aux_pool); - if (!e) { - return -1; - } - - memset(e, 0, sizeof(*e)); - e->sch.sched_cb = ble_ll_aux_scan_cb; - e->sch.sched_type = BLE_LL_SCHED_TYPE_AUX_SCAN; - e->ref_cnt = 1; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - e->rpa_index = -1; -#endif - ble_ll_trace_u32x2(BLE_LL_TRACE_ID_AUX_REF, (uint32_t)e, e->ref_cnt); - - *aux_data = e; - STATS_INC(ble_ll_stats, aux_allocated); - - return 0; -} -#endif - -static inline uint32_t -ble_ll_scan_time_hci_to_ticks(uint16_t value) -{ - return os_cputime_usecs_to_ticks(value * BLE_HCI_SCAN_ITVL); -} - -/* See Vol 6 Part B Section 4.4.3.2. Active scanning backoff */ -static void -ble_ll_scan_req_backoff(struct ble_ll_scan_sm *scansm, int success) -{ - BLE_LL_ASSERT(scansm->backoff_count == 0); - BLE_LL_ASSERT(scansm->scan_rsp_pending == 0); - - if (success) { - scansm->scan_rsp_cons_fails = 0; - ++scansm->scan_rsp_cons_ok; - if (scansm->scan_rsp_cons_ok == 2) { - scansm->scan_rsp_cons_ok = 0; - if (scansm->upper_limit > 1) { - scansm->upper_limit >>= 1; - } - } - STATS_INC(ble_ll_stats, scan_req_txg); - } else { - scansm->scan_rsp_cons_ok = 0; - ++scansm->scan_rsp_cons_fails; - if (scansm->scan_rsp_cons_fails == 2) { - scansm->scan_rsp_cons_fails = 0; - if (scansm->upper_limit < 256) { - scansm->upper_limit <<= 1; - } - } - STATS_INC(ble_ll_stats, scan_req_txf); - } - - scansm->backoff_count = rand() & (scansm->upper_limit - 1); - ++scansm->backoff_count; - BLE_LL_ASSERT(scansm->backoff_count <= 256); -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -static void -ble_ll_scan_refresh_nrpa(struct ble_ll_scan_sm *scansm) -{ - ble_npl_time_t now; - - now = ble_npl_time_get(); - if ((ble_npl_stime_t)(now - scansm->scan_nrpa_timer) >= 0) { - /* Generate new NRPA */ - ble_ll_rand_data_get(scansm->scan_nrpa, BLE_DEV_ADDR_LEN); - scansm->scan_nrpa[5] &= ~0xc0; - - /* We'll use the same timeout as for RPA rotation */ - scansm->scan_nrpa_timer = now + ble_ll_resolv_get_rpa_tmo(); - } -} -#endif - -static void -ble_ll_scan_req_pdu_prepare(struct ble_ll_scan_sm *scansm, - const uint8_t *adv_addr, uint8_t adv_addr_type, - struct ble_ll_resolv_entry *rl) -{ - uint8_t hdr_byte; - struct ble_ll_scan_pdu_data *pdu_data; - uint8_t *scana; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - uint8_t rpa[BLE_DEV_ADDR_LEN]; -#endif - - pdu_data = &scansm->pdu_data; - - /* Construct first PDU header byte */ - hdr_byte = BLE_ADV_PDU_TYPE_SCAN_REQ; - if (adv_addr_type) { - hdr_byte |= BLE_ADV_PDU_HDR_RXADD_RAND; - } - - /* Determine ScanA */ - if (scansm->own_addr_type & 0x01) { - hdr_byte |= BLE_ADV_PDU_HDR_TXADD_RAND; - scana = g_random_addr; - } else { - scana = g_dev_addr; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (scansm->own_addr_type & 0x02) { - /* - * If device is on RL and we have local IRK, we use RPA generated using - * that IRK as ScanA. Otherwise we use NRPA as ScanA to prevent our - * device from being tracked when doing an active scan (Core 5.1, Vol 6, - * Part B, section 6.3) - */ - if (rl && rl->rl_has_local) { - ble_ll_resolv_get_priv_addr(rl, 1, rpa); - scana = rpa; - } else { - ble_ll_scan_refresh_nrpa(scansm); - scana = scansm->scan_nrpa; - } - - hdr_byte |= BLE_ADV_PDU_HDR_TXADD_RAND; - } -#endif - - /* Save scan request data */ - pdu_data->hdr_byte = hdr_byte; - memcpy(pdu_data->scana, scana, BLE_DEV_ADDR_LEN); - memcpy(pdu_data->adva, adv_addr, BLE_DEV_ADDR_LEN); -} - -static uint8_t -ble_ll_scan_req_tx_pdu_cb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) -{ - struct ble_ll_scan_sm *scansm = pducb_arg; - struct ble_ll_scan_pdu_data *pdu_data = &scansm->pdu_data; - - memcpy(dptr, pdu_data->scana, BLE_DEV_ADDR_LEN); - memcpy(dptr + BLE_DEV_ADDR_LEN, pdu_data->adva, BLE_DEV_ADDR_LEN); - - *hdr_byte = pdu_data->hdr_byte; - - return BLE_DEV_ADDR_LEN * 2; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -/* if copy_from is provided new report is initialized with that instead of - * defaults - */ -static struct ble_hci_ev * -ble_ll_scan_get_ext_adv_report(struct ext_adv_report *copy_from) -{ - struct ble_hci_ev_le_subev_ext_adv_rpt *ev; - struct ext_adv_report *report; - struct ble_hci_ev *hci_ev; - - hci_ev = ( void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); - if (!hci_ev) { - return NULL; - } - - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev) + sizeof(*report); - ev = (void *) hci_ev->data; - - memset(ev, 0, sizeof(*ev)); - ev->subev_code = BLE_HCI_LE_SUBEV_EXT_ADV_RPT; - /* We support only one report per event now */ - ev->num_reports = 1; - - report = ev->reports; - - if (copy_from) { - memcpy(report, copy_from, sizeof(*report)); - report->data_len = 0; - } else { - memset(report, 0, sizeof(*report)); - - report->pri_phy = BLE_PHY_1M; - /* Init SID with "Not available" which is 0xFF */ - report->sid = 0xFF; - /* Init TX Power with "Not available" which is 127 */ - report->tx_power = 127; - /* Init RSSI with "Not available" which is 127 */ - report->rssi = 127; - /* Init address type with "anonymous" which is 0xFF */ - report->addr_type = 0xFF; - } - - return hci_ev; -} - -static void -ble_ll_scan_send_truncated(struct ble_ll_aux_data *aux_data) -{ - struct ble_hci_ev_le_subev_ext_adv_rpt *ev; - struct ext_adv_report *report; - struct ble_hci_ev *hci_ev; - - if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { - return; - } - - BLE_LL_ASSERT(aux_data); - - /* No need to send if we did not send any report or sent truncated already */ - if (!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY) || - (aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)) { - return; - } - - BLE_LL_ASSERT(aux_data->evt); - hci_ev = aux_data->evt; - aux_data->evt = NULL; - - hci_ev->length = sizeof(*ev) + sizeof(*report); - - ev = (void *) hci_ev->data; - report = ev->reports; - - report->data_len = 0; - - report->evt_type = aux_data->evt_type; - report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; - - if (aux_data->flags & BLE_LL_AUX_HAS_ADVA) { - memcpy(report->addr, aux_data->adva, 6); - report->addr_type = aux_data->adva_type; - } - - if (aux_data->flags & BLE_LL_AUX_HAS_TARGETA) { - memcpy(report->dir_addr, aux_data->targeta, 6); - report->dir_addr_type = aux_data->targeta_type; - } - - report->sid = aux_data->adi >> 12; - ble_ll_hci_event_send(hci_ev); - - aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; - aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_ANY; - aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED; -} - -static int -ble_ll_scan_get_adi(struct ble_ll_aux_data *aux_data, uint16_t *adi) -{ - if (!aux_data || !(aux_data->flags & BLE_LL_AUX_HAS_ADI)) { - return -1; - } - - *adi = aux_data->adi; - - return 0; -} - -void -ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data) -{ - /* Make sure we send report with 'truncated' data state if needed */ - ble_ll_scan_send_truncated(aux_data); -} -#endif - -static void -ble_ll_scan_clean_cur_aux_data(void) -{ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - - /* If scanner was reading aux ptr, we need to clean it up */ - if (scansm->cur_aux_data) { - ble_ll_scan_end_adv_evt(scansm->cur_aux_data); - ble_ll_scan_aux_data_unref(scansm->cur_aux_data); - scansm->cur_aux_data = NULL; - } -#endif -} - -void -ble_ll_scan_halt(void) -{ - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - - ble_ll_scan_clean_cur_aux_data(); - - /* Update backoff if we failed to receive scan response */ - if (scansm->scan_rsp_pending) { - scansm->scan_rsp_pending = 0; - ble_ll_scan_req_backoff(scansm, 0); - } -} - -/** - * Checks to see if we have received a scan response from this advertiser. - * - * @param adv_addr Address of advertiser - * @param txadd TxAdd bit (0: public; random otherwise) - * - * @return int 0: have not received a scan response; 1 otherwise. - */ -static int -ble_ll_scan_have_rxd_scan_rsp(uint8_t *addr, uint8_t txadd, - uint8_t ext_adv, uint16_t adi) -{ - uint8_t num_advs; - struct ble_ll_scan_advertisers *adv; - - /* Do we have an address match? Must match address type */ - adv = &g_ble_ll_scan_rsp_advs[0]; - num_advs = g_ble_ll_scan_num_rsp_advs; - while (num_advs) { - if (!memcmp(&adv->adv_addr, addr, BLE_DEV_ADDR_LEN)) { - /* Address type must match */ - if (txadd) { - if (adv->sc_adv_flags & BLE_LL_SC_ADV_F_RANDOM_ADDR) { - if (ext_adv) { - if (adi == adv->adi) { - return 1; - } - goto next; - } - return 1; - } - } else { - if ((adv->sc_adv_flags & BLE_LL_SC_ADV_F_RANDOM_ADDR) == 0) { - if (ext_adv) { - if (adi == adv->adi) { - return 1; - } - goto next; - } - return 1; - } - } - } -next: - ++adv; - --num_advs; - } - - return 0; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static void -ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd, - uint8_t ext_adv, uint16_t adi) -{ - uint8_t num_advs; - struct ble_ll_scan_advertisers *adv; - - /* XXX: for now, if we dont have room, just leave */ - num_advs = g_ble_ll_scan_num_rsp_advs; - if (num_advs == MYNEWT_VAL(BLE_LL_NUM_SCAN_RSP_ADVS)) { - return; - } - - /* Check if address is already on the list */ - if (ble_ll_scan_have_rxd_scan_rsp(addr, txadd, ext_adv, adi)) { - return; - } - - /* Add the advertiser to the array */ - adv = &g_ble_ll_scan_rsp_advs[num_advs]; - memcpy(&adv->adv_addr, addr, BLE_DEV_ADDR_LEN); - adv->sc_adv_flags = BLE_LL_SC_ADV_F_SCAN_RSP_RXD; - if (txadd) { - adv->sc_adv_flags |= BLE_LL_SC_ADV_F_RANDOM_ADDR; - } - adv->adi = adi; - ++g_ble_ll_scan_num_rsp_advs; - - return; -} - -static int -ble_ll_hci_send_legacy_ext_adv_report(uint8_t evtype, - const uint8_t *addr, uint8_t addr_type, - uint8_t rssi, - uint8_t adv_data_len, - struct os_mbuf *adv_data, - const uint8_t *inita, uint8_t inita_type) -{ - struct ble_hci_ev_le_subev_ext_adv_rpt *ev; - struct ext_adv_report *report; - struct ble_hci_ev *hci_ev; - - if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { - return -1; - } - - /* Drop packet if adv data doesn't fit */ - if ((sizeof(*ev) + sizeof(ev->reports[0]) + adv_data_len) > BLE_HCI_MAX_DATA_LEN) { - STATS_INC(ble_ll_stats, adv_evt_dropped); - return -1; - } - - hci_ev = ble_ll_scan_get_ext_adv_report(NULL); - if (!hci_ev) { - return -1; - } - - ev = (void *) hci_ev->data; - report = ev->reports; - - switch (evtype) { - case BLE_HCI_ADV_RPT_EVTYPE_ADV_IND: - report->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_IND; - break; - case BLE_HCI_ADV_RPT_EVTYPE_DIR_IND: - report->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_DIRECT_IND; - break; - case BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND: - report->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_NONCON_IND; - break; - case BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP: - report->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_IND; - break; - case BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND: - report->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_SCAN_IND; - break; - default: - BLE_LL_ASSERT(0); - ble_hci_trans_buf_free((uint8_t *) hci_ev); - return -1; - } - - report->addr_type = addr_type; - memcpy(report->addr, addr, BLE_DEV_ADDR_LEN); - report->pri_phy = BLE_PHY_1M; - report->sid = 0xFF; - report->tx_power = 127; - report->rssi = rssi; - - if (inita) { - report->dir_addr_type = inita_type; - memcpy(report->dir_addr, inita, BLE_DEV_ADDR_LEN); - } - - if (adv_data_len) { - hci_ev->length += adv_data_len; - report->data_len = adv_data_len; - os_mbuf_copydata(adv_data, 0, adv_data_len, report->data); - } - - return ble_ll_hci_event_send(hci_ev); -} -#endif - -static int -ble_ll_hci_send_adv_report(uint8_t evtype, - const uint8_t *addr, uint8_t addr_type, int8_t rssi, - uint8_t adv_data_len, struct os_mbuf *adv_data) -{ - struct ble_hci_ev_le_subev_adv_rpt *ev; - struct ble_hci_ev *hci_ev; - int8_t *ev_rssi; - - if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_ADV_RPT)) { - return -1; - } - - /* Drop packet if adv data doesn't fit, note extra 1 is for RSSI */ - if ((sizeof(*ev) + sizeof(ev->reports[0]) + adv_data_len + 1) > BLE_HCI_MAX_DATA_LEN) { - STATS_INC(ble_ll_stats, adv_evt_dropped); - return -1; - } - - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); - if (!hci_ev) { - return -1; - } - - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev) + sizeof(ev->reports[0]) + adv_data_len + 1; - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_ADV_RPT; - ev->num_reports = 1; - - ev->reports[0].type = evtype; - ev->reports[0].addr_type = addr_type; - memcpy(ev->reports[0].addr, addr, BLE_DEV_ADDR_LEN); - ev->reports[0].data_len = adv_data_len; - os_mbuf_copydata(adv_data, 0, adv_data_len, ev->reports[0].data); - - /* RSSI is after adv data... */ - ev_rssi = (int8_t *) (hci_ev->data + sizeof(*ev) + sizeof(ev->reports[0]) + adv_data_len); - *ev_rssi = rssi; - - return ble_ll_hci_event_send(hci_ev); -} - -static int -ble_ll_hci_send_dir_adv_report(const uint8_t *addr, uint8_t addr_type, - const uint8_t *inita, uint8_t inita_type, - int8_t rssi) -{ - struct ble_hci_ev_le_subev_direct_adv_rpt *ev; - struct ble_hci_ev *hci_ev; - - if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT)) { - return -1; - } - - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); - if (!hci_ev) { - return -1; - } - - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev) + sizeof(*(ev->reports)); - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT; - ev->num_reports = 1; - - ev->reports[0].type = BLE_HCI_ADV_RPT_EVTYPE_DIR_IND; - ev->reports[0].addr_type = addr_type; - memcpy(ev->reports[0].addr, addr, BLE_DEV_ADDR_LEN); - ev->reports[0].dir_addr_type = inita_type; - memcpy(ev->reports[0].dir_addr, inita, BLE_DEV_ADDR_LEN); - ev->reports[0].rssi = rssi; - - return ble_ll_hci_event_send(hci_ev); -} - -static int -ble_ll_scan_dup_update_legacy(uint8_t addr_type, const uint8_t *addr, - uint8_t subev, uint8_t evtype) -{ - struct ble_ll_scan_dup_entry *e; - uint8_t type; - - type = BLE_LL_SCAN_ENTRY_TYPE_LEGACY(addr_type); - - /* - * We assume ble_ll_scan_dup_check() was called before which either matched - * some entry or allocated new one and placed in on the top of queue. - */ - - e = TAILQ_FIRST(&g_scan_dup_list); - BLE_LL_ASSERT(e && e->type == type && !memcmp(e->addr, addr, 6)); - - if (subev == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) { - e->flags |= BLE_LL_SCAN_DUP_F_DIR_ADV_REPORT_SENT; - } else { - if (evtype == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) { - e->flags |= BLE_LL_SCAN_DUP_F_SCAN_RSP_SENT; - } else { - e->flags |= BLE_LL_SCAN_DUP_F_ADV_REPORT_SENT; - } - } - - return 0; -} - -/** - * Send an advertising report to the host. - * - * NOTE: while we are allowed to send multiple devices in one report, we - * will just send for one for now. - * - * @param pdu_type - * @param txadd - * @param rxbuf - * @param hdr - * @param scansm - */ -static void -ble_ll_scan_send_adv_report(uint8_t pdu_type, - const uint8_t *adva, uint8_t adva_type, - const uint8_t *inita, uint8_t inita_type, - struct os_mbuf *om, - struct ble_mbuf_hdr *hdr, - struct ble_ll_scan_sm *scansm) -{ - uint8_t subev = BLE_HCI_LE_SUBEV_ADV_RPT; - uint8_t adv_data_len; - uint8_t evtype; - int rc; - - if (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND) { - if (ble_ll_is_rpa(inita, inita_type)) { - /* For resolvable we send separate subevent */ - subev = BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT; - } - - evtype = BLE_HCI_ADV_RPT_EVTYPE_DIR_IND; - adv_data_len = 0; - } else { - if (pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) { - evtype = BLE_HCI_ADV_RPT_EVTYPE_ADV_IND; - } else if (pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND) { - evtype = BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND; - } else if (pdu_type == BLE_ADV_PDU_TYPE_ADV_NONCONN_IND) { - evtype = BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND; - } else { - evtype = BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP; - } - adv_data_len = om->om_data[1] - BLE_DEV_ADDR_LEN; - os_mbuf_adj(om, BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN); - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* If RPA has been used, make sure we use correct address types - * in the advertising report. - */ - if (BLE_MBUF_HDR_RESOLVED(hdr)) { - adva_type += 2; - } - if (BLE_MBUF_HDR_TARGETA_RESOLVED(hdr)) { - inita_type += 2; - } -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (scansm->ext_scanning) { - rc = ble_ll_hci_send_legacy_ext_adv_report(evtype, - adva, adva_type, - hdr->rxinfo.rssi, - adv_data_len, om, - inita, inita_type); - goto done; - } -#endif - - if (subev == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) { - rc = ble_ll_hci_send_dir_adv_report(adva, adva_type, inita, inita_type, - hdr->rxinfo.rssi); - goto done; - } - - rc = ble_ll_hci_send_adv_report(evtype, adva, adva_type, hdr->rxinfo.rssi, - adv_data_len, om); -done: - if (!rc && scansm->scan_filt_dups) { - ble_ll_scan_dup_update_legacy(adva_type, adva, subev, evtype); - } -} - -static void -ble_ll_get_chan_to_scan(struct ble_ll_scan_sm *scansm, uint8_t *chan, - int *phy) -{ - struct ble_ll_scan_params *scanp = scansm->scanp; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_ll_aux_data *aux_data = scansm->cur_aux_data; - - if (!scansm->ext_scanning || !aux_data || !aux_data->scanning) { - *chan = scanp->scan_chan; - *phy = scanp->phy; - return; - } - - *chan = aux_data->chan; - *phy = aux_data->aux_phy; -#else - *chan = scanp->scan_chan; - *phy = scanp->phy; -#endif -} -/** - * Called to enable the receiver for scanning. - * - * Context: Link Layer task - * - * @param sch - * - * @return int - */ -static int -ble_ll_scan_start(struct ble_ll_scan_sm *scansm, struct ble_ll_sched_item *sch) -{ - int rc; - struct ble_ll_scan_params *scanp = scansm->scanp; - uint8_t scan_chan; -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - uint8_t phy_mode; -#endif - int phy; - - BLE_LL_ASSERT(scansm->scan_rsp_pending == 0); - - ble_ll_get_chan_to_scan(scansm, &scan_chan, &phy); - - /* XXX: right now scheduled item is only present if we schedule for aux - * scan just make sanity check that we have proper combination of - * sch and resulting scan_chan - */ - BLE_LL_ASSERT(!sch || scan_chan < BLE_PHY_ADV_CHAN_START); - BLE_LL_ASSERT(sch || scan_chan >= BLE_PHY_ADV_CHAN_START); - - /* Set channel */ - rc = ble_phy_setchan(scan_chan, BLE_ACCESS_ADDR_ADV, BLE_LL_CRCINIT_ADV); - BLE_LL_ASSERT(rc == 0); - - /* - * Set transmit end callback to NULL in case we transmit a scan request. - * There is a callback for the connect request. - */ - ble_phy_set_txend_cb(NULL, NULL); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - ble_phy_encrypt_disable(); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (ble_ll_resolv_enabled()) { - ble_phy_resolv_list_enable(); - } else { - ble_phy_resolv_list_disable(); - } -#endif - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - phy_mode = ble_ll_phy_to_phy_mode(phy, BLE_HCI_LE_PHY_CODED_ANY); - ble_phy_mode_set(phy_mode, phy_mode); -#endif - - /* XXX: probably need to make sure hfxo is running too */ - /* XXX: can make this better; want to just start asap. */ - if (sch) { - rc = ble_phy_rx_set_start_time(sch->start_time + - g_ble_ll_sched_offset_ticks, - sch->remainder); - } else { - rc = ble_phy_rx_set_start_time(os_cputime_get32() + - g_ble_ll_sched_offset_ticks, 0); - } - if (!rc || rc == BLE_PHY_ERR_RX_LATE) { - /* If we are late here, it is still OK because we keep scanning. - * Clear error - */ - rc = 0; - - /* Enable/disable whitelisting */ - if (scanp->scan_filt_policy & 1) { - ble_ll_whitelist_enable(); - } else { - ble_ll_whitelist_disable(); - } - - /* Set link layer state to scanning */ - if (scanp->scan_type == BLE_SCAN_TYPE_INITIATE) { - ble_ll_state_set(BLE_LL_STATE_INITIATING); - } else { - ble_ll_state_set(BLE_LL_STATE_SCANNING); - } - } - - return rc; -} - -static uint8_t -ble_ll_scan_get_next_adv_prim_chan(uint8_t chan) -{ - ++chan; - if (chan == BLE_PHY_NUM_CHANS) { - chan = BLE_PHY_ADV_CHAN_START; - } - - return chan; -} - -static uint32_t -ble_ll_scan_move_window_to(struct ble_ll_scan_params *scanp, uint32_t time) -{ - uint32_t end_time; - - /* - * Move window until given tick is before or inside window and move to next - * channel for each skipped interval. - */ - - end_time = scanp->timing.start_time + scanp->timing.window; - while (CPUTIME_GEQ(time, end_time)) { - scanp->timing.start_time += scanp->timing.interval; - scanp->scan_chan = ble_ll_scan_get_next_adv_prim_chan(scanp->scan_chan); - end_time = scanp->timing.start_time + scanp->timing.window; - } - - return scanp->timing.start_time; -} - -static bool -ble_ll_scan_is_inside_window(struct ble_ll_scan_params *scanp, uint32_t time) -{ - uint32_t start_time; - - /* Make sure we are checking against closest window */ - start_time = ble_ll_scan_move_window_to(scanp, time); - - if (scanp->timing.window == scanp->timing.interval) { - /* always inside window in continuous scan */ - return true; - } - - return CPUTIME_GEQ(time, start_time) && - CPUTIME_LT(time, start_time + scanp->timing.window); -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static void -ble_ll_scan_aux_data_free(struct ble_ll_aux_data *aux_data) -{ - if (aux_data) { - if (aux_data->evt) { - ble_hci_trans_buf_free((uint8_t *)aux_data->evt); - aux_data->evt = NULL; - } - os_memblock_put(&ext_scan_aux_pool, aux_data); - STATS_INC(ble_ll_stats, aux_freed); - } -} - -struct ble_ll_aux_data * -ble_ll_scan_aux_data_ref(struct ble_ll_aux_data *aux_data) -{ - os_sr_t sr; - - BLE_LL_ASSERT(aux_data); - - OS_ENTER_CRITICAL(sr); - aux_data->ref_cnt++; - ble_ll_trace_u32x2(BLE_LL_TRACE_ID_AUX_REF, (uint32_t) aux_data, aux_data->ref_cnt); - - OS_EXIT_CRITICAL(sr); - - return aux_data; -} - -void -ble_ll_scan_aux_data_unref(struct ble_ll_aux_data *aux_data) -{ - os_sr_t sr; - - BLE_LL_ASSERT(aux_data); - - OS_ENTER_CRITICAL(sr); - aux_data->ref_cnt--; - ble_ll_trace_u32x2(BLE_LL_TRACE_ID_AUX_UNREF, (uint32_t) aux_data, aux_data->ref_cnt); - - if (aux_data->ref_cnt == 0) { - /* - * Some validation to make sure that we completed scan properly: - * - we either did not send any report or sent completed/truncated - * - we only sent one of completed/truncated - * - in case of error, we wither did not send anything or sent truncated - */ - BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY) || - ((aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY) && - (aux_data->flags_ll & (BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED | BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)))); - BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED) || !(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)); - BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_ERROR) || - !(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY) || - (aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)); - - ble_ll_scan_aux_data_free(aux_data); - } - - OS_EXIT_CRITICAL(sr); -} - -static void -ble_ll_scan_sched_remove(struct ble_ll_sched_item *sch) -{ - ble_ll_scan_end_adv_evt(sch->cb_arg); - ble_ll_scan_aux_data_unref(sch->cb_arg); - sch->cb_arg = NULL; -} -#endif -/** - * Stop the scanning state machine - */ -void -ble_ll_scan_sm_stop(int chk_disable) -{ - os_sr_t sr; - uint8_t lls; - struct ble_ll_scan_sm *scansm; - - /* Stop the scanning timer */ - scansm = &g_ble_ll_scan_sm; - os_cputime_timer_stop(&scansm->scan_timer); - - OS_ENTER_CRITICAL(sr); - - /* Disable scanning state machine */ - scansm->scan_enabled = 0; - scansm->restart_timer_needed = 0; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (scansm->ext_scanning) { - ble_ll_scan_clean_cur_aux_data(); - ble_ll_sched_rmv_elem_type(BLE_LL_SCHED_TYPE_AUX_SCAN, ble_ll_scan_sched_remove); - scansm->ext_scanning = 0; - } -#endif - - /* Update backoff if we failed to receive scan response */ - if (scansm->scan_rsp_pending) { - scansm->scan_rsp_pending = 0; - ble_ll_scan_req_backoff(scansm, 0); - } - OS_EXIT_CRITICAL(sr); - - /* Count # of times stopped */ - STATS_INC(ble_ll_stats, scan_stops); - - /* Only set state if we are currently in a scan window */ - if (chk_disable) { - OS_ENTER_CRITICAL(sr); - lls = ble_ll_state_get(); - - if ((lls == BLE_LL_STATE_SCANNING) || - (lls == BLE_LL_STATE_INITIATING && chk_disable == 1)) { - /* Disable phy */ - ble_phy_disable(); - - /* Set LL state to standby */ - ble_ll_state_set(BLE_LL_STATE_STANDBY); - } - OS_EXIT_CRITICAL(sr); - } - - /* No need for RF anymore */ - OS_ENTER_CRITICAL(sr); - ble_ll_rfmgmt_scan_changed(false, 0); - ble_ll_rfmgmt_release(); - OS_EXIT_CRITICAL(sr); -} - -static int -ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm) -{ - struct ble_ll_scan_params *scanp; - struct ble_ll_scan_params *scanp_next; - - if (!ble_ll_is_valid_own_addr_type(scansm->own_addr_type, g_random_addr)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - BLE_LL_ASSERT(scansm->scanp); - scanp = scansm->scanp; - scanp_next = scansm->scanp_next; - - /* Count # of times started */ - STATS_INC(ble_ll_stats, scan_starts); - - /* Set flag telling us that scanning is enabled */ - scansm->scan_enabled = 1; - - /* Set first advertising channel */ - scanp->scan_chan = BLE_PHY_ADV_CHAN_START; - if (scanp_next) { - scanp_next->scan_chan = BLE_PHY_ADV_CHAN_START; - } - - /* Reset scan request backoff parameters to default */ - scansm->upper_limit = 1; - scansm->backoff_count = 1; - scansm->scan_rsp_pending = 0; - - /* Forget filtered advertisers from previous scan. */ - g_ble_ll_scan_num_rsp_advs = 0; - - os_mempool_clear(&g_scan_dup_pool); - TAILQ_INIT(&g_scan_dup_list); - - /* - * First scan window can start when RF is enabled. Add 1 tick since we are - * most likely not aligned with ticks so RF may be effectively enabled 1 - * tick later. - */ - scanp->timing.start_time = ble_ll_rfmgmt_enable_now(); - ble_ll_rfmgmt_scan_changed(true, scanp->timing.start_time); - - if (scanp_next) { - /* Schedule start time right after first phy */ - scanp_next->timing.start_time = scanp->timing.start_time + - scanp->timing.window; - } - - /* Start scan at 1st window */ - os_cputime_timer_start(&scansm->scan_timer, scanp->timing.start_time); - - return BLE_ERR_SUCCESS; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static void -ble_ll_aux_scan_rsp_failed(struct ble_ll_scan_sm *scansm) -{ - if (!scansm->cur_aux_data) { - return; - } - - STATS_INC(ble_ll_stats, aux_scan_rsp_err); - ble_ll_scan_interrupted(scansm); -} -#endif - -static void -ble_ll_scan_interrupted_event_cb(struct ble_npl_event *ev) -{ - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_ll_aux_data *aux_data; -#endif - - if (!scansm->scan_enabled) { - return; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - aux_data = ble_npl_event_get_arg(ev); - - if (aux_data) { - if (scansm->scan_rsp_pending) { - STATS_INC(ble_ll_stats, aux_scan_rsp_err); - } - ble_ll_scan_end_adv_evt(aux_data); - ble_ll_scan_aux_data_unref(aux_data); - ble_npl_event_set_arg(ev, NULL); - STATS_INC(ble_ll_stats, aux_missed_adv); - } -#endif - - /* - * If we timed out waiting for a response, the scan response pending - * flag should be set. Deal with scan backoff. Put device back into rx. - */ - - if (scansm->scan_rsp_pending) { - scansm->scan_rsp_pending = 0; - ble_ll_scan_req_backoff(scansm, 0); - } - - ble_ll_scan_chk_resume(); -} - -/** - * Called to process the scanning OS event which was posted to the LL task - * - * Context: Link Layer task. - * - * @param arg - */ -static void -ble_ll_scan_event_proc(struct ble_npl_event *ev) -{ - struct ble_ll_scan_sm *scansm; - os_sr_t sr; - bool start_scan; - bool inside_window; - struct ble_ll_scan_params *scanp; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - bool inside_window_next; - struct ble_ll_scan_params *scanp_next; -#endif - uint32_t next_proc_time; - uint32_t now; - /* - * Get the scanning state machine. If not enabled (this is possible), just - * leave and do nothing (just make sure timer is stopped). - */ - scansm = (struct ble_ll_scan_sm *)ble_npl_event_get_arg(ev); - scanp = scansm->scanp; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - scanp_next = scansm->scanp_next; -#endif - - OS_ENTER_CRITICAL(sr); - if (!scansm->scan_enabled) { - os_cputime_timer_stop(&scansm->scan_timer); - ble_ll_rfmgmt_scan_changed(false, 0); - ble_ll_rfmgmt_release(); - OS_EXIT_CRITICAL(sr); - return; - } - - if (scansm->cur_aux_data || scansm->scan_rsp_pending) { - /* Aux scan in progress. Wait */ - STATS_INC(ble_ll_stats, scan_timer_stopped); - scansm->restart_timer_needed = 1; - OS_EXIT_CRITICAL(sr); - return; - } - - now = os_cputime_get32(); - - inside_window = ble_ll_scan_is_inside_window(scanp, now); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* Update also next PHY if configured */ - if (scanp_next) { - inside_window_next = ble_ll_scan_is_inside_window(scanp_next, now); - - /* - * Switch PHY if current PHY is outside window and next PHY is either - * inside window or has next window earlier than current PHY. - */ - if (!inside_window && - ((inside_window_next || CPUTIME_LEQ(scanp_next->timing.start_time, - scanp->timing.start_time)))) { - scansm->scanp = scanp_next; - scansm->scanp_next = scanp; - scanp = scansm->scanp; - scanp_next = scansm->scanp_next; - inside_window = inside_window_next; - } - } -#endif - - /* - * At this point scanp and scanp_next point to current or closest scan - * window on both PHYs (scanp is the closer one). Make sure RF is enabled - * on time. - */ - ble_ll_rfmgmt_scan_changed(true, scanp->timing.start_time); - - /* - * If we are inside window, next scan proc should happen at the end of - * current window to either disable scan or switch to next PHY. - * If we are outside window, next scan proc should happen at the time of - * closest scan window. - */ - if (inside_window) { - next_proc_time = scanp->timing.start_time + scanp->timing.window; - } else { - next_proc_time = scanp->timing.start_time; - } - - /* - * If we are not in the standby state it means that the scheduled - * scanning event was overlapped in the schedule. In this case all we do - * is post the scan schedule end event. - */ - start_scan = inside_window; - switch (ble_ll_state_get()) { - case BLE_LL_STATE_ADV: - case BLE_LL_STATE_CONNECTION: - case BLE_LL_STATE_SYNC: - start_scan = false; - break; - case BLE_LL_STATE_INITIATING: - /* Must disable PHY since we will move to a new channel */ - ble_phy_disable(); - if (!inside_window) { - ble_ll_state_set(BLE_LL_STATE_STANDBY); - } - /* PHY is disabled - make sure we do not wait for AUX_CONNECT_RSP */ - ble_ll_conn_reset_pending_aux_conn_rsp(); - break; - case BLE_LL_STATE_SCANNING: - /* Must disable PHY since we will move to a new channel */ - ble_phy_disable(); - if (!inside_window) { - ble_ll_state_set(BLE_LL_STATE_STANDBY); - } - break; - case BLE_LL_STATE_STANDBY: - break; - default: - BLE_LL_ASSERT(0); - break; - } - - if (start_scan) { - ble_ll_scan_start(scansm, NULL); - } else { - ble_ll_rfmgmt_release(); - } - - OS_EXIT_CRITICAL(sr); - os_cputime_timer_start(&scansm->scan_timer, next_proc_time); -} - -/** - * ble ll scan rx pdu start - * - * Called when a PDU reception has started and the Link Layer is in the - * scanning state. - * - * Context: Interrupt - * - * @param pdu_type - * @param rxflags - * - * @return int - * 0: we will not attempt to reply to this frame - * 1: we may send a response to this frame. - */ -int -ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags) -{ - int rc; - struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_params *scanp; - - rc = 0; - scansm = &g_ble_ll_scan_sm; - scanp = scansm->scanp; - - switch (scanp->scan_type) { - case BLE_SCAN_TYPE_ACTIVE: - /* If adv ind or scan ind, we may send scan request */ - if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) || - (pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND)) { - rc = 1; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND && scansm->ext_scanning)) { - *rxflags |= BLE_MBUF_HDR_F_EXT_ADV; - rc = 1; - } -#endif - - if (scansm->cur_aux_data && !scansm->scan_rsp_pending ) { - STATS_INC(ble_ll_stats, aux_received); - } - - /* - * If this is the first PDU after we sent the scan response (as - * denoted by the scan rsp pending flag), we set a bit in the ble - * header so the link layer can check to see if the scan request - * was successful. We do it this way to let the Link Layer do the - * work for successful scan requests. If failed, we do the work here. - */ - if (scansm->scan_rsp_pending) { - scansm->scan_rsp_pending = 0; - - if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_RSP) { - *rxflags |= BLE_MBUF_HDR_F_SCAN_RSP_RXD; - } else if (pdu_type == BLE_ADV_PDU_TYPE_AUX_SCAN_RSP) { - *rxflags |= BLE_MBUF_HDR_F_SCAN_RSP_RXD; - } else { - ble_ll_scan_req_backoff(scansm, 0); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - ble_ll_aux_scan_rsp_failed(scansm); -#endif - } - } - break; - case BLE_SCAN_TYPE_PASSIVE: -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND && scansm->ext_scanning)) { - *rxflags |= BLE_MBUF_HDR_F_EXT_ADV; - } - break; -#endif - default: - break; - } - - return rc; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static uint8_t -ble_ll_ext_adv_phy_mode_to_local_phy(uint8_t adv_phy_mode) -{ - switch (adv_phy_mode) { - case 0x00: - return BLE_PHY_1M; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - case 0x01: - return BLE_PHY_2M; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - case 0x02: - return BLE_PHY_CODED; -#endif - } - - return 0; -} - -static int -ble_ll_ext_scan_parse_aux_ptr(struct ble_ll_aux_data *aux_data, uint8_t *buf) -{ - uint32_t aux_ptr_field = get_le32(buf) & 0x00FFFFFF; - - aux_data->chan = (aux_ptr_field) & 0x3F; - if (aux_data->chan >= BLE_PHY_NUM_DATA_CHANS) { - return -1; - } - - /* TODO use CA aux_ptr_field >> 6 */ - - aux_data->offset = 30 * ((aux_ptr_field >> 8) & 0x1FFF); - - if ((aux_ptr_field >> 7) & 0x01) { - aux_data->offset *= 10; - aux_data->offset_units = 1; - } - - if (aux_data->offset < BLE_LL_MAFS) { - return -1; - } - - aux_data->aux_phy = - ble_ll_ext_adv_phy_mode_to_local_phy((aux_ptr_field >> 21) & 0x07); - if (aux_data->aux_phy == 0) { - return -1; - } - - return 0; -} - -static void -ble_ll_ext_scan_parse_adv_info(struct ext_adv_report *report, const uint8_t *buf) -{ - uint16_t adv_info = get_le16(buf); - - /* TODO Use DID */ - - report->sid = (adv_info >> 12); -} - -/** - * ble_ll_scan_update_aux_data - * - * Update aux_data stored in ble_hdr.rxinfo.user_data. If no aux_data is present - * (i.e. processing ADV_EXT_IND) this will try to allocate new aux_data. - * - * Context: Interrupt - * - * @param ble_hdr - * @param rxbuf - * - * @return int - * 1: do not scan for next AUX (no AuxPtr or malformed data) - * 0: scan for next AUX (valid AuxPtr found) - * -1: error - */ -int -ble_ll_scan_update_aux_data(struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf, - bool *adva_present) -{ - uint8_t pdu_hdr; - uint8_t pdu_len; - uint8_t adv_mode; - uint8_t eh_len; - uint8_t eh_flags; - uint8_t *eh; - struct ble_ll_aux_data *aux_data; - bool is_aux; - - aux_data = ble_hdr->rxinfo.user_data; - /* aux_data is initially not set only for ADV_EXT_IND */ - is_aux = aux_data; - - pdu_hdr = rxbuf[0]; - pdu_len = rxbuf[1]; - - /* PDU without at least Extended Header Length is invalid */ - if (pdu_len == 0) { - return -1; - } - - adv_mode = rxbuf[2] >> 6; - eh_len = rxbuf[2] & 0x3f; - eh_flags = rxbuf[3]; - eh = &rxbuf[4]; - - /* - * PDU without Extended Header is valid in case of last AUX_CHAIN_IND in - * chain so aux_data has to be set and advertising mode has to be 00b, - * otherwise it's an invalid PDU. - */ - if (eh_len == 0) { - if (!aux_data || adv_mode) { - return -1; - } - aux_data->flags_isr |= BLE_LL_AUX_FLAG_SCAN_COMPLETE; - return 1; - } - - /* - * If aux_data is not set, this is ADV_EXT_IND which starts new extended - * advertising event. - */ - if (!aux_data) { - if (ble_ll_scan_ext_adv_init(&aux_data)) { - return -1; - } - - aux_data->aux_primary_phy = ble_hdr->rxinfo.phy; - } else { - if (aux_data->flags_isr & BLE_LL_AUX_FLAG_AUX_ADV_RECEIVED) { - aux_data->flags_isr |= BLE_LL_AUX_FLAG_AUX_CHAIN_RECEIVED; - } else { - aux_data->flags_isr |= BLE_LL_AUX_FLAG_AUX_ADV_RECEIVED; - } - } - - /* Now parse extended header... */ - - if (eh_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { - aux_data->flags |= BLE_LL_AUX_HAS_ADVA; - memcpy(aux_data->adva, eh, 6); - aux_data->adva_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_TXADD_MASK); - eh += BLE_LL_EXT_ADV_ADVA_SIZE; - - if (adva_present) { - *adva_present = true; - } - } else if (adva_present) { - *adva_present = false; - } - - if (eh_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { - aux_data->flags |= BLE_LL_AUX_HAS_TARGETA; - memcpy(aux_data->targeta, eh, 6); - aux_data->targeta_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_RXADD_MASK); - eh += BLE_LL_EXT_ADV_TARGETA_SIZE; - } - - - if (eh_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { - eh += 1; - } - - if (eh_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { - aux_data->flags |= BLE_LL_AUX_HAS_ADI; - if (is_aux) { - if (get_le16(eh) != aux_data->adi) { - aux_data->flags_isr |= BLE_LL_AUX_FLAG_SCAN_ERROR; - STATS_INC(ble_ll_stats, aux_chain_err); - } - } else { - aux_data->adi = get_le16(eh); - } - eh += BLE_LL_EXT_ADV_DATA_INFO_SIZE; - } - - if (eh_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { - if (ble_ll_ext_scan_parse_aux_ptr(aux_data, eh)) { - aux_data->flags_isr |= BLE_LL_AUX_FLAG_SCAN_ERROR; - } - } else if (!(adv_mode & BLE_LL_EXT_ADV_MODE_SCAN)) { - /* No AuxPtr for scannable PDU is ignored since we can still scan it */ - aux_data->flags_isr |= BLE_LL_AUX_FLAG_SCAN_COMPLETE; - } - - ble_hdr->rxinfo.user_data = aux_data; - - /* Do not scan for next AUX if either no AuxPtr or malformed data found */ - return !(eh_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) || - (aux_data->flags_isr & BLE_LL_AUX_FLAG_SCAN_ERROR); -} - -/** - * Called when a receive ADV_EXT PDU has ended. - * - * Context: Interrupt - * - * @return int - * < 0 Error - * >= 0: Success (number of bytes left in PDU) - * - */ -static int -ble_ll_scan_parse_ext_hdr(struct os_mbuf *om, - const uint8_t *adva, uint8_t adva_type, - const uint8_t *inita, uint8_t inita_type, - struct ble_mbuf_hdr *ble_hdr, - struct ext_adv_report *report) -{ - uint8_t pdu_len; - uint8_t ext_hdr_len; - uint8_t ext_hdr_flags; - uint8_t *ext_hdr; - uint8_t *rxbuf = om->om_data; - int i = 1; - struct ble_ll_scan_sm *scansm; - struct ble_ll_aux_data *aux_data = ble_hdr->rxinfo.user_data; - - BLE_LL_ASSERT(report); - - scansm = &g_ble_ll_scan_sm; - - if (!scansm->ext_scanning) { - /* Ignore ext adv if host does not want it*/ - return -1; - } - - pdu_len = rxbuf[1]; - if (pdu_len == 0) { - return -1; - } - - report->evt_type = rxbuf[2] >> 6; - if ( report->evt_type > BLE_LL_EXT_ADV_MODE_SCAN) { - return -1; - } - - if (BLE_MBUF_HDR_SCAN_RSP_RXD(ble_hdr)) { - report->evt_type |= BLE_HCI_ADV_SCAN_RSP_MASK; - } - - ext_hdr_len = rxbuf[2] & 0x3F; - os_mbuf_adj(om, 3); - - ext_hdr_flags = rxbuf[3]; - ext_hdr = &rxbuf[4]; - - if (ext_hdr_len) { - i = 0; - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { - i += BLE_LL_EXT_ADV_ADVA_SIZE; - } - - if (adva) { - memcpy(report->addr, adva, 6); - report->addr_type = adva_type; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { - i += BLE_LL_EXT_ADV_TARGETA_SIZE; - } - - if (inita) { - memcpy(report->dir_addr, inita, 6); - report->dir_addr_type = inita_type; - report->evt_type |= BLE_HCI_ADV_DIRECT_MASK; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { - /* Just skip it for now*/ - i += 1; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { - ble_ll_ext_scan_parse_adv_info(report, (ext_hdr + i)); - i += BLE_LL_EXT_ADV_DATA_INFO_SIZE; - } else if (report->evt_type & BLE_HCI_ADV_SCAN_RSP_MASK) { - report->sid = (aux_data->adi >> 12); - } - - /* In this point of time we don't want to care about aux ptr */ - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { - i += BLE_LL_EXT_ADV_AUX_PTR_SIZE; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) { - report->periodic_itvl = get_le16(ext_hdr + i + 2); - i += BLE_LL_EXT_ADV_SYNC_INFO_SIZE; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { - report->tx_power = *(ext_hdr + i); - i += BLE_LL_EXT_ADV_TX_POWER_SIZE; - } - - /* TODO Handle ACAD if needed */ - } - - /* In the event we need information on primary and secondary PHY used during - * advertising. - */ - if (!aux_data) { - report->pri_phy = ble_hdr->rxinfo.phy; - goto done; - } - - report->sec_phy = aux_data->aux_phy; - report->pri_phy = aux_data->aux_primary_phy; - - if (ext_hdr_len) { - /* Adjust mbuf to contain advertising data only */ - os_mbuf_adj(om, ext_hdr_len); - } - - /* Let us first keep update event type in aux data. - * Note that in aux chain and aux scan response packets - * we do miss original event type, which we need for advertising report. - */ - aux_data->evt_type |= report->evt_type; - report->evt_type = aux_data->evt_type; - -done: - return pdu_len - ext_hdr_len - 1; -} - -static int -ble_ll_scan_get_addr_from_ext_adv(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr, - uint8_t **addr, uint8_t *addr_type, - uint8_t **inita, uint8_t *inita_type, - int *ext_mode) -{ - uint8_t pdu_len; - uint8_t ext_hdr_len; - uint8_t ext_hdr_flags; - uint8_t *ext_hdr; - bool has_adva = false; - bool has_inita = false; - int i; - struct ble_ll_aux_data *aux_data = ble_hdr->rxinfo.user_data; - - *addr = NULL; - *inita = NULL; - - pdu_len = rxbuf[1]; - if (pdu_len == 0) { - return -1; - } - - *ext_mode = rxbuf[2] >> 6; - if (*ext_mode > BLE_LL_EXT_ADV_MODE_SCAN) { - return -1; - } - - ext_hdr_len = rxbuf[2] & 0x3F; - if (ext_hdr_len == 0) { - goto done; - } - - ext_hdr_flags = rxbuf[3]; - ext_hdr = &rxbuf[4]; - - i = 0; - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { - if (ext_hdr_len < BLE_LL_EXT_ADV_ADVA_SIZE) { - return -1; - } - - *addr = ext_hdr + i; - *addr_type = - ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK); - i += BLE_LL_EXT_ADV_ADVA_SIZE; - - has_adva = true; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { - *inita = ext_hdr + i; - *inita_type = - ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK); - i += BLE_LL_EXT_ADV_TARGETA_SIZE; - - has_inita = true; - } - -done: - /* Check if we had address already. If yes, replace it with new one */ - - if (aux_data) { - /* If address has been provided, we do have it already in aux_data.*/ - if (aux_data->flags & BLE_LL_AUX_HAS_ADVA) { - if (!has_adva) { - *addr = aux_data->adva; - *addr_type = aux_data->adva_type; - } else { - memcpy(aux_data->adva, *addr, 6); - aux_data->adva_type = *addr_type; - } - } - - if (aux_data->flags & BLE_LL_AUX_HAS_TARGETA) { - if (!has_inita) { - *inita = aux_data->targeta; - *inita_type = aux_data->targeta_type; - } else { - memcpy(aux_data->targeta, *inita, 6); - aux_data->targeta_type = *inita_type; - } - } - } - - return 0; -} -#endif - -int -ble_ll_scan_adv_decode_addr(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_mbuf_hdr *ble_hdr, - uint8_t **addr, uint8_t *addr_type, - uint8_t **inita, uint8_t *inita_type, - int *ext_mode) -{ - /* - * XXX this should be only used for legacy advertising, but need to refactor - * code in ble_ll_init first so it does not call this for ext - */ - - if (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND && - pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) { - /* Legacy advertising */ - *addr_type = ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK); - *addr = rxbuf + BLE_LL_PDU_HDR_LEN; - - if (pdu_type != BLE_ADV_PDU_TYPE_ADV_DIRECT_IND) { - *inita = NULL; - *inita_type = 0; - return 0; - } - - *inita = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN; - *inita_type = ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK); - - return 0; - } - - /* Extended advertising */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - return ble_ll_scan_get_addr_from_ext_adv(rxbuf, ble_hdr, addr, addr_type, - inita, inita_type, ext_mode); -#else - return -1; -#endif - - return 0; -} - -static void -ble_ll_scan_get_addr_data_from_legacy(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_ll_scan_addr_data *addrd) -{ - BLE_LL_ASSERT(pdu_type < BLE_ADV_PDU_TYPE_ADV_EXT_IND); - - addrd->adva_present = true; - - addrd->adva = rxbuf + BLE_LL_PDU_HDR_LEN; - addrd->adva_type = ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK); - - if (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND) { - addrd->targeta = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN; - addrd->targeta_type = ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK); - } else { - addrd->targeta = NULL; - addrd->targeta_type = 0; - } -} - -/* - * Matches incoming PDU using scan filter policy and whitelist, if applicable. - * This will also resolve addresses and update flags/fields in header and - * addr_data as needed. - * - * @return 0 = no match - * 1 = match - * 2 = match, but do not scan - */ -static int -ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *addrd) -{ - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - struct ble_ll_scan_params *scanp = scansm->scanp; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_ll_aux_data *aux_data = hdr->rxinfo.user_data; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; - struct ble_ll_resolv_entry *rl = NULL; -#endif - bool scan_req_allowed = true; - int resolved = 0; - - /* Use AdvA as initial advertiser address, we may try to resolve it later */ - addrd->adv_addr = addrd->adva; - addrd->adv_addr_type = addrd->adva_type; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* By default, assume AdvA is not resolved */ - rxinfo->rpa_index = -1; - - switch (ble_ll_addr_subtype(addrd->adva, addrd->adva_type)) { - case BLE_LL_ADDR_SUBTYPE_RPA: - /* - * Only resolve if packet actually contained AdvA. - * In extended advertising PDUs we may use RL index from a PDU that - * already had AdvA (e.g. ADV_EXT_IND in case of AUX_ADV_IND without - * AdvA). In legacy advertising PDUs we always need to resolve AdvA. - */ - if (addrd->adva_present) { - rxinfo->rpa_index = ble_hw_resolv_list_match(); - } else { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - BLE_LL_ASSERT(aux_data); - rxinfo->rpa_index = aux_data->rpa_index; -#else - BLE_LL_ASSERT(false); - rxinfo->rpa_index = -1; -#endif - } - - if (rxinfo->rpa_index < 0) { - break; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (aux_data) { - aux_data->rpa_index = rxinfo->rpa_index; - } -#endif - - /* Use resolved identity address as advertiser address */ - rl = &g_ble_ll_resolv_list[rxinfo->rpa_index]; - addrd->adv_addr = rl->rl_identity_addr; - addrd->adv_addr_type = rl->rl_addr_type; - addrd->rl = rl; - - rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED; - resolved = 1; - break; - case BLE_LL_ADDR_SUBTYPE_IDENTITY: - /* - * If AdvA is an identity address, we need to check if that device was - * added to RL in order to use proper privacy mode. - */ - rl = ble_ll_resolv_list_find(addrd->adva, addrd->adva_type); - if (!rl) { - break; - } - - addrd->rl = rl; - - /* Ignore device if using network privacy mode and it has IRK */ - if ((rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && rl->rl_has_peer) { - return 0; - } - break; - default: - /* NRPA goes through filtering policy directly */ - break; - } - - if (addrd->targeta) { - switch (ble_ll_addr_subtype(addrd->targeta, addrd->targeta_type)) { - case BLE_LL_ADDR_SUBTYPE_RPA: - /* Check if TargetA can be resolved using the same RL entry as AdvA */ - if (rl && ble_ll_resolv_rpa(addrd->targeta, rl->rl_local_irk)) { - rxinfo->flags |= BLE_MBUF_HDR_F_TARGETA_RESOLVED; - break; - } - - /* Check if scan filter policy allows unresolved RPAs to be processed */ - if (!(scanp->scan_filt_policy & 0x02)) { - return 0; - } - - /* - * We will notify host as requited by scan policy, but make sure we - * do not send scan request since we do not know if this is directed - * to us. - */ - scan_req_allowed = false; - break; - case BLE_LL_ADDR_SUBTYPE_IDENTITY: - /* We shall ignore identity in TargetA if we are using RPA */ - if ((scanp->own_addr_type & 0x02) && rl && rl->rl_has_local) { - return 0; - } - /* Ignore if not directed to us */ - if (!ble_ll_is_our_devaddr(addrd->targeta, addrd->targeta_type)) { - return 0; - } - break; - default: - /* NRPA goes through filtering policy directly */ - break; - } - } -#else - /* Ignore if not directed to us */ - if (addrd->targeta && - !ble_ll_is_our_devaddr(addrd->targeta, addrd->targeta_type)) { - return 0; - } -#endif - - /* Check on WL if required by scan filter policy */ - if (scanp->scan_filt_policy & 0x01) { - if (!ble_ll_whitelist_match(addrd->adv_addr, addrd->adv_addr_type, resolved)) { - return 0; - } - } - - return scan_req_allowed ? 1 : 2; -} - -static int -ble_ll_scan_rx_isr_on_legacy(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_mbuf_hdr *hdr, - struct ble_ll_scan_addr_data *addrd) -{ - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - struct ble_ll_scan_params *scanp = scansm->scanp; - struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; - uint8_t sreq_adva_type; - uint8_t *sreq_adva; - int rc; - - ble_ll_scan_get_addr_data_from_legacy(pdu_type, rxbuf, addrd); - - if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_RSP) { - if (!BLE_MBUF_HDR_SCAN_RSP_RXD(hdr)) { - /* - * We were not expecting scan response so just ignore and do not - * update backoff. - */ - return -1; - } - - sreq_adva_type = !!(scansm->pdu_data.hdr_byte & BLE_ADV_PDU_HDR_RXADD_MASK); - sreq_adva = scansm->pdu_data.adva; - - /* - * Ignore scan response if AdvA does not match AdvA in request and also - * update backoff as if there was no scan response. - */ - if ((addrd->adva_type != sreq_adva_type) || - memcmp(addrd->adva, sreq_adva, BLE_DEV_ADDR_LEN)) { - ble_ll_scan_req_backoff(scansm, 0); - return -1; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* - * We are not pushing this one through filters so need to update - * rpa_index here as otherwise pkt_in won't be able to determine - * advertiser address properly. - */ - rxinfo->rpa_index = ble_hw_resolv_list_match(); - if (rxinfo->rpa_index >= 0) { - rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED; - } -#endif - - rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; - - return 0; - } - - rc = ble_ll_scan_rx_filter(hdr, addrd); - if (!rc) { - return 0; - } - - rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; - - if (rc == 2) { - /* Scan request forbidden by filter policy */ - return 0; - } - - return (scanp->scan_type == BLE_SCAN_TYPE_ACTIVE) && - ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) || - (pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND)); -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static int -ble_ll_scan_rx_isr_on_aux(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_mbuf_hdr *hdr, - struct ble_ll_scan_addr_data *addrd) -{ - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - struct ble_ll_scan_params *scanp = scansm->scanp; - struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; - struct ble_ll_aux_data *aux_data; - int rc; - - if (!scansm->ext_scanning) { - return -1; - } - - rc = ble_ll_scan_update_aux_data(hdr, rxbuf, &addrd->adva_present); - if (rc < 0) { - rxinfo->flags |= BLE_MBUF_HDR_F_AUX_INVALID; - return -1; - } else if (rc == 0) { - rxinfo->flags |= BLE_MBUF_HDR_F_AUX_PTR_WAIT; - } - - /* Now we can update aux_data from header since it may have just been created */ - aux_data = rxinfo->user_data; - - /* - * Restore proper header flags if filtering was already done successfully on - * some previous PDU in an event. - */ - if (aux_data->flags & BLE_LL_AUX_IS_MATCHED) { - rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; - rxinfo->rpa_index = aux_data->rpa_index; - if (rxinfo->rpa_index >= 0) { - rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED; - } - if (aux_data->flags & BLE_LL_AUX_IS_TARGETA_RESOLVED) { - rxinfo->flags |= BLE_MBUF_HDR_F_TARGETA_RESOLVED; - } - goto done; - } - - if (aux_data->flags & BLE_LL_AUX_HAS_ADVA) { - addrd->adva = aux_data->adva; - addrd->adva_type = aux_data->adva_type; - } else { - /* Accept this PDU and wait for AdvA in aux */ - rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; - return 0; - } - if (aux_data->flags & BLE_LL_AUX_HAS_TARGETA) { - addrd->targeta = aux_data->targeta; - addrd->targeta_type = aux_data->targeta_type; - } else { - addrd->targeta = NULL; - } - - rc = ble_ll_scan_rx_filter(hdr, addrd); - if (!rc) { - return 0; - } - - rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; - - /* - * Once we matched device, there's no need to go through filtering on every - * other PDU in an event so just store info required to restore state for - * subsequent PDUs in aux_data. - */ - aux_data->flags |= BLE_LL_AUX_IS_MATCHED; - if (rxinfo->flags & BLE_MBUF_HDR_F_TARGETA_RESOLVED) { - aux_data->flags |= BLE_LL_AUX_IS_TARGETA_RESOLVED; - /* AdvA state is already stored in rpa_index */ - } - - if (rc == 2) { - /* Scan request forbidden by filter policy */ - return 0; - } - -done: - return (scanp->scan_type == BLE_SCAN_TYPE_ACTIVE) && - ((rxbuf[2] >> 6) == BLE_LL_EXT_ADV_MODE_SCAN); -} -#endif - -static bool -ble_ll_scan_send_scan_req(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_mbuf_hdr *hdr, - struct ble_ll_scan_addr_data *addrd) -{ - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_ll_aux_data *aux_data = rxinfo->user_data; - uint8_t phy_mode; -#endif - bool is_ext_adv = false; - uint16_t adi = 0; - int rc; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND) { - if (ble_ll_scan_get_adi(aux_data, &adi) < 0) { - return false; - } - is_ext_adv = true; - } -#endif - - /* Check if we already scanned this device successfully */ - if (ble_ll_scan_have_rxd_scan_rsp(addrd->adv_addr, addrd->adv_addr_type, - is_ext_adv, adi)) { - return false; - } - - /* Better not be a scan response pending */ - BLE_LL_ASSERT(scansm->scan_rsp_pending == 0); - - /* We want to send a request. See if backoff allows us */ - if (scansm->backoff_count > 0) { - if (--scansm->backoff_count != 0) { - return false; - } - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - phy_mode = ble_ll_phy_to_phy_mode(rxinfo->phy, BLE_HCI_LE_PHY_CODED_ANY); - if (ble_ll_sched_scan_req_over_aux_ptr(rxinfo->channel, phy_mode)) { - return false; - } -#endif - - /* Use original AdvA in scan request (Core 5.1, Vol 6, Part B, section 6.3) */ - ble_ll_scan_req_pdu_prepare(scansm, addrd->adva, addrd->adva_type, addrd->rl); - - rc = ble_phy_tx(ble_ll_scan_req_tx_pdu_cb, scansm, BLE_PHY_TRANSITION_TX_RX); - if (rc) { - return false; - } - - scansm->scan_rsp_pending = 1; - rxinfo->flags |= BLE_MBUF_HDR_F_SCAN_REQ_TXD; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (rxinfo->channel < BLE_PHY_NUM_DATA_CHANS) { - /* Keep aux_data for expected scan response */ - scansm->cur_aux_data = ble_ll_scan_aux_data_ref(aux_data); - STATS_INC(ble_ll_stats, aux_scan_req_tx); - } -#endif - - return true; -} - -/** - * Called when a receive PDU has ended. - * - * Context: Interrupt - * - * @param rxpdu - * - * @return int - * < 0: Disable the phy after reception. - * == 0: Success. Do not disable the PHY. - * > 0: Do not disable PHY as that has already been done. - */ -int -ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) -{ - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - struct ble_mbuf_hdr *hdr = BLE_MBUF_HDR_PTR(rxpdu); - struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; - uint8_t *rxbuf; - uint8_t pdu_type; - struct ble_ll_scan_addr_data addrd; - int rc; - - /* - * If buffer for incoming PDU was not allocated we need to force scan to be - * restarted since LL will not be notified. Keep PHY enabled. - */ - if (rxpdu == NULL) { - ble_ll_scan_interrupted(scansm); - return 0; - } - - rxbuf = rxpdu->om_data; - pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* - * In case aux was expected, copy aux_data for LL to use. Make sure this was - * indeed an aux as otherwise there's no need to process it and just pass to - * LL immediately. - */ - if (scansm->cur_aux_data) { - rxinfo->user_data = scansm->cur_aux_data; - scansm->cur_aux_data = NULL; - if (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND) { - ble_ll_state_set(BLE_LL_STATE_STANDBY); - return -1; - } - } -#endif - - if (!crcok) { - goto scan_rx_isr_ignore; - } - - /* - * Addresses will be always set in handlers, no need to initialize them. We - * only need to initialize rl which may not be always set, depending on how - * filtering goes. - */ - addrd.rl = NULL; - - switch (pdu_type) { - case BLE_ADV_PDU_TYPE_ADV_IND: - case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND: - case BLE_ADV_PDU_TYPE_ADV_NONCONN_IND: - case BLE_ADV_PDU_TYPE_SCAN_RSP: - case BLE_ADV_PDU_TYPE_ADV_SCAN_IND: - rc = ble_ll_scan_rx_isr_on_legacy(pdu_type, rxbuf, hdr, &addrd); - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - case BLE_ADV_PDU_TYPE_ADV_EXT_IND: - rc = ble_ll_scan_rx_isr_on_aux(pdu_type, rxbuf, hdr, &addrd); - break; -#endif - default: - /* This is not something we would like to process here */ - rc = -1; - break; - } - - if (rc == -1) { - goto scan_rx_isr_ignore; - } else if (rc == 1) { - if (ble_ll_scan_send_scan_req(pdu_type, rxbuf, hdr, &addrd)) { - /* Keep PHY active and LL in scanning state */ - return 0; - } - } - - /* We are done with this PDU so go to standby and let LL resume if needed */ - ble_ll_state_set(BLE_LL_STATE_STANDBY); - return -1; - -scan_rx_isr_ignore: - rxinfo->flags |= BLE_MBUF_HDR_F_IGNORED; - ble_ll_state_set(BLE_LL_STATE_STANDBY); - return -1; -} - -/** - * Called to resume scanning. This is called after an advertising event or - * connection event has ended. It is also called if we receive a packet while - * in the initiating or scanning state. - * - * If periodic advertising is enabled this is also called on sync event end - * or sync packet received if chaining - * - * Context: Link Layer task - */ -void -ble_ll_scan_chk_resume(void) -{ - os_sr_t sr; - struct ble_ll_scan_sm *scansm; - uint32_t now; - - scansm = &g_ble_ll_scan_sm; - if (scansm->scan_enabled) { - OS_ENTER_CRITICAL(sr); - if (scansm->restart_timer_needed) { - scansm->restart_timer_needed = 0; - ble_ll_event_send(&scansm->scan_sched_ev); - STATS_INC(ble_ll_stats, scan_timer_restarted); - OS_EXIT_CRITICAL(sr); - return; - } - - now = os_cputime_get32(); - if (ble_ll_state_get() == BLE_LL_STATE_STANDBY && - ble_ll_scan_is_inside_window(scansm->scanp, now)) { - /* Turn on the receiver and set state */ - ble_ll_scan_start(scansm, NULL); - } - OS_EXIT_CRITICAL(sr); - } -} - -/** - * Scan timer callback; means that the scan window timeout has been reached - * and we should perform the appropriate actions. - * - * Context: Interrupt (cputimer) - * - * @param arg Pointer to scan state machine. - */ -void -ble_ll_scan_timer_cb(void *arg) -{ - struct ble_ll_scan_sm *scansm; - - scansm = (struct ble_ll_scan_sm *)arg; - ble_ll_event_send(&scansm->scan_sched_ev); -} - -void -ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm) -{ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - ble_npl_event_set_arg(&scansm->scan_interrupted_ev, scansm->cur_aux_data); - scansm->cur_aux_data = NULL; -#endif - - ble_ll_event_send(&scansm->scan_interrupted_ev); -} - -/** - * Called when the wait for response timer expires while in the scanning - * state. - * - * Context: Interrupt. - */ -void -ble_ll_scan_wfr_timer_exp(void) -{ - struct ble_ll_scan_sm *scansm; - uint8_t chan; - int phy; - int rc; -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - uint8_t phy_mode; -#endif - uint32_t now; - - scansm = &g_ble_ll_scan_sm; - - /* Update backoff if we failed to receive scan response */ - if (scansm->scan_rsp_pending) { - scansm->scan_rsp_pending = 0; - ble_ll_scan_req_backoff(scansm, 0); - } - - if (scansm->cur_aux_data) { - /* We actually care about interrupted scan only for EXT ADV because only - * then we might consider to send truncated event to the host. - */ - ble_ll_scan_interrupted(scansm); - - /* Need to disable phy since we are going to move to BLE_LL_STATE_STANDBY - * or we will need to change channel to primary one - */ - ble_phy_disable(); - - now = os_cputime_get32(); - if (!ble_ll_scan_is_inside_window(scansm->scanp, now)) { - /* Outside the window scan */ - ble_ll_state_set(BLE_LL_STATE_STANDBY); - return; - } - - ble_ll_get_chan_to_scan(scansm, &chan, &phy); -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - phy_mode = ble_ll_phy_to_phy_mode(phy, BLE_HCI_LE_PHY_CODED_ANY); - ble_phy_mode_set(phy_mode, phy_mode); -#endif - rc = ble_phy_setchan(chan, BLE_ACCESS_ADDR_ADV, BLE_LL_CRCINIT_ADV); - BLE_LL_ASSERT(rc == 0); - } - - - ble_phy_restart_rx(); -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -/* - * Send extended advertising report - * - * @return -1 on error (data truncated or other error) - * 0 on success (data status is "completed") - * 1 on success (data status is not "completed") - */ -static int -ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type, - uint8_t *inita, uint8_t inita_type, - struct os_mbuf *om, - struct ble_mbuf_hdr *hdr) -{ - struct ble_ll_aux_data *aux_data = hdr->rxinfo.user_data; - struct ble_hci_ev_le_subev_ext_adv_rpt *ev; - struct ext_adv_report *report; - struct ble_hci_ev *hci_ev; - struct ble_hci_ev *hci_ev_next; - int offset; - int datalen; - int rc; - bool need_event; - bool is_scannable_aux; - uint8_t max_data_len; - - if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { - rc = -1; - goto done; - } - - /* - * We keep one allocated event in aux_data to be able to truncate chain - * properly in case of error. If there is no event in aux_data it means this - * is the first event for this chain. - */ - if (aux_data && aux_data->evt) { - hci_ev = aux_data->evt; - aux_data->evt = NULL; - - hci_ev->length = sizeof(*ev) + sizeof(*report); - } else { - hci_ev = ble_ll_scan_get_ext_adv_report(NULL); - if (!hci_ev) { - rc = -1; - goto done; - } - } - - ev = (void *) hci_ev->data; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* If RPA has been used, make sure we use correct address types - * in the advertising report. - */ - if (BLE_MBUF_HDR_RESOLVED(hdr)) { - adva_type += 2; - } - if (BLE_MBUF_HDR_TARGETA_RESOLVED(hdr)) { - inita_type += 2; - } -#endif - - datalen = ble_ll_scan_parse_ext_hdr(om, adva, adva_type, inita, inita_type, - hdr, ev->reports); - if (datalen < 0) { - rc = -1; - - /* Need to send truncated event if we already sent some reports */ - if (aux_data && (aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY)) { - BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED)); - BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)); - - aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; - aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED; - - report = ev->reports; - report->data_len = 0; - report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; - - ble_ll_hci_event_send(hci_ev); - goto done; - } - - ble_hci_trans_buf_free((uint8_t *)hci_ev); - goto done; - } - - is_scannable_aux = aux_data && - (aux_data->evt_type & BLE_HCI_ADV_SCAN_MASK) && - !(aux_data->evt_type & BLE_HCI_ADV_SCAN_RSP_MASK); - - max_data_len = BLE_LL_MAX_EVT_LEN - sizeof(*hci_ev) - sizeof(*ev) - sizeof(*report); - offset = 0; - - do { - hci_ev_next = NULL; - - ev = (void *) hci_ev->data; - report = ev->reports; - - report->data_len = min(max_data_len, datalen - offset); - - /* adjust event length */ - hci_ev->length += report->data_len; - report->rssi = hdr->rxinfo.rssi; - - os_mbuf_copydata(om, offset, report->data_len, report->data); - offset += report->data_len; - - /* - * We need another event if either there are still some data left to - * send in current PDU or scan is not completed. The only exception is - * when this is a scannable event which is not a scan response. - */ - need_event = ((offset < datalen) || (aux_data && !(aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_COMPLETE))) && !is_scannable_aux; - - if (need_event) { - /* - * We will need another event so let's try to allocate one now. If - * we cannot do this, need to mark event as truncated. - */ - hci_ev_next = ble_ll_scan_get_ext_adv_report(report); - - if (hci_ev_next) { - report->evt_type |= BLE_HCI_ADV_DATA_STATUS_INCOMPLETE; - rc = 1; - } else { - report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; - rc = -1; - } - } else if (aux_data && (aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_ERROR)) { - report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; - rc = -1; - } else { - rc = 0; - } - - if ((rc == -1) && aux_data) { - aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; - - if (!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY)) { - ble_hci_trans_buf_free((uint8_t *)hci_ev); - goto done; - } - - aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED; - } else if (!is_scannable_aux) { - /* - * We do not set 'sent' flags for scannable AUX since we only care - * about scan response that will come next. - */ - aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_ANY; - if (rc == 0) { - aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED; - } - } - - ble_ll_hci_event_send(hci_ev); - - hci_ev = hci_ev_next; - } while ((offset < datalen) && hci_ev); - - BLE_LL_ASSERT(offset <= datalen); - - if (aux_data) { - /* Store any event left for later use */ - aux_data->evt = hci_ev; - } else { - /* If it is empty beacon, evt shall be NULL */ - BLE_LL_ASSERT(!hci_ev); - } - -done: - if (!aux_data) { - return rc; - } - - if (rc == 0) { - if (aux_data->evt_type & BLE_HCI_ADV_SCAN_RSP_MASK) { - /* Complete scan response can be added to duplicates list */ - ble_ll_scan_add_scan_rsp_adv(aux_data->adva, aux_data->adva_type, - 1, aux_data->adi); - } else if (is_scannable_aux) { - /* - * Scannable AUX is marked as incomplete because we do not want to - * add this to duplicates list now, this should happen only after - * we receive complete scan response. The drawback here is that we - * will keep receiving reports for scannable PDUs until complete - * scan response is received. - * - * XXX ^^ extend duplicates list to fix - */ - rc = 1; - } - } else if (rc < 0) { - aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; - } - - return rc; -} -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) -static void -ble_ll_scan_check_periodic_sync(const struct os_mbuf *om, struct ble_mbuf_hdr *rxhdr, - uint8_t *adva, uint8_t adva_type, int rpa_index) -{ - uint8_t pdu_len; - uint8_t ext_hdr_len; - uint8_t ext_hdr_flags; - uint8_t *ext_hdr; - uint8_t *rxbuf = om->om_data; - uint8_t sid; - int i; - - pdu_len = rxbuf[1]; - if (pdu_len == 0) { - return; - } - - ext_hdr_len = rxbuf[2] & 0x3F; - - if (ext_hdr_len) { - ext_hdr_flags = rxbuf[3]; - ext_hdr = &rxbuf[4]; - i = 0; - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { - i += BLE_LL_EXT_ADV_ADVA_SIZE; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { - i += BLE_LL_EXT_ADV_TARGETA_SIZE; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { - i += 1; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { - sid = (get_le16(ext_hdr + i) >> 12); - i += BLE_LL_EXT_ADV_DATA_INFO_SIZE; - } else { - /* ADI is mandatory */ - return; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { - i += BLE_LL_EXT_ADV_AUX_PTR_SIZE; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) { - ble_ll_sync_info_event(adva, adva_type, rpa_index, sid, rxhdr, - ext_hdr + i); - } - } -} -#endif - -static inline void -ble_ll_scan_dup_move_to_head(struct ble_ll_scan_dup_entry *e) -{ - if (e != TAILQ_FIRST(&g_scan_dup_list)) { - TAILQ_REMOVE(&g_scan_dup_list, e, link); - TAILQ_INSERT_HEAD(&g_scan_dup_list, e, link); - } -} - -static inline struct ble_ll_scan_dup_entry * -ble_ll_scan_dup_new(void) -{ - struct ble_ll_scan_dup_entry *e; - - e = os_memblock_get(&g_scan_dup_pool); - if (!e) { - e = TAILQ_LAST(&g_scan_dup_list, ble_ll_scan_dup_list); - TAILQ_REMOVE(&g_scan_dup_list, e, link); - } - - memset(e, 0, sizeof(*e)); - - return e; -} - -static int -ble_ll_scan_dup_check_legacy(uint8_t addr_type, uint8_t *addr, uint8_t pdu_type) -{ - struct ble_ll_scan_dup_entry *e; - uint8_t type; - int rc; - - type = BLE_LL_SCAN_ENTRY_TYPE_LEGACY(addr_type); - - TAILQ_FOREACH(e, &g_scan_dup_list, link) { - if ((e->type == type) && !memcmp(e->addr, addr, 6)) { - break; - } - } - - if (e) { - if (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND) { - rc = e->flags & BLE_LL_SCAN_DUP_F_DIR_ADV_REPORT_SENT; - } else if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_RSP) { - rc = e->flags & BLE_LL_SCAN_DUP_F_SCAN_RSP_SENT; - } else { - rc = e->flags & BLE_LL_SCAN_DUP_F_ADV_REPORT_SENT; - } - - ble_ll_scan_dup_move_to_head(e); - } else { - rc = 0; - - e = ble_ll_scan_dup_new(); - e->flags = 0; - e->type = type; - memcpy(e->addr, addr, 6); - - TAILQ_INSERT_HEAD(&g_scan_dup_list, e, link); - } - - return rc; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static int -ble_ll_scan_dup_check_ext(uint8_t addr_type, uint8_t *addr, - struct ble_ll_aux_data *aux_data) -{ - struct ble_ll_scan_dup_entry *e; - bool has_aux; - bool is_anon; - uint16_t adi; - uint8_t type; - int rc; - - has_aux = aux_data != NULL; - is_anon = addr == NULL; - adi = has_aux ? aux_data->adi : 0; - - type = BLE_LL_SCAN_ENTRY_TYPE_EXT(addr_type, has_aux, is_anon, adi); - - TAILQ_FOREACH(e, &g_scan_dup_list, link) { - if ((e->type == type) && - (is_anon || !memcmp(e->addr, addr, BLE_DEV_ADDR_LEN))) { - break; - } - } - - if (e) { - if (e->adi != adi) { - rc = 0; - - e->flags = 0; - e->adi = adi; - } else { - rc = e->flags & BLE_LL_SCAN_DUP_F_ADV_REPORT_SENT; - } - - ble_ll_scan_dup_move_to_head(e); - } else { - rc = 0; - - e = ble_ll_scan_dup_new(); - e->flags = 0; - e->type = type; - e->adi = adi; - if (!is_anon) { - memcpy(e->addr, addr, 6); - } - - TAILQ_INSERT_HEAD(&g_scan_dup_list, e, link); - } - - return rc; -} - -static int -ble_ll_scan_dup_update_ext(uint8_t addr_type, uint8_t *addr, - struct ble_ll_aux_data *aux_data) -{ - struct ble_ll_scan_dup_entry *e; - bool has_aux; - bool is_anon; - uint16_t adi; - uint8_t type; - - has_aux = aux_data != NULL; - is_anon = addr == NULL; - adi = has_aux ? aux_data->adi : 0; - - type = BLE_LL_SCAN_ENTRY_TYPE_EXT(addr_type, has_aux, is_anon, adi); - - /* - * We assume ble_ll_scan_dup_check() was called before which either matched - * some entry or allocated new one and placed in on the top of queue. - */ - - e = TAILQ_FIRST(&g_scan_dup_list); - BLE_LL_ASSERT(e && e->type == type && (is_anon || !memcmp(e->addr, addr, 6))); - - e->flags |= BLE_LL_SCAN_DUP_F_ADV_REPORT_SENT; - - return 0; -} -#endif - -static void -ble_ll_scan_rx_pkt_in_restore_addr_data(struct ble_mbuf_hdr *hdr, - struct ble_ll_scan_addr_data *addrd) -{ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; - struct ble_ll_resolv_entry *rl; -#endif - - addrd->adv_addr = addrd->adva; - addrd->adv_addr_type = addrd->adva_type; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (rxinfo->rpa_index >= 0) { - rl = &g_ble_ll_resolv_list[rxinfo->rpa_index]; - addrd->adv_addr = rl->rl_identity_addr; - addrd->adv_addr_type = rl->rl_addr_type; - addrd->rl = rl; - } - if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_TARGETA_RESOLVED) { - addrd->targeta = ble_ll_get_our_devaddr(scansm->own_addr_type & 1); - addrd->targeta_type = scansm->own_addr_type & 1; - } -#endif -} - -static void -ble_ll_scan_rx_pkt_in_on_legacy(uint8_t pdu_type, struct os_mbuf *om, - struct ble_mbuf_hdr *hdr, - struct ble_ll_scan_addr_data *addrd) -{ - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - uint8_t *rxbuf = om->om_data; - bool send_hci_report; - - - if (!BLE_MBUF_HDR_DEVMATCH(hdr) || - !BLE_MBUF_HDR_CRC_OK(hdr) || - BLE_MBUF_HDR_IGNORED(hdr)) { - return; - } - - ble_ll_scan_get_addr_data_from_legacy(pdu_type, rxbuf, addrd); - ble_ll_scan_rx_pkt_in_restore_addr_data(hdr, addrd); - - send_hci_report = !scansm->scan_filt_dups || - !ble_ll_scan_dup_check_legacy(addrd->adv_addr_type, - addrd->adv_addr, - pdu_type); - if (send_hci_report) { - /* Sending advertising report will also update scan_dup list */ - ble_ll_scan_send_adv_report(pdu_type, - addrd->adv_addr, addrd->adv_addr_type, - addrd->targeta, addrd->targeta_type, - om, hdr, scansm); - } - - if (BLE_MBUF_HDR_SCAN_RSP_RXD(hdr)) { - ble_ll_scan_req_backoff(scansm, 1); - } -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static void -ble_ll_scan_rx_pkt_in_on_aux(uint8_t pdu_type, struct os_mbuf *om, - struct ble_mbuf_hdr *hdr, - struct ble_ll_scan_addr_data *addrd) -{ - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - uint8_t *rxbuf = om->om_data; -#endif - struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; - struct ble_ll_aux_data *aux_data = rxinfo->user_data; - bool send_hci_report; - int rc; - - if (!scansm->ext_scanning) { - goto scan_continue; - } - - if (aux_data) { - aux_data->flags_ll |= aux_data->flags_isr; - } - - /* - * For every new extended advertising event scanned, rx_isr_end will either - * allocate new aux_data or set 'invalid' flag. This means if no 'invalid' - * flag is set, aux_data is always valid. - */ - - /* Drop on scan error or if we received not what we expected to receive */ - if (!BLE_MBUF_HDR_CRC_OK(hdr) || - BLE_MBUF_HDR_IGNORED(hdr) || - BLE_MBUF_HDR_AUX_INVALID(hdr) || - (aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_ERROR) || - (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND)) { - if (aux_data) { - ble_ll_scan_end_adv_evt(aux_data); - ble_ll_scan_aux_data_unref(aux_data); - rxinfo->user_data = NULL; - } - return; - } - - BLE_LL_ASSERT(aux_data); - - if (aux_data->flags & BLE_LL_AUX_HAS_ADVA) { - addrd->adva = aux_data->adva; - addrd->adva_type = aux_data->adva_type; - } else { - addrd->adva = NULL; - addrd->adva_type = 0; - } - if (aux_data->flags & BLE_LL_AUX_HAS_TARGETA) { - addrd->targeta = aux_data->targeta; - addrd->targeta_type = aux_data->targeta_type; - } else { - addrd->targeta = NULL; - addrd->targeta_type = 0; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - /* - * Periodic scan uses own filter list so we need to let it do own filtering - * regardless of scanner filtering. Just make sure we already have AdvA. - */ - if (ble_ll_sync_enabled() && - ((rxbuf[2] >> 6) == BLE_LL_EXT_ADV_MODE_NON_CONN) && addrd->adva && - !(aux_data->flags_ll & BLE_LL_AUX_FLAG_AUX_CHAIN_RECEIVED)) { - ble_ll_scan_check_periodic_sync(om, hdr, addrd->adva, addrd->adva_type, - rxinfo->rpa_index); - } -#endif - - /* Ignore if device was not matched by either whitelist or scan policy */ - if (!BLE_MBUF_HDR_DEVMATCH(hdr)) { - goto scan_continue; - } - - ble_ll_scan_rx_pkt_in_restore_addr_data(hdr, addrd); - - /* - * If there is AuxPtr in this PDU, we should first try to schedule scan for - * subsequent aux. - */ - if (BLE_MBUF_HDR_WAIT_AUX(hdr)) { - if (ble_ll_sched_aux_scan(hdr, scansm, aux_data)) { - rxinfo->flags &= ~BLE_MBUF_HDR_F_AUX_PTR_WAIT; - aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; - - /* Silently ignore if no HCI event was sent to host */ - if (!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY)) { - goto scan_continue; - } - } - - /* Ignore if this was just ADV_EXT_IND with AuxPtr, will process aux */ - if (!(aux_data->flags_ll & BLE_LL_AUX_FLAG_AUX_ADV_RECEIVED)) { - goto scan_continue; - } - - STATS_INC(ble_ll_stats, aux_chain_cnt); - } - - send_hci_report = !scansm->scan_filt_dups || - !ble_ll_scan_dup_check_ext(addrd->adv_addr_type, - addrd->adv_addr, aux_data); - if (send_hci_report) { - rc = ble_ll_hci_send_ext_adv_report(pdu_type, - addrd->adv_addr, addrd->adv_addr_type, - addrd->targeta, addrd->targeta_type, - om, hdr); - if ((rc < 0) && BLE_MBUF_HDR_WAIT_AUX(hdr)) { - /* Data were truncated so stop scanning for subsequent auxes */ - aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; - - if (ble_ll_sched_rmv_elem(&aux_data->sch) == 0) { - ble_ll_scan_aux_data_unref(aux_data->sch.cb_arg); - aux_data->sch.cb_arg = NULL; - } - } else if ((rc == 0) && scansm->scan_filt_dups) { - /* Complete data were send so we can update scan_dup list */ - ble_ll_scan_dup_update_ext(addrd->adv_addr_type, addrd->adv_addr, - aux_data); - } - } - - if (BLE_MBUF_HDR_SCAN_RSP_RXD(hdr)) { - /* - * For now assume success if we just received direct scan response, - * don't care about complete aux chain. - */ - ble_ll_scan_req_backoff(scansm, 1); - } - -scan_continue: - ble_ll_scan_aux_data_unref(rxinfo->user_data); - rxinfo->user_data = NULL; -} -#endif - -/** - * Process a received PDU while in the scanning state. - * - * Context: Link Layer task. - * - * @param pdu_type - * @param rxbuf - */ -void -ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hdr) -{ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; - struct ble_ll_aux_data *aux_data = rxinfo->user_data; -#endif - struct ble_ll_scan_addr_data addrd; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (aux_data || (ptype == BLE_ADV_PDU_TYPE_ADV_EXT_IND)) { - ble_ll_scan_rx_pkt_in_on_aux(ptype, om, hdr, &addrd); - ble_ll_scan_chk_resume(); - return; - } -#endif - - ble_ll_scan_rx_pkt_in_on_legacy(ptype, om, hdr, &addrd); - ble_ll_scan_chk_resume(); -} - -int -ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_scan_params_cp *cmd = (const void *)cmdbuf; - uint16_t scan_itvl; - uint16_t scan_window; - struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_params *scanp; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* If already enabled, we return an error */ - scansm = &g_ble_ll_scan_sm; - if (scansm->scan_enabled) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* Get the scan interval and window */ - scan_itvl = le16toh(cmd->scan_itvl); - scan_window = le16toh(cmd->scan_window); - - /* Check scan type */ - if ((cmd->scan_type != BLE_HCI_SCAN_TYPE_PASSIVE) && - (cmd->scan_type != BLE_HCI_SCAN_TYPE_ACTIVE)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check interval and window */ - if ((scan_itvl < BLE_HCI_SCAN_ITVL_MIN) || - (scan_itvl > BLE_HCI_SCAN_ITVL_MAX) || - (scan_window < BLE_HCI_SCAN_WINDOW_MIN) || - (scan_window > BLE_HCI_SCAN_WINDOW_MAX) || - (scan_itvl < scan_window)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check own addr type */ - if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check scanner filter policy */ - if (cmd->filter_policy > BLE_HCI_SCAN_FILT_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Store scan parameters */ - scanp = &g_ble_ll_scan_params[PHY_UNCODED]; - scanp->configured = 1; - scanp->scan_type = cmd->scan_type; - scanp->timing.interval = ble_ll_scan_time_hci_to_ticks(scan_itvl); - scanp->timing.window = ble_ll_scan_time_hci_to_ticks(scan_window); - scanp->scan_filt_policy = cmd->filter_policy; - scanp->own_addr_type = cmd->own_addr_type; - -#if (BLE_LL_SCAN_PHY_NUMBER == 2) - g_ble_ll_scan_params[PHY_CODED].configured = 0; -#endif - - return 0; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static int -ble_ll_check_scan_params(uint8_t type, uint16_t itvl, uint16_t window) -{ - /* Check scan type */ - if ((type != BLE_HCI_SCAN_TYPE_PASSIVE) && - (type != BLE_HCI_SCAN_TYPE_ACTIVE)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check interval and window */ - if ((itvl < BLE_HCI_SCAN_ITVL_MIN) || - (itvl > BLE_HCI_SCAN_ITVL_MAX) || - (window < BLE_HCI_SCAN_WINDOW_MIN) || - (window > BLE_HCI_SCAN_WINDOW_MAX) || - (itvl < window)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return 0; -} - -int -ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_ext_scan_params_cp *cmd = (const void *) cmdbuf; - const struct scan_params *params = cmd->scans; - - struct ble_ll_scan_params new_params[BLE_LL_SCAN_PHY_NUMBER] = { }; - struct ble_ll_scan_params *uncoded = &new_params[PHY_UNCODED]; - struct ble_ll_scan_params *coded = &new_params[PHY_CODED]; - uint16_t interval; - uint16_t window; - int rc; - - if (len <= sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - len -= sizeof(*cmd); - - /* If already enabled, we return an error */ - if (g_ble_ll_scan_sm.scan_enabled) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* Check own addr type */ - if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - coded->own_addr_type = cmd->own_addr_type; - uncoded->own_addr_type = cmd->own_addr_type; - - /* Check scanner filter policy */ - if (cmd->filter_policy > BLE_HCI_SCAN_FILT_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - coded->scan_filt_policy = cmd->filter_policy; - uncoded->scan_filt_policy = cmd->filter_policy; - - /* Check if no reserved bits in PHYS are set and that at least one valid PHY - * is set. - */ - if (!(cmd->phys & SCAN_VALID_PHY_MASK) || - (cmd->phys & ~SCAN_VALID_PHY_MASK)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (cmd->phys & BLE_HCI_LE_PHY_1M_PREF_MASK) { - if (len < sizeof(*params)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - interval = le16toh(params->itvl); - window = le16toh(params->window); - - rc = ble_ll_check_scan_params(params->type, interval, window); - if (rc) { - return rc; - } - - uncoded->scan_type = params->type; - uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(interval); - uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(window); - - /* That means user wants to use this PHY for scanning */ - uncoded->configured = 1; - params++; - len -= sizeof(*params); - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - if (cmd->phys & BLE_HCI_LE_PHY_CODED_PREF_MASK) { - if (len < sizeof(*params)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - interval = le16toh(params->itvl); - window = le16toh(params->window); - - rc = ble_ll_check_scan_params(params->type, interval, window); - if (rc) { - return rc; - } - - coded->scan_type = params->type; - coded->timing.interval = ble_ll_scan_time_hci_to_ticks(interval); - coded->timing.window = ble_ll_scan_time_hci_to_ticks(window); - - /* That means user wants to use this PHY for scanning */ - coded->configured = 1; - } -#endif - - /* if any of PHYs is configured for continuous scan we alter interval to - * fit other PHY - */ - if (coded->configured && uncoded->configured) { - if (coded->timing.interval == coded->timing.window) { - coded->timing.interval += uncoded->timing.window; - } - - if (uncoded->timing.interval == uncoded->timing.window) { - uncoded->timing.window += coded->timing.window; - } - } - - memcpy(g_ble_ll_scan_params, new_params, sizeof(new_params)); - - return 0; -} - -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static void -ble_ll_scan_duration_period_timers_restart(struct ble_ll_scan_sm *scansm) -{ - uint32_t now; - - now = os_cputime_get32(); - - os_cputime_timer_stop(&scansm->duration_timer); - os_cputime_timer_stop(&scansm->period_timer); - - if (scansm->duration_ticks) { - os_cputime_timer_start(&scansm->duration_timer, - now + scansm->duration_ticks); - - if (scansm->period_ticks) { - os_cputime_timer_start(&scansm->period_timer, - now + scansm->period_ticks); - } - } -} - -static void -ble_ll_scan_duration_timer_cb(void *arg) -{ - struct ble_ll_scan_sm *scansm; - - scansm = (struct ble_ll_scan_sm *)arg; - - ble_ll_scan_sm_stop(2); - - /* if period is set both timers get started from period cb */ - if (!scansm->period_ticks) { - ble_ll_hci_ev_send_scan_timeout(); - } -} - -static void -ble_ll_scan_period_timer_cb(void *arg) -{ - struct ble_ll_scan_sm *scansm = arg; - - ble_ll_scan_sm_start(scansm); - - /* always start timer regardless of ble_ll_scan_sm_start result - * if it failed will restart in next period - */ - ble_ll_scan_duration_period_timers_restart(scansm); -} -#endif - -/** - * ble ll scan set enable - * - * HCI scan set enable command processing function - * - * Context: Link Layer task (HCI Command parser). - * - * @return int BLE error code. - */ -static int -ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, - uint16_t dur, bool ext) -{ - int rc; - struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_params *scanp; - struct ble_ll_scan_params *scanp_phy; - int i; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - uint32_t period_ticks = 0; - uint32_t dur_ticks = 0; -#endif - - /* Check for valid parameters */ - if ((filter_dups > 1) || (enable > 1)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - scansm = &g_ble_ll_scan_sm; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* we can do that here since value will never change until reset */ - scansm->ext_scanning = ext; - - if (ext) { - /* Period parameter is ignored when the Duration parameter is zero */ - if (!dur) { - period = 0; - } - - /* period is in 1.28 sec units - * TODO support full range, would require os_cputime milliseconds API - */ - if (period > 3355) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - period_ticks = os_cputime_usecs_to_ticks(period * 1280000); - - /* duration is in 10ms units */ - dur_ticks = os_cputime_usecs_to_ticks(dur * 10000); - - if (dur_ticks && period_ticks && (dur_ticks >= period_ticks)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - } -#endif - - /* disable*/ - if (!enable) { - if (scansm->scan_enabled) { - ble_ll_scan_sm_stop(1); - } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - os_cputime_timer_stop(&scansm->duration_timer); - os_cputime_timer_stop(&scansm->period_timer); -#endif - - return BLE_ERR_SUCCESS; - } - - /* if already enable we just need to update parameters */ - if (scansm->scan_enabled) { - /* Controller does not allow initiating and scanning.*/ - for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) { - scanp_phy = &scansm->scanp_phys[i]; - if (scanp_phy->configured && - scanp_phy->scan_type == BLE_SCAN_TYPE_INITIATE) { - return BLE_ERR_CMD_DISALLOWED; - } - } - -#if MYNEWT_VAL(BLE_LL_NUM_SCAN_DUP_ADVS) - /* update filter policy */ - scansm->scan_filt_dups = filter_dups; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* restart timers according to new settings */ - scansm->duration_ticks = dur_ticks; - scansm->period_ticks = period_ticks; - ble_ll_scan_duration_period_timers_restart(scansm); -#endif - - return BLE_ERR_SUCCESS; - } - - /* we can store those upfront regardless of start scan result since scan is - * disabled now - */ - -#if MYNEWT_VAL(BLE_LL_NUM_SCAN_DUP_ADVS) - scansm->scan_filt_dups = filter_dups; -#endif - scansm->scanp = NULL; - scansm->scanp_next = NULL; - - for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) { - scanp_phy = &scansm->scanp_phys[i]; - scanp = &g_ble_ll_scan_params[i]; - - if (!scanp->configured) { - continue; - } - - scanp_phy->configured = scanp->configured; - scanp_phy->scan_type = scanp->scan_type; - scanp_phy->timing = scanp->timing; - scanp_phy->scan_filt_policy = scanp->scan_filt_policy; - scanp_phy->own_addr_type = scanp->own_addr_type; - - if (!scansm->scanp) { - scansm->scanp = scanp_phy; - /* Take own_addr_type from the first configured PHY. - * Note: All configured PHYs shall have the same own_addr_type - */ - scansm->own_addr_type = scanp_phy->own_addr_type; - } else { - scansm->scanp_next = scanp_phy; - } - } - - /* spec is not really clear if we should use defaults in this case - * or just disallow starting scan without explicit configuration - * For now be nice to host and just use values based on LE Set Scan - * Parameters defaults. - */ - if (!scansm->scanp) { - scansm->scanp = &scansm->scanp_phys[PHY_UNCODED]; - scansm->own_addr_type = BLE_ADDR_PUBLIC; - - scanp_phy = scansm->scanp; - scanp_phy->configured = 1; - scanp_phy->scan_type = BLE_SCAN_TYPE_PASSIVE; - scanp_phy->timing.interval = - ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_ITVL_DEF); - scanp_phy->timing.window = - ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_WINDOW_DEF); - scanp_phy->scan_filt_policy = BLE_HCI_SCAN_FILT_NO_WL; - scanp_phy->own_addr_type = BLE_ADDR_PUBLIC; - } - - rc = ble_ll_scan_sm_start(scansm); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (rc == BLE_ERR_SUCCESS) { - scansm->duration_ticks = dur_ticks; - scansm->period_ticks = period_ticks; - ble_ll_scan_duration_period_timers_restart(scansm); - } -#endif - - return rc; -} - -int ble_ll_hci_scan_set_enable(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_scan_enable_cp *cmd = (const void *) cmdbuf; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return ble_ll_scan_set_enable(cmd->enable, cmd->filter_duplicates, 0, 0, - false); -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -int ble_ll_hci_ext_scan_set_enable(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_ext_scan_enable_cp *cmd = (const void *) cmdbuf; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return ble_ll_scan_set_enable(cmd->enable, cmd->filter_dup, - le16toh(cmd->period), le16toh(cmd->duration), - true); -} -#endif - -/** - * Checks if controller can change the whitelist. If scanning is enabled and - * using the whitelist the controller is not allowed to change the whitelist. - * - * @return int 0: not allowed to change whitelist; 1: change allowed. - */ -int -ble_ll_scan_can_chg_whitelist(void) -{ - int rc; - struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_params *scanp; - - scansm = &g_ble_ll_scan_sm; - scanp = scansm->scanp; - if (scansm->scan_enabled && (scanp->scan_filt_policy & 1)) { - rc = 0; - } else { - rc = 1; - } - - return rc; -} - -int -ble_ll_scan_initiator_start(struct hci_create_conn *hcc, - struct ble_ll_scan_sm **sm) -{ - struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_params *scanp; - int rc; - - scansm = &g_ble_ll_scan_sm; - scansm->own_addr_type = hcc->own_addr_type; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - scansm->ext_scanning = 0; -#endif - scansm->scanp = &scansm->scanp_phys[PHY_UNCODED]; - scansm->scanp_next = NULL; - - scanp = scansm->scanp; - scanp->scan_filt_policy = hcc->filter_policy; - scanp->timing.interval = ble_ll_scan_time_hci_to_ticks(hcc->scan_itvl); - scanp->timing.window = ble_ll_scan_time_hci_to_ticks(hcc->scan_window); - scanp->scan_type = BLE_SCAN_TYPE_INITIATE; - - rc = ble_ll_scan_sm_start(scansm); - if (sm == NULL) { - return rc; - } - - if (rc == BLE_ERR_SUCCESS) { - *sm = scansm; - } else { - *sm = NULL; - } - - return rc; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -int -ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, - struct ble_ll_scan_sm **sm) -{ - struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_params *scanp_uncoded; - struct ble_ll_scan_params *scanp_coded; - struct hci_ext_conn_params *params; - int rc; - - scansm = &g_ble_ll_scan_sm; - scansm->own_addr_type = hcc->own_addr_type; - scansm->scanp = NULL; - scansm->scanp_next = NULL; - scansm->ext_scanning = 1; - - if (hcc->init_phy_mask & BLE_PHY_MASK_1M) { - params = &hcc->params[0]; - scanp_uncoded = &scansm->scanp_phys[PHY_UNCODED]; - - scanp_uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl); - scanp_uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window); - scanp_uncoded->scan_type = BLE_SCAN_TYPE_INITIATE; - scanp_uncoded->scan_filt_policy = hcc->filter_policy; - scansm->scanp = scanp_uncoded; - } - - if (hcc->init_phy_mask & BLE_PHY_MASK_CODED) { - params = &hcc->params[2]; - scanp_coded = &scansm->scanp_phys[PHY_CODED]; - - scanp_coded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl); - scanp_coded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window); - scanp_coded->scan_type = BLE_SCAN_TYPE_INITIATE; - scanp_coded->scan_filt_policy = hcc->filter_policy; - if (scansm->scanp) { - scansm->scanp_next = scanp_coded; - } else { - scansm->scanp = scanp_coded; - } - } - - /* if any of PHYs is configured for continuous scan we alter interval to - * fit other PHY - */ - if (scansm->scanp && scansm->scanp_next && scanp_coded->configured && - scanp_uncoded->configured) { - if (scanp_coded->timing.interval == scanp_coded->timing.window) { - scanp_coded->timing.interval += scanp_uncoded->timing.window; - } - - if (scanp_uncoded->timing.interval == scanp_uncoded->timing.window) { - scanp_uncoded->timing.interval += scanp_coded->timing.window; - } - } - - rc = ble_ll_scan_sm_start(scansm); - if (sm == NULL) { - return rc; - } - - if (rc == BLE_ERR_SUCCESS) { - *sm = scansm; - } else { - *sm = NULL; - } - - return rc; -} -#endif - -/** - * Checks to see if the scanner is enabled. - * - * @return int 0: not enabled; enabled otherwise - */ -int -ble_ll_scan_enabled(void) -{ - return (int)g_ble_ll_scan_sm.scan_enabled; -} - -/** - * Returns the peer resolvable private address of last device connecting to us - * - * @return uint8_t* - */ -uint8_t * -ble_ll_scan_get_peer_rpa(void) -{ - struct ble_ll_scan_sm *scansm; - - /* XXX: should this go into IRK list or connection? */ - scansm = &g_ble_ll_scan_sm; - return scansm->scan_peer_rpa; -} - -/** - * Returns the local resolvable private address currently being using by - * the scanner/initiator - * - * @return uint8_t* - */ -uint8_t * -ble_ll_scan_get_local_rpa(void) -{ - return g_ble_ll_scan_sm.pdu_data.scana; -} - -/** - * Set the Resolvable Private Address in the scanning (or initiating) state - * machine. - * - * XXX: should this go into IRK list or connection? - * - * @param rpa - */ -void -ble_ll_scan_set_peer_rpa(uint8_t *rpa) -{ - struct ble_ll_scan_sm *scansm; - - scansm = &g_ble_ll_scan_sm; - memcpy(scansm->scan_peer_rpa, rpa, BLE_DEV_ADDR_LEN); -} - -struct ble_ll_scan_pdu_data * -ble_ll_scan_get_pdu_data(void) -{ - return &g_ble_ll_scan_sm.pdu_data; -} - -/* Returns true if whitelist is enabled for scanning */ -int -ble_ll_scan_whitelist_enabled(void) -{ - return g_ble_ll_scan_sm.scanp->scan_filt_policy & 1; -} - -static void -ble_ll_scan_common_init(void) -{ - struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_params *scanp; - int i; - - /* Clear state machine in case re-initialized */ - scansm = &g_ble_ll_scan_sm; - memset(scansm, 0, sizeof(struct ble_ll_scan_sm)); - - /* Clear scan parameters in case re-initialized */ - memset(g_ble_ll_scan_params, 0, sizeof(g_ble_ll_scan_params)); - - /* Initialize scanning window end event */ - ble_npl_event_init(&scansm->scan_sched_ev, ble_ll_scan_event_proc, scansm); - - for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) { - /* Set all non-zero default parameters */ - scanp = &g_ble_ll_scan_params[i]; - scanp->timing.interval = - ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_ITVL_DEF); - scanp->timing.window = - ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_WINDOW_DEF); - } - - scansm->scanp_phys[PHY_UNCODED].phy = BLE_PHY_1M; -#if (BLE_LL_SCAN_PHY_NUMBER == 2) - scansm->scanp_phys[PHY_CODED].phy = BLE_PHY_CODED; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* Make sure we'll generate new NRPA if necessary */ - scansm->scan_nrpa_timer = ble_npl_time_get(); -#endif - - /* Initialize scanning timer */ - os_cputime_timer_init(&scansm->scan_timer, ble_ll_scan_timer_cb, scansm); - - /* Initialize extended scan timers */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - os_cputime_timer_init(&scansm->duration_timer, - ble_ll_scan_duration_timer_cb, scansm); - os_cputime_timer_init(&scansm->period_timer, ble_ll_scan_period_timer_cb, - scansm); -#endif - - ble_npl_event_init(&scansm->scan_interrupted_ev, ble_ll_scan_interrupted_event_cb, NULL); -} - -/** - * Called when the controller receives the reset command. Resets the - * scanning state machine to its initial state. - * - * @return int - */ -void -ble_ll_scan_reset(void) -{ - struct ble_ll_scan_sm *scansm; - - scansm = &g_ble_ll_scan_sm; - - /* If enabled, stop it. */ - if (scansm->scan_enabled) { - ble_ll_scan_sm_stop(0); - } - - /* stop extended scan timers */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - os_cputime_timer_stop(&scansm->duration_timer); - os_cputime_timer_stop(&scansm->period_timer); -#endif - - /* Reset duplicate advertisers and those from which we rxd a response */ - g_ble_ll_scan_num_rsp_advs = 0; - memset(&g_ble_ll_scan_rsp_advs[0], 0, sizeof(g_ble_ll_scan_rsp_advs)); - - os_mempool_clear(&g_scan_dup_pool); - TAILQ_INIT(&g_scan_dup_list); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* clear memory pool for AUX scan results */ - os_mempool_clear(&ext_scan_aux_pool); -#endif - - /* Call the common init function again */ - ble_ll_scan_common_init(); -} - -/** - * ble ll scan init - * - * Initialize a scanner. Must be called before scanning can be started. - * Expected to be called with a un-initialized scanning state machine. - */ -void -ble_ll_scan_init(void) -{ - os_error_t err; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - err = os_mempool_init(&ext_scan_aux_pool, - MYNEWT_VAL(BLE_LL_EXT_ADV_AUX_PTR_CNT), - sizeof (struct ble_ll_aux_data), - ext_scan_aux_mem, - "ble_ll_aux_scan_pool"); - BLE_LL_ASSERT(err == 0); -#endif - - err = os_mempool_init(&g_scan_dup_pool, - MYNEWT_VAL(BLE_LL_NUM_SCAN_DUP_ADVS), - sizeof(struct ble_ll_scan_dup_entry), - g_scan_dup_mem, - "ble_ll_scan_dup_pool"); - BLE_LL_ASSERT(err == 0); - - TAILQ_INIT(&g_scan_dup_list); - - ble_ll_scan_common_init(); -} - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sched.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sched.c deleted file mode 100644 index 77c107f82..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sched.c +++ /dev/null @@ -1,1838 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include -#include -#include -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/porting/nimble/include/os/os_cputime.h" - -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) -#include "nimble/nimble/drivers/nrf51/include/ble/xcvr.h" -#elif defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) -#include "nimble/nimble/drivers/nrf52/include/ble/xcvr.h" -#endif - -#include "../include/controller/ble_phy.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_rfmgmt.h" -#include "../include/controller/ble_ll_trace.h" -#include "../include/controller/ble_ll_sync.h" -#include "ble_ll_priv.h" -#include "ble_ll_conn_priv.h" - -/* XXX: this is temporary. Not sure what I want to do here */ -struct hal_timer g_ble_ll_sched_timer; - -uint8_t g_ble_ll_sched_offset_ticks; - -#define BLE_LL_SCHED_ADV_WORST_CASE_USECS \ - (BLE_LL_SCHED_MAX_ADV_PDU_USECS + BLE_LL_IFS + BLE_LL_SCHED_ADV_MAX_USECS \ - + XCVR_TX_SCHED_DELAY_USECS) - -#if (BLE_LL_SCHED_DEBUG == 1) -int32_t g_ble_ll_sched_max_late; -int32_t g_ble_ll_sched_max_early; -#endif - -/* XXX: TODO: - * 1) Add some accounting to the schedule code to see how late we are - * (min/max?) - * - * 2) Need to determine how we really want to handle the case when we execute - * a schedule item but there is a current event. We could: - * -> Reschedule the schedule item and let current event finish - * -> Kill the current event and run the scheduled item. - * -> Disable schedule timer while in an event; could cause us to be late. - * -> Wait for current event to finish hoping it does before schedule item. - */ - -/* Queue for timers */ -TAILQ_HEAD(ll_sched_qhead, ble_ll_sched_item) g_ble_ll_sched_q; - -#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) -struct ble_ll_sched_obj g_ble_ll_sched_data; -#endif - -/** - * Checks if two events in the schedule will overlap in time. NOTE: consecutive - * schedule items can end and start at the same time. - * - * @param s1 - * @param s2 - * - * @return int 0: dont overlap 1:overlap - */ -static int -ble_ll_sched_is_overlap(struct ble_ll_sched_item *s1, - struct ble_ll_sched_item *s2) -{ - int rc; - - rc = 1; - if ((int32_t)(s1->start_time - s2->start_time) < 0) { - /* Make sure this event does not overlap current event */ - if ((int32_t)(s1->end_time - s2->start_time) <= 0) { - rc = 0; - } - } else { - /* Check for overlap */ - if ((int32_t)(s1->start_time - s2->end_time) >= 0) { - rc = 0; - } - } - - return rc; -} - -/* - * Determines if the schedule item overlaps the currently running schedule - * item. We only care about connection schedule items - */ -static int -ble_ll_sched_overlaps_current(struct ble_ll_sched_item *sch) -{ - int rc; - uint32_t ce_end_time; - - rc = 0; - if (ble_ll_state_get() == BLE_LL_STATE_CONNECTION) { - ce_end_time = ble_ll_conn_get_ce_end_time(); - if ((int32_t)(ce_end_time - sch->start_time) > 0) { - rc = 1; - } - } - return rc; -} - -static int -ble_ll_sched_conn_overlap(struct ble_ll_sched_item *entry) -{ - int rc; - struct ble_ll_conn_sm *connsm; - - /* Should only be advertising or a connection here */ - if (entry->sched_type == BLE_LL_SCHED_TYPE_CONN) { - connsm = (struct ble_ll_conn_sm *)entry->cb_arg; - entry->enqueued = 0; - TAILQ_REMOVE(&g_ble_ll_sched_q, entry, link); - ble_ll_event_send(&connsm->conn_ev_end); - rc = 0; - } else { - rc = -1; - } - - return rc; -} - -static struct ble_ll_sched_item * -ble_ll_sched_insert_if_empty(struct ble_ll_sched_item *sch) -{ - struct ble_ll_sched_item *entry; - - entry = TAILQ_FIRST(&g_ble_ll_sched_q); - if (!entry) { - TAILQ_INSERT_HEAD(&g_ble_ll_sched_q, sch, link); - sch->enqueued = 1; - } - return entry; -} - -int -ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm) -{ - int rc; - os_sr_t sr; - uint32_t usecs; - struct ble_ll_sched_item *sch; - struct ble_ll_sched_item *start_overlap; - struct ble_ll_sched_item *end_overlap; - struct ble_ll_sched_item *entry; - struct ble_ll_conn_sm *tmp; - - /* Get schedule element from connection */ - sch = &connsm->conn_sch; - - /* Set schedule start and end times */ - sch->start_time = connsm->anchor_point - g_ble_ll_sched_offset_ticks; - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - usecs = connsm->slave_cur_window_widening; - sch->start_time -= (os_cputime_usecs_to_ticks(usecs) + 1); - sch->remainder = 0; - } else { - sch->remainder = connsm->anchor_point_usecs; - } - sch->end_time = connsm->ce_end_time; - - /* Better be past current time or we just leave */ - if ((int32_t)(sch->start_time - os_cputime_get32()) < 0) { - return -1; - } - - /* We have to find a place for this schedule */ - OS_ENTER_CRITICAL(sr); - - if (ble_ll_sched_overlaps_current(sch)) { - OS_EXIT_CRITICAL(sr); - return -1; - } - - /* Stop timer since we will add an element */ - os_cputime_timer_stop(&g_ble_ll_sched_timer); - - start_overlap = NULL; - end_overlap = NULL; - rc = 0; - TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { - if (ble_ll_sched_is_overlap(sch, entry)) { - if (entry->sched_type == BLE_LL_SCHED_TYPE_CONN && - !ble_ll_conn_is_lru((struct ble_ll_conn_sm *)sch->cb_arg, - (struct ble_ll_conn_sm *)entry->cb_arg)) { - /* Only insert if this element is older than all that we - * overlap - */ - start_overlap = NULL; - rc = -1; - break; - } - - if (start_overlap == NULL) { - start_overlap = entry; - end_overlap = entry; - } else { - end_overlap = entry; - } - } else { - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { - rc = 0; - TAILQ_INSERT_BEFORE(entry, sch, link); - break; - } - } - } - - if (!rc) { - if (!entry) { - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - } - sch->enqueued = 1; - } - - /* Remove first to last scheduled elements */ - entry = start_overlap; - while (entry) { - start_overlap = TAILQ_NEXT(entry,link); - switch (entry->sched_type) { - case BLE_LL_SCHED_TYPE_CONN: - tmp = (struct ble_ll_conn_sm *)entry->cb_arg; - ble_ll_event_send(&tmp->conn_ev_end); - break; - case BLE_LL_SCHED_TYPE_ADV: - ble_ll_adv_event_rmvd_from_sched((struct ble_ll_adv_sm *)entry->cb_arg); - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - case BLE_LL_SCHED_TYPE_AUX_SCAN: - ble_ll_scan_end_adv_evt((struct ble_ll_aux_data *)entry->cb_arg); - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - case BLE_LL_SCHED_TYPE_PERIODIC: - ble_ll_adv_periodic_rmvd_from_sched((struct ble_ll_adv_sm *)entry->cb_arg); - break; - case BLE_LL_SCHED_TYPE_SYNC: - ble_ll_sync_rmvd_from_sched((struct ble_ll_sync_sm *)entry->cb_arg); - break; -#endif -#endif - default: - BLE_LL_ASSERT(0); - break; - } - - TAILQ_REMOVE(&g_ble_ll_sched_q, entry, link); - entry->enqueued = 0; - - if (entry == end_overlap) { - break; - } - entry = start_overlap; - } - - entry = TAILQ_FIRST(&g_ble_ll_sched_q); - if (entry == sch) { - ble_ll_rfmgmt_sched_changed(sch); - } else { - sch = entry; - } - - OS_EXIT_CRITICAL(sr); - - /* Restart timer */ - BLE_LL_ASSERT(sch != NULL); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); - - return rc; -} - -/** - * Called to schedule a connection when the current role is master. - * - * Context: Interrupt - * - * @param connsm - * @param ble_hdr - * @param pyld_len - * - * @return int - */ -#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) -int -ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, - struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len) -{ - int rc; - os_sr_t sr; - uint32_t initial_start; - uint32_t earliest_start; - uint32_t earliest_end; - uint32_t dur; - uint32_t itvl_t; - uint32_t adv_rxend; - int i; - uint32_t tpp; - uint32_t tse; - uint32_t np; - uint32_t cp; - uint32_t tick_in_period; - - struct ble_ll_sched_item *entry; - struct ble_ll_sched_item *sch; - - /* Better have a connsm */ - BLE_LL_ASSERT(connsm != NULL); - - /* Get schedule element from connection */ - rc = -1; - sch = &connsm->conn_sch; - - /* XXX: - * The calculations for the 32kHz crystal bear alot of explanation. The - * earliest possible time that the master can start the connection with a - * slave is 1.25 msecs from the end of the connection request. The - * connection request is sent an IFS time from the end of the advertising - * packet that was received plus the time it takes to send the connection - * request. At 1 Mbps, this is 1752 usecs, or 57.41 ticks. Using 57 ticks - * makes us off ~13 usecs. Since we dont want to actually calculate the - * receive end time tick (this would take too long), we assume the end of - * the advertising PDU is 'now' (we call os_cputime_get32). We dont know - * how much time it will take to service the ISR but if we are more than the - * rx to tx time of the chip we will not be successful transmitting the - * connect request. All this means is that we presume that the slave will - * receive the connect request later than we expect but no earlier than - * 13 usecs before (this is important). - * - * The code then attempts to schedule the connection at the - * earliest time although this may not be possible. When the actual - * schedule start time is determined, the master has to determine if this - * time is more than a transmit window offset interval (1.25 msecs). The - * master has to tell the slave how many transmit window offsets there are - * from the earliest possible time to when the actual transmit start will - * occur. Later in this function you will see the calculation. The actual - * transmission start has to occur within the transmit window. The transmit - * window interval is in units of 1.25 msecs and has to be at least 1. To - * make things a bit easier (but less power efficient for the slave), we - * use a transmit window of 2. We do this because we dont quite know the - * exact start of the transmission and if we are too early or too late we - * could miss the transmit window. A final note: the actual transmission - * start (the anchor point) is sched offset ticks from the schedule start - * time. We dont add this to the calculation when calculating the window - * offset. The reason we dont do this is we want to insure we transmit - * after the window offset we tell the slave. For example, say we think - * we are transmitting 1253 usecs from the earliest start. This would cause - * us to send a transmit window offset of 1. Since we are actually - * transmitting earlier than the slave thinks we could end up transmitting - * before the window offset. Transmitting later is fine since we have the - * transmit window to do so. Transmitting before is bad, since the slave - * wont be listening. We could do better calculation if we wanted to use - * a transmit window of 1 as opposed to 2, but for now we dont care. - */ - dur = os_cputime_usecs_to_ticks(g_ble_ll_sched_data.sch_ticks_per_period); - adv_rxend = os_cputime_get32(); - if (ble_hdr->rxinfo.channel >= BLE_PHY_NUM_DATA_CHANS) { - /* - * We received packet on advertising channel which means this is a legacy - * PDU on 1 Mbps - we do as described above. - */ - earliest_start = adv_rxend + 57; - } else { - /* - * The calculations are similar as above. - * - * We received packet on data channel which means this is AUX_ADV_IND - * received on secondary adv channel. We can schedule first packet at - * the earliest after "T_IFS + AUX_CONNECT_REQ + transmitWindowDelay". - * AUX_CONNECT_REQ and transmitWindowDelay times vary depending on which - * PHY we received on. - * - */ - if (ble_hdr->rxinfo.phy == BLE_PHY_1M) { - // 150 + 352 + 2500 = 3002us = 98.37 ticks - earliest_start = adv_rxend + 98; - } else if (ble_hdr->rxinfo.phy == BLE_PHY_2M) { - // 150 + 180 + 2500 = 2830us = 92.73 ticks - earliest_start = adv_rxend + 93; - } else if (ble_hdr->rxinfo.phy == BLE_PHY_CODED) { - // 150 + 2896 + 3750 = 6796us = 222.69 ticks - earliest_start = adv_rxend + 223; - } else { - BLE_LL_ASSERT(0); - } - } - earliest_start += MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET) * - BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT; - itvl_t = connsm->conn_itvl_ticks; - - /* We have to find a place for this schedule */ - OS_ENTER_CRITICAL(sr); - - /* - * Are there any allocated periods? If not, set epoch start to earliest - * time - */ - if (g_ble_ll_sched_data.sch_num_occ_periods == 0) { - g_ble_ll_sched_data.sch_epoch_start = earliest_start; - cp = 0; - } else { - /* - * Earliest start must occur on period boundary. - * (tse = ticks since epoch) - */ - tpp = g_ble_ll_sched_data.sch_ticks_per_period; - tse = earliest_start - g_ble_ll_sched_data.sch_epoch_start; - np = tse / tpp; - cp = np % BLE_LL_SCHED_PERIODS; - tick_in_period = tse - (np * tpp); - if (tick_in_period != 0) { - ++cp; - if (cp == BLE_LL_SCHED_PERIODS) { - cp = 0; - } - earliest_start += (tpp - tick_in_period); - } - - /* Now find first un-occupied period starting from cp */ - for (i = 0; i < BLE_LL_SCHED_PERIODS; ++i) { - if (g_ble_ll_sched_data.sch_occ_period_mask & (1 << cp)) { - ++cp; - if (cp == BLE_LL_SCHED_PERIODS) { - cp = 0; - } - earliest_start += tpp; - } else { - /* not occupied */ - break; - } - } - /* Should never happen but if it does... */ - if (i == BLE_LL_SCHED_PERIODS) { - OS_EXIT_CRITICAL(sr); - return rc; - } - } - - sch->start_time = earliest_start; - initial_start = earliest_start; - earliest_end = earliest_start + dur; - - if (!ble_ll_sched_insert_if_empty(sch)) { - /* Nothing in schedule. Schedule as soon as possible */ - rc = 0; - connsm->tx_win_off = MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET); - } else { - os_cputime_timer_stop(&g_ble_ll_sched_timer); - TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { - /* Set these because overlap function needs them to be set */ - sch->start_time = earliest_start; - sch->end_time = earliest_end; - - /* We can insert if before entry in list */ - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { - if ((earliest_start - initial_start) <= itvl_t) { - rc = 0; - TAILQ_INSERT_BEFORE(entry, sch, link); - } - break; - } - - /* Check for overlapping events */ - if (ble_ll_sched_is_overlap(sch, entry)) { - /* Earliest start is end of this event since we overlap */ - earliest_start = entry->end_time; - earliest_end = earliest_start + dur; - } - } - - /* Must be able to schedule within one connection interval */ - if (!entry) { - if ((earliest_start - initial_start) <= itvl_t) { - rc = 0; - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - } - } - - if (!rc) { - /* calculate number of window offsets. Each offset is 1.25 ms */ - sch->enqueued = 1; - /* - * NOTE: we dont add sched offset ticks as we want to under-estimate - * the transmit window slightly since the window size is currently - * 2 when using a 32768 crystal. - */ - dur = os_cputime_ticks_to_usecs(earliest_start - initial_start); - connsm->tx_win_off = dur / BLE_LL_CONN_TX_OFF_USECS; - } - } - - if (!rc) { - sch->start_time = earliest_start; - sch->end_time = earliest_end; - /* - * Since we have the transmit window to transmit in, we dont need - * to set the anchor point usecs; just transmit to the nearest tick. - */ - connsm->anchor_point = earliest_start + g_ble_ll_sched_offset_ticks; - connsm->anchor_point_usecs = 0; - connsm->ce_end_time = earliest_end; - connsm->period_occ_mask = (1 << cp); - g_ble_ll_sched_data.sch_occ_period_mask |= connsm->period_occ_mask; - ++g_ble_ll_sched_data.sch_num_occ_periods; - } - - - /* Get head of list to restart timer */ - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - ble_ll_rfmgmt_sched_changed(sch); - - OS_EXIT_CRITICAL(sr); - - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); - - return rc; -} -#else -int -ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, - struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len) -{ - int rc; - os_sr_t sr; - uint8_t req_slots; - uint32_t initial_start; - uint32_t earliest_start; - uint32_t earliest_end; - uint32_t dur; - uint32_t itvl_t; - uint32_t adv_rxend; - struct ble_ll_sched_item *entry; - struct ble_ll_sched_item *sch; - - /* - * XXX: TODO this code assumes the advertisement and connect request were - * sent at 1Mbps. - */ - - /* Get schedule element from connection */ - rc = -1; - sch = &connsm->conn_sch; - req_slots = MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS); - - /* XXX: - * The calculations for the 32kHz crystal bear alot of explanation. The - * earliest possible time that the master can start the connection with a - * slave is 1.25 msecs from the end of the connection request. The - * connection request is sent an IFS time from the end of the advertising - * packet that was received plus the time it takes to send the connection - * request. At 1 Mbps, this is 1752 usecs, or 57.41 ticks. Using 57 ticks - * makes us off ~13 usecs. Since we dont want to actually calculate the - * receive end time tick (this would take too long), we assume the end of - * the advertising PDU is 'now' (we call os_cputime_get32). We dont know - * how much time it will take to service the ISR but if we are more than the - * rx to tx time of the chip we will not be successful transmitting the - * connect request. All this means is that we presume that the slave will - * receive the connect request later than we expect but no earlier than - * 13 usecs before (this is important). - * - * The code then attempts to schedule the connection at the - * earliest time although this may not be possible. When the actual - * schedule start time is determined, the master has to determine if this - * time is more than a transmit window offset interval (1.25 msecs). The - * master has to tell the slave how many transmit window offsets there are - * from the earliest possible time to when the actual transmit start will - * occur. Later in this function you will see the calculation. The actual - * transmission start has to occur within the transmit window. The transmit - * window interval is in units of 1.25 msecs and has to be at least 1. To - * make things a bit easier (but less power efficient for the slave), we - * use a transmit window of 2. We do this because we dont quite know the - * exact start of the transmission and if we are too early or too late we - * could miss the transmit window. A final note: the actual transmission - * start (the anchor point) is sched offset ticks from the schedule start - * time. We dont add this to the calculation when calculating the window - * offset. The reason we dont do this is we want to insure we transmit - * after the window offset we tell the slave. For example, say we think - * we are transmitting 1253 usecs from the earliest start. This would cause - * us to send a transmit window offset of 1. Since we are actually - * transmitting earlier than the slave thinks we could end up transmitting - * before the window offset. Transmitting later is fine since we have the - * transmit window to do so. Transmitting before is bad, since the slave - * wont be listening. We could do better calculation if we wanted to use - * a transmit window of 1 as opposed to 2, but for now we dont care. - */ - dur = req_slots * BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT; - adv_rxend = os_cputime_get32(); - if (ble_hdr->rxinfo.channel >= BLE_PHY_NUM_DATA_CHANS) { - /* - * We received packet on advertising channel which means this is a legacy - * PDU on 1 Mbps - we do as described above. - */ - earliest_start = adv_rxend + 57; - } else { - /* - * The calculations are similar as above. - * - * We received packet on data channel which means this is AUX_ADV_IND - * received on secondary adv channel. We can schedule first packet at - * the earliest after "T_IFS + AUX_CONNECT_REQ + transmitWindowDelay". - * AUX_CONNECT_REQ and transmitWindowDelay times vary depending on which - * PHY we received on. - * - */ - if (ble_hdr->rxinfo.phy == BLE_PHY_1M) { - // 150 + 352 + 2500 = 3002us = 98.37 ticks - earliest_start = adv_rxend + 98; - } else if (ble_hdr->rxinfo.phy == BLE_PHY_2M) { - // 150 + 180 + 2500 = 2830us = 92.73 ticks - earliest_start = adv_rxend + 93; - } else if (ble_hdr->rxinfo.phy == BLE_PHY_CODED) { - // 150 + 2896 + 3750 = 6796us = 222.69 ticks - earliest_start = adv_rxend + 223; - } else { - BLE_LL_ASSERT(0); - } - } - earliest_start += MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET) * - BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT; - earliest_end = earliest_start + dur; - itvl_t = connsm->conn_itvl_ticks; - - /* We have to find a place for this schedule */ - OS_ENTER_CRITICAL(sr); - - /* The schedule item must occur after current running item (if any) */ - sch->start_time = earliest_start; - initial_start = earliest_start; - - if (!ble_ll_sched_insert_if_empty(sch)) { - /* Nothing in schedule. Schedule as soon as possible */ - rc = 0; - connsm->tx_win_off = MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET); - } else { - os_cputime_timer_stop(&g_ble_ll_sched_timer); - TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { - /* Set these because overlap function needs them to be set */ - sch->start_time = earliest_start; - sch->end_time = earliest_end; - - /* We can insert if before entry in list */ - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { - if ((earliest_start - initial_start) <= itvl_t) { - rc = 0; - TAILQ_INSERT_BEFORE(entry, sch, link); - } - break; - } - - /* Check for overlapping events */ - if (ble_ll_sched_is_overlap(sch, entry)) { - /* Earliest start is end of this event since we overlap */ - earliest_start = entry->end_time; - earliest_end = earliest_start + dur; - } - } - - /* Must be able to schedule within one connection interval */ - if (!entry) { - if ((earliest_start - initial_start) <= itvl_t) { - rc = 0; - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - } - } - - if (!rc) { - /* calculate number of window offsets. Each offset is 1.25 ms */ - sch->enqueued = 1; - /* - * NOTE: we dont add sched offset ticks as we want to under-estimate - * the transmit window slightly since the window size is currently - * 2 when using a 32768 crystal. - */ - dur = os_cputime_ticks_to_usecs(earliest_start - initial_start); - connsm->tx_win_off = dur / BLE_LL_CONN_TX_OFF_USECS; - } - } - - if (!rc) { - sch->start_time = earliest_start; - sch->end_time = earliest_end; - /* - * Since we have the transmit window to transmit in, we dont need - * to set the anchor point usecs; just transmit to the nearest tick. - */ - connsm->anchor_point = earliest_start + g_ble_ll_sched_offset_ticks; - connsm->anchor_point_usecs = 0; - connsm->ce_end_time = earliest_end; - } - - /* Get head of list to restart timer */ - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - ble_ll_rfmgmt_sched_changed(sch); - - OS_EXIT_CRITICAL(sr); - - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); - - return rc; -} -#endif - -/** - * Schedules a slave connection for the first time. - * - * Context: Link Layer - * - * @param connsm - * - * @return int - */ -int -ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm) -{ - int rc; - os_sr_t sr; - struct ble_ll_sched_item *entry; - struct ble_ll_sched_item *next_sch; - struct ble_ll_sched_item *sch; - int first = 0; - - /* Get schedule element from connection */ - rc = -1; - sch = &connsm->conn_sch; - - /* Set schedule start and end times */ - /* - * XXX: for now, we dont care about anchor point usecs for the slave. It - * does not matter if we turn on the receiver up to one tick before w - * need to. We also subtract one extra tick since the conversion from - * usecs to ticks could be off by up to 1 tick. - */ - sch->start_time = connsm->anchor_point - g_ble_ll_sched_offset_ticks - - os_cputime_usecs_to_ticks(connsm->slave_cur_window_widening) - 1; - sch->end_time = connsm->ce_end_time; - sch->remainder = 0; - - /* We have to find a place for this schedule */ - OS_ENTER_CRITICAL(sr); - - /* The schedule item must occur after current running item (if any) */ - if (ble_ll_sched_overlaps_current(sch)) { - OS_EXIT_CRITICAL(sr); - return rc; - } - - entry = ble_ll_sched_insert_if_empty(sch); - if (!entry) { - /* Nothing in schedule. Schedule as soon as possible */ - rc = 0; - first = 1; - } else { - os_cputime_timer_stop(&g_ble_ll_sched_timer); - while (1) { - next_sch = entry->link.tqe_next; - /* Insert if event ends before next starts */ - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { - rc = 0; - TAILQ_INSERT_BEFORE(entry, sch, link); - break; - } - - if (ble_ll_sched_is_overlap(sch, entry)) { - /* If we overlap with a connection, we re-schedule */ - if (ble_ll_sched_conn_overlap(entry)) { - break; - } - } - - /* Move to next entry */ - entry = next_sch; - - /* Insert at tail if none left to check */ - if (!entry) { - rc = 0; - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - break; - } - } - - if (!rc) { - sch->enqueued = 1; - } - - next_sch = TAILQ_FIRST(&g_ble_ll_sched_q); - if (next_sch == sch) { - first = 1; - } else { - sch = next_sch; - } - } - - if (first) { - ble_ll_rfmgmt_sched_changed(sch); - } - - OS_EXIT_CRITICAL(sr); - - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); - - return rc; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) -/* - * Determines if the schedule item overlaps the currently running schedule - * item. This function cares about connection and sync. - */ -static int -ble_ll_sched_sync_overlaps_current(struct ble_ll_sched_item *sch) -{ - uint32_t end_time; - uint8_t state; - - state = ble_ll_state_get(); - switch (state) { - case BLE_LL_STATE_CONNECTION: - end_time = ble_ll_conn_get_ce_end_time(); - break; - case BLE_LL_STATE_SYNC: - end_time = ble_ll_sync_get_event_end_time(); - break; - default: - return 0; - } - - return CPUTIME_GT(end_time, sch->start_time); -} - -int -ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch, - uint32_t anchor_point, uint8_t anchor_point_usecs, - uint32_t window_widening, - int8_t phy_mode) -{ - struct ble_ll_sched_item *entry; - uint8_t start_time_rem_usecs; - uint8_t window_rem_usecs; - uint32_t window_ticks; - uint32_t start_time; - uint32_t end_time; - uint32_t dur; - int rc = 0; - os_sr_t sr; - - window_ticks = os_cputime_usecs_to_ticks(window_widening); - window_rem_usecs = window_widening - os_cputime_ticks_to_usecs(window_ticks); - - /* adjust for subtraction */ - anchor_point_usecs += 31; - anchor_point--; - - start_time = anchor_point - window_ticks; - start_time_rem_usecs = anchor_point_usecs - window_rem_usecs; - if (start_time_rem_usecs >= 31) { - start_time++; - start_time_rem_usecs -= 31; - } - - dur = ble_ll_pdu_tx_time_get(MYNEWT_VAL(BLE_LL_SCHED_SCAN_SYNC_PDU_LEN), - phy_mode); - end_time = start_time + os_cputime_usecs_to_ticks(dur); - - start_time -= g_ble_ll_sched_offset_ticks; - - /* Set schedule start and end times */ - sch->start_time = start_time; - sch->remainder = start_time_rem_usecs; - sch->end_time = end_time; - - /* Better be past current time or we just leave */ - if (CPUTIME_LEQ(sch->start_time, os_cputime_get32())) { - return -1; - } - - /* We have to find a place for this schedule */ - OS_ENTER_CRITICAL(sr); - - if (ble_ll_sched_sync_overlaps_current(sch)) { - OS_EXIT_CRITICAL(sr); - return -1; - } - - /* Try to find slot for sync scan. */ - os_cputime_timer_stop(&g_ble_ll_sched_timer); - - TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { - /* We can insert if before entry in list */ - if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { - TAILQ_INSERT_BEFORE(entry, sch, link); - sch->enqueued = 1; - break; - } - - /* Check for overlapping events. For now drop if it overlaps with - * anything. We can make it smarter later on - */ - if (ble_ll_sched_is_overlap(sch, entry)) { - rc = -1; - break; - } - } - - if (!entry) { - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - sch->enqueued = 1; - } - - entry = TAILQ_FIRST(&g_ble_ll_sched_q); - if (entry == sch) { - ble_ll_rfmgmt_sched_changed(sch); - } else { - sch = entry; - } - - OS_EXIT_CRITICAL(sr); - - /* Restart timer */ - BLE_LL_ASSERT(sch != NULL); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); - - return rc; -} - -int -ble_ll_sched_sync(struct ble_ll_sched_item *sch, - uint32_t beg_cputime, uint32_t rem_usecs, - uint32_t offset, int8_t phy_mode) -{ - struct ble_ll_sched_item *entry; - uint32_t start_time_rem_usecs; - uint32_t off_rem_usecs; - uint32_t start_time; - uint32_t off_ticks; - uint32_t end_time; - uint32_t dur; - os_sr_t sr; - int rc = 0; - - off_ticks = os_cputime_usecs_to_ticks(offset); - off_rem_usecs = offset - os_cputime_ticks_to_usecs(off_ticks); - - start_time = beg_cputime + off_ticks; - start_time_rem_usecs = rem_usecs + off_rem_usecs; - if (start_time_rem_usecs >= 31) { - start_time++; - start_time_rem_usecs -= 31; - } - - dur = ble_ll_pdu_tx_time_get(MYNEWT_VAL(BLE_LL_SCHED_SCAN_SYNC_PDU_LEN), - phy_mode); - end_time = start_time + os_cputime_usecs_to_ticks(dur); - - start_time -= g_ble_ll_sched_offset_ticks; - - sch->start_time = start_time; - sch->remainder = start_time_rem_usecs; - sch->end_time = end_time; - - OS_ENTER_CRITICAL(sr); - - if (!ble_ll_sched_insert_if_empty(sch)) { - /* Nothing in schedule. Schedule as soon as possible - * If we are here it means sch has been added to the scheduler */ - goto done; - } - - /* Try to find slot for scan. */ - os_cputime_timer_stop(&g_ble_ll_sched_timer); - TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { - /* We can insert if before entry in list */ - if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { - TAILQ_INSERT_BEFORE(entry, sch, link); - sch->enqueued = 1; - break; - } - - /* Check for overlapping events. For now drop if it overlaps with - * anything. We can make it smarter later on - */ - if (ble_ll_sched_is_overlap(sch, entry)) { - rc = -1; - break; - } - } - - if (!entry) { - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - sch->enqueued = 1; - } - -done: - entry = TAILQ_FIRST(&g_ble_ll_sched_q); - if (entry == sch) { - ble_ll_rfmgmt_sched_changed(sch); - } else { - sch = entry; - } - - OS_EXIT_CRITICAL(sr); - - /* Restart timer */ - BLE_LL_ASSERT(sch != NULL); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); - - STATS_INC(ble_ll_stats, sync_scheduled); - return rc; -} -#endif - -int -ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, ble_ll_sched_adv_new_cb cb, - void *arg) -{ - os_sr_t sr; - uint32_t adv_start; - uint32_t duration; - struct ble_ll_sched_item *entry; - struct ble_ll_sched_item *orig; - - /* Get length of schedule item */ - duration = sch->end_time - sch->start_time; - orig = sch; - - OS_ENTER_CRITICAL(sr); - entry = ble_ll_sched_insert_if_empty(sch); - if (!entry) { - adv_start = sch->start_time; - } else { - /* XXX: no need to stop timer if not first on list. Modify code? */ - os_cputime_timer_stop(&g_ble_ll_sched_timer); - TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { - /* We can insert if before entry in list */ - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { - TAILQ_INSERT_BEFORE(entry, sch, link); - break; - } - - /* Check for overlapping events */ - if (ble_ll_sched_is_overlap(sch, entry)) { - /* Earliest start is end of this event since we overlap */ - sch->start_time = entry->end_time; - sch->end_time = sch->start_time + duration; - } - } - - if (!entry) { - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - } - adv_start = sch->start_time; - - sch->enqueued = 1; - - /* Restart with head of list */ - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - } - - if (cb) { - cb((struct ble_ll_adv_sm *)orig->cb_arg, adv_start, arg); - } - - if (orig == sch) { - ble_ll_rfmgmt_sched_changed(sch); - } - - OS_EXIT_CRITICAL(sr); - - /* Restart timer */ - BLE_LL_ASSERT(sch != NULL); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); - - return 0; -} - -int -ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, uint32_t *start, - bool after_overlap) -{ - int rc = 0; - os_sr_t sr; - uint32_t adv_start; - uint32_t duration; - struct ble_ll_sched_item *entry; - struct ble_ll_sched_item *orig = sch; - - /* Get length of schedule item */ - duration = sch->end_time - sch->start_time; - - OS_ENTER_CRITICAL(sr); - entry = ble_ll_sched_insert_if_empty(sch); - if (!entry) { - adv_start = sch->start_time; - } else { - /* XXX: no need to stop timer if not first on list. Modify code? */ - os_cputime_timer_stop(&g_ble_ll_sched_timer); - TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { - /* We can insert if before entry in list */ - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { - TAILQ_INSERT_BEFORE(entry, sch, link); - break; - } - - /* Check for overlapping events */ - if (ble_ll_sched_is_overlap(sch, entry)) { - if (after_overlap) { - /* Earliest start is end of this event since we overlap */ - sch->start_time = entry->end_time; - sch->end_time = sch->start_time + duration; - } else { - rc = -1; - break; - } - } - } - - if (!entry) { - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - } - adv_start = sch->start_time; - - if (!rc) { - sch->enqueued = 1; - } - - /* Restart with head of list */ - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - } - - if (!rc) { - *start = adv_start; - } - - if (orig == sch) { - ble_ll_rfmgmt_sched_changed(sch); - } - - OS_EXIT_CRITICAL(sr); - - /* Restart timer */ - BLE_LL_ASSERT(sch != NULL); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); - - return rc; -} - -int -ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start, - uint32_t max_delay_ticks) -{ - int rc; - os_sr_t sr; - uint32_t orig_start; - uint32_t duration; - uint32_t rand_ticks; - struct ble_ll_sched_item *entry; - struct ble_ll_sched_item *next_sch; - struct ble_ll_sched_item *before; - struct ble_ll_sched_item *start_overlap; - struct ble_ll_sched_item *end_overlap; - - /* Get length of schedule item */ - duration = sch->end_time - sch->start_time; - - /* Add maximum randomization delay to end */ - rand_ticks = max_delay_ticks; - sch->end_time += max_delay_ticks; - - start_overlap = NULL; - end_overlap = NULL; - before = NULL; - rc = 0; - OS_ENTER_CRITICAL(sr); - - entry = ble_ll_sched_insert_if_empty(sch); - if (entry) { - os_cputime_timer_stop(&g_ble_ll_sched_timer); - while (1) { - next_sch = entry->link.tqe_next; - if (ble_ll_sched_is_overlap(sch, entry)) { - if (start_overlap == NULL) { - start_overlap = entry; - end_overlap = entry; - } else { - end_overlap = entry; - } - } else { - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { - before = entry; - break; - } - } - - entry = next_sch; - if (entry == NULL) { - break; - } - } - - /* - * If there is no overlap, we either insert before the 'before' entry - * or we insert at the end if there is no before entry. - */ - if (start_overlap == NULL) { - if (before) { - TAILQ_INSERT_BEFORE(before, sch, link); - } else { - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - } - } else { - /* - * This item will overlap with others. See if we can fit it in - * with original duration. - */ - before = NULL; - orig_start = sch->start_time; - entry = start_overlap; - sch->end_time = sch->start_time + duration; - while (1) { - next_sch = entry->link.tqe_next; - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { - rand_ticks = entry->start_time - sch->end_time; - before = entry; - TAILQ_INSERT_BEFORE(before, sch, link); - break; - } else { - sch->start_time = entry->end_time; - sch->end_time = sch->start_time + duration; - } - - if (entry == end_overlap) { - rand_ticks = (orig_start + max_delay_ticks) - sch->start_time; - if (rand_ticks > max_delay_ticks) { - /* No place for advertisement. */ - rc = -1; - } else { - if (next_sch == NULL) { - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - } else { - TAILQ_INSERT_BEFORE(next_sch, sch, link); - } - } - break; - } - entry = next_sch; - BLE_LL_ASSERT(entry != NULL); - } - } - } - - if (!rc) { - sch->enqueued = 1; - if (rand_ticks) { - sch->start_time += rand() % rand_ticks; - } - sch->end_time = sch->start_time + duration; - *start = sch->start_time; - - if (sch == TAILQ_FIRST(&g_ble_ll_sched_q)) { - ble_ll_rfmgmt_sched_changed(sch); - } - } - - OS_EXIT_CRITICAL(sr); - - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); - - return rc; -} - -int -ble_ll_sched_adv_resched_pdu(struct ble_ll_sched_item *sch) -{ - uint8_t lls; - os_sr_t sr; - struct ble_ll_sched_item *entry; - - OS_ENTER_CRITICAL(sr); - - lls = ble_ll_state_get(); - if ((lls == BLE_LL_STATE_ADV) || (lls == BLE_LL_STATE_CONNECTION) || - (lls == BLE_LL_STATE_SYNC)) { - goto adv_resched_pdu_fail; - } - - entry = ble_ll_sched_insert_if_empty(sch); - if (entry) { - /* If we overlap with the first item, simply re-schedule */ - if (ble_ll_sched_is_overlap(sch, entry)) { - goto adv_resched_pdu_fail; - } - os_cputime_timer_stop(&g_ble_ll_sched_timer); - TAILQ_INSERT_BEFORE(entry, sch, link); - sch->enqueued = 1; - } - - ble_ll_rfmgmt_sched_changed(TAILQ_FIRST(&g_ble_ll_sched_q)); - - OS_EXIT_CRITICAL(sr); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); - return 0; - -adv_resched_pdu_fail: - OS_EXIT_CRITICAL(sr); - return -1; -} - -/** - * Remove a schedule element - * - * @param sched_type - * - * @return int 0 - removed, 1 - not in the list - */ -int -ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch) -{ - os_sr_t sr; - struct ble_ll_sched_item *first; - int rc = 1; - - if (!sch) { - return rc; - } - - OS_ENTER_CRITICAL(sr); - if (sch->enqueued) { - first = TAILQ_FIRST(&g_ble_ll_sched_q); - if (first == sch) { - os_cputime_timer_stop(&g_ble_ll_sched_timer); - } - - TAILQ_REMOVE(&g_ble_ll_sched_q, sch, link); - sch->enqueued = 0; - rc = 0; - - if (first == sch) { - first = TAILQ_FIRST(&g_ble_ll_sched_q); - if (first) { - os_cputime_timer_start(&g_ble_ll_sched_timer, first->start_time); - } - ble_ll_rfmgmt_sched_changed(first); - } - } - OS_EXIT_CRITICAL(sr); - - return rc; -} - -void -ble_ll_sched_rmv_elem_type(uint8_t type, sched_remove_cb_func remove_cb) -{ - os_sr_t sr; - struct ble_ll_sched_item *entry; - struct ble_ll_sched_item *first; - - OS_ENTER_CRITICAL(sr); - first = TAILQ_FIRST(&g_ble_ll_sched_q); - - if (!first) { - OS_EXIT_CRITICAL(sr); - return; - } - - TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { - if (entry->sched_type == type) { - if (first == entry) { - os_cputime_timer_stop(&g_ble_ll_sched_timer); - first = NULL; - } - - TAILQ_REMOVE(&g_ble_ll_sched_q, entry, link); - remove_cb(entry); - entry->enqueued = 0; - } - } - - if (!first) { - first = TAILQ_FIRST(&g_ble_ll_sched_q); - if (first) { - os_cputime_timer_start(&g_ble_ll_sched_timer, first->start_time); - } - ble_ll_rfmgmt_sched_changed(first); - } - - OS_EXIT_CRITICAL(sr); -} - -/** - * Executes a schedule item by calling the schedule callback function. - * - * Context: Interrupt - * - * @param sch Pointer to schedule item - * - * @return int 0: schedule item is not over; otherwise schedule item is done. - */ -static int -ble_ll_sched_execute_item(struct ble_ll_sched_item *sch) -{ - int rc; - uint8_t lls; - - lls = ble_ll_state_get(); - - ble_ll_trace_u32x3(BLE_LL_TRACE_ID_SCHED, lls, os_cputime_get32(), - sch->start_time); - - if (lls == BLE_LL_STATE_STANDBY) { - goto sched; - } - - /* If aux scan scheduled and LL is in state when scanner is running - * in 3 states: - * BLE_LL_STATE_SCANNING - * BLE_LL_STATE_INITIATING - * BLE_LL_STATE_STANDBY - * - * Let scanner to decide to disable phy or not. - */ - if (sch->sched_type == BLE_LL_SCHED_TYPE_AUX_SCAN) { - if (lls == BLE_LL_STATE_INITIATING || lls == BLE_LL_STATE_SCANNING) { - goto sched; - } - } - - /* - * This is either an advertising event or connection event start. If - * we are scanning or initiating just stop it. - */ - - /* We have to disable the PHY no matter what */ - ble_phy_disable(); - - if (lls == BLE_LL_STATE_SCANNING) { - ble_ll_state_set(BLE_LL_STATE_STANDBY); - ble_ll_scan_halt(); - } else if (lls == BLE_LL_STATE_INITIATING) { - ble_ll_state_set(BLE_LL_STATE_STANDBY); - ble_ll_scan_halt(); - /* PHY is disabled - make sure we do not wait for AUX_CONNECT_RSP */ - ble_ll_conn_reset_pending_aux_conn_rsp(); - } else if (lls == BLE_LL_STATE_ADV) { - STATS_INC(ble_ll_stats, sched_state_adv_errs); - ble_ll_adv_halt(); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - } else if (lls == BLE_LL_STATE_SYNC) { - STATS_INC(ble_ll_stats, sched_state_sync_errs); - ble_ll_sync_halt(); -#endif - } else { - STATS_INC(ble_ll_stats, sched_state_conn_errs); - ble_ll_conn_event_halt(); - } - -sched: - BLE_LL_DEBUG_GPIO(SCHED_ITEM_CB, 1); - BLE_LL_ASSERT(sch->sched_cb); - rc = sch->sched_cb(sch); - BLE_LL_DEBUG_GPIO(SCHED_ITEM_CB, 0); - return rc; -} - -/** - * Run the BLE scheduler. Iterate through all items on the schedule queue. - * - * Context: interrupt (scheduler) - * - * @return int - */ -static void -ble_ll_sched_run(void *arg) -{ - struct ble_ll_sched_item *sch; - - BLE_LL_DEBUG_GPIO(SCHED_RUN, 1); - - /* Look through schedule queue */ - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - if (sch) { -#if (BLE_LL_SCHED_DEBUG == 1) - int32_t dt; - - /* Make sure we have passed the start time of the first event */ - dt = (int32_t)(os_cputime_get32() - sch->start_time); - if (dt > g_ble_ll_sched_max_late) { - g_ble_ll_sched_max_late = dt; - } - if (dt < g_ble_ll_sched_max_early) { - g_ble_ll_sched_max_early = dt; - } -#endif - - /* Remove schedule item and execute the callback */ - TAILQ_REMOVE(&g_ble_ll_sched_q, sch, link); - sch->enqueued = 0; - ble_ll_sched_execute_item(sch); - - /* Restart if there is an item on the schedule */ - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - if (sch) { - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); - } - ble_ll_rfmgmt_sched_changed(sch); - } - - BLE_LL_DEBUG_GPIO(SCHED_RUN, 0); -} - -/** - * Called to determine when the next scheduled event will occur. - * - * If there are not scheduled events this function returns 0; otherwise it - * returns 1 and *next_event_time is set to the start time of the next event. - * - * @param next_event_time - * - * @return int 0: No events are scheduled 1: there is an upcoming event - */ -int -ble_ll_sched_next_time(uint32_t *next_event_time) -{ - int rc; - os_sr_t sr; - struct ble_ll_sched_item *first; - - rc = 0; - OS_ENTER_CRITICAL(sr); - first = TAILQ_FIRST(&g_ble_ll_sched_q); - if (first) { - *next_event_time = first->start_time; - rc = 1; - } - OS_EXIT_CRITICAL(sr); - - return rc; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -/** - * Called to check if there is place for a planned scan req. - * - * @param chan - * @param phy_mode - * - * @return int 0: Clear for scan req 1: there is an upcoming event - */ -int -ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode) -{ - struct ble_ll_sched_item *sch; - uint32_t usec_dur; - uint32_t now = os_cputime_get32(); - - /* Lets calculate roughly how much time we need for scan req and scan rsp */ - usec_dur = ble_ll_pdu_tx_time_get(BLE_SCAN_REQ_LEN, phy_mode); - if (chan >= BLE_PHY_NUM_DATA_CHANS) { - usec_dur += ble_ll_pdu_tx_time_get(BLE_SCAN_RSP_MAX_LEN, phy_mode); - } else { - usec_dur += ble_ll_pdu_tx_time_get(BLE_SCAN_RSP_MAX_EXT_LEN, phy_mode); - } - - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - while (sch) { - /* Let's check if there is no scheduled item which want to start within - * given usecs.*/ - if ((int32_t)(sch->start_time - now + os_cputime_usecs_to_ticks(usec_dur)) > 0) { - /* We are fine. Have time for scan req */ - return 0; - } - - /* There is something in the scheduler. If it is not aux ptr we assume - * it is more important that scan req - */ - if (sch->sched_type != BLE_LL_SCHED_TYPE_AUX_SCAN) { - return 1; - } - - ble_ll_scan_end_adv_evt((struct ble_ll_aux_data *)sch->cb_arg); - TAILQ_REMOVE(&g_ble_ll_sched_q, sch, link); - sch->enqueued = 0; - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - } - return 0; -} - -/** - * Called to schedule a aux scan. - * - * Context: Interrupt - * - * @param ble_hdr - * @param scansm - * @param aux_scan - * - * @return 0 on success, 1 otherwise - */ -int -ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr, - struct ble_ll_scan_sm *scansm, - struct ble_ll_aux_data *aux_scan) -{ - int rc = 1; - os_sr_t sr; - uint32_t off_ticks; - uint32_t off_rem_usecs; - uint32_t start_time; - uint32_t start_time_rem_usecs; - uint32_t end_time; - uint32_t dur; - struct ble_ll_sched_item *entry; - struct ble_ll_sched_item *sch; - int phy_mode; - - sch = &aux_scan->sch; - BLE_LL_ASSERT(sch->cb_arg == NULL); - - off_ticks = os_cputime_usecs_to_ticks(aux_scan->offset); - off_rem_usecs = aux_scan->offset - os_cputime_ticks_to_usecs(off_ticks); - - start_time = ble_hdr->beg_cputime + off_ticks; - start_time_rem_usecs = ble_hdr->rem_usecs + off_rem_usecs; - if (start_time_rem_usecs >= 31) { - start_time++; - start_time_rem_usecs -= 31; - } - start_time -= g_ble_ll_sched_offset_ticks; - - /* Let's calculate time we reserve for aux packet. For now we assume to wait - * for fixed number of bytes and handle possible interrupting it in - * ble_ll_sched_execute_item(). This is because aux packet can be up to - * 256bytes and we don't want to block sched that long - */ - phy_mode = ble_ll_phy_to_phy_mode(aux_scan->aux_phy, - BLE_HCI_LE_PHY_CODED_ANY); - dur = ble_ll_pdu_tx_time_get(MYNEWT_VAL(BLE_LL_SCHED_SCAN_AUX_PDU_LEN), - phy_mode); - end_time = start_time + os_cputime_usecs_to_ticks(dur); - - sch->start_time = start_time; - sch->remainder = start_time_rem_usecs; - sch->end_time = end_time; - - OS_ENTER_CRITICAL(sr); - - if (!ble_ll_sched_insert_if_empty(sch)) { - /* Nothing in schedule. Schedule as soon as possible - * If we are here it means sch has been added to the scheduler */ - rc = 0; - goto done; - } - - /* Try to find slot for aux scan. */ - os_cputime_timer_stop(&g_ble_ll_sched_timer); - TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { - /* We can insert if before entry in list */ - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { - rc = 0; - TAILQ_INSERT_BEFORE(entry, sch, link); - sch->enqueued = 1; - break; - } - - /* Check for overlapping events. For now drop if it overlaps with - * anything. We can make it smarter later on - */ - if (ble_ll_sched_is_overlap(sch, entry)) { - break; - } - } - - if (!entry) { - rc = 0; - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - sch->enqueued = 1; - } - -done: - - if (rc == 0) { - sch->cb_arg = ble_ll_scan_aux_data_ref(aux_scan); - STATS_INC(ble_ll_stats, aux_scheduled); - } - - /* Get head of list to restart timer */ - entry = TAILQ_FIRST(&g_ble_ll_sched_q); - if (entry == sch) { - ble_ll_rfmgmt_sched_changed(sch); - } else { - sch = entry; - } - - OS_EXIT_CRITICAL(sr); - - /* Restart timer */ - BLE_LL_ASSERT(sch != NULL); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); - - return rc; -} -#endif - -#if MYNEWT_VAL(BLE_LL_DTM) -int ble_ll_sched_dtm(struct ble_ll_sched_item *sch) -{ - int rc; - os_sr_t sr; - struct ble_ll_sched_item *entry; - - OS_ENTER_CRITICAL(sr); - - if (!ble_ll_sched_insert_if_empty(sch)) { - /* Nothing in schedule. Schedule as soon as possible - * If we are here it means sch has been added to the scheduler */ - rc = 0; - goto done; - } - - /* Try to find slot for test. */ - os_cputime_timer_stop(&g_ble_ll_sched_timer); - TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { - /* We can insert if before entry in list */ - if (sch->end_time <= entry->start_time) { - rc = 0; - TAILQ_INSERT_BEFORE(entry, sch, link); - sch->enqueued = 1; - break; - } - - /* Check for overlapping events. For now drop if it overlaps with - * anything. We can make it smarter later on - */ - if (ble_ll_sched_is_overlap(sch, entry)) { - OS_EXIT_CRITICAL(sr); - return -1; - } - } - - if (!entry) { - rc = 0; - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - sch->enqueued = 1; - } - -done: - - /* Get head of list to restart timer */ - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - - ble_ll_rfmgmt_sched_changed(sch); - - OS_EXIT_CRITICAL(sr); - - /* Restart timer */ - BLE_LL_ASSERT(sch != NULL); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); - - return rc; -} -#endif -/** - * Stop the scheduler - * - * Context: Link Layer task - */ -void -ble_ll_sched_stop(void) -{ - os_cputime_timer_stop(&g_ble_ll_sched_timer); -} - -/** - * Initialize the scheduler. Should only be called once and should be called - * before any of the scheduler API are called. - * - * @return int - */ -int -ble_ll_sched_init(void) -{ - BLE_LL_DEBUG_GPIO_INIT(SCHED_ITEM_CB); - BLE_LL_DEBUG_GPIO_INIT(SCHED_RUN); - - /* - * Initialize max early to large negative number. This is used - * to determine the worst-case "early" time the schedule was called. Dont - * expect this to be less than -3 or -4. - */ -#if (BLE_LL_SCHED_DEBUG == 1) - g_ble_ll_sched_max_early = -50000; -#endif - - /* - * This is the offset from the start of the scheduled item until the actual - * tx/rx should occur, in ticks. We also "round up" to the nearest tick. - */ - g_ble_ll_sched_offset_ticks = - (uint8_t) os_cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS + 30); - - /* Initialize cputimer for the scheduler */ - os_cputime_timer_init(&g_ble_ll_sched_timer, ble_ll_sched_run, NULL); - -#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) - memset(&g_ble_ll_sched_data, 0, sizeof(struct ble_ll_sched_obj)); - g_ble_ll_sched_data.sch_ticks_per_period = - os_cputime_usecs_to_ticks(MYNEWT_VAL(BLE_LL_USECS_PER_PERIOD)); - g_ble_ll_sched_data.sch_ticks_per_epoch = BLE_LL_SCHED_PERIODS * - g_ble_ll_sched_data.sch_ticks_per_period; -#endif - - return 0; -} - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_supp_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_supp_cmd.c deleted file mode 100644 index 6ee912fa3..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_supp_cmd.c +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include - -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_hci.h" - -/* Octet 0 */ -#define BLE_SUPP_CMD_DISCONNECT (1 << 5) -#define BLE_LL_SUPP_CMD_OCTET_0 (BLE_SUPP_CMD_DISCONNECT) - -/* Octet 5 */ -#define BLE_SUPP_CMD_SET_EVENT_MASK (1 << 6) -#define BLE_LL_SUPP_CMD_OCTET_5 (BLE_SUPP_CMD_SET_EVENT_MASK) - -/* Octet 10 */ -#define BLE_SUPP_CMD_RD_TX_PWR (0 << 2) -#define BLE_LL_SUPP_CMD_OCTET_10 (BLE_SUPP_CMD_RD_TX_PWR) - -/* Octet 14 */ -#define BLE_SUPP_CMD_RD_LOC_VER (1 << 3) -#define BLE_SUPP_CMD_RD_LOC_SUPP_FEAT (1 << 5) -#define BLE_LL_SUPP_CMD_OCTET_14 \ -( \ - BLE_SUPP_CMD_RD_LOC_VER | \ - BLE_SUPP_CMD_RD_LOC_SUPP_FEAT \ -) - -/* Octet 15 */ -#define BLE_SUPP_CMD_RD_BD_ADDR (1 << 1) -#define BLE_SUPP_CMD_RD_RSSI (1 << 5) - -#define BLE_LL_SUPP_CMD_OCTET_15 \ -( \ - BLE_SUPP_CMD_RD_BD_ADDR | \ - BLE_SUPP_CMD_RD_RSSI \ -) - -/* Octet 25 */ -#define BLE_SUPP_CMD_LE_SET_EV_MASK (1 << 0) -#define BLE_SUPP_CMD_LE_RD_BUF_SIZE (1 << 1) -#define BLE_SUPP_CMD_LE_RD_LOC_FEAT (1 << 2) -#define BLE_SUPP_CMD_LE_SET_RAND_ADDR (1 << 4) -#define BLE_SUPP_CMD_LE_SET_ADV_PARAMS (1 << 5) -#define BLE_SUPP_CMD_LE_SET_ADV_TX_PWR (1 << 6) -#define BLE_SUPP_CMD_LE_SET_ADV_DATA (1 << 7) - -#define BLE_LL_SUPP_CMD_OCTET_25 \ -( \ - BLE_SUPP_CMD_LE_SET_EV_MASK | \ - BLE_SUPP_CMD_LE_RD_BUF_SIZE | \ - BLE_SUPP_CMD_LE_RD_LOC_FEAT | \ - BLE_SUPP_CMD_LE_SET_RAND_ADDR | \ - BLE_SUPP_CMD_LE_SET_ADV_PARAMS | \ - BLE_SUPP_CMD_LE_SET_ADV_TX_PWR | \ - BLE_SUPP_CMD_LE_SET_ADV_DATA \ -) - -/* Octet 26 */ -#define BLE_SUPP_CMD_LE_SET_SCAN_RSP_DATA (1 << 0) -#define BLE_SUPP_CMD_LE_SET_ADV_ENABLE (1 << 1) -#define BLE_SUPP_CMD_LE_SET_SCAN_PARAMS (1 << 2) -#define BLE_SUPP_CMD_LE_SET_SCAN_ENABLE (1 << 3) -#define BLE_SUPP_CMD_LE_CREATE_CONN (1 << 4) -#define BLE_SUPP_CMD_LE_CREATE_CONN_CANCEL (1 << 5) -#define BLE_SUPP_CMD_LE_RD_WHITELIST_SIZE (1 << 6) -#define BLE_SUPP_CMD_LE_CLR_WHITELIST (1 << 7) - -#define BLE_LL_SUPP_CMD_OCTET_26 \ -( \ - BLE_SUPP_CMD_LE_SET_SCAN_RSP_DATA | \ - BLE_SUPP_CMD_LE_SET_ADV_ENABLE | \ - BLE_SUPP_CMD_LE_SET_SCAN_PARAMS | \ - BLE_SUPP_CMD_LE_SET_SCAN_ENABLE | \ - BLE_SUPP_CMD_LE_CREATE_CONN | \ - BLE_SUPP_CMD_LE_CREATE_CONN_CANCEL | \ - BLE_SUPP_CMD_LE_RD_WHITELIST_SIZE | \ - BLE_SUPP_CMD_LE_CLR_WHITELIST \ -) - -/* Octet 27 */ -#define BLE_SUPP_CMD_LE_ADD_DEV_WHITELIST (1 << 0) -#define BLE_SUPP_CMD_LE_RMV_DEV_WHITELIST (1 << 1) -#define BLE_SUPP_CMD_LE_CONN_UPDATE (1 << 2) -#define BLE_SUPP_CMD_LE_SET_HOST_CHAN_CLASS (1 << 3) -#define BLE_SUPP_CMD_LE_RD_CHAN_MAP (1 << 4) -#define BLE_SUPP_CMD_LE_RD_REM_USED_FEAT (1 << 5) -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -#define BLE_SUPP_CMD_LE_ENCRYPT (1 << 6) -#else -#define BLE_SUPP_CMD_LE_ENCRYPT (0 << 6) -#endif -#define BLE_SUPP_CMD_LE_RAND (1 << 7) - -#define BLE_LL_SUPP_CMD_OCTET_27 \ -( \ - BLE_SUPP_CMD_LE_ENCRYPT | \ - BLE_SUPP_CMD_LE_RAND | \ - BLE_SUPP_CMD_LE_ADD_DEV_WHITELIST | \ - BLE_SUPP_CMD_LE_RMV_DEV_WHITELIST | \ - BLE_SUPP_CMD_LE_CONN_UPDATE | \ - BLE_SUPP_CMD_LE_SET_HOST_CHAN_CLASS | \ - BLE_SUPP_CMD_LE_RD_CHAN_MAP | \ - BLE_SUPP_CMD_LE_RD_REM_USED_FEAT \ -) - -/* Octet 28 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -#define BLE_SUPP_CMD_LE_START_ENCRYPT (1 << 0) -#define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (1 << 1) -#define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (1 << 2) -#else -#define BLE_SUPP_CMD_LE_START_ENCRYPT (0 << 0) -#define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (0 << 1) -#define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (0 << 2) -#endif -#define BLE_SUPP_CMD_LE_READ_SUPP_STATES (1 << 3) - -#if MYNEWT_VAL(BLE_LL_DTM) -#define BLE_SUPP_CMD_LE_RX_TEST (1 << 4) -#define BLE_SUPP_CMD_LE_TX_TEST (1 << 5) -#define BLE_SUPP_CMD_LE_TEST_END (1 << 6) - -#else -#define BLE_SUPP_CMD_LE_RX_TEST (0 << 4) -#define BLE_SUPP_CMD_LE_TX_TEST (0 << 5) -#define BLE_SUPP_CMD_LE_TEST_END (0 << 6) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_28 \ -( \ - BLE_SUPP_CMD_LE_START_ENCRYPT | \ - BLE_SUPP_CMD_LE_LTK_REQ_REPLY | \ - BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY | \ - BLE_SUPP_CMD_LE_READ_SUPP_STATES | \ - BLE_SUPP_CMD_LE_RX_TEST | \ - BLE_SUPP_CMD_LE_TX_TEST | \ - BLE_SUPP_CMD_LE_TEST_END \ -) - -/* Octet 33 */ -#define BLE_SUPP_CMD_LE_REM_CONN_PRR (1 << 4) -#define BLE_SUPP_CMD_LE_REM_CONN_PRNR (1 << 5) -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) -#define BLE_SUPP_CMD_LE_SET_DATALEN (1 << 6) -#define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (1 << 7) -#else -#define BLE_SUPP_CMD_LE_SET_DATALEN (0 << 6) -#define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_33 \ -( \ - BLE_SUPP_CMD_LE_REM_CONN_PRR | \ - BLE_SUPP_CMD_LE_REM_CONN_PRNR | \ - BLE_SUPP_CMD_LE_SET_DATALEN | \ - BLE_SUPP_CMD_LE_RD_SUGG_DATALEN \ -) - -/* Octet 34 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) -#define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (1 << 0) -#else -#define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (0 << 0) -#endif -#define BLE_SUPP_CMD_LE_READ_LOCAL_P256_PK (0 << 1) -#define BLE_SUPP_CMD_LE_GENERATE_DH_KEY (0 << 2) -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -#define BLE_SUPP_CMD_LE_ADD_RESOLV_LIST (1 << 3) -#define BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST (1 << 4) -#define BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST (1 << 5) -#define BLE_SUPP_CMD_LE_RD_RESOLV_SIZE (1 << 6) -#define BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR (1 << 7) -#else -#define BLE_SUPP_CMD_LE_ADD_RESOLV_LIST (0 << 3) -#define BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST (0 << 4) -#define BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST (0 << 5) -#define BLE_SUPP_CMD_LE_RD_RESOLV_SIZE (0 << 6) -#define BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_34 \ -( \ - BLE_SUPP_CMD_LE_WR_SUGG_DATALEN | \ - BLE_SUPP_CMD_LE_READ_LOCAL_P256_PK | \ - BLE_SUPP_CMD_LE_GENERATE_DH_KEY | \ - BLE_SUPP_CMD_LE_ADD_RESOLV_LIST | \ - BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST | \ - BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST | \ - BLE_SUPP_CMD_LE_RD_RESOLV_SIZE | \ - BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR \ -) - -/* Octet 35 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -#define BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR (1 << 0) -#define BLE_SUPP_CMD_LE_SET_ADDR_RES_EN (1 << 1) -#define BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO (1 << 2) -#else -#define BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR (0 << 0) -#define BLE_SUPP_CMD_LE_SET_ADDR_RES_EN (0 << 1) -#define BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO (0 << 2) -#endif -#define BLE_SUPP_CMD_LE_RD_MAX_DATALEN (1 << 3) -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) -#define BLE_SUPP_CMD_LE_READ_PHY (1 << 4) -#define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (1 << 5) -#define BLE_SUPP_CMD_LE_SET_PHY (1 << 6) -#else -#define BLE_SUPP_CMD_LE_READ_PHY (0 << 4) -#define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (0 << 5) -#define BLE_SUPP_CMD_LE_SET_PHY (0 << 6) -#endif - -#if MYNEWT_VAL(BLE_LL_DTM) -#define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST (1 << 7) -#else -#define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_35 \ -( \ - BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR | \ - BLE_SUPP_CMD_LE_SET_ADDR_RES_EN | \ - BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO | \ - BLE_SUPP_CMD_LE_RD_MAX_DATALEN | \ - BLE_SUPP_CMD_LE_READ_PHY | \ - BLE_SUPP_CMD_LE_SET_DEFAULT_PHY | \ - BLE_SUPP_CMD_LE_SET_PHY | \ - BLE_SUPP_CMD_LE_ENHANCED_RX_TEST \ -) - -/* Octet 36 */ -#if MYNEWT_VAL(BLE_LL_DTM) -#define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST (1 << 0) -#else -#define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST (0 << 0) -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#define BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR (1 << 1) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM (1 << 2) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA (1 << 3) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP (1 << 4) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE (1 << 5) -#define BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN (1 << 6) -#define BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS (1 << 7) -#else -#define BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR (0 << 1) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM (0 << 2) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA (0 << 3) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP (0 << 4) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE (0 << 5) -#define BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN (0 << 6) -#define BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_36 \ -( \ - BLE_SUPP_CMD_LE_ENHANCED_TX_TEST | \ - BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR | \ - BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM | \ - BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA | \ - BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP | \ - BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE | \ - BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN | \ - BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS \ -) - -/* Octet 37 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#define BLE_SUPP_CMD_LE_REMOVE_ADVS (1 << 0) -#define BLE_SUPP_CMD_LE_CLEAR_ADVS (1 << 1) -#else -#define BLE_SUPP_CMD_LE_REMOVE_ADVS (0 << 0) -#define BLE_SUPP_CMD_LE_CLEAR_ADVS (0 << 1) -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) -#define BLE_SUPP_CMD_LE_SET_PADV_PARAM (1 << 2) -#define BLE_SUPP_CMD_LE_SET_PADV_DATA (1 << 3) -#define BLE_SUPP_CMD_LE_SET_PADV_ENABLE (1 << 4) -#else -#define BLE_SUPP_CMD_LE_SET_PADV_PARAM (0 << 2) -#define BLE_SUPP_CMD_LE_SET_PADV_DATA (0 << 3) -#define BLE_SUPP_CMD_LE_SET_PADV_ENABLE (0 << 4) -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (1 << 5) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (1 << 6) -#define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (1 << 7) -#else -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (0 << 5) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (0 << 6) -#define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_37 \ -( \ - BLE_SUPP_CMD_LE_REMOVE_ADVS | \ - BLE_SUPP_CMD_LE_CLEAR_ADVS | \ - BLE_SUPP_CMD_LE_SET_PADV_PARAM | \ - BLE_SUPP_CMD_LE_SET_PADV_DATA | \ - BLE_SUPP_CMD_LE_SET_PADV_ENABLE | \ - BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM | \ - BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE | \ - BLE_SUPP_CMD_LE_EXT_CREATE_CONN \ -) - -/* Octet 38 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) -#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC (1 << 0) -#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C (1 << 1) -#define BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC (1 << 2) -#define BLE_SUPP_CMD_LE_ADD_PADV_LIST (1 << 3) -#define BLE_SUPP_CMD_LE_REMOVE_PADV_LIST (1 << 4) -#define BLE_SUPP_CMD_LE_CLEAR_PADV_LIST (1 << 5) -#define BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE (1 << 6) -#else -#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC (0 << 0) -#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C (0 << 1) -#define BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC (0 << 2) -#define BLE_SUPP_CMD_LE_ADD_PADV_LIST (0 << 3) -#define BLE_SUPP_CMD_LE_REMOVE_PADV_LIST (0 << 4) -#define BLE_SUPP_CMD_LE_CLEAR_PADV_LIST (0 << 5) -#define BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE (0 << 6) -#endif -#define BLE_SUPP_CMD_LE_RD_TX_POWER (1 << 7) - -#define BLE_LL_SUPP_CMD_OCTET_38 \ -( \ - BLE_SUPP_CMD_LE_PADV_CREATE_SYNC | \ - BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C | \ - BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC | \ - BLE_SUPP_CMD_LE_ADD_PADV_LIST | \ - BLE_SUPP_CMD_LE_REMOVE_PADV_LIST | \ - BLE_SUPP_CMD_LE_CLEAR_PADV_LIST | \ - BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE | \ - BLE_SUPP_CMD_LE_RD_TX_POWER \ -) - -/* Octet 39 */ -#define BLE_SUPP_CMD_LE_RD_RF_PATH_COMP (1 << 0) -#define BLE_SUPP_CMD_LE_WR_RF_PATH_COMP (1 << 1) -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -#define BLE_SUPP_CMD_LE_SET_PRIVACY_MODE (1 << 2) -#else -#define BLE_SUPP_CMD_LE_SET_PRIVACY_MODE (0 << 2) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_39 \ -( \ - BLE_SUPP_CMD_LE_RD_RF_PATH_COMP | \ - BLE_SUPP_CMD_LE_WR_RF_PATH_COMP | \ - BLE_SUPP_CMD_LE_SET_PRIVACY_MODE \ -) - -/* Octet 40 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_VERSION) >= 51 -#define BLE_SUPP_CMD_LE_PADV_RECV_ENABLE (1 << 5) -#else -#define BLE_SUPP_CMD_LE_PADV_RECV_ENABLE (0 << 5) -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER (1 << 6) -#define BLE_SUPP_CMD_LE_PADV_SET_INFO_TRANSFER (1 << 7) -#else -#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER (0 << 6) -#define BLE_SUPP_CMD_LE_PADV_SET_INFO_TRANSFER (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_40 \ -( \ - BLE_SUPP_CMD_LE_PADV_RECV_ENABLE | \ - BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER | \ - BLE_SUPP_CMD_LE_PADV_SET_INFO_TRANSFER \ -) - -/* Octet 41 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS (1 << 0) -#define BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS (1 << 1) -#else -#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS (0 << 0) -#define BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS (0 << 1) -#endif -#define BLE_LL_SUPP_CMD_OCTET_41 \ -( \ - BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS | \ - BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS \ -) - -/* Defines the array of supported commands */ -const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN] = -{ - BLE_LL_SUPP_CMD_OCTET_0, /* Octet 0 */ - 0, - 0, - 0, - 0, - BLE_LL_SUPP_CMD_OCTET_5, - 0, - 0, - 0, /* Octet 8 */ - 0, - BLE_LL_SUPP_CMD_OCTET_10, - 0, - 0, - 0, - BLE_LL_SUPP_CMD_OCTET_14, - BLE_LL_SUPP_CMD_OCTET_15, - 0, /* Octet 16 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, /* Octet 24 */ - BLE_LL_SUPP_CMD_OCTET_25, - BLE_LL_SUPP_CMD_OCTET_26, - BLE_LL_SUPP_CMD_OCTET_27, - BLE_LL_SUPP_CMD_OCTET_28, - 0, - 0, - 0, - 0, /* Octet 32 */ - BLE_LL_SUPP_CMD_OCTET_33, - BLE_LL_SUPP_CMD_OCTET_34, - BLE_LL_SUPP_CMD_OCTET_35, - BLE_LL_SUPP_CMD_OCTET_36, - BLE_LL_SUPP_CMD_OCTET_37, - BLE_LL_SUPP_CMD_OCTET_38, - BLE_LL_SUPP_CMD_OCTET_39, - BLE_LL_SUPP_CMD_OCTET_40, /* Octet 40 */ - BLE_LL_SUPP_CMD_OCTET_41, -}; - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sync.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sync.c deleted file mode 100644 index 231a4d633..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sync.c +++ /dev/null @@ -1,2248 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include -#include - -#include "nimble/porting/nimble/include/syscfg/syscfg.h" - -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_sync.h" -#include "../include/controller/ble_ll_utils.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_whitelist.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_resolv.h" -#include "../include/controller/ble_ll_rfmgmt.h" - -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "nimble/nimble/include/nimble/ble_hci_trans.h" - -#include "ble_ll_conn_priv.h" - -#include "nimble/porting/nimble/include/stats/stats.h" - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - -/* defines number of events that can be lost during sync establishment - * before failed to be established error is reported - */ -#define BLE_LL_SYNC_ESTABLISH_CNT 6 - -#define BLE_LL_SYNC_CNT MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_CNT) -#define BLE_LL_SYNC_LIST_CNT MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_LIST_CNT) - -#define BLE_LL_SYNC_SM_FLAG_RESERVED 0x0001 -#define BLE_LL_SYNC_SM_FLAG_ESTABLISHING 0x0002 -#define BLE_LL_SYNC_SM_FLAG_ESTABLISHED 0x0004 -#define BLE_LL_SYNC_SM_FLAG_SET_ANCHOR 0x0008 -#define BLE_LL_SYNC_SM_FLAG_OFFSET_300 0x0010 -#define BLE_LL_SYNC_SM_FLAG_SYNC_INFO 0x0020 -#define BLE_LL_SYNC_SM_FLAG_DISABLED 0x0040 -#define BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED 0x0080 -#define BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED 0x0100 - -#define BLE_LL_SYNC_CHMAP_LEN 5 -#define BLE_LL_SYNC_ITVL_USECS 1250 - -struct ble_ll_sync_sm { - uint16_t flags; - - uint8_t adv_sid; - uint8_t adv_addr[BLE_DEV_ADDR_LEN]; - uint8_t adv_addr_type; - - uint8_t sca; - uint8_t chanmap[BLE_LL_SYNC_CHMAP_LEN]; - uint8_t num_used_chans; - - uint8_t chan_index; - uint8_t chan_chain; - - uint8_t phy_mode; - - uint8_t sync_pending_cnt; - - uint32_t timeout; - uint16_t skip; - - uint16_t itvl; - uint8_t itvl_usecs; - uint32_t itvl_ticks; - - uint32_t crcinit; /* only 3 bytes are used */ - uint32_t access_addr; - uint16_t event_cntr; - uint16_t channel_id; - - uint32_t window_widening; - uint32_t last_anchor_point; - uint32_t anchor_point; - uint8_t anchor_point_usecs; - - struct ble_ll_sched_item sch; - - struct ble_npl_event sync_ev_end; - - uint8_t *next_report; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - struct ble_ll_conn_sm *transfer_conn; - uint8_t *transfer_received_ev; - uint16_t transfer_id; - uint16_t event_cntr_last_received; - uint8_t adv_addr_rpa[6]; -#endif -}; - -static struct ble_ll_sync_sm g_ble_ll_sync_sm[BLE_LL_SYNC_CNT]; - -static struct { - uint8_t adv_sid; - uint8_t adv_addr[BLE_DEV_ADDR_LEN]; - uint8_t adv_addr_type; -} g_ble_ll_sync_adv_list[BLE_LL_SYNC_LIST_CNT]; - -static struct { - uint32_t timeout; - uint16_t max_skip; - uint16_t options; -} g_ble_ll_sync_create_params; - -/* if this is set HCI LE Sync Create is pending */ -static uint8_t *g_ble_ll_sync_create_comp_ev; - -static struct ble_ll_sync_sm *g_ble_ll_sync_sm_current; - -static int -ble_ll_sync_on_list(const uint8_t *addr, uint8_t addr_type, uint8_t sid) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { - if ((g_ble_ll_sync_adv_list[i].adv_sid == sid) && - (g_ble_ll_sync_adv_list[i].adv_addr_type == addr_type) && - !memcmp(g_ble_ll_sync_adv_list[i].adv_addr, addr, BLE_DEV_ADDR_LEN)) { - return i; - } - } - - return -1; -} - -static int -ble_ll_sync_list_get_free(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { - if (g_ble_ll_sync_adv_list[i].adv_sid == 0xff) { - return i; - } - } - - return -1; -} - -static bool -ble_ll_sync_list_empty(void) { - int i; - - for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { - if (g_ble_ll_sync_adv_list[i].adv_sid != 0xff) { - return false; - } - } - - return true; -} - -static uint8_t -ble_ll_sync_get_handle(struct ble_ll_sync_sm *sm) -{ - /* handle number is offset in global array */ - return sm - g_ble_ll_sync_sm; -} - -static void -ble_ll_sync_sm_clear(struct ble_ll_sync_sm *sm) -{ - if (sm->flags & (BLE_LL_SYNC_SM_FLAG_ESTABLISHING | - BLE_LL_SYNC_SM_FLAG_ESTABLISHED)) { - ble_ll_sched_rmv_elem(&sm->sch); - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &sm->sync_ev_end); - } - - if (sm->next_report) { - ble_hci_trans_buf_free(sm->next_report); - } - - if (g_ble_ll_sync_sm_current == sm) { - ble_phy_disable(); - ble_ll_state_set(BLE_LL_STATE_STANDBY); - g_ble_ll_sync_sm_current = NULL; - ble_ll_scan_chk_resume(); - } - - ble_ll_rfmgmt_release(); - - BLE_LL_ASSERT(sm->sync_ev_end.ev.ev_queued == 0); - BLE_LL_ASSERT(sm->sch.enqueued == 0); - memset(sm, 0, sizeof(*sm)); -} - -static uint8_t -ble_ll_sync_phy_mode_to_hci(int8_t phy_mode) -{ -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - switch (phy_mode) { - case BLE_PHY_MODE_1M: - return BLE_HCI_LE_PHY_1M; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - case BLE_PHY_MODE_2M: - return BLE_HCI_LE_PHY_2M; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - case BLE_PHY_MODE_CODED_125KBPS: - case BLE_PHY_MODE_CODED_500KBPS: - return BLE_HCI_LE_PHY_CODED; -#endif - default: - BLE_LL_ASSERT(false); - return BLE_PHY_MODE_1M; - } -#else - return BLE_PHY_MODE_1M; -#endif -} - -static struct ble_ll_sync_sm * -ble_ll_sync_find(const uint8_t *addr, uint8_t addr_type, uint8_t sid) -{ - struct ble_ll_sync_sm *sm; - int i; - - for (i = 0; i < BLE_LL_SYNC_CNT; i++) { - sm = &g_ble_ll_sync_sm[i]; - - if (!sm->flags) { - continue; - } - if ((sm->adv_sid == sid) && (sm->adv_addr_type == addr_type) && - !memcmp(&sm->adv_addr, addr, BLE_DEV_ADDR_LEN)) { - return sm; - } - } - - return NULL; -} - -static uint16_t -get_max_skip(uint32_t interval_us, uint32_t timeout_us) -{ - uint16_t max_skip; - - BLE_LL_ASSERT(interval_us); - BLE_LL_ASSERT(timeout_us); - - if (timeout_us <= interval_us) { - return 0; - } - - /* - * Calculate max allowed skip to receive something before timeout. We adjust - * current skip value to be no more than max_skip-6 so we have at least few - * attempts to receive an event (so we don't timeout immediately after just - * one missed event). - */ - - max_skip = (timeout_us / interval_us) - 1; - - if (max_skip < 6) { - return 0; - } - - return max_skip - 6; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -static void -ble_ll_sync_transfer_received(struct ble_ll_sync_sm *sm, uint8_t status) -{ - struct ble_hci_ev_le_subev_periodic_adv_sync_transfer *ev; - struct ble_hci_ev *hci_ev; - - BLE_LL_ASSERT(sm->transfer_received_ev); - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER)) { - hci_ev = (void *) sm->transfer_received_ev; - - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - - ev = (void *) hci_ev->data; - ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER; - - ev->status = status; - ev->conn_handle = htole16(sm->transfer_conn->conn_handle); - ev->service_data = htole16(sm->transfer_id); - - /* this is ignored by host on error */ - ev->sync_handle = htole16(ble_ll_sync_get_handle(sm)); - ev->sid = sm->adv_sid; - ev->peer_addr_type = sm->adv_addr_type; - if (sm->flags & BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED) { - ev->peer_addr_type += 2; - } - memcpy(ev->peer_addr, sm->adv_addr, BLE_DEV_ADDR_LEN); - ev->phy = ble_ll_sync_phy_mode_to_hci(sm->phy_mode); - ev->interval = htole16(sm->itvl); - ev->aca = sm->sca; - - ble_ll_hci_event_send(hci_ev); - } else { - ble_hci_trans_buf_free(sm->transfer_received_ev); - } - - sm->transfer_received_ev = NULL; - sm->transfer_conn = NULL; -} -#endif - -static void -ble_ll_sync_est_event_success(struct ble_ll_sync_sm *sm) -{ - struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev; - struct ble_hci_ev *hci_ev; - - BLE_LL_ASSERT(g_ble_ll_sync_create_comp_ev); - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB)) { - hci_ev = (void *) g_ble_ll_sync_create_comp_ev; - - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB; - ev->status = BLE_ERR_SUCCESS; - ev->sync_handle = htole16(ble_ll_sync_get_handle(sm)); - ev->sid = sm->adv_sid; - ev->peer_addr_type = sm->adv_addr_type; - if (sm->flags & BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED) { - ev->peer_addr_type += 2; - } - memcpy(ev->peer_addr, sm->adv_addr, BLE_DEV_ADDR_LEN); - ev->phy = ble_ll_sync_phy_mode_to_hci(sm->phy_mode); - ev->interval = htole16(sm->itvl); - ev->aca = sm->sca; - - ble_ll_hci_event_send(hci_ev); - } else { - ble_hci_trans_buf_free(g_ble_ll_sync_create_comp_ev); - } - - g_ble_ll_sync_create_comp_ev = NULL; -} - -static void -ble_ll_sync_est_event_failed(uint8_t status) -{ - struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev; - struct ble_hci_ev *hci_ev; - - BLE_LL_ASSERT(g_ble_ll_sync_create_comp_ev); - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB)) { - hci_ev = (void *) g_ble_ll_sync_create_comp_ev; - - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - memset(ev, 0, sizeof(*ev)); - - ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB; - ev->status = status; - - ble_ll_hci_event_send(hci_ev); - } else { - ble_hci_trans_buf_free(g_ble_ll_sync_create_comp_ev); - } - - g_ble_ll_sync_create_comp_ev = NULL; -} - -static void -ble_ll_sync_lost_event(struct ble_ll_sync_sm *sm) -{ - struct ble_hci_ev_le_subev_periodic_adv_sync_lost *ev; - struct ble_hci_ev *hci_ev; - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_LOST)) { - hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_LOST; - ev->sync_handle = htole16(ble_ll_sync_get_handle(sm)); - - ble_ll_hci_event_send(hci_ev); - } - } -} - -static void -ble_ll_sync_current_sm_over(void) -{ - /* Disable the PHY */ - ble_phy_disable(); - - /* Link-layer is in standby state now */ - ble_ll_state_set(BLE_LL_STATE_STANDBY); - - /* Set current LL sync to NULL */ - g_ble_ll_sync_sm_current = NULL; -} - -static int -ble_ll_sync_event_start_cb(struct ble_ll_sched_item *sch) -{ - struct ble_ll_sync_sm *sm; - uint32_t wfr_usecs; - uint32_t start; - int rc; - - /* Set current connection state machine */ - sm = sch->cb_arg; - BLE_LL_ASSERT(sm); - - g_ble_ll_sync_sm_current = sm; - - /* Disable whitelisting */ - ble_ll_whitelist_disable(); - - /* Set LL state */ - ble_ll_state_set(BLE_LL_STATE_SYNC); - - /* Set channel */ - ble_phy_setchan(sm->chan_index, sm->access_addr, sm->crcinit); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - ble_phy_resolv_list_disable(); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - ble_phy_encrypt_disable(); -#endif - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_set(sm->phy_mode, sm->phy_mode); -#endif - - start = sch->start_time + g_ble_ll_sched_offset_ticks; - rc = ble_phy_rx_set_start_time(start, sch->remainder); - if (rc && rc != BLE_PHY_ERR_RX_LATE) { - STATS_INC(ble_ll_stats, sync_event_failed); - rc = BLE_LL_SCHED_STATE_DONE; - ble_ll_event_send(&sm->sync_ev_end); - ble_ll_sync_current_sm_over(); - } else { - /* - * Set flag that tells to set last anchor point if a packet - * has been received. - */ - sm->flags |= BLE_LL_SYNC_SM_FLAG_SET_ANCHOR; - - /* Set WFR timer. - * If establishing we always adjust with offset unit. - * If this is first packet of sync (one that was pointed by from - * SyncInfo we don't adjust WFT with window widening. - */ - if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) { - wfr_usecs = (sm->flags & BLE_LL_SYNC_SM_FLAG_OFFSET_300) ? 300 : 30; - if (!(sm->flags & BLE_LL_SYNC_SM_FLAG_SYNC_INFO)) { - wfr_usecs += 2 * sm->window_widening; - } - } else { - wfr_usecs = 2 * sm->window_widening; - } - ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, wfr_usecs); - - rc = BLE_LL_SCHED_STATE_RUNNING; - } - - sm->flags &= ~BLE_LL_SYNC_SM_FLAG_SYNC_INFO; - - return rc; -} - -/** - * Called when a receive PDU has started. - * - * Context: interrupt - * - * @return int - * < 0: A frame we dont want to receive. - * = 0: Continue to receive frame. Dont go from rx to tx - */ -int -ble_ll_sync_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr) -{ - BLE_LL_ASSERT(g_ble_ll_sync_sm_current); - - /* this also handles chains as those have same PDU type */ - if (pdu_type != BLE_ADV_PDU_TYPE_AUX_SYNC_IND) { - ble_ll_event_send(&g_ble_ll_sync_sm_current->sync_ev_end); - ble_ll_sync_current_sm_over(); - STATS_INC(ble_ll_stats, sched_invalid_pdu); - return -1; - } - - STATS_INC(ble_ll_stats, sync_received); - return 0; -} - -static int -ble_ll_sync_parse_ext_hdr(struct os_mbuf *om, uint8_t **aux, int8_t *tx_power) -{ - uint8_t *rxbuf = om->om_data; - uint8_t ext_hdr_flags; - uint8_t ext_hdr_len; - uint8_t *ext_hdr; - uint8_t pdu_len; - int i; - - pdu_len = rxbuf[1]; - if (pdu_len == 0) { - return -1; - } - ext_hdr_len = rxbuf[2] & 0x3F; - if (ext_hdr_len > (pdu_len - 1)) { - return -1; - } - - if (ext_hdr_len) { - ext_hdr_flags = rxbuf[3]; - ext_hdr = &rxbuf[4]; - - i = 0; - - /* there should be no AdvA in Sync or chain, skip it */ - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { - i += BLE_LL_EXT_ADV_ADVA_SIZE; - } - - /* there should be no TargetA in Sync or chain, skip it */ - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { - i += BLE_LL_EXT_ADV_TARGETA_SIZE; - } - - /* Ignore CTE for now */ - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { - i += 1; - } - - /* there should be no ADI in Sync or chain, skip it */ - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { - i += BLE_LL_EXT_ADV_DATA_INFO_SIZE; - } - - /* get AuXPTR if present */ - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { - *aux = ext_hdr + i; - i += BLE_LL_EXT_ADV_AUX_PTR_SIZE; - } - - /* there should be no SyncInfo in Sync or chain, skip it */ - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) { - i += BLE_LL_EXT_ADV_SYNC_INFO_SIZE; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { - *tx_power = *(ext_hdr + i); - i += BLE_LL_EXT_ADV_TX_POWER_SIZE; - } - - /* TODO Handle ACAD if needed */ - - /* sanity check */ - if (i > ext_hdr_len) { - return -1; - } - } - - return pdu_len - ext_hdr_len - 1; -} - -static void -ble_ll_sync_adjust_ext_hdr(struct os_mbuf *om) -{ - uint8_t *rxbuf = om->om_data; - uint8_t ext_hdr_len; - - /* this was already verified in ble_ll_sync_parse_ext_hdr() */ - ext_hdr_len = rxbuf[2] & 0x3F; - - os_mbuf_adj(om, 3 + ext_hdr_len); -} - -static void -ble_ll_sync_send_truncated_per_adv_rpt(struct ble_ll_sync_sm *sm, uint8_t *evbuf) -{ - struct ble_hci_ev_le_subev_periodic_adv_rpt *ev; - struct ble_hci_ev *hci_ev; - - if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT) || - (sm->flags & BLE_LL_SYNC_SM_FLAG_DISABLED)) { - ble_hci_trans_buf_free(evbuf); - return; - } - - hci_ev = (void *) evbuf; - - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT; - ev->sync_handle = htole16(ble_ll_sync_get_handle(sm)); - ev->tx_power = 127; /* not available */ - ev->rssi = 127; /* not available */ - ev->cte_type = 0xff; - ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED; - ev->data_len = 0; - - ble_ll_hci_event_send(hci_ev); -} - -static void -ble_ll_sync_send_per_adv_rpt(struct ble_ll_sync_sm *sm, struct os_mbuf *rxpdu, - int8_t rssi, int8_t tx_power, int datalen, - uint8_t *aux, bool aux_scheduled) -{ - struct ble_hci_ev_le_subev_periodic_adv_rpt *ev; - struct ble_hci_ev *hci_ev; - struct ble_hci_ev *hci_ev_next = NULL; - uint8_t max_data_len; - int offset; - - /* use next report buffer if present, this means we are chaining */ - if (sm->next_report) { - hci_ev = (void *) sm->next_report; - sm->next_report = NULL; - } else { - hci_ev = (void * )ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); - if (!hci_ev) { - goto done; - } - } - - max_data_len = BLE_LL_MAX_EVT_LEN - sizeof(*hci_ev) - sizeof(*ev); - offset = 0; - - do { - if (hci_ev_next) { - hci_ev = hci_ev_next; - hci_ev_next = NULL; - } - - hci_ev->opcode = BLE_HCI_EVCODE_LE_META; - hci_ev->length = sizeof(*ev); - - ev = (void *) hci_ev->data; - - ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT; - ev->sync_handle = htole16(ble_ll_sync_get_handle(sm)); - ev->tx_power = tx_power; - ev->rssi = rssi; - ev->cte_type = 0xff; - - ev->data_len = min(max_data_len, datalen - offset); - /* adjust event length */ - hci_ev->length += ev->data_len; - - os_mbuf_copydata(rxpdu, offset, ev->data_len, ev->data); - offset += ev->data_len; - - /* Need another event for next fragment of this PDU */ - if (offset < datalen) { - hci_ev_next = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); - if (hci_ev_next) { - ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_INCOMPLETE; - } else { - ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED; - } - } else { - /* last report of this PDU */ - if (aux) { - if (aux_scheduled) { - /* if we scheduled aux, we need buffer for next report */ - hci_ev_next = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); - if (hci_ev_next) { - ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_INCOMPLETE; - } else { - ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED; - } - } else { - ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED; - } - } else { - ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_COMPLETE; - } - } - ble_ll_hci_event_send(hci_ev); - } while ((offset < datalen) && hci_ev_next); - -done: - /* this means that we already truncated data (or didn't sent first at all) - * in HCI report but has scheduled for next PDU in chain. In that case mark - * it so that we end event properly when next PDU is received. - * */ - if (aux_scheduled && !hci_ev_next) { - sm->flags |= BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED; - } - - /* store for chain */ - sm->next_report = (void *) hci_ev_next; -} - -/** - * Called when a receive PDU has ended. - * - * Context: Interrupt - * - * @param rxpdu - * - * @return int - * < 0: Disable the phy after reception. - * == 0: Success. Do not disable the PHY. - * > 0: Do not disable PHY as that has already been done. - */ -int -ble_ll_sync_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) -{ - struct ble_mbuf_hdr *ble_hdr; - struct os_mbuf *rxpdu; - - BLE_LL_ASSERT(g_ble_ll_sync_sm_current); - - /* type was verified in isr_start */ - - rxpdu = ble_ll_rxpdu_alloc(rxbuf[1] + BLE_LL_PDU_HDR_LEN); - if (rxpdu) { - ble_phy_rxpdu_copy(rxbuf, rxpdu); - - ble_hdr = BLE_MBUF_HDR_PTR(rxpdu); - ble_hdr->rxinfo.user_data = g_ble_ll_sync_sm_current; - - ble_ll_rx_pdu_in(rxpdu); - } else { - STATS_INC(ble_ll_stats, sync_rx_buf_err); - ble_ll_event_send(&g_ble_ll_sync_sm_current->sync_ev_end); - } - - /* PHY is disabled here */ - ble_ll_sync_current_sm_over(); - - return 1; -} - -/** - * Called when the wait for response timer expires while in the sync state. - * - * Context: Interrupt. - */ -void -ble_ll_sync_wfr_timer_exp(void) -{ - struct ble_ll_sync_sm *sm = g_ble_ll_sync_sm_current; - - BLE_LL_ASSERT(g_ble_ll_sync_sm_current); - STATS_INC(ble_ll_stats, sync_missed_err); - - ble_ll_sync_current_sm_over(); - ble_ll_event_send(&sm->sync_ev_end); -} - -/** - * Called when sync event needs to be halted. This normally should not be called - * and is only called when a scheduled item executes but scanning for sync/chain - * is stil ongoing - * Context: Interrupt - */ -void -ble_ll_sync_halt(void) -{ - struct ble_ll_sync_sm *sm = g_ble_ll_sync_sm_current; - - ble_ll_sync_current_sm_over(); - - if (sm) { - ble_ll_event_send(&sm->sync_ev_end); - } -} - -uint32_t -ble_ll_sync_get_event_end_time(void) -{ - uint32_t end_time; - - if (g_ble_ll_sync_sm_current) { - end_time = g_ble_ll_sync_sm_current->sch.end_time; - } else { - end_time = os_cputime_get32(); - } - return end_time; -} - -static uint8_t -ble_ll_sync_phy_mode_to_aux_phy(uint8_t phy_mode) -{ - switch (phy_mode) { - case BLE_PHY_MODE_1M: - return 0x00; - case BLE_PHY_MODE_2M: - return 0x01; - case BLE_PHY_MODE_CODED_125KBPS: - case BLE_PHY_MODE_CODED_500KBPS: - return 0x02; - default: - BLE_LL_ASSERT(false); - return 0x00; - } -} - -static void -ble_ll_sync_parse_aux_ptr(const uint8_t *buf, uint8_t *chan, uint32_t *offset, - uint8_t *offset_units, uint8_t *phy) -{ - uint32_t aux_ptr_field = get_le32(buf) & 0x00FFFFFF; - - *chan = aux_ptr_field & 0x3F; - - /* TODO use CA aux_ptr_field >> 6 */ - - if ((aux_ptr_field >> 7) & 0x01) { - *offset = 300 * ((aux_ptr_field >> 8) & 0x1FFF); - *offset_units = 1; - } else { - *offset = 30 * ((aux_ptr_field >> 8) & 0x1FFF); - *offset_units = 0; - } - - *phy = (aux_ptr_field >> 21) & 0x07; -} - -static int -ble_ll_sync_chain_start_cb(struct ble_ll_sched_item *sch) -{ - struct ble_ll_sync_sm *sm; - uint32_t wfr_usecs; - uint32_t start; - int rc; - - /* Set current connection state machine */ - sm = sch->cb_arg; - g_ble_ll_sync_sm_current = sm; - BLE_LL_ASSERT(sm); - - /* Disable whitelisting */ - ble_ll_whitelist_disable(); - - /* Set LL state */ - ble_ll_state_set(BLE_LL_STATE_SYNC); - - /* Set channel */ - ble_phy_setchan(sm->chan_chain, sm->access_addr, sm->crcinit); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - ble_phy_resolv_list_disable(); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - ble_phy_encrypt_disable(); -#endif - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_set(sm->phy_mode, sm->phy_mode); -#endif - - start = sch->start_time + g_ble_ll_sched_offset_ticks; - rc = ble_phy_rx_set_start_time(start, sch->remainder); - if (rc && rc != BLE_PHY_ERR_RX_LATE) { - STATS_INC(ble_ll_stats, sync_chain_failed); - rc = BLE_LL_SCHED_STATE_DONE; - ble_ll_event_send(&sm->sync_ev_end); - ble_ll_sync_current_sm_over(); - } else { - /* - * Clear flag that tells to set last anchor point if a packet - * has been received, this is chain and we don't need it. - */ - sm->flags &= ~BLE_LL_SYNC_SM_FLAG_SET_ANCHOR; - - wfr_usecs = (sm->flags & BLE_LL_SYNC_SM_FLAG_OFFSET_300) ? 300 : 30; - - ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, wfr_usecs); - rc = BLE_LL_SCHED_STATE_RUNNING; - } - - return rc; -} - -static int -ble_ll_sync_schedule_chain(struct ble_ll_sync_sm *sm, struct ble_mbuf_hdr *hdr, - const uint8_t *aux) -{ - uint8_t offset_units; - uint32_t offset; - uint8_t chan; - uint8_t phy; - - ble_ll_sync_parse_aux_ptr(aux, &chan, &offset, &offset_units, &phy); - - if (chan >= BLE_PHY_NUM_DATA_CHANS) { - return -1; - } - - if (offset < BLE_LL_MAFS) { - return -1; - } - - /* chain should use same PHY as master PDU */ - if (phy != ble_ll_sync_phy_mode_to_aux_phy(sm->phy_mode)) { - return -1; - } - - if (offset_units) { - sm->flags |= BLE_LL_SYNC_SM_FLAG_OFFSET_300; - } else { - sm->flags &= ~BLE_LL_SYNC_SM_FLAG_OFFSET_300; - } - - sm->chan_chain = chan; - - sm->sch.sched_cb = ble_ll_sync_chain_start_cb; - sm->sch.cb_arg = sm; - sm->sch.sched_type = BLE_LL_SCHED_TYPE_SYNC; - - return ble_ll_sched_sync(&sm->sch, hdr->beg_cputime, hdr->rem_usecs, - offset, sm->phy_mode); -} - -static void -ble_ll_sync_established(struct ble_ll_sync_sm *sm) -{ - BLE_LL_ASSERT(sm->sync_pending_cnt); - - /* mark as established */ - - sm->flags |= BLE_LL_SYNC_SM_FLAG_ESTABLISHED; - sm->flags &= ~BLE_LL_SYNC_SM_FLAG_ESTABLISHING; - - sm->sync_pending_cnt = 0; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - if (sm->transfer_conn) { - ble_ll_sync_transfer_received(sm, BLE_ERR_SUCCESS); - return; - } -#endif - - ble_ll_sync_est_event_success(sm); -} - -static void -ble_ll_sync_check_failed(struct ble_ll_sync_sm *sm) -{ - BLE_LL_ASSERT(sm->sync_pending_cnt); - - /* if we can retry on next event */ - if (--sm->sync_pending_cnt) { - return; - } - - sm->flags &= ~BLE_LL_SYNC_SM_FLAG_ESTABLISHING; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - if (sm->transfer_conn) { - ble_ll_sync_transfer_received(sm, BLE_ERR_CONN_ESTABLISHMENT); - return; - } -#endif - - ble_ll_sync_est_event_failed(BLE_ERR_CONN_ESTABLISHMENT); -} - -void -ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) -{ - struct ble_ll_sync_sm *sm = hdr->rxinfo.user_data; - bool aux_scheduled = false; - int8_t tx_power = 127; /* defaults to not available */ - uint8_t *aux = NULL; - int datalen; - - BLE_LL_ASSERT(sm); - - /* this could happen if sync was cancelled or terminated while pkt_in was - * already in LL queue, just drop in that case - */ - if (!sm->flags) { - ble_ll_scan_chk_resume(); - ble_ll_rfmgmt_release(); - return; - } - - /* Set anchor point (and last) if 1st rxd frame in sync event. - * According to spec this should be done even if CRC is not valid so we - * can store it here - */ - if (sm->flags & BLE_LL_SYNC_SM_FLAG_SET_ANCHOR) { - sm->flags &= ~BLE_LL_SYNC_SM_FLAG_SET_ANCHOR; - - sm->anchor_point = hdr->beg_cputime; - sm->anchor_point_usecs = hdr->rem_usecs; - sm->last_anchor_point = sm->anchor_point; - } - - /* CRC error, end event */ - if (!BLE_MBUF_HDR_CRC_OK(hdr)) { - STATS_INC(ble_ll_stats, sync_crc_err); - goto end_event; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - /* save last pa counter */ - sm->event_cntr_last_received = sm->event_cntr; -#endif - - /* this means we are chaining but due to low buffers already sent data - * truncated report to host (or didn't sent any at all). If this happens - * next_buf should be already set to NULL and we just end event. - */ - if (sm->flags & BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED) { - BLE_LL_ASSERT(!sm->next_report); - goto end_event; - } - - if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT) && - !(sm->flags & BLE_LL_SYNC_SM_FLAG_DISABLED)) { - /* get ext header data */ - datalen = ble_ll_sync_parse_ext_hdr(rxpdu, &aux, &tx_power); - if (datalen < 0) { - /* we got bad packet, end event */ - goto end_event; - } - - /* if aux is present, we need to schedule ASAP */ - if (aux && (ble_ll_sync_schedule_chain(sm, hdr, aux) == 0)) { - aux_scheduled = true; - } - - /* in case data reporting is enabled we need to send sync established here */ - if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) { - ble_ll_sync_established(sm); - } - - /* Adjust rxpdu to contain advertising data only */ - ble_ll_sync_adjust_ext_hdr(rxpdu); - - /* send reports from this PDU */ - ble_ll_sync_send_per_adv_rpt(sm, rxpdu, hdr->rxinfo.rssi, tx_power, - datalen, aux, aux_scheduled); - } else { - /* we need to establish link even if reporting was disabled */ - if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) { - ble_ll_sync_established(sm); - } - } - - /* if chain was scheduled we don't end event yet */ - /* TODO should we check resume only if offset is high? */ - if (aux_scheduled) { - ble_ll_scan_chk_resume(); - ble_ll_rfmgmt_release(); - return; - } - -end_event: - ble_ll_event_send(&sm->sync_ev_end); - ble_ll_rfmgmt_release(); -} - -static int -ble_ll_sync_next_event(struct ble_ll_sync_sm *sm, uint32_t cur_ww_adjust) -{ - uint32_t cur_ww; - uint32_t max_ww; - uint32_t ticks; - uint32_t itvl; - uint8_t usecs; - uint16_t skip = sm->skip; - - /* don't skip if are establishing sync or we missed last event */ - if (skip && ((sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) || - CPUTIME_LT(sm->last_anchor_point, sm->anchor_point))) { - skip = 0; - } - - /* Set next event start time, we can use pre-calculated values for one - * interval if not skipping - */ - if (skip == 0) { - ticks = sm->itvl_ticks; - usecs = sm->itvl_usecs; - } else { - itvl = sm->itvl * BLE_LL_SYNC_ITVL_USECS * (1 + skip); - ticks = os_cputime_usecs_to_ticks(itvl); - usecs = itvl - os_cputime_ticks_to_usecs(ticks); - } - - sm->anchor_point += ticks; - sm->anchor_point_usecs += usecs; - if (sm->anchor_point_usecs >= 31) { - sm->anchor_point++; - sm->anchor_point_usecs -= 31; - } - - /* Set event counter to the next event */ - sm->event_cntr += 1 + skip; - - /* Calculate channel index of next event */ - sm->chan_index = ble_ll_utils_calc_dci_csa2(sm->event_cntr, sm->channel_id, - sm->num_used_chans, sm->chanmap); - - cur_ww = ble_ll_utils_calc_window_widening(sm->anchor_point, - sm->last_anchor_point, - sm->sca); - - cur_ww += cur_ww_adjust; - - max_ww = (sm->itvl * (BLE_LL_SYNC_ITVL_USECS / 2)) - BLE_LL_IFS; - if (cur_ww >= max_ww) { - return -1; - } - - cur_ww += BLE_LL_JITTER_USECS; - - /* if updated anchor is pass last anchor + timeout it means we will not be - * able to get it in time and hit sync timeout - * - * note that this may result in sync timeout being sent before real - * timeout but we won't be able to fit in time anyway.. - * - * We don't do that when establishing since we try up to - * BLE_LL_SYNC_ESTABLISH_CNT events before failing regardless of timeout - */ - if (!(sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING)) { - if (CPUTIME_GT(sm->anchor_point - os_cputime_usecs_to_ticks(cur_ww), - sm->last_anchor_point + sm->timeout )) { - return -1; - } - } - - sm->window_widening = cur_ww; - - return 0; -} - -static void -ble_ll_sync_event_end(struct ble_npl_event *ev) -{ - struct ble_ll_sync_sm *sm; - - /* Better be a connection state machine! */ - sm = ble_npl_event_get_arg(ev); - BLE_LL_ASSERT(sm); - - ble_ll_rfmgmt_release(); - - if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) { - ble_ll_sync_check_failed(sm); - } - - /* Check if we need to resume scanning */ - ble_ll_scan_chk_resume(); - - /* Remove any end events that might be enqueued */ - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &sm->sync_ev_end); - - /* don't schedule next event if sync is not established nor establishing - * at this point SM is no longer valid - */ - if (!(sm->flags & (BLE_LL_SYNC_SM_FLAG_ESTABLISHED | - BLE_LL_SYNC_SM_FLAG_ESTABLISHING))) { - ble_ll_sync_sm_clear(sm); - return; - } - - /* if we had prepared buffer for next even it means we were chaining and - * must send truncated report to host - */ - if (sm->next_report) { - BLE_LL_ASSERT(!(sm->flags & BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED)); - ble_ll_sync_send_truncated_per_adv_rpt(sm, sm->next_report); - sm->next_report = NULL; - } - - /* Event ended so we are no longer chaining */ - sm->flags &= ~BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED; - - sm->sch.sched_cb = ble_ll_sync_event_start_cb; - sm->sch.cb_arg = sm; - sm->sch.sched_type = BLE_LL_SCHED_TYPE_SYNC; - - do { - if (ble_ll_sync_next_event(sm, 0) < 0) { - if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) { - /* don't allow any retry if this failed */ - sm->sync_pending_cnt = 1; - ble_ll_sync_check_failed(sm); - } else { - ble_ll_sync_lost_event(sm); - } - - /* at this point SM is no longer valid */ - ble_ll_sync_sm_clear(sm); - return; - } - } while (ble_ll_sched_sync_reschedule(&sm->sch, sm->anchor_point, - sm->anchor_point_usecs, - sm->window_widening, sm->phy_mode)); -} - -void -ble_ll_sync_info_event(const uint8_t *addr, uint8_t addr_type, int rpa_index, - uint8_t sid, struct ble_mbuf_hdr *rxhdr, - const uint8_t *syncinfo) -{ - struct ble_ll_sync_sm *sm = NULL; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - const uint8_t *rpa = NULL; -#endif - uint16_t max_skip; - uint32_t offset; - uint32_t usecs; - uint16_t itvl; - int i; - - /* ignore if not synchronizing */ - if (!g_ble_ll_sync_create_comp_ev) { - return; - } - - /* get reserved SM */ - for (i = 0; i < BLE_LL_SYNC_CNT; i++) { - if (g_ble_ll_sync_sm[i].flags & BLE_LL_SYNC_SM_FLAG_RESERVED) { - sm = &g_ble_ll_sync_sm[i]; - break; - } - } - - /* this means we already got sync info event and pending sync */ - if (!sm) { - return; - } - - /* check if resolved */ - if (rpa_index >= 0) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - rpa = addr; -#endif - addr = g_ble_ll_resolv_list[rpa_index].rl_identity_addr; - addr_type = g_ble_ll_resolv_list[rpa_index].rl_addr_type; - } - - /* check peer */ - if (g_ble_ll_sync_create_params.options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER) { - if (ble_ll_sync_on_list(addr, addr_type, sid) < 0) { - return; - } - - /* set addr and sid in sm */ - sm->adv_sid = sid; - sm->adv_addr_type = addr_type; - memcpy(sm->adv_addr, addr, BLE_DEV_ADDR_LEN); - } else { - if ((sm->adv_sid != sid) || (sm->adv_addr_type != addr_type) || - memcmp(sm->adv_addr, addr, BLE_DEV_ADDR_LEN)) { - return; - } - } - - /* Sync Packet Offset (13 bits), Offset Units (1 bit), RFU (2 bits) */ - offset = syncinfo[0]; - offset |= (uint16_t)(syncinfo[1] & 0x1f) << 8; - - /* ignore if offset is not valid */ - if (!offset) { - return; - } - - /* Interval (2 bytes), ignore if invalid */ - itvl = get_le16(&syncinfo[2]); - if (itvl < 6) { - return; - } - - if (rpa_index >= 0) { - sm->flags |= BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - memcpy(sm->adv_addr_rpa, rpa, BLE_DEV_ADDR_LEN); -#endif - } - - /* set params from HCI LE Create Periodic Sync */ - sm->timeout = g_ble_ll_sync_create_params.timeout; - sm->skip = g_ble_ll_sync_create_params.max_skip; - sm->sync_pending_cnt = BLE_LL_SYNC_ESTABLISH_CNT; - - if (syncinfo[1] & 0x20) { - offset *= 300; - sm->flags |= BLE_LL_SYNC_SM_FLAG_OFFSET_300; - } else { - offset *= 30; - sm->flags &= ~BLE_LL_SYNC_SM_FLAG_OFFSET_300; - } - - /* sync end event */ - ble_npl_event_init(&sm->sync_ev_end, ble_ll_sync_event_end, sm); - - sm->itvl = itvl; - - /* precalculate interval ticks and usecs */ - usecs = sm->itvl * BLE_LL_SYNC_ITVL_USECS; - sm->itvl_ticks = os_cputime_usecs_to_ticks(usecs); - sm->itvl_usecs = (uint8_t)(usecs - - os_cputime_ticks_to_usecs(sm->itvl_ticks)); - if (sm->itvl_usecs == 31) { - sm->itvl_usecs = 0; - sm->itvl_ticks++; - } - - /* Channels Mask (37 bits) */ - sm->chanmap[0] = syncinfo[4]; - sm->chanmap[1] = syncinfo[5]; - sm->chanmap[2] = syncinfo[6]; - sm->chanmap[3] = syncinfo[7]; - sm->chanmap[4] = syncinfo[8] & 0x1f; - sm->num_used_chans = ble_ll_utils_calc_num_used_chans(sm->chanmap); - - /* SCA (3 bits) */ - sm->sca = syncinfo[8] >> 5; - - /* AA (4 bytes) */ - sm->access_addr = get_le32(&syncinfo[9]); - sm->channel_id = ((sm->access_addr & 0xffff0000) >> 16) ^ - (sm->access_addr & 0x0000ffff); - - /* CRCInit (3 bytes) */ - sm->crcinit = syncinfo[15]; - sm->crcinit = (sm->crcinit << 8) | syncinfo[14]; - sm->crcinit = (sm->crcinit << 8) | syncinfo[13]; - - /* Event Counter (2 bytes) */ - sm->event_cntr = get_le16(&syncinfo[16]); - - /* adjust skip if pass timeout */ - max_skip = get_max_skip(sm->itvl * BLE_LL_SYNC_ITVL_USECS, sm->timeout); - if (sm->skip > max_skip) { - sm->skip = max_skip; - } - - /* from now on we only need timeout in ticks */ - sm->timeout = os_cputime_usecs_to_ticks(sm->timeout); - - sm->phy_mode = rxhdr->rxinfo.phy_mode; - sm->window_widening = BLE_LL_JITTER_USECS; - - /* Calculate channel index of first event */ - sm->chan_index = ble_ll_utils_calc_dci_csa2(sm->event_cntr, sm->channel_id, - sm->num_used_chans, sm->chanmap); - - sm->sch.sched_cb = ble_ll_sync_event_start_cb; - sm->sch.cb_arg = sm; - sm->sch.sched_type = BLE_LL_SCHED_TYPE_SYNC; - - if (ble_ll_sched_sync(&sm->sch, rxhdr->beg_cputime, rxhdr->rem_usecs, - offset, sm->phy_mode)) { - return; - } - - sm->anchor_point = sm->sch.start_time + g_ble_ll_sched_offset_ticks; - sm->anchor_point_usecs = sm->sch.remainder; - sm->last_anchor_point = sm->anchor_point; - -#if MYNEWT_VAL(BLE_VERSION) >= 51 - if (g_ble_ll_sync_create_params.options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DISABLED) { - sm->flags |= BLE_LL_SYNC_SM_FLAG_DISABLED; - } -#endif - - sm->flags &= ~BLE_LL_SYNC_SM_FLAG_RESERVED; - sm->flags |= BLE_LL_SYNC_SM_FLAG_ESTABLISHING; - sm->flags |= BLE_LL_SYNC_SM_FLAG_SYNC_INFO; -} - -static struct ble_ll_sync_sm * -ble_ll_sync_reserve(void) -{ - struct ble_ll_sync_sm *sm; - int i; - - for (i = 0; i < BLE_LL_SYNC_CNT; i++) { - sm = &g_ble_ll_sync_sm[i]; - - if (!sm->flags) { - sm->flags |= BLE_LL_SYNC_SM_FLAG_RESERVED; - return sm; - } - } - - return NULL; -} - -int -ble_ll_sync_create(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_periodic_adv_create_sync_cp *cmd = (const void *) cmdbuf; - struct ble_ll_sync_sm *sm; - uint16_t timeout; - os_sr_t sr; - - if (g_ble_ll_sync_create_comp_ev) { - return BLE_ERR_CMD_DISALLOWED; - } - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - -#if MYNEWT_VAL(BLE_VERSION) >= 51 - if (cmd->options > BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DISABLED) { -#else - if (cmd->options > BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER) { -#endif - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (cmd->skip > 0x01f3) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - timeout = le16toh(cmd->sync_timeout); - if (timeout < 0x000a || timeout > 0x4000) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - -#if MYNEWT_VAL(BLE_VERSION) >= 51 - /* we don't support any CTE yet */ - if (cmd->sync_cte_type) { - if (cmd->sync_cte_type > 4) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return BLE_ERR_UNSUPPORTED; - } -#endif - - if (cmd->options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER) { - if (ble_ll_sync_list_empty()) { - return BLE_ERR_CMD_DISALLOWED; - } - } else { - if (cmd->sid > 0x0f) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (cmd->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - OS_ENTER_CRITICAL(sr); - sm = ble_ll_sync_find(cmd->peer_addr, cmd->peer_addr_type, cmd->sid); - OS_EXIT_CRITICAL(sr); - - if (sm) { - return BLE_ERR_ACL_CONN_EXISTS; - } - } - - /* reserve buffer for sync complete event */ - g_ble_ll_sync_create_comp_ev = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (!g_ble_ll_sync_create_comp_ev) { - return BLE_ERR_MEM_CAPACITY; - } - - OS_ENTER_CRITICAL(sr); - - /* reserve 1 SM for created sync */ - sm = ble_ll_sync_reserve(); - if (!sm) { - ble_hci_trans_buf_free(g_ble_ll_sync_create_comp_ev); - g_ble_ll_sync_create_comp_ev = NULL; - OS_EXIT_CRITICAL(sr); - return BLE_ERR_MEM_CAPACITY; - } - - /* if we don't use list, store expected address in reserved SM */ - if (!(cmd->options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER)) { - sm->adv_sid = cmd->sid; - sm->adv_addr_type = cmd->peer_addr_type; - memcpy(&sm->adv_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); - } - - g_ble_ll_sync_create_params.timeout = timeout * 10000; /* 10ms units, store in us */; - g_ble_ll_sync_create_params.max_skip = cmd->skip; - g_ble_ll_sync_create_params.options = cmd->options; - - OS_EXIT_CRITICAL(sr); - return BLE_ERR_SUCCESS; -} - -static void -ble_ll_sync_cancel_complete_event(void) -{ - ble_ll_sync_est_event_failed(BLE_ERR_OPERATION_CANCELLED); -} - -int -ble_ll_sync_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb) -{ - struct ble_ll_sync_sm *sm; - os_sr_t sr; - int i; - - if (!g_ble_ll_sync_create_comp_ev) { - return BLE_ERR_CMD_DISALLOWED; - } - - OS_ENTER_CRITICAL(sr); - - for (i = 0; i < BLE_LL_SYNC_CNT; i++) { - sm = &g_ble_ll_sync_sm[i]; - - /* cancelled before fist sync info packet */ - if (sm->flags & BLE_LL_SYNC_SM_FLAG_RESERVED) { - memset(sm, 0, sizeof(*sm)); - break; - } - - /* cancelled while pending sync */ - if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) { - ble_ll_sync_sm_clear(sm); - break; - } - } - - OS_EXIT_CRITICAL(sr); - - /* g_ble_ll_sync_create_comp_ev will be cleared by this callback */ - *post_cmd_cb = ble_ll_sync_cancel_complete_event; - - return BLE_ERR_SUCCESS; -} - -int -ble_ll_sync_terminate(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_periodic_adv_term_sync_cp *cmd = (const void *) cmdbuf; - struct ble_ll_sync_sm *sm; - uint16_t handle; - os_sr_t sr; - - if (g_ble_ll_sync_create_comp_ev) { - return BLE_ERR_CMD_DISALLOWED; - } - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - handle = le16toh(cmd->sync_handle); - if (handle > 0xeff) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (handle >= BLE_LL_SYNC_CNT) { - return BLE_ERR_UNK_ADV_INDENT; - } - - sm = &g_ble_ll_sync_sm[handle]; - - OS_ENTER_CRITICAL(sr); - - if (!(sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHED)) { - OS_EXIT_CRITICAL(sr); - return BLE_ERR_UNK_ADV_INDENT; - } - - ble_ll_sync_sm_clear(sm); - - OS_EXIT_CRITICAL(sr); - - return BLE_ERR_SUCCESS; -} - -int -ble_ll_sync_list_add(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_add_dev_to_periodic_adv_list_cp *cmd = (const void *)cmdbuf; - int i; - - if (g_ble_ll_sync_create_comp_ev) { - return BLE_ERR_CMD_DISALLOWED; - } - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (cmd->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - if (cmd->sid > 0x0f) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - i = ble_ll_sync_on_list(cmd->peer_addr, cmd->peer_addr_type, cmd->sid); - if (i >= 0) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - i = ble_ll_sync_list_get_free(); - if (i < 0) { - return BLE_ERR_MEM_CAPACITY; - } - - g_ble_ll_sync_adv_list[i].adv_sid = cmd->sid; - g_ble_ll_sync_adv_list[i].adv_addr_type = cmd->peer_addr_type; - memcpy(&g_ble_ll_sync_adv_list[i].adv_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); - - return BLE_ERR_SUCCESS; -} - -int -ble_ll_sync_list_remove(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_rem_dev_from_periodic_adv_list_cp *cmd = (const void *)cmdbuf; - int i; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (g_ble_ll_sync_create_comp_ev) { - return BLE_ERR_CMD_DISALLOWED; - } - - if (cmd->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (cmd->sid > 0x0f) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - i = ble_ll_sync_on_list(cmd->peer_addr, cmd->peer_addr_type, cmd->sid); - if (i < 0) { - return BLE_ERR_UNK_ADV_INDENT; - } - - memset(&g_ble_ll_sync_adv_list[i], 0, sizeof(g_ble_ll_sync_adv_list[i])); - g_ble_ll_sync_adv_list[i].adv_sid = 0xff; - - return BLE_ERR_SUCCESS; -} - -int -ble_ll_sync_list_clear(void) -{ - int i; - - if (g_ble_ll_sync_create_comp_ev) { - return BLE_ERR_CMD_DISALLOWED; - } - - for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { - memset(&g_ble_ll_sync_adv_list[i], 0, sizeof(g_ble_ll_sync_adv_list[i])); - g_ble_ll_sync_adv_list[i].adv_sid = 0xff; - } - - return BLE_ERR_SUCCESS; -} - -int -ble_ll_sync_list_size(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_le_rd_periodic_adv_list_size_rp *rsp = (void *) rspbuf; - - rsp->list_size = ARRAY_SIZE(g_ble_ll_sync_adv_list); - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} - -#if MYNEWT_VAL(BLE_VERSION) >= 51 -int -ble_ll_sync_receive_enable(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_periodic_adv_receive_enable_cp *cmd = (const void *)cmdbuf; - struct ble_ll_sync_sm *sm; - uint16_t handle; - os_sr_t sr; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (cmd->enable > 0x01) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - handle = le16toh(cmd->sync_handle); - if (handle > 0xeff) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (handle >= BLE_LL_SYNC_CNT) { - return BLE_ERR_UNK_ADV_INDENT; - } - - sm = &g_ble_ll_sync_sm[handle]; - - OS_ENTER_CRITICAL(sr); - - if (!(sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHED)) { - OS_EXIT_CRITICAL(sr); - return BLE_ERR_UNK_ADV_INDENT; - } - - if (cmd->enable) { - sm->flags &= ~BLE_LL_SYNC_SM_FLAG_DISABLED; - } else { - sm->flags |= BLE_LL_SYNC_SM_FLAG_DISABLED; - } - - OS_EXIT_CRITICAL(sr); - return BLE_ERR_SUCCESS; -} -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -static struct ble_ll_sync_sm * -ble_ll_sync_transfer_get(const uint8_t *addr, uint8_t addr_type, uint8_t sid) -{ - struct ble_ll_sync_sm *sm; - int i; - - for (i = 0; i < BLE_LL_SYNC_CNT; i++) { - sm = &g_ble_ll_sync_sm[i]; - - if (!sm->flags) { - /* allocate event for transfer received event */ - sm->transfer_received_ev = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (!sm->transfer_received_ev) { - break; - } - - sm->adv_sid = sid; - sm->adv_addr_type = addr_type; - memcpy(&sm->adv_addr, addr, BLE_DEV_ADDR_LEN); - - sm->flags |= BLE_LL_SYNC_SM_FLAG_ESTABLISHING; - return sm; - } - } - - return NULL; -} - -void -ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, - const uint8_t *sync_ind, bool reports_disabled, - uint16_t max_skip, uint32_t sync_timeout) -{ - const uint8_t *syncinfo = sync_ind + 2; - uint16_t sync_conn_event_count; - uint16_t last_pa_event_count; - struct ble_ll_sync_sm *sm; - uint16_t conn_event_count; - uint8_t sync_anchor_usecs; - const uint8_t *rpa = NULL; - int last_pa_diff; - uint32_t sync_anchor; - const uint8_t *addr; - uint16_t event_cntr; - uint32_t itvl_usecs; - uint32_t ww_adjust; - uint8_t addr_type; - uint8_t phy_mode; - uint32_t offset; - uint32_t future; - uint16_t itvl; - int rpa_index; - uint8_t sid; - uint8_t sca; - os_sr_t sr; - - phy_mode = ble_ll_ctrl_phy_from_phy_mask(sync_ind[25]); - itvl = get_le16(syncinfo + 2); - /* ignore if sync params are not valid */ - if ((phy_mode == 0) || (itvl < 6)) { - return; - } - - last_pa_event_count = get_le16(sync_ind + 22); - event_cntr = get_le16(syncinfo + 16); - itvl_usecs = itvl * BLE_LL_SYNC_ITVL_USECS; - - last_pa_diff = abs((int16_t)(event_cntr - last_pa_event_count)); - /* check if not 5 seconds apart, if so ignore sync transfer */ - if ((last_pa_diff * itvl_usecs) > 5000000) { - return; - } - - sid = (sync_ind[24] & 0x0f); - addr_type = (sync_ind[24] & 0x10) ? BLE_ADDR_RANDOM : BLE_ADDR_PUBLIC; - addr = sync_ind + 26; - - rpa_index = -1; - - /* check if need to resolve */ - if (ble_ll_is_rpa(addr, addr_type)) { - rpa_index = ble_ll_resolv_peer_rpa_any(addr); - if (rpa_index >= 0) { - rpa = addr; - addr = g_ble_ll_resolv_list[rpa_index].rl_identity_addr; - addr_type = g_ble_ll_resolv_list[rpa_index].rl_addr_type; - } - } - - OS_ENTER_CRITICAL(sr); - /* check if already synchronized with this peer */ - sm = ble_ll_sync_find(addr, addr_type, sid); - if (sm) { - OS_EXIT_CRITICAL(sr); - return; - } - - /* ignore if no memory for new sync */ - sm = ble_ll_sync_transfer_get(addr, addr_type, sid); - if (!sm) { - OS_EXIT_CRITICAL(sr); - return; - } - - OS_EXIT_CRITICAL(sr); - - if (rpa_index >= 0) { - sm->flags |= BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED; - memcpy(sm->adv_addr_rpa, rpa, BLE_DEV_ADDR_LEN); - } - - /* set params from transfer */ - sm->timeout = os_cputime_usecs_to_ticks(sync_timeout); - sm->skip = max_skip; - sm->sync_pending_cnt = BLE_LL_SYNC_ESTABLISH_CNT; - sm->transfer_id = get_le16(sync_ind); /* first two bytes */ - sm->transfer_conn = connsm; - - /* Sync Packet Offset (13 bits), Offset Units (1 bit), Offset Adjust (1 bit), - * RFU (1 bit) - */ - offset = syncinfo[0]; - offset |= (uint16_t)(syncinfo[1] & 0x1f) << 8; - - if (syncinfo[1] & 0x20) { - if (syncinfo[1] & 0x40) { - offset += 0x2000; - } - - offset *= 300; - sm->flags |= BLE_LL_SYNC_SM_FLAG_OFFSET_300; - } else { - offset *= 30; - sm->flags &= ~BLE_LL_SYNC_SM_FLAG_OFFSET_300; - } - - /* sync end event */ - ble_npl_event_init(&sm->sync_ev_end, ble_ll_sync_event_end, sm); - - sm->itvl = itvl; - - /* precalculate interval ticks and usecs */ - sm->itvl_ticks = os_cputime_usecs_to_ticks(itvl_usecs); - sm->itvl_usecs = (uint8_t)(itvl_usecs - - os_cputime_ticks_to_usecs(sm->itvl_ticks)); - if (sm->itvl_usecs == 31) { - sm->itvl_usecs = 0; - sm->itvl_ticks++; - } - - /* Channels Mask (37 bits) */ - sm->chanmap[0] = syncinfo[4]; - sm->chanmap[1] = syncinfo[5]; - sm->chanmap[2] = syncinfo[6]; - sm->chanmap[3] = syncinfo[7]; - sm->chanmap[4] = syncinfo[8] & 0x1f; - sm->num_used_chans = ble_ll_utils_calc_num_used_chans(sm->chanmap); - - /* SCA (3 bits) */ - sm->sca = syncinfo[8] >> 5; - - /* AA (4 bytes) */ - sm->access_addr = get_le32(syncinfo + 9); - sm->channel_id = ((sm->access_addr & 0xffff0000) >> 16) ^ - (sm->access_addr & 0x0000ffff); - - /* CRCInit (3 bytes) */ - sm->crcinit = syncinfo[13]; - sm->crcinit |= syncinfo[14] << 8; - sm->crcinit |= syncinfo[15] << 16; - - /* Event Counter (2 bytes) */ - sm->event_cntr = event_cntr; - - /* adjust skip if pass timeout */ - max_skip = get_max_skip(sm->itvl * BLE_LL_SYNC_ITVL_USECS, sync_timeout); - if (sm->skip > max_skip) { - sm->skip = max_skip; - } - - sm->phy_mode = phy_mode; - - /* Calculate channel index of first event */ - sm->chan_index = ble_ll_utils_calc_dci_csa2(sm->event_cntr, sm->channel_id, - sm->num_used_chans, sm->chanmap); - - sm->sch.sched_cb = ble_ll_sync_event_start_cb; - sm->sch.cb_arg = sm; - sm->sch.sched_type = BLE_LL_SCHED_TYPE_SYNC; - - /* get anchor for specified conn event */ - conn_event_count = get_le16(sync_ind + 20); - ble_ll_conn_get_anchor(connsm, conn_event_count, &sm->anchor_point, - &sm->anchor_point_usecs); - - /* Set last anchor point */ - sm->last_anchor_point = sm->anchor_point - (last_pa_diff * sm->itvl_ticks); - - /* calculate extra window widening */ - sync_conn_event_count = get_le16(sync_ind + 32); - sca = sync_ind[24] >> 5; - ble_ll_conn_get_anchor(connsm, sync_conn_event_count, &sync_anchor, - &sync_anchor_usecs); - ww_adjust = ble_ll_utils_calc_window_widening(connsm->anchor_point, - sync_anchor, sca); - - /* spin until we get anchor in future */ - future = os_cputime_get32() + g_ble_ll_sched_offset_ticks; - while (CPUTIME_LT(sm->anchor_point, future)) { - if (ble_ll_sync_next_event(sm, ww_adjust) < 0) { - /* release SM if this failed */ - ble_ll_sync_transfer_received(sm, BLE_ERR_CONN_ESTABLISHMENT); - memset(sm, 0, sizeof(*sm)); - return; - } - } - - if (ble_ll_sched_sync(&sm->sch, sm->anchor_point, sm->anchor_point_usecs, - offset, sm->phy_mode)) { - /* release SM if this failed */ - ble_ll_sync_transfer_received(sm, BLE_ERR_CONN_ESTABLISHMENT); - memset(sm, 0, sizeof(*sm)); - return; - } - - /* Set new anchor point */ - sm->anchor_point = sm->sch.start_time + g_ble_ll_sched_offset_ticks; - sm->anchor_point_usecs = sm->sch.remainder; - - if (reports_disabled) { - sm->flags |= BLE_LL_SYNC_SM_FLAG_DISABLED; - } -} - -static void -ble_ll_sync_put_syncinfo(struct ble_ll_sync_sm *syncsm, - struct ble_ll_conn_sm *connsm, uint8_t *conn_event_cnt, - uint8_t *dptr) -{ - uint8_t anchor_usecs; - uint16_t conn_cnt; - uint32_t offset; - uint32_t anchor; - uint8_t units; - - anchor = connsm->anchor_point; - anchor_usecs = connsm->anchor_point_usecs; - conn_cnt = connsm->event_cntr; - - /* get anchor for conn event that is before periodic_adv_event_start_time */ - while (CPUTIME_GT(anchor, syncsm->anchor_point)) { - ble_ll_conn_get_anchor(connsm, --conn_cnt, &anchor, &anchor_usecs); - } - - offset = os_cputime_ticks_to_usecs(syncsm->anchor_point - anchor); - offset -= anchor_usecs; - offset += syncsm->anchor_point_usecs; - - /* connEventCount */ - put_le16(conn_event_cnt, conn_cnt); - - /* Sync Packet Offset (13 bits), Offset Units (1 bit), Offset Adjust (1 bit), - * RFU (1 bit) - */ - if (offset > 245700) { - units = 0x20; - - if (offset >= 0x2000) { - offset -= 0x2000; - units |= 0x40; - } - - offset = offset / 300; - } else { - units = 0x00; - offset = offset / 30; - } - - dptr[0] = (offset & 0x000000ff); - dptr[1] = ((offset >> 8) & 0x0000001f) | units; - - /* Interval (2 bytes) */ - put_le16(&dptr[2], syncsm->itvl); - - /* Channels Mask (37 bits) */ - dptr[4] = syncsm->chanmap[0]; - dptr[5] = syncsm->chanmap[1]; - dptr[6] = syncsm->chanmap[2]; - dptr[7] = syncsm->chanmap[3]; - dptr[8] = syncsm->chanmap[4] & 0x1f; - - /* SCA (3 bits) */ - dptr[8] |= syncsm->sca << 5; - - /* AA (4 bytes) */ - put_le32(&dptr[9], syncsm->access_addr); - - /* CRCInit (3 bytes) */ - dptr[13] = (uint8_t)syncsm->crcinit; - dptr[14] = (uint8_t)(syncsm->crcinit >> 8); - dptr[15] = (uint8_t)(syncsm->crcinit >> 16); - - /* Event Counter (2 bytes) */ - put_le16(&dptr[16], syncsm->event_cntr); -} - -static int -ble_ll_sync_send_sync_ind(struct ble_ll_sync_sm *syncsm, - struct ble_ll_conn_sm *connsm, uint16_t service_data) -{ - struct os_mbuf *om; - uint8_t *sync_ind; - - om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN, - sizeof(struct ble_mbuf_hdr)); - if (!om) { - return BLE_ERR_MEM_CAPACITY; - } - - om->om_data[0] = BLE_LL_CTRL_PERIODIC_SYNC_IND; - - sync_ind = om->om_data + 1; - - /* ID (service_data), already in LE order */ - memcpy(sync_ind, &service_data, sizeof(service_data)); - - /* fill in syncinfo */ - ble_ll_sync_put_syncinfo(syncsm, connsm, sync_ind + 20, sync_ind + 2); - - /* lastPaEventCounter */ - put_le16(sync_ind + 22, syncsm->event_cntr_last_received); - - /* SID, AType, SCA */ - sync_ind[24] = syncsm->adv_sid; - - if (syncsm->flags & BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED) { - sync_ind[24] |= 1 << 4; - } else { - sync_ind[24] |= (syncsm->adv_addr_type == BLE_ADDR_RANDOM) << 4 ; - } - - sync_ind[24] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5; - - /* PHY */ - sync_ind[25] = (0x01 << (ble_ll_sync_phy_mode_to_hci(syncsm->phy_mode) - 1)); - - /* AdvA */ - if (syncsm->flags & BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED) { - memcpy(sync_ind + 26, syncsm->adv_addr_rpa, BLE_DEV_ADDR_LEN); - } else { - memcpy(sync_ind + 26, syncsm->adv_addr, BLE_DEV_ADDR_LEN); - } - - /* syncConnEventCount */ - put_le16(sync_ind + 32, connsm->event_cntr); - - ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, - BLE_LL_CTRL_PERIODIC_SYNC_IND_LEN + 1); - - return BLE_ERR_SUCCESS; -} - -int -ble_ll_sync_transfer(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_periodic_adv_sync_transfer_cp *cmd = (const void *)cmdbuf; - struct ble_hci_le_periodic_adv_sync_transfer_rp *rsp = (void *) rspbuf; - struct ble_ll_conn_sm *connsm; - struct ble_ll_sync_sm *sm; - uint16_t handle; - os_sr_t sr; - int rc; - - if (len != sizeof(*cmd)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - handle = le16toh(cmd->sync_handle); - if (handle > 0xeff) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - - if (handle >= BLE_LL_SYNC_CNT) { - rc = BLE_ERR_UNK_ADV_INDENT; - goto done; - } - - sm = &g_ble_ll_sync_sm[handle]; - - OS_ENTER_CRITICAL(sr); - - if (!(sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHED)) { - rc = BLE_ERR_UNK_ADV_INDENT; - OS_EXIT_CRITICAL(sr); - goto done; - } - - handle = le16toh(cmd->conn_handle); - if (handle > 0xeff) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - OS_EXIT_CRITICAL(sr); - goto done; - } - - connsm = ble_ll_conn_find_active_conn(handle); - if (!connsm) { - rc = BLE_ERR_UNK_CONN_ID; - OS_EXIT_CRITICAL(sr); - goto done; - } - - /* TODO should not need to shift - * byte 3 (0 byte is conn_feature) , bit 1 - * - * Allow initiate LL procedure only if remote supports it. - */ - if (!(connsm->remote_features[2] & (BLE_LL_FEAT_SYNC_TRANS_RECV >> (8 * 3)))) { - rc = BLE_ERR_UNSUPP_REM_FEATURE; - goto done; - } - - rc = ble_ll_sync_send_sync_ind(sm, connsm, cmd->service_data); - - OS_EXIT_CRITICAL(sr); -done: - rsp->conn_handle = cmd->conn_handle; - *rsplen = sizeof(*rsp); - return rc; -} -#endif - -/* - * Called when a sync scan event has been removed from the scheduler - * without being run. - */ -void -ble_ll_sync_rmvd_from_sched(struct ble_ll_sync_sm *sm) -{ - ble_ll_event_send(&sm->sync_ev_end); -} - -bool -ble_ll_sync_enabled(void) -{ - return g_ble_ll_sync_create_comp_ev != NULL; -} - -/** - * Called to reset the sync module. When this function is called the - * scheduler has been stopped and the phy has been disabled. The LL should - * be in the standby state. - */ -void -ble_ll_sync_reset(void) -{ - int i; - - for (i = 0; i < BLE_LL_SYNC_CNT; i++) { - ble_ll_sync_sm_clear(&g_ble_ll_sync_sm[i]); - } - - for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { - memset(&g_ble_ll_sync_adv_list[i], 0, sizeof(g_ble_ll_sync_adv_list[i])); - g_ble_ll_sync_adv_list[i].adv_sid = 0xff; - } - - g_ble_ll_sync_create_params.timeout = 0; - g_ble_ll_sync_create_params.max_skip = 0; - g_ble_ll_sync_create_params.options = 0; - - g_ble_ll_sync_sm_current = NULL; - - if (g_ble_ll_sync_create_comp_ev) { - ble_hci_trans_buf_free(g_ble_ll_sync_create_comp_ev); - g_ble_ll_sync_create_comp_ev = NULL; - } -} - -void -ble_ll_sync_init(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { - g_ble_ll_sync_adv_list[i].adv_sid = 0xff; - } -} -#endif -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_trace.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_trace.c deleted file mode 100644 index c5d2b1d41..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_trace.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os_trace_api.h" - -#if MYNEWT_VAL(BLE_LL_SYSVIEW) - -static os_trace_module_t g_ble_ll_trace_mod; -uint32_t ble_ll_trace_off; - -static void -ble_ll_trace_module_send_desc(void) -{ - os_trace_module_desc(&g_ble_ll_trace_mod, "0 ll_sched lls=%u cputime=%u start_time=%u"); - os_trace_module_desc(&g_ble_ll_trace_mod, "1 ll_rx_start lls=%u pdu_type=%x"); - os_trace_module_desc(&g_ble_ll_trace_mod, "2 ll_rx_end pdu_type=%x len=%u flags=%x"); - os_trace_module_desc(&g_ble_ll_trace_mod, "3 ll_wfr_timer_exp lls=%u xcvr=%u rx_start=%u"); - os_trace_module_desc(&g_ble_ll_trace_mod, "4 ll_ctrl_rx opcode=%u len=%u"); - os_trace_module_desc(&g_ble_ll_trace_mod, "5 ll_conn_ev_start conn_handle=%u"); - os_trace_module_desc(&g_ble_ll_trace_mod, "6 ll_conn_ev_end conn_handle=%u event_cntr=%u"); - os_trace_module_desc(&g_ble_ll_trace_mod, "7 ll_conn_end conn_handle=%u event_cntr=%u err=%u"); - os_trace_module_desc(&g_ble_ll_trace_mod, "8 ll_conn_tx len=%u offset=%u"); - os_trace_module_desc(&g_ble_ll_trace_mod, "9 ll_conn_rx conn_sn=%u pdu_nesn=%u"); - os_trace_module_desc(&g_ble_ll_trace_mod, "10 ll_adv_txdone inst=%u chanset=%x"); - os_trace_module_desc(&g_ble_ll_trace_mod, "11 ll_adv_halt inst=%u"); - os_trace_module_desc(&g_ble_ll_trace_mod, "12 ll_aux_ref aux=%p ref=%u"); - os_trace_module_desc(&g_ble_ll_trace_mod, "13 ll_aux_unref aux=%p ref=%u"); -} - -void -ble_ll_trace_init(void) -{ - ble_ll_trace_off = - os_trace_module_register(&g_ble_ll_trace_mod, "ble_ll", 12, - ble_ll_trace_module_send_desc); -} -#endif -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_utils.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_utils.c deleted file mode 100644 index 3814e58a8..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_utils.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include -#include "nimble/nimble/include/nimble/ble.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_utils.h" - -/* 37 bits require 5 bytes */ -#define BLE_LL_CHMAP_LEN (5) - -/* Sleep clock accuracy table (in ppm) */ -static const uint16_t g_ble_sca_ppm_tbl[8] = { - 500, 250, 150, 100, 75, 50, 30, 20 -}; - -uint32_t -ble_ll_utils_calc_access_addr(void) -{ - uint32_t aa; - uint16_t aa_low; - uint16_t aa_high; - uint32_t temp; - uint32_t mask; - uint32_t prev_bit; - uint8_t bits_diff; - uint8_t consecutive; - uint8_t transitions; - uint8_t ones; - int tmp; - - /* Calculate a random access address */ - aa = 0; - while (1) { - /* Get two, 16-bit random numbers */ - aa_low = rand() & 0xFFFF; - aa_high = rand() & 0xFFFF; - - /* All four bytes cannot be equal */ - if (aa_low == aa_high) { - continue; - } - - /* Upper 6 bits must have 2 transitions */ - tmp = (int16_t)aa_high >> 10; - if (__builtin_popcount(tmp ^ (tmp >> 1)) < 2) { - continue; - } - - /* Cannot be access address or be 1 bit different */ - aa = aa_high; - aa = (aa << 16) | aa_low; - bits_diff = 0; - temp = aa ^ BLE_ACCESS_ADDR_ADV; - for (mask = 0x00000001; mask != 0; mask <<= 1) { - if (mask & temp) { - ++bits_diff; - if (bits_diff > 1) { - break; - } - } - } - if (bits_diff <= 1) { - continue; - } - - /* Cannot have more than 24 transitions */ - transitions = 0; - consecutive = 1; - ones = 0; - mask = 0x00000001; - while (mask < 0x80000000) { - prev_bit = aa & mask; - mask <<= 1; - if (mask & aa) { - if (prev_bit == 0) { - ++transitions; - consecutive = 1; - } else { - ++consecutive; - } - } else { - if (prev_bit == 0) { - ++consecutive; - } else { - ++transitions; - consecutive = 1; - } - } - - if (prev_bit) { - ones++; - } - - /* 8 lsb should have at least three 1 */ - if (mask == 0x00000100 && ones < 3) { - break; - } - - /* 16 lsb should have no more than 11 transitions */ - if (mask == 0x00010000 && transitions > 11) { - break; - } - - /* This is invalid! */ - if (consecutive > 6) { - /* Make sure we always detect invalid sequence below */ - mask = 0; - break; - } - } - - /* Invalid sequence found */ - if (mask != 0x80000000) { - continue; - } - - /* Cannot be more than 24 transitions */ - if (transitions > 24) { - continue; - } - - /* We have a valid access address */ - break; - } - return aa; -} - -uint8_t -ble_ll_utils_remapped_channel(uint8_t remap_index, const uint8_t *chanmap) -{ - uint8_t cntr; - uint8_t mask; - uint8_t usable_chans; - uint8_t chan; - int i, j; - - /* NOTE: possible to build a map but this would use memory. For now, - * we just calculate - * Iterate through channel map to find this channel - */ - chan = 0; - cntr = 0; - for (i = 0; i < BLE_LL_CHMAP_LEN; i++) { - usable_chans = chanmap[i]; - if (usable_chans != 0) { - mask = 0x01; - for (j = 0; j < 8; j++) { - if (usable_chans & mask) { - if (cntr == remap_index) { - return (chan + j); - } - ++cntr; - } - mask <<= 1; - } - } - chan += 8; - } - - /* we should never reach here */ - BLE_LL_ASSERT(0); - return 0; -} - -uint8_t -ble_ll_utils_calc_num_used_chans(const uint8_t *chmap) -{ - int i; - int j; - uint8_t mask; - uint8_t chanbyte; - uint8_t used_channels; - - used_channels = 0; - for (i = 0; i < BLE_LL_CHMAP_LEN; ++i) { - chanbyte = chmap[i]; - if (chanbyte) { - if (chanbyte == 0xff) { - used_channels += 8; - } else { - mask = 0x01; - for (j = 0; j < 8; ++j) { - if (chanbyte & mask) { - ++used_channels; - } - mask <<= 1; - } - } - } - } - return used_channels; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) -static uint16_t -ble_ll_utils_csa2_perm(uint16_t in) -{ - uint16_t out = 0; - int i; - - for (i = 0; i < 8; i++) { - out |= ((in >> i) & 0x00000001) << (7 - i); - } - - for (i = 8; i < 16; i++) { - out |= ((in >> i) & 0x00000001) << (15 + 8 - i); - } - - return out; -} - -static uint16_t -ble_ll_utils_csa2_prng(uint16_t counter, uint16_t ch_id) -{ - uint16_t prn_e; - - prn_e = counter ^ ch_id; - - prn_e = ble_ll_utils_csa2_perm(prn_e); - prn_e = (prn_e * 17) + ch_id; - - prn_e = ble_ll_utils_csa2_perm(prn_e); - prn_e = (prn_e * 17) + ch_id; - - prn_e = ble_ll_utils_csa2_perm(prn_e); - prn_e = (prn_e * 17) + ch_id; - - prn_e = prn_e ^ ch_id; - - return prn_e; -} - -uint8_t -ble_ll_utils_calc_dci_csa2(uint16_t event_cntr, uint16_t channel_id, - uint8_t num_used_chans, const uint8_t *chanmap) -{ - uint16_t channel_unmapped; - uint8_t remap_index; - - uint16_t prn_e; - uint8_t bitpos; - - prn_e = ble_ll_utils_csa2_prng(event_cntr, channel_id); - - channel_unmapped = prn_e % 37; - - /* - * If unmapped channel is the channel index of a used channel it is used - * as channel index. - */ - bitpos = 1 << (channel_unmapped & 0x07); - if (chanmap[channel_unmapped >> 3] & bitpos) { - return channel_unmapped; - } - - remap_index = (num_used_chans * prn_e) / 0x10000; - - return ble_ll_utils_remapped_channel(remap_index, chanmap); -} -#endif - -uint32_t -ble_ll_utils_calc_window_widening(uint32_t anchor_point, - uint32_t last_anchor_point, - uint8_t master_sca) -{ - uint32_t total_sca_ppm; - uint32_t window_widening; - int32_t time_since_last_anchor; - uint32_t delta_msec; - - window_widening = 0; - - time_since_last_anchor = (int32_t)(anchor_point - last_anchor_point); - if (time_since_last_anchor > 0) { - delta_msec = os_cputime_ticks_to_usecs(time_since_last_anchor) / 1000; - total_sca_ppm = g_ble_sca_ppm_tbl[master_sca] + - MYNEWT_VAL(BLE_LL_OUR_SCA); - window_widening = (total_sca_ppm * delta_msec) / 1000; - } - - return window_widening; -} -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_whitelist.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_whitelist.c deleted file mode 100644 index 8b9251117..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_whitelist.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" - -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) -#include "nimble/nimble/drivers/nrf51/include/ble/xcvr.h" -#elif defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) -#include "nimble/nimble/drivers/nrf52/include/ble/xcvr.h" -#endif - -#include "../include/controller/ble_ll_whitelist.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_hw.h" - -#if (MYNEWT_VAL(BLE_LL_WHITELIST_SIZE) < BLE_HW_WHITE_LIST_SIZE) -#define BLE_LL_WHITELIST_SIZE MYNEWT_VAL(BLE_LL_WHITELIST_SIZE) -#else -#define BLE_LL_WHITELIST_SIZE BLE_HW_WHITE_LIST_SIZE -#endif - -struct ble_ll_whitelist_entry -{ - uint8_t wl_valid; - uint8_t wl_addr_type; - uint8_t wl_dev_addr[BLE_DEV_ADDR_LEN]; -}; - -struct ble_ll_whitelist_entry g_ble_ll_whitelist[BLE_LL_WHITELIST_SIZE]; - -static int -ble_ll_whitelist_chg_allowed(void) -{ - int rc; - - /* - * This command is not allowed if: - * -> advertising uses the whitelist and we are currently advertising. - * -> scanning uses the whitelist and is enabled. - * -> initiating uses whitelist and a LE create connection command is in - * progress - */ - rc = 1; - if (!ble_ll_adv_can_chg_whitelist() || !ble_ll_scan_can_chg_whitelist()) { - rc = 0; - } - return rc; -} - -/** - * Clear the whitelist. - * - * @return int 0: success, BLE error code otherwise - */ -int -ble_ll_whitelist_clear(void) -{ - int i; - struct ble_ll_whitelist_entry *wl; - - /* Check proper state */ - if (!ble_ll_whitelist_chg_allowed()) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* Set the number of entries to 0 */ - wl = &g_ble_ll_whitelist[0]; - for (i = 0; i < BLE_LL_WHITELIST_SIZE; ++i) { - wl->wl_valid = 0; - ++wl; - } - -#if (BLE_USES_HW_WHITELIST == 1) - ble_hw_whitelist_clear(); -#endif - - return BLE_ERR_SUCCESS; -} - -/** - * Read the size of the whitelist. This is the total number of whitelist - * entries allowed by the controller. - * - * @param rspbuf Pointer to response buffer - * - * @return int 0: success. - */ -int -ble_ll_whitelist_read_size(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_le_rd_white_list_rp *rsp = (void *) rspbuf; - - rsp->size = BLE_LL_WHITELIST_SIZE; - - *rsplen = sizeof(*rsp); - - return BLE_ERR_SUCCESS; -} - -/** - * Searches the whitelist to determine if the address is present in the - * whitelist. This is an internal API that only searches the link layer - * whitelist and does not care about the hardware whitelist - * - * @param addr Device or identity address to check. - * @param addr_type Public address (0) or random address (1) - * - * @return int 0: device is not on whitelist; otherwise the return value - * is the 'position' of the device in the whitelist (the index of the element - * plus 1). - */ -static int -ble_ll_whitelist_search(const uint8_t *addr, uint8_t addr_type) -{ - int i; - struct ble_ll_whitelist_entry *wl; - - wl = &g_ble_ll_whitelist[0]; - for (i = 0; i < BLE_LL_WHITELIST_SIZE; ++i) { - if ((wl->wl_valid) && (wl->wl_addr_type == addr_type) && - (!memcmp(&wl->wl_dev_addr[0], addr, BLE_DEV_ADDR_LEN))) { - return i + 1; - } - ++wl; - } - - return 0; -} - -/** - * Is there a match between the device and a device on the whitelist. - * - * NOTE: This API uses the HW, if present, to determine if there was a match - * between a received address and an address in the whitelist. If the HW does - * not support whitelisting this API is the same as the whitelist search API - * - * @param addr - * @param addr_type Public address (0) or random address (1) - * @param is_ident True if addr is an identity address; false otherwise - * - * @return int - */ -int -ble_ll_whitelist_match(uint8_t *addr, uint8_t addr_type, int is_ident) -{ - int rc; -#if (BLE_USES_HW_WHITELIST == 1) - /* - * XXX: This should be changed. This is HW specific: some HW may be able - * to both resolve a private address and perform a whitelist check. The - * current BLE hw cannot support this. - */ - if (is_ident) { - rc = ble_ll_whitelist_search(addr, addr_type); - } else { - rc = ble_hw_whitelist_match(); - } -#else - rc = ble_ll_whitelist_search(addr, addr_type); -#endif - return rc; -} - -/** - * Add a device to the whitelist - * - * @return int - */ -int -ble_ll_whitelist_add(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_add_whte_list_cp *cmd = (const void *) cmdbuf; - struct ble_ll_whitelist_entry *wl; - int rc; - int i; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Must be in proper state */ - if (!ble_ll_whitelist_chg_allowed()) { - return BLE_ERR_CMD_DISALLOWED; - } - - /* Check if we have any open entries */ - rc = BLE_ERR_SUCCESS; - if (!ble_ll_whitelist_search(cmd->addr, cmd->addr_type)) { - wl = &g_ble_ll_whitelist[0]; - for (i = 0; i < BLE_LL_WHITELIST_SIZE; ++i) { - if (wl->wl_valid == 0) { - memcpy(&wl->wl_dev_addr[0], cmd->addr, BLE_DEV_ADDR_LEN); - wl->wl_addr_type = cmd->addr_type; - wl->wl_valid = 1; - break; - } - ++wl; - } - - if (i == BLE_LL_WHITELIST_SIZE) { - rc = BLE_ERR_MEM_CAPACITY; - } else { -#if (BLE_USES_HW_WHITELIST == 1) - rc = ble_hw_whitelist_add(cmd->addr, cmd->addr_type); -#endif - } - } - - return rc; -} - -/** - * Remove a device from the whitelist - * - * @param cmdbuf - * - * @return int 0: success, BLE error code otherwise - */ -int -ble_ll_whitelist_rmv(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_rmv_white_list_cp *cmd = (const void *) cmdbuf; - int position; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Must be in proper state */ - if (!ble_ll_whitelist_chg_allowed()) { - return BLE_ERR_CMD_DISALLOWED; - } - - position = ble_ll_whitelist_search(cmd->addr, cmd->addr_type); - if (position) { - g_ble_ll_whitelist[position - 1].wl_valid = 0; - } - -#if (BLE_USES_HW_WHITELIST == 1) - ble_hw_whitelist_rmv(cmd->addr, cmd->addr_type); -#endif - - return BLE_ERR_SUCCESS; -} - -/** - * Enable whitelisting. - * - * Note: This function has no effect if we are not using HW whitelisting - */ -void -ble_ll_whitelist_enable(void) -{ -#if (BLE_USES_HW_WHITELIST == 1) - ble_hw_whitelist_enable(); -#endif -} - -/** - * Disable whitelisting. - * - * Note: This function has no effect if we are not using HW whitelisting - */ -void -ble_ll_whitelist_disable(void) -{ -#if (BLE_USES_HW_WHITELIST == 1) - ble_hw_whitelist_disable(); -#endif -} - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/syscfg.yml deleted file mode 100644 index 85049cb09..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/syscfg.yml +++ /dev/null @@ -1,434 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - BLE_CONTROLLER: - description: > - Indicates that NimBLE controller is present. The default value for - this setting shall not be overriden. - value: 1 - - BLE_HW_WHITELIST_ENABLE: - description: > - Used to enable hardware white list - value: 1 - - BLE_LL_SYSVIEW: - description: > - Enable SystemView tracing module for controller. - value: 0 - - BLE_LL_PRIO: - description: 'The priority of the LL task' - type: 'task_priority' - value: 0 - - # Sleep clock accuracy (sca). This is the amount of drift in the system - # during when the device is sleeping (in parts per million). - # - # NOTE: 'the' master sca is an enumerated value based on the sca. Rather - # than have a piece of code calculate this value, the developer must set - # this value based on the value of the SCA using the following table: - # - # SCA between 251 and 500 ppm (inclusive); master sca = 0 - # SCA between 151 and 250 ppm (inclusive); master sca = 1 - # SCA between 101 and 150 ppm (inclusive); master sca = 2 - # SCA between 76 and 100 ppm (inclusive); master sca = 3 - # SCA between 51 and 75 ppm (inclusive); master sca = 4 - # SCA between 31 and 50 ppm (inclusive); master sca = 5 - # SCA between 21 and 30 ppm (inclusive); master sca = 6 - # SCA between 0 and 20 ppm (inclusive); master sca = 7 - # - # For example: - # if your clock drift is 101 ppm, your master should be set to 2. - # if your clock drift is 20, your master sca should be set to 7. - # - # The values provided below are merely meant to be an example and should - # be replaced by values appropriate for your platform. - BLE_LL_OUR_SCA: - description: 'The system clock accuracy of the device.' - value: '60' # in ppm - - BLE_LL_MASTER_SCA: - description: 'Enumerated value based on our sca' - value: '4' - - BLE_LL_TX_PWR_DBM: - description: 'Transmit power level.' - value: '0' - - BLE_LL_NUM_COMP_PKT_ITVL_MS: - description: > - Determines the interval at which the controller will send the - number of completed packets event to the host. Rate is in milliseconds. - value: 2000 - - BLE_LL_MFRG_ID: - description: > - Manufacturer ID. Should be set to unique ID per manufacturer. - value: '0xFFFF' - - # Configuration items for the number of duplicate advertisers and the - # number of advertisers from which we have heard a scan response. - BLE_LL_NUM_SCAN_DUP_ADVS: - description: 'The number of duplicate advertisers stored.' - value: '8' - BLE_LL_NUM_SCAN_RSP_ADVS: - description: > - The number of advertisers from which we have heard a scan - response. Prevents sending duplicate events to host. - value: '8' - - BLE_LL_WHITELIST_SIZE: - description: 'Size of the LL whitelist.' - value: '8' - - BLE_LL_RESOLV_LIST_SIZE: - description: 'Size of the resolving list.' - value: '4' - - # Data length management definitions for connections. These define the - # maximum size of the PDU's that will be sent and/or received in a - # connection. - BLE_LL_MAX_PKT_SIZE: - description: 'The maximum PDU size that can be sent/received' - value: '251' - BLE_LL_SUPP_MAX_RX_BYTES: - description: 'The maximum supported received PDU size' - value: MYNEWT_VAL(BLE_LL_MAX_PKT_SIZE) - BLE_LL_SUPP_MAX_TX_BYTES: - description: 'The maximum supported transmit PDU size' - value: MYNEWT_VAL(BLE_LL_MAX_PKT_SIZE) - BLE_LL_CONN_INIT_MAX_TX_BYTES: - description: > - Used to set the initial maximum transmit PDU size in a - connection. If this is set to a value greater than 27, - the controller will automatically attempt to do the - data length update procedure. The host can always tell - the controller to update this value. - value: '27' - - # The number of slots that will be allocated to each connection - BLE_LL_CONN_INIT_SLOTS: - description: > - This is the number of "slots" allocated to a connection when scheduling - connections. Each slot is 1.25 msecs long. Note that a connection event may - last longer than the number of slots allocated here and may also end earlier - (depending on when the next scheduled event occurs and how much data needs - to be transferred in the connection). However, you will be guaranteed that - a connection event will be given this much time, if needed. Consecutively - scheduled items will be at least this far apart - value: '4' - - BLE_LL_CONN_INIT_MIN_WIN_OFFSET: - description: > - This is the minimum number of "slots" for WindowOffset value used for - CONNECT_IND when creating new connection as a master. Each slot is 1.25 - msecs long. Increasing this value will delay first connection event after - connection is created. However, older TI CC254x controllers cannot change - connection parameters later if WindowOffset was set to 0 in CONNECT_IND. To - ensure interoperability with such devices set this value to 2 (or more). - value: '0' - - # Strict scheduling - BLE_LL_STRICT_CONN_SCHEDULING: - description: > - Forces the scheduler on a central to schedule connections in fixed - time intervals called periods. If set to 0, the scheduler is not forced - to do this. If set to 1, the scheduler will only schedule connections at - period boundaries. See comments in ble_ll_sched.h for more details. - value: '0' - - BLE_LL_ADD_STRICT_SCHED_PERIODS: - description: > - The number of additional periods that will be allocated for strict - scheduling. The total # of periods allocated for strict scheduling - will be equal to the number of connections plus this number. - value: '0' - - BLE_LL_USECS_PER_PERIOD: - description: > - The number of usecs per period. - value: '3250' - - # The number of random bytes to store - BLE_LL_RNG_BUFSIZE: - description: > - The number of random bytes that the link layer will try to - always have available for the host to use. Decreasing this - value may cause host delays if the host needs lots of random - material often. - value: '32' - - BLE_LL_RFMGMT_ENABLE_TIME: - description: > - Time required for radio and/or related components to be fully - enabled before any request from LL is sent. This value is used - by rfmgmt to enable PHY in advance, before request from LL is - made. It depends on radio driver selected and may also depend - on hardware used: - - nrf51 - time required for XTAL to settle - - nrf52 - time required for XTAL to settle - Value is specified in microseconds. If set to 0, rfmgmt keeps - PHY enabled all the time. - value: MYNEWT_VAL(BLE_XTAL_SETTLE_TIME) - - # Configuration for LL supported features. - # - # There are a total 8 features that the LL can support. These can be found - # in v4.2, Vol 6 Part B Section 4.6. - # - # These feature definitions are used to inform a host or other controller - # about the LL features supported by the controller. - # - # NOTE: 'the' controller always supports extended reject indicate and thus - # is not listed here. - - - BLE_LL_CFG_FEAT_LE_ENCRYPTION: - description: > - This option enables/disables encryption support in the controller. - This option saves both both code and RAM. - value: '1' - - BLE_LL_CFG_FEAT_CONN_PARAM_REQ: - description: > - This option enables/disables the connection parameter request - procedure. This is implemented in the controller but is disabled - by default. - value: '1' - - BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG: - description: > - This option allows a slave to initiate the feature exchange - procedure. This feature is implemented but currently has no impact - on code or ram size - value: '1' - - BLE_LL_CFG_FEAT_LE_PING: - description: > - This option allows a controller to send/receive LE pings. - Currently, this feature is not implemented by the controller so - turning it on or off has no effect. - value: 'MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_ENCRYPTION' - - BLE_LL_CFG_FEAT_DATA_LEN_EXT: - description: > - This option enables/disables the data length update procedure in - the controller. If enabled, the controller is allowed to change the - size of tx/rx pdu's used in a connection. This option has only - minor impact on code size and non on RAM. - value: '1' - - BLE_LL_CFG_FEAT_LL_PRIVACY: - description: > - This option is used to enable/disable LL privacy. - value: '1' - - BLE_LL_CFG_FEAT_LE_CSA2: - description: > - This option is used to enable/disable support for LE Channel - Selection Algorithm #2. - value: '0' - - BLE_LL_CFG_FEAT_LE_2M_PHY: - description: > - This option is used to enable/disable support for the 2Mbps PHY. - value: '0' - - BLE_LL_CFG_FEAT_LE_CODED_PHY: - description: > - This option is used to enable/disable support for the coded PHY. - value: '0' - - BLE_LL_CFG_FEAT_LL_EXT_ADV: - description: > - This option is used to enable/disable support for Extended - Advertising Feature. That means extended scanner, advertiser - and connect. - value: MYNEWT_VAL(BLE_EXT_ADV) - - BLE_LL_CFG_FEAT_LL_PERIODIC_ADV: - description: > - This option is used to enable/disable support for Periodic - Advertising Feature. - value: MYNEWT_VAL(BLE_PERIODIC_ADV) - - BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_CNT: - description: > - This option is used to configure number of supported periodic syncs. - value: MYNEWT_VAL(BLE_MAX_PERIODIC_SYNCS) - - BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_LIST_CNT: - description: > - Size of Periodic Advertiser sync list. - value: MYNEWT_VAL(BLE_MAX_PERIODIC_SYNCS) - - BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER: - description: > - This option is use to enable/disable support for Periodic - Advertising Sync Transfer Feature. - value: MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER) - - BLE_LL_EXT_ADV_AUX_PTR_CNT: - description: > - This option configure a max number of scheduled outstanding auxiliary - packets for receive on secondary advertising channel. - value: 0 - - BLE_PUBLIC_DEV_ADDR: - description: > - Allows the target or app to override the public device address - used by the controller. If all zero, the controller will - attempt to retrieve the public device address from its - chip specific location. If non-zero, this address will - be used. - value: "(uint8_t[6]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}" - - BLE_LL_DTM: - description: > - Enables HCI Test commands needed for Bluetooth SIG certification - value: MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) - BLE_LL_DTM_EXTENSIONS: - description: > - Enables non-standard extensions to HCI test commands. Once enabled, - HCI_LE_Transmitter_Test accepts extra parameters in addition to - those defined in Core specification - interval (2 octets) interval between packets (usecs), overrides - standard interval - pkt_count (2 octets) number of packets to transmit, controller - will automatically stop sending packets - after given number of packets was sent - Setting either of these parameters to 0 will configure for default - behavior, as per Core specification. - If specified interval is shorter then allowed by specification it - will be ignored. - Extended parameters shall immediately follow standard parameters. - Controller can accept both standard and extended version of command - depending on specified HCI command length. - value: 0 - - BLE_LL_VND_EVENT_ON_ASSERT: - description: > - This options enables controller to send a vendor-specific event on - an assertion in controller code. The event contains file name and - line number where assertion occured. - value: 0 - - BLE_LL_SYSINIT_STAGE: - description: > - Sysinit stage for the NimBLE controller. - value: 250 - - BLE_LL_DEBUG_GPIO_HCI_CMD: - description: > - GPIO pin number to debug HCI commands flow. Pin is set to high state - when HCI command is being processed. - value: -1 - BLE_LL_DEBUG_GPIO_HCI_EV: - description: > - GPIO pin number to debug HCI events flow. Pin is set to high state - when HCI event is being sent. - value: -1 - BLE_LL_DEBUG_GPIO_SCHED_RUN: - description: > - GPIO pin number to debug scheduler running (on timer). Pin is set - to high state while scheduler is running. - value: -1 - BLE_LL_DEBUG_GPIO_SCHED_ITEM_CB: - description: > - GPIO pin number to debug scheduler item execution times. Pin is set - to high state while item is executed. - value: -1 - -# Below settings allow to change scheduler timings. These should be left at -# default values unless you know what you are doing! - BLE_LL_SCHED_AUX_MAFS_DELAY: - description: > - Additional delay [us] between last ADV_EXT_IND and AUX_ADV_IND PDUs - when scheduling extended advertising event. This extends T_MAFS. - value: 0 - BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY: - description: > - Additional delay [us] between consecutive AUX_CHAIN_IND PDUs - when scheduling extended or periodic advertising event. This extends - T_MAFS. - value: 0 - BLE_LL_SCHED_SCAN_AUX_PDU_LEN: - description: > - This is expected PDU len for AUX_ADV_IND and subsequent - AUX_CHAIN_IND. When scheduling scan scheduler will reserve time for - receiving this amount of time. Setting this to high value improves - reception of large PDUs but results in wasting scheduler space when - receiving small PDUs only. On the other hand too low value can - result in not being able to scan whole PDU due to being preempted - by next scheduled item. By default size matching legacy ADV_IND PDU - payload is used: ExtHeader (Flags, AdvA, ADI) + 31 bytes of data. - range: 1..257 - value: 41 - - BLE_LL_SCHED_SCAN_SYNC_PDU_LEN: - description: > - This is expected PDU len for AUX_SYNC_IND and subsequent - AUX_CHAIN_IND. When scheduling scan scheduler will reserve time for - receiving this amount of time. Setting this to high value improves - reception of large PDUs but results in wasting scheduler space when - receiving small PDUs only. On the other hand too low value can - result in not being able to scan whole PDU due to being preempted - by next scheduled item. By default size matching PDU with legacy - data size is used: ExtHeader + 31 bytes of data. - range: 1..257 - value: 32 - -# deprecated settings (to be defunct/removed eventually) - BLE_LL_DIRECT_TEST_MODE: - description: use BLE_LL_DTM instead - value: 0 - deprecated: 1 - BLE_XTAL_SETTLE_TIME: - description: use BLE_LL_RFMGMT_ENABLE_TIME instead - value: 0 - deprecated: 1 - -# defunct settings (to be removed eventually) - BLE_DEVICE: - description: Superseded by BLE_CONTROLLER - value: 1 - defunct: 1 - BLE_LP_CLOCK: - description: Superseded by BLE_CONTROLLER - value: 1 - defunct: 1 - BLE_NUM_COMP_PKT_RATE: - description: Superseded by BLE_LL_NUM_COMP_PKT_ITVL_MS - value: '(2 * OS_TICKS_PER_SEC)' - defunct: 1 - - -syscfg.vals.BLE_LL_CFG_FEAT_LL_EXT_ADV: - BLE_LL_CFG_FEAT_LE_CSA2: 1 - BLE_HW_WHITELIST_ENABLE: 0 - BLE_LL_EXT_ADV_AUX_PTR_CNT: 5 - -# Enable vendor event on assert in standalone build to make failed assertions in -# controller code visible when connected to external host -syscfg.vals.!BLE_HOST: - BLE_LL_VND_EVENT_ON_ASSERT: 1 - -syscfg.restrictions: - - OS_CPUTIME_FREQ == 32768 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/include/ble/xcvr.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/include/ble/xcvr.h deleted file mode 100644 index 6c1fb7b24..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/include/ble/xcvr.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - #if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) - -#ifndef H_BLE_XCVR_ -#define H_BLE_XCVR_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Transceiver specific defintions */ -/* NOTE: we have to account for the RTC output compare issue */ -#define XCVR_PROC_DELAY_USECS (230) - -#define XCVR_RX_START_DELAY_USECS (140) -#define XCVR_TX_START_DELAY_USECS (140) -#define XCVR_TX_SCHED_DELAY_USECS \ - (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS) -#define XCVR_RX_SCHED_DELAY_USECS \ - (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS) - -/* - * Define HW whitelist size. This is the total possible whitelist size; - * not necessarily the size that will be used (may be smaller) - */ -#define BLE_HW_WHITE_LIST_SIZE (8) - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_XCVR_ */ -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/pkg.yml deleted file mode 100644 index 816a56355..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/pkg.yml +++ /dev/null @@ -1,31 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/drivers/nrf51 -pkg.description: BLE driver for nRF51 systems. -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - -pkg.apis: ble_driver -pkg.deps: - - nimble - - nimble/controller diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_hw.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_hw.c deleted file mode 100644 index 3d4966b2d..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_hw.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) - -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "../include/ble/xcvr.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nrf.h" -#include "nimble/nimble/controller/include/controller/ble_hw.h" -#if MYNEWT -#include "mcu/cmsis_nvic.h" -#else -#include "core_cm0.h" -#include "nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h" -#endif -#include "nimble/porting/nimble/include/os/os_trace_api.h" - -/* Total number of resolving list elements */ -#define BLE_HW_RESOLV_LIST_SIZE (16) - -/* We use this to keep track of which entries are set to valid addresses */ -static uint8_t g_ble_hw_whitelist_mask; - -/* Random number generator isr callback */ -ble_rng_isr_cb_t g_ble_rng_isr_cb; - -/* If LL privacy is enabled, allocate memory for AAR */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - -/* The NRF51 supports up to 16 IRK entries */ -#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16) -#define NRF_IRK_LIST_ENTRIES (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)) -#else -#define NRF_IRK_LIST_ENTRIES (16) -#endif - -/* NOTE: each entry is 16 bytes long. */ -uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4]; - -/* Current number of IRK entries */ -uint8_t g_nrf_num_irks; - -#endif - -/* Returns public device address or -1 if not present */ -int -ble_hw_get_public_addr(ble_addr_t *addr) -{ - uint32_t addr_high; - uint32_t addr_low; - - /* Does FICR have a public address */ - if ((NRF_FICR->DEVICEADDRTYPE & 1) != 0) { - return -1; - } - - /* Copy into device address. We can do this because we know platform */ - addr_low = NRF_FICR->DEVICEADDR[0]; - addr_high = NRF_FICR->DEVICEADDR[1]; - memcpy(addr->val, &addr_low, 4); - memcpy(&addr->val[4], &addr_high, 2); - addr->type = BLE_ADDR_PUBLIC; - - return 0; -} - -/* Returns random static address or -1 if not present */ -int -ble_hw_get_static_addr(ble_addr_t *addr) -{ - int rc; - - if ((NRF_FICR->DEVICEADDRTYPE & 1) == 1) { - memcpy(addr->val, (void *)&NRF_FICR->DEVICEADDR[0], 4); - memcpy(&addr->val[4], (void *)&NRF_FICR->DEVICEADDR[1], 2); - addr->val[5] |= 0xc0; - addr->type = BLE_ADDR_RANDOM; - rc = 0; - } else { - rc = -1; - } - - return rc; -} - -/** - * Clear the whitelist - * - * @return int - */ -void -ble_hw_whitelist_clear(void) -{ - NRF_RADIO->DACNF = 0; - g_ble_hw_whitelist_mask = 0; -} - -/** - * Add a device to the hw whitelist - * - * @param addr - * @param addr_type - * - * @return int 0: success, BLE error code otherwise - */ -int -ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type) -{ - int i; - uint32_t mask; - - /* Find first ununsed device address match element */ - mask = 0x01; - for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) { - if ((mask & g_ble_hw_whitelist_mask) == 0) { - NRF_RADIO->DAB[i] = get_le32(addr); - NRF_RADIO->DAP[i] = get_le16(addr + 4); - if (addr_type == BLE_ADDR_RANDOM) { - NRF_RADIO->DACNF |= (mask << 8); - } - g_ble_hw_whitelist_mask |= mask; - return BLE_ERR_SUCCESS; - } - mask <<= 1; - } - - return BLE_ERR_MEM_CAPACITY; -} - -/** - * Remove a device from the hw whitelist - * - * @param addr - * @param addr_type - * - */ -void -ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type) -{ - int i; - uint8_t cfg_addr; - uint16_t dap; - uint16_t txadd; - uint32_t dab; - uint32_t mask; - - /* Find first ununsed device address match element */ - dab = get_le32(addr); - dap = get_le16(addr + 4); - txadd = NRF_RADIO->DACNF >> 8; - mask = 0x01; - for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) { - if (mask & g_ble_hw_whitelist_mask) { - if ((dab == NRF_RADIO->DAB[i]) && (dap == NRF_RADIO->DAP[i])) { - cfg_addr = txadd & mask; - if (addr_type == BLE_ADDR_RANDOM) { - if (cfg_addr != 0) { - break; - } - } else { - if (cfg_addr == 0) { - break; - } - } - } - } - mask <<= 1; - } - - if (i < BLE_HW_WHITE_LIST_SIZE) { - g_ble_hw_whitelist_mask &= ~mask; - NRF_RADIO->DACNF &= ~mask; - } -} - -/** - * Returns the size of the whitelist in HW - * - * @return int Number of devices allowed in whitelist - */ -uint8_t -ble_hw_whitelist_size(void) -{ - return BLE_HW_WHITE_LIST_SIZE; -} - -/** - * Enable the whitelisted devices - */ -void -ble_hw_whitelist_enable(void) -{ - /* Enable the configured device addresses */ - NRF_RADIO->DACNF |= g_ble_hw_whitelist_mask; -} - -/** - * Disables the whitelisted devices - */ -void -ble_hw_whitelist_disable(void) -{ - /* Disable all whitelist devices */ - NRF_RADIO->DACNF &= 0x0000ff00; -} - -/** - * Boolean function which returns true ('1') if there is a match on the - * whitelist. - * - * @return int - */ -int -ble_hw_whitelist_match(void) -{ - return (int)NRF_RADIO->EVENTS_DEVMATCH; -} - -/* Encrypt data */ -int -ble_hw_encrypt_block(struct ble_encryption_block *ecb) -{ - int rc; - uint32_t end; - uint32_t err; - - /* Stop ECB */ - NRF_ECB->TASKS_STOPECB = 1; - /* XXX: does task stop clear these counters? Anyway to do this quicker? */ - NRF_ECB->EVENTS_ENDECB = 0; - NRF_ECB->EVENTS_ERRORECB = 0; - NRF_ECB->ECBDATAPTR = (uint32_t)ecb; - - /* Start ECB */ - NRF_ECB->TASKS_STARTECB = 1; - - /* Wait till error or done */ - rc = 0; - while (1) { - end = NRF_ECB->EVENTS_ENDECB; - err = NRF_ECB->EVENTS_ERRORECB; - if (end || err) { - if (err) { - rc = -1; - } - break; - } - } - - return rc; -} - -/** - * Random number generator ISR. - */ -static void -ble_rng_isr(void) -{ - uint8_t rnum; - - os_trace_isr_enter(); - - /* No callback? Clear and disable interrupts */ - if (g_ble_rng_isr_cb == NULL) { - NRF_RNG->INTENCLR = 1; - NRF_RNG->EVENTS_VALRDY = 0; - (void)NRF_RNG->SHORTS; - os_trace_isr_exit(); - return; - } - - /* If there is a value ready grab it */ - if (NRF_RNG->EVENTS_VALRDY) { - NRF_RNG->EVENTS_VALRDY = 0; - rnum = (uint8_t)NRF_RNG->VALUE; - (*g_ble_rng_isr_cb)(rnum); - } - - os_trace_isr_exit(); -} - -/** - * Initialize the random number generator - * - * @param cb - * @param bias - * - * @return int - */ -int -ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias) -{ - /* Set bias */ - if (bias) { - NRF_RNG->CONFIG = 1; - } else { - NRF_RNG->CONFIG = 0; - } - - /* If we were passed a function pointer we need to enable the interrupt */ - if (cb != NULL) { -#ifndef RIOT_VERSION - NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1); -#endif -#if MYNEWT - NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr); -#else - ble_npl_hw_set_isr(RNG_IRQn, ble_rng_isr); -#endif - NVIC_EnableIRQ(RNG_IRQn); - g_ble_rng_isr_cb = cb; - } - - return 0; -} - -/** - * Start the random number generator - * - * @return int - */ -int -ble_hw_rng_start(void) -{ - os_sr_t sr; - - /* No need for interrupt if there is no callback */ - OS_ENTER_CRITICAL(sr); - NRF_RNG->EVENTS_VALRDY = 0; - if (g_ble_rng_isr_cb) { - NRF_RNG->INTENSET = 1; - } - NRF_RNG->TASKS_START = 1; - OS_EXIT_CRITICAL(sr); - - return 0; -} - -/** - * Stop the random generator - * - * @return int - */ -int -ble_hw_rng_stop(void) -{ - os_sr_t sr; - - /* No need for interrupt if there is no callback */ - OS_ENTER_CRITICAL(sr); - NRF_RNG->INTENCLR = 1; - NRF_RNG->TASKS_STOP = 1; - NRF_RNG->EVENTS_VALRDY = 0; - OS_EXIT_CRITICAL(sr); - - return 0; -} - -/** - * Read the random number generator. - * - * @return uint8_t - */ -uint8_t -ble_hw_rng_read(void) -{ - uint8_t rnum; - - /* Wait for a sample */ - while (NRF_RNG->EVENTS_VALRDY == 0) { - } - - NRF_RNG->EVENTS_VALRDY = 0; - rnum = (uint8_t)NRF_RNG->VALUE; - - return rnum; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -/** - * Clear the resolving list - * - * @return int - */ -void -ble_hw_resolv_list_clear(void) -{ - g_nrf_num_irks = 0; -} - -/** - * Add a device to the hw resolving list - * - * @param irk Pointer to IRK to add - * - * @return int 0: success, BLE error code otherwise - */ -int -ble_hw_resolv_list_add(uint8_t *irk) -{ - uint32_t *nrf_entry; - - /* Find first ununsed device address match element */ - if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) { - return BLE_ERR_MEM_CAPACITY; - } - - /* Copy into irk list */ - nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks]; - memcpy(nrf_entry, irk, 16); - - /* Add to total */ - ++g_nrf_num_irks; - return BLE_ERR_SUCCESS; -} - -/** - * Remove a device from the hw resolving list - * - * @param index Index of IRK to remove - */ -void -ble_hw_resolv_list_rmv(int index) -{ - uint32_t *irk_entry; - - if (index < g_nrf_num_irks) { - --g_nrf_num_irks; - irk_entry = &g_nrf_irk_list[index]; - if (g_nrf_num_irks > index) { - memmove(irk_entry, irk_entry + 4, 16 * (g_nrf_num_irks - index)); - } - } -} - -/** - * Returns the size of the resolving list. NOTE: this returns the maximum - * allowable entries in the HW. Configuration options may limit this. - * - * @return int Number of devices allowed in resolving list - */ -uint8_t -ble_hw_resolv_list_size(void) -{ - return BLE_HW_RESOLV_LIST_SIZE; -} - -/** - * Called to determine if the address received was resolved. - * - * @return int Negative values indicate unresolved address; positive values - * indicate index in resolving list of resolved address. - */ -int -ble_hw_resolv_list_match(void) -{ - uint32_t index; - - if (NRF_AAR->EVENTS_END) { - if (NRF_AAR->EVENTS_RESOLVED) { - index = NRF_AAR->STATUS; - return (int)index; - } - } - - return -1; -} -#endif -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_phy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_phy.c deleted file mode 100644 index 3bfed096a..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_phy.c +++ /dev/null @@ -1,1527 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - #if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) - -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "../include/ble/xcvr.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/controller/include/controller/ble_phy.h" -#include "nimble/nimble/controller/include/controller/ble_phy_trace.h" -#include "nimble/nimble/controller/include/controller/ble_ll.h" -#include "nrf.h" - -#if MYNEWT -#include "mcu/nrf51_clock.h" -#include "mcu/cmsis_nvic.h" -#else -#include "core_cm0.h" -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) -#error LE 2M PHY cannot be enabled on nRF51 -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) -#error LE Coded PHY cannot be enabled on nRF51 -#endif - -/* XXX: 4) Make sure RF is higher priority interrupt than schedule */ - -/* - * XXX: Maximum possible transmit time is 1 msec for a 60ppm crystal - * and 16ms for a 30ppm crystal! We need to limit PDU size based on - * crystal accuracy. Look at this in the spec. - */ - -/* XXX: private header file? */ -extern uint8_t g_nrf_num_irks; -extern uint32_t g_nrf_irk_list[]; - -/* To disable all radio interrupts */ -#define NRF_RADIO_IRQ_MASK_ALL (0x34FF) - -/* - * We configure the nrf with a 1 byte S0 field, 8 bit length field, and - * zero bit S1 field. The preamble is 8 bits long. - */ -#define NRF_LFLEN_BITS (8) -#define NRF_S0_LEN (1) - -/* Maximum length of frames */ -#define NRF_MAXLEN (255) -#define NRF_BALEN (3) /* For base address of 3 bytes */ - -/* Maximum tx power */ -#define NRF_TX_PWR_MAX_DBM (4) -#define NRF_TX_PWR_MIN_DBM (-40) - -/* Max. encrypted payload length */ -#define NRF_MAX_ENCRYPTED_PYLD_LEN (27) -#define NRF_ENC_HDR_SIZE (3) -#define NRF_ENC_BUF_SIZE \ - (NRF_MAX_ENCRYPTED_PYLD_LEN + NRF_ENC_HDR_SIZE + BLE_LL_DATA_MIC_LEN) - -/* BLE PHY data structure */ -struct ble_phy_obj -{ - uint8_t phy_stats_initialized; - int8_t phy_txpwr_dbm; - uint8_t phy_chan; - uint8_t phy_state; - uint8_t phy_transition; - uint8_t phy_rx_started; - uint8_t phy_encrypted; - uint8_t phy_privacy; - uint8_t phy_tx_pyld_len; - uint8_t *rxdptr; - int8_t rx_pwr_compensation; - uint32_t phy_aar_scratch; - uint32_t phy_access_address; - struct ble_mbuf_hdr rxhdr; - void *txend_arg; - ble_phy_tx_end_func txend_cb; - uint32_t phy_start_cputime; -}; -struct ble_phy_obj g_ble_phy_data; - -/* XXX: if 27 byte packets desired we can make this smaller */ -/* Global transmit/receive buffer */ -static uint32_t g_ble_phy_tx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; -static uint32_t g_ble_phy_rx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/* Make sure word-aligned for faster copies */ -static uint32_t g_ble_phy_enc_buf[(NRF_ENC_BUF_SIZE + 3) / 4]; -#endif - -/* RF center frequency for each channel index (offset from 2400 MHz) */ -static const uint8_t g_ble_phy_chan_freq[BLE_PHY_NUM_CHANS] = { - 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, /* 0-9 */ - 24, 28, 30, 32, 34, 36, 38, 40, 42, 44, /* 10-19 */ - 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, /* 20-29 */ - 66, 68, 70, 72, 74, 76, 78, 2, 26, 80, /* 30-39 */ -}; - -/* Statistics */ -STATS_SECT_START(ble_phy_stats) - STATS_SECT_ENTRY(phy_isrs) - STATS_SECT_ENTRY(tx_good) - STATS_SECT_ENTRY(tx_fail) - STATS_SECT_ENTRY(tx_late) - STATS_SECT_ENTRY(tx_bytes) - STATS_SECT_ENTRY(rx_starts) - STATS_SECT_ENTRY(rx_aborts) - STATS_SECT_ENTRY(rx_valid) - STATS_SECT_ENTRY(rx_crc_err) - STATS_SECT_ENTRY(rx_late) - STATS_SECT_ENTRY(radio_state_errs) - STATS_SECT_ENTRY(rx_hw_err) - STATS_SECT_ENTRY(tx_hw_err) -STATS_SECT_END -STATS_SECT_DECL(ble_phy_stats) ble_phy_stats; - -STATS_NAME_START(ble_phy_stats) - STATS_NAME(ble_phy_stats, phy_isrs) - STATS_NAME(ble_phy_stats, tx_good) - STATS_NAME(ble_phy_stats, tx_fail) - STATS_NAME(ble_phy_stats, tx_late) - STATS_NAME(ble_phy_stats, tx_bytes) - STATS_NAME(ble_phy_stats, rx_starts) - STATS_NAME(ble_phy_stats, rx_aborts) - STATS_NAME(ble_phy_stats, rx_valid) - STATS_NAME(ble_phy_stats, rx_crc_err) - STATS_NAME(ble_phy_stats, rx_late) - STATS_NAME(ble_phy_stats, radio_state_errs) - STATS_NAME(ble_phy_stats, rx_hw_err) - STATS_NAME(ble_phy_stats, tx_hw_err) -STATS_NAME_END(ble_phy_stats) - -/* - * NOTE: - * Tested the following to see what would happen: - * -> NVIC has radio irq enabled (interrupt # 1, mask 0x2). - * -> Set up nrf to receive. Clear ADDRESS event register. - * -> Enable ADDRESS interrupt on nrf5 by writing to INTENSET. - * -> Enable RX. - * -> Disable interrupts globally using OS_ENTER_CRITICAL(). - * -> Wait until a packet is received and the ADDRESS event occurs. - * -> Call ble_phy_disable(). - * - * At this point I wanted to see the state of the cortex NVIC. The IRQ - * pending bit was TRUE for the radio interrupt (as expected) as we never - * serviced the radio interrupt (interrupts were disabled). - * - * What was unexpected was this: without clearing the pending IRQ in the NVIC, - * when radio interrupts were re-enabled (address event bit in INTENSET set to - * 1) and the radio ADDRESS event register read 1 (it was never cleared after - * the first address event), the radio did not enter the ISR! I would have - * expected that if the following were true, an interrupt would occur: - * -> NVIC ISER bit set to TRUE - * -> NVIC ISPR bit reads TRUE, meaning interrupt is pending. - * -> Radio peripheral interrupts are enabled for some event (or events). - * -> Corresponding event register(s) in radio peripheral read 1. - * - * Not sure what the end result of all this is. We will clear the pending - * bit in the NVIC just to be sure when we disable the PHY. - */ - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/* Per nordic, the number of bytes needed for scratch is 16 + MAX_PKT_SIZE. */ -#define NRF_ENC_SCRATCH_WORDS (((NRF_MAX_ENCRYPTED_PYLD_LEN + 16) + 3) / 4) - -uint32_t g_nrf_encrypt_scratchpad[NRF_ENC_SCRATCH_WORDS]; - -struct nrf_ccm_data -{ - uint8_t key[16]; - uint64_t pkt_counter; - uint8_t dir_bit; - uint8_t iv[8]; -} __attribute__((packed)); - -struct nrf_ccm_data g_nrf_ccm_data; -#endif - -/** - * Copies the data from the phy receive buffer into a mbuf chain. - * - * @param dptr Pointer to receive buffer - * @param rxpdu Pointer to already allocated mbuf chain - * - * NOTE: the packet header already has the total mbuf length in it. The - * lengths of the individual mbufs are not set prior to calling. - * - */ -void -ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu) -{ - uint32_t rem_len; - uint32_t copy_len; - uint32_t block_len; - uint32_t block_rem_len; - void *dst; - void *src; - struct os_mbuf * om; - - /* Better be aligned */ - assert(((uint32_t)dptr & 3) == 0); - - block_len = rxpdu->om_omp->omp_databuf_len; - rem_len = OS_MBUF_PKTHDR(rxpdu)->omp_len; - src = dptr; - - /* - * Setup for copying from first mbuf which is shorter due to packet header - * and extra leading space - */ - copy_len = block_len - rxpdu->om_pkthdr_len - 4; - om = rxpdu; - dst = om->om_data; - - while (true) { - /* - * Always copy blocks of length aligned to word size, only last mbuf - * will have remaining non-word size bytes appended. - */ - block_rem_len = copy_len; - copy_len = min(copy_len, rem_len); - copy_len &= ~3; - - dst = om->om_data; - om->om_len = copy_len; - rem_len -= copy_len; - block_rem_len -= copy_len; - - __asm__ volatile (".syntax unified \n" - " mov r4, %[len] \n" - " b 2f \n" - "1: ldr r3, [%[src], %[len]] \n" - " str r3, [%[dst], %[len]] \n" - "2: subs %[len], #4 \n" - " bpl 1b \n" - " adds %[src], %[src], r4 \n" - " adds %[dst], %[dst], r4 \n" - : [dst] "+l" (dst), [src] "+l" (src), - [len] "+l" (copy_len) - : - : "r3", "r4", "memory" - ); - - if ((rem_len < 4) && (block_rem_len >= rem_len)) { - break; - } - - /* Move to next mbuf */ - om = SLIST_NEXT(om, om_next); - copy_len = block_len; - } - - /* Copy remaining bytes, if any, to last mbuf */ - om->om_len += rem_len; - __asm__ volatile (".syntax unified \n" - " b 2f \n" - "1: ldrb r3, [%[src], %[len]] \n" - " strb r3, [%[dst], %[len]] \n" - "2: subs %[len], #1 \n" - " bpl 1b \n" - : [len] "+l" (rem_len) - : [dst] "l" (dst), [src] "l" (src) - : "r3", "memory" - ); - - /* Copy header */ - memcpy(BLE_MBUF_HDR_PTR(rxpdu), &g_ble_phy_data.rxhdr, - sizeof(struct ble_mbuf_hdr)); -} - -/** - * Called when we want to wait if the radio is in either the rx or tx - * disable states. We want to wait until that state is over before doing - * anything to the radio - */ -static void -nrf_wait_disabled(void) -{ - uint32_t state; - - /* - * RX and TX states have the same values except for 3rd bit (0=RX, 1=TX) so - * we use RX symbols only. - */ - state = NRF_RADIO->STATE & 0x07; - - if (state != RADIO_STATE_STATE_Disabled) { - /* If PHY is in idle state for whatever reason, disable it now */ - if (state == RADIO_STATE_STATE_RxIdle) { - NRF_RADIO->TASKS_DISABLE = 1; - STATS_INC(ble_phy_stats, radio_state_errs); - } - - if (state == RADIO_STATE_STATE_RxDisable) { - /* This will end within a short time (6 usecs). Just poll */ - while (NRF_RADIO->STATE == state) { - /* If this fails, something is really wrong. Should last - * no more than 6 usecs */ - } - } - } -} - -/** - * - * - */ -int -ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs) -{ - uint32_t next_cc; - uint32_t cur_cc; - uint32_t cntr; - uint32_t delta; - - /* - * XXX: The TXEN time is 140 usecs but there may be additional delays - * Need to look at this. - */ - - /* - * With the 32.768 kHz crystal, we may need to adjust the RTC compare - * value by 1 tick due to the time it takes for TXEN. The code uses a 5 RTC - * tick offset, which is 152.5 usecs. The TXEN time is 140 usecs. This - * means that with a remainder of 0, TIMER0 should be set to 12 or 13 (as - * TIMER0 counts at 1MHz). A remainder of 19 or more we will need to add - * 1 tick. We dont need to add 1 tick per se, but it does give us slightly - * more time and thus less of a chance to miss a tick. Another note: we - * cant set TIMER0 CC to 0 as the compare wont occur; it must be 1 or more. - * This is why we subtract 18 (as opposed to 19) as rem_uses will be >= 1. - */ - if (rem_usecs <= 18) { - cputime -= 5; - rem_usecs += 12; - } else { - cputime -= 4; - rem_usecs -= 18; - } - - /* - * Can we set the RTC compare to start TIMER0? We can do it if: - * a) Current compare value is not N+1 or N+2 ticks from current - * counter. - * b) The value we want to set is not at least N+2 from current - * counter. - * - * NOTE: since the counter can tick 1 while we do these calculations we - * need to account for it. - */ - next_cc = cputime & 0xffffff; - cur_cc = NRF_RTC0->CC[0]; - cntr = NRF_RTC0->COUNTER; - - delta = (cur_cc - cntr) & 0xffffff; - if ((delta <= 3) && (delta != 0)) { - return -1; - } - delta = (next_cc - cntr) & 0xffffff; - if ((delta & 0x800000) || (delta < 3)) { - return -1; - } - - /* Clear and set TIMER0 to fire off at proper time */ - NRF_TIMER0->TASKS_CLEAR = 1; - NRF_TIMER0->CC[0] = rem_usecs; - NRF_TIMER0->EVENTS_COMPARE[0] = 0; - - /* Set RTC compare to start TIMER0 */ - NRF_RTC0->EVENTS_COMPARE[0] = 0; - NRF_RTC0->CC[0] = next_cc; - NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; - - /* Enable PPI */ - NRF_PPI->CHENSET = PPI_CHEN_CH31_Msk; - - /* Store the cputime at which we set the RTC */ - g_ble_phy_data.phy_start_cputime = cputime; - - return 0; -} - -/** - * Function is used to set PPI so that we can time out waiting for a reception - * to occur. This happens for two reasons: we have sent a packet and we are - * waiting for a respons (txrx should be set to ENABLE_TXRX) or we are - * starting a connection event and we are a slave and we are waiting for the - * master to send us a packet (txrx should be set to ENABLE_RX). - * - * NOTE: when waiting for a txrx turn-around, wfr_usecs is not used as there - * is no additional time to wait; we know when we should receive the address of - * the received frame. - * - * @param txrx Flag denoting if this wfr is a txrx turn-around or not. - * @param tx_phy_mode phy mode for last TX (not used on nRF51) - * @param wfr_usecs Amount of usecs to wait. - */ -void -ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) -{ - uint32_t end_time; - - if (txrx == BLE_PHY_WFR_ENABLE_TXRX) { - /* - * Timeout occurs an IFS time plus time it takes to receive address - * from the transmit end. We add additional time to make sure the - * address event comes before the compare. Note that transmit end - * is captured in CC[2]. I just made up the 16 usecs I add here. - */ - end_time = NRF_TIMER0->CC[2] + BLE_LL_IFS + - ble_phy_mode_pdu_start_off(BLE_PHY_MODE_1M) + 16; - } else { - /* CC[0] is set to when RXEN occurs. */ - end_time = NRF_TIMER0->CC[0] + XCVR_RX_START_DELAY_USECS + wfr_usecs + - ble_phy_mode_pdu_start_off(BLE_PHY_MODE_1M) + BLE_LL_JITTER_USECS; - } - - /* wfr_secs is the time from rxen until timeout */ - NRF_TIMER0->CC[3] = end_time; - NRF_TIMER0->EVENTS_COMPARE[3] = 0; - - /* Enable wait for response PPI */ - NRF_PPI->CHENSET = (PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk); - - /* Enable the disabled interrupt so we time out on events compare */ - NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; -} - -/** - * Setup transceiver for receive. - */ -static void -ble_phy_rx_xcvr_setup(void) -{ - uint8_t *dptr; - - dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (g_ble_phy_data.phy_encrypted) { - dptr += 3; - NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_enc_buf[0]; - NRF_CCM->INPTR = (uint32_t)&g_ble_phy_enc_buf[0]; - NRF_CCM->OUTPTR = (uint32_t)dptr; - NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0]; - NRF_CCM->MODE = CCM_MODE_MODE_Decryption; - NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data; - NRF_CCM->SHORTS = 0; - NRF_CCM->EVENTS_ERROR = 0; - NRF_CCM->EVENTS_ENDCRYPT = 0; - NRF_PPI->CHENSET = PPI_CHEN_CH24_Msk | PPI_CHEN_CH25_Msk; - } else { - NRF_RADIO->PACKETPTR = (uint32_t)dptr; - } -#else - NRF_RADIO->PACKETPTR = (uint32_t)dptr; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (g_ble_phy_data.phy_privacy) { - dptr += 3; - NRF_RADIO->PACKETPTR = (uint32_t)dptr; - NRF_RADIO->PCNF0 = (6 << RADIO_PCNF0_LFLEN_Pos) | - (2 << RADIO_PCNF0_S1LEN_Pos) | - (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); - NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Enabled; - NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; - NRF_AAR->SCRATCHPTR = (uint32_t)&g_ble_phy_data.phy_aar_scratch; - NRF_AAR->EVENTS_END = 0; - NRF_AAR->EVENTS_RESOLVED = 0; - NRF_AAR->EVENTS_NOTRESOLVED = 0; - } else { - if (g_ble_phy_data.phy_encrypted == 0) { - NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | - (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); - /* XXX: do I only need to do this once? Figure out what I can do - once. */ - NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled; - } - } -#endif - - /* Turn off trigger TXEN on output compare match and AAR on bcmatch */ - NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk | PPI_CHEN_CH23_Msk; - - /* Reset the rx started flag. Used for the wait for response */ - g_ble_phy_data.phy_rx_started = 0; - g_ble_phy_data.phy_state = BLE_PHY_STATE_RX; - g_ble_phy_data.rxdptr = dptr; - - /* I want to know when 1st byte received (after address) */ - NRF_RADIO->BCC = 8; /* in bits */ - NRF_RADIO->EVENTS_ADDRESS = 0; - NRF_RADIO->EVENTS_DEVMATCH = 0; - NRF_RADIO->EVENTS_BCMATCH = 0; - NRF_RADIO->EVENTS_RSSIEND = 0; - NRF_RADIO->SHORTS = RADIO_SHORTS_END_DISABLE_Msk | - RADIO_SHORTS_READY_START_Msk | - RADIO_SHORTS_DISABLED_TXEN_Msk | - RADIO_SHORTS_ADDRESS_BCSTART_Msk | - RADIO_SHORTS_ADDRESS_RSSISTART_Msk | - RADIO_SHORTS_DISABLED_RSSISTOP_Msk; - - NRF_RADIO->INTENSET = RADIO_INTENSET_ADDRESS_Msk; -} - -/** - * Called from interrupt context when the transmit ends - * - */ -static void -ble_phy_tx_end_isr(void) -{ - uint8_t was_encrypted; - uint8_t transition; - uint8_t txlen; - uint32_t wfr_time; - - /* If this transmission was encrypted we need to remember it */ - was_encrypted = g_ble_phy_data.phy_encrypted; - (void)was_encrypted; - - /* Better be in TX state! */ - assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX); - - /* Clear events and clear interrupt on disabled event */ - NRF_RADIO->EVENTS_DISABLED = 0; - NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk; - NRF_RADIO->EVENTS_END = 0; - wfr_time = NRF_RADIO->SHORTS; - (void)wfr_time; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - /* - * XXX: not sure what to do. We had a HW error during transmission. - * For now I just count a stat but continue on like all is good. - */ - if (was_encrypted) { - if (NRF_CCM->EVENTS_ERROR) { - STATS_INC(ble_phy_stats, tx_hw_err); - NRF_CCM->EVENTS_ERROR = 0; - } - } -#endif - - /* Call transmit end callback */ - if (g_ble_phy_data.txend_cb) { - g_ble_phy_data.txend_cb(g_ble_phy_data.txend_arg); - } - - transition = g_ble_phy_data.phy_transition; - if (transition == BLE_PHY_TRANSITION_TX_RX) { - /* Packet pointer needs to be reset. */ - ble_phy_rx_xcvr_setup(); - - /* - * Enable the wait for response timer. Note that cc #1 on - * timer 0 contains the transmit start time - */ - txlen = g_ble_phy_data.phy_tx_pyld_len; - if (txlen && was_encrypted) { - txlen += BLE_LL_DATA_MIC_LEN; - } - ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, 0, 0); - } else { - /* - * XXX: not sure we need to stop the timer here all the time. Or that - * it should be stopped here. - */ - NRF_TIMER0->TASKS_STOP = 1; - NRF_TIMER0->TASKS_SHUTDOWN = 1; - NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | - PPI_CHEN_CH20_Msk | PPI_CHEN_CH31_Msk; - assert(transition == BLE_PHY_TRANSITION_NONE); - } -} - -static void -ble_phy_rx_end_isr(void) -{ - int rc; - uint8_t *dptr; - uint8_t crcok; - struct ble_mbuf_hdr *ble_hdr; - - /* Clear events and clear interrupt */ - NRF_RADIO->EVENTS_END = 0; - NRF_RADIO->INTENCLR = RADIO_INTENCLR_END_Msk; - - /* Disable automatic RXEN */ - NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk; - - /* Set RSSI and CRC status flag in header */ - ble_hdr = &g_ble_phy_data.rxhdr; - assert(NRF_RADIO->EVENTS_RSSIEND != 0); - ble_hdr->rxinfo.rssi = (-1 * NRF_RADIO->RSSISAMPLE) + - g_ble_phy_data.rx_pwr_compensation; - - dptr = g_ble_phy_data.rxdptr; - - /* Count PHY crc errors and valid packets */ - crcok = (uint8_t)NRF_RADIO->CRCSTATUS; - if (!crcok) { - STATS_INC(ble_phy_stats, rx_crc_err); - } else { - STATS_INC(ble_phy_stats, rx_valid); - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (g_ble_phy_data.phy_encrypted) { - /* Only set MIC failure flag if frame is not zero length */ - if ((dptr[1] != 0) && (NRF_CCM->MICSTATUS == 0)) { - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_MIC_FAILURE; - } - - /* - * XXX: not sure how to deal with this. This should not - * be a MIC failure but we should not hand it up. I guess - * this is just some form of rx error and that is how we - * handle it? For now, just set CRC error flags - */ - if (NRF_CCM->EVENTS_ERROR) { - STATS_INC(ble_phy_stats, rx_hw_err); - ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; - } - - /* - * XXX: This is a total hack work-around for now but I dont - * know what else to do. If ENDCRYPT is not set and we are - * encrypted we need to not trust this frame and drop it. - */ - if (NRF_CCM->EVENTS_ENDCRYPT == 0) { - STATS_INC(ble_phy_stats, rx_hw_err); - ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; - } - } -#endif - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (g_ble_phy_data.phy_encrypted || g_ble_phy_data.phy_privacy) { - /* - * XXX: This is a horrible ugly hack to deal with the RAM S1 byte. - * This should get fixed as we should not be handing up the header - * and length as part of the pdu. - */ - dptr[2] = dptr[1]; - dptr[1] = dptr[0]; - ++dptr; - } -#endif - rc = ble_ll_rx_end(dptr, ble_hdr); - if (rc < 0) { - ble_phy_disable(); - } -} - -static void -ble_phy_rx_start_isr(void) -{ - int rc; - uint32_t state; - uint32_t usecs; - uint32_t ticks; - struct ble_mbuf_hdr *ble_hdr; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - uint8_t *dptr; - - dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; -#endif - - /* Clear events and clear interrupt */ - NRF_RADIO->EVENTS_ADDRESS = 0; - - /* Clear wfr timer channels and DISABLED interrupt */ - NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk | RADIO_INTENCLR_ADDRESS_Msk; - NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk; - - /* Initialize flags, channel and state in ble header at rx start */ - ble_hdr = &g_ble_phy_data.rxhdr; - ble_hdr->rxinfo.flags = ble_ll_state_get(); - ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan; - ble_hdr->rxinfo.handle = 0; - ble_hdr->rxinfo.phy = BLE_PHY_1M; - ble_hdr->rxinfo.phy_mode = BLE_PHY_MODE_1M; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - ble_hdr->rxinfo.user_data = NULL; -#endif - - /* - * Calculate receive start time. - * - * XXX: possibly use other routine with remainder! - */ - usecs = NRF_TIMER0->CC[1] - ble_phy_mode_pdu_start_off(BLE_PHY_MODE_1M); - ticks = os_cputime_usecs_to_ticks(usecs); - ble_hdr->rem_usecs = usecs - os_cputime_ticks_to_usecs(ticks); - if (ble_hdr->rem_usecs == 31) { - ble_hdr->rem_usecs = 0; - ++ticks; - } - ble_hdr->beg_cputime = g_ble_phy_data.phy_start_cputime + ticks; - - /* Wait to get 1st byte of frame */ - while (1) { - state = NRF_RADIO->STATE; - if (NRF_RADIO->EVENTS_BCMATCH != 0) { - break; - } - - /* - * If state is disabled, we should have the BCMATCH. If not, - * something is wrong! - */ - if (state == RADIO_STATE_STATE_Disabled) { - NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; - NRF_RADIO->SHORTS = 0; - return; - } - } - - /* Call Link Layer receive start function */ - rc = ble_ll_rx_start(g_ble_phy_data.rxdptr, g_ble_phy_data.phy_chan, - &g_ble_phy_data.rxhdr); - if (rc >= 0) { - /* Set rx started flag and enable rx end ISR */ - g_ble_phy_data.phy_rx_started = 1; - NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* Must start aar if we need to */ - if (g_ble_phy_data.phy_privacy) { - NRF_RADIO->EVENTS_BCMATCH = 0; - NRF_PPI->CHENSET = PPI_CHEN_CH23_Msk; - /* - * Setup AAR to resolve AdvA and trigger it after complete address - * is received, i.e. after PDU header and AdvA is received. - * - * AdvA starts at 4th octet in receive buffer, after S0, len and S1 - * fields. - * - * In case of extended advertising AdvA is located after extended - * header (+2 octets). - */ - if (BLE_MBUF_HDR_EXT_ADV(&g_ble_phy_data.rxhdr)) { - NRF_AAR->ADDRPTR = (uint32_t)(dptr + 5); - NRF_RADIO->BCC = (BLE_DEV_ADDR_LEN + BLE_LL_PDU_HDR_LEN + 2) * 8; - - } else { - NRF_AAR->ADDRPTR = (uint32_t)(dptr + 3); - NRF_RADIO->BCC = (BLE_DEV_ADDR_LEN + BLE_LL_PDU_HDR_LEN) * 8; - } - } -#endif - } else { - /* Disable PHY */ - ble_phy_disable(); - STATS_INC(ble_phy_stats, rx_aborts); - } - - /* Count rx starts */ - STATS_INC(ble_phy_stats, rx_starts); -} - -static void -ble_phy_isr(void) -{ - uint32_t irq_en; - - os_trace_isr_enter(); - - /* Read irq register to determine which interrupts are enabled */ - irq_en = NRF_RADIO->INTENCLR; - - /* - * NOTE: order of checking is important! Possible, if things get delayed, - * we have both an ADDRESS and DISABLED interrupt in rx state. If we get - * an address, we disable the DISABLED interrupt. - */ - - /* We get this if we have started to receive a frame */ - if ((irq_en & RADIO_INTENCLR_ADDRESS_Msk) && NRF_RADIO->EVENTS_ADDRESS) { - irq_en &= ~RADIO_INTENCLR_DISABLED_Msk; - ble_phy_rx_start_isr(); - } - - /* Check for disabled event. This only happens for transmits now */ - if ((irq_en & RADIO_INTENCLR_DISABLED_Msk) && NRF_RADIO->EVENTS_DISABLED) { - if (g_ble_phy_data.phy_state == BLE_PHY_STATE_RX) { - NRF_RADIO->EVENTS_DISABLED = 0; - ble_ll_wfr_timer_exp(NULL); - } else { - ble_phy_tx_end_isr(); - } - } - - /* Receive packet end (we dont enable this for transmit) */ - if ((irq_en & RADIO_INTENCLR_END_Msk) && NRF_RADIO->EVENTS_END) { - ble_phy_rx_end_isr(); - } - - /* Ensures IRQ is cleared */ - irq_en = NRF_RADIO->SHORTS; - - /* Count # of interrupts */ - STATS_INC(ble_phy_stats, phy_isrs); - - os_trace_isr_exit(); -} - -/** - * ble phy init - * - * Initialize the PHY. - * - * @return int 0: success; PHY error code otherwise - */ -int -ble_phy_init(void) -{ - int rc; - - /* Set phy channel to an invalid channel so first set channel works */ - g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS; - - g_ble_phy_data.rx_pwr_compensation = 0; - - /* Toggle peripheral power to reset (just in case) */ - NRF_RADIO->POWER = 0; - NRF_RADIO->POWER = 1; - - /* Disable all interrupts */ - NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; - - /* Set configuration registers */ - NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit; - NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | - (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); - /* XXX: should maxlen be 251 for encryption? */ - NRF_RADIO->PCNF1 = NRF_MAXLEN | - (RADIO_PCNF1_ENDIAN_Little << RADIO_PCNF1_ENDIAN_Pos) | - (NRF_BALEN << RADIO_PCNF1_BALEN_Pos) | - RADIO_PCNF1_WHITEEN_Msk; - - /* Set base0 with the advertising access address */ - NRF_RADIO->BASE0 = (BLE_ACCESS_ADDR_ADV << 8) & 0xFFFFFF00; - NRF_RADIO->PREFIX0 = (BLE_ACCESS_ADDR_ADV >> 24) & 0xFF; - - /* Configure the CRC registers */ - NRF_RADIO->CRCCNF = RADIO_CRCCNF_SKIPADDR_Msk | RADIO_CRCCNF_LEN_Three; - - /* Configure BLE poly */ - NRF_RADIO->CRCPOLY = 0x0100065B; - - /* Configure IFS */ - NRF_RADIO->TIFS = BLE_LL_IFS; - - /* Captures tx/rx start in timer0 cc 1 and tx/rx end in timer0 cc 2 */ - NRF_PPI->CHENSET = PPI_CHEN_CH26_Msk | PPI_CHEN_CH27_Msk; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - NRF_CCM->INTENCLR = 0xffffffff; - NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; - NRF_CCM->EVENTS_ERROR = 0; - memset(g_nrf_encrypt_scratchpad, 0, sizeof(g_nrf_encrypt_scratchpad)); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - g_ble_phy_data.phy_aar_scratch = 0; - NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; - NRF_AAR->INTENCLR = 0xffffffff; - NRF_AAR->EVENTS_END = 0; - NRF_AAR->EVENTS_RESOLVED = 0; - NRF_AAR->EVENTS_NOTRESOLVED = 0; - NRF_AAR->NIRK = 0; -#endif - - /* TIMER0 setup for PHY when using RTC */ - NRF_TIMER0->TASKS_STOP = 1; - NRF_TIMER0->TASKS_SHUTDOWN = 1; - NRF_TIMER0->BITMODE = 3; /* 32-bit timer */ - NRF_TIMER0->MODE = 0; /* Timer mode */ - NRF_TIMER0->PRESCALER = 4; /* gives us 1 MHz */ - - /* - * PPI setup. - * Channel 4: Captures TIMER0 in CC[3] when EVENTS_ADDRESS occurs. Used - * to cancel the wait for response timer. - * Channel 5: TIMER0 CC[3] to TASKS_DISABLE on radio. This is the wait - * for response timer. - */ - NRF_PPI->CH[4].EEP = (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS); - NRF_PPI->CH[4].TEP = (uint32_t)&(NRF_TIMER0->TASKS_CAPTURE[3]); - NRF_PPI->CH[5].EEP = (uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]); - NRF_PPI->CH[5].TEP = (uint32_t)&(NRF_RADIO->TASKS_DISABLE); - - /* Set isr in vector table and enable interrupt */ -#ifndef RIOT_VERSION - NVIC_SetPriority(RADIO_IRQn, 0); -#endif -#if MYNEWT - NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr); -#else - ble_npl_hw_set_isr(RADIO_IRQn, ble_phy_isr); -#endif - NVIC_EnableIRQ(RADIO_IRQn); - - /* Register phy statistics */ - if (!g_ble_phy_data.phy_stats_initialized) { - rc = stats_init_and_reg(STATS_HDR(ble_phy_stats), - STATS_SIZE_INIT_PARMS(ble_phy_stats, - STATS_SIZE_32), - STATS_NAME_INIT_PARMS(ble_phy_stats), - "ble_phy"); - assert(rc == 0); - - g_ble_phy_data.phy_stats_initialized = 1; - } - - return 0; -} - -/** - * Puts the phy into receive mode. - * - * @return int 0: success; BLE Phy error code otherwise - */ -int -ble_phy_rx(void) -{ - /* Check radio state */ - nrf_wait_disabled(); - if (NRF_RADIO->STATE != RADIO_STATE_STATE_Disabled) { - ble_phy_disable(); - STATS_INC(ble_phy_stats, radio_state_errs); - return BLE_PHY_ERR_RADIO_STATE; - } - - /* Make sure all interrupts are disabled */ - NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; - - /* Clear events prior to enabling receive */ - NRF_RADIO->EVENTS_END = 0; - NRF_RADIO->EVENTS_DISABLED = 0; - - /* Setup for rx */ - ble_phy_rx_xcvr_setup(); - - /* Start the receive task in the radio if not automatically going to rx */ - if ((NRF_PPI->CHEN & PPI_CHEN_CH21_Msk) == 0) { - NRF_RADIO->TASKS_RXEN = 1; - } - - return 0; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/** - * Called to enable encryption at the PHY. Note that this state will persist - * in the PHY; in other words, if you call this function you have to call - * disable so that future PHY transmits/receives will not be encrypted. - * - * @param pkt_counter - * @param iv - * @param key - * @param is_master - */ -void -ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, - uint8_t is_master) -{ - memcpy(g_nrf_ccm_data.key, key, 16); - g_nrf_ccm_data.pkt_counter = pkt_counter; - memcpy(g_nrf_ccm_data.iv, iv, 8); - g_nrf_ccm_data.dir_bit = is_master; - g_ble_phy_data.phy_encrypted = 1; - - /* Encryption uses LFLEN=5, S1LEN = 3. */ - NRF_RADIO->PCNF0 = (5 << RADIO_PCNF0_LFLEN_Pos) | - (3 << RADIO_PCNF0_S1LEN_Pos) | - (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); - - /* Enable the module (AAR cannot be on while CCM on) */ - NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled; - NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled; -} - -void -ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir) -{ - g_nrf_ccm_data.pkt_counter = pkt_counter; - g_nrf_ccm_data.dir_bit = dir; -} - -void -ble_phy_encrypt_disable(void) -{ - NRF_PPI->CHENCLR = (PPI_CHEN_CH24_Msk | PPI_CHEN_CH25_Msk); - NRF_CCM->TASKS_STOP = 1; - NRF_CCM->EVENTS_ERROR = 0; - NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled; - - /* Switch back to normal length */ - NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | - (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); - - g_ble_phy_data.phy_encrypted = 0; -} -#endif - -void -ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg) -{ - /* Set transmit end callback and arg */ - g_ble_phy_data.txend_cb = txend_cb; - g_ble_phy_data.txend_arg = arg; -} - -/** - * Called to set the start time of a transmission. - * - * This function is called to set the start time when we are not going from - * rx to tx automatically. - * - * NOTE: care must be taken when calling this function. The channel should - * already be set. - * - * @param cputime This is the tick at which the 1st bit of the preamble - * should be transmitted - * @param rem_usecs This is used only when the underlying timing uses a 32.768 - * kHz crystal. It is the # of usecs from the cputime tick - * at which the first bit of the preamble should be - * transmitted. - * @return int - */ -int -ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs) -{ - int rc; - - ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_TX, cputime, rem_usecs); - - /* XXX: This should not be necessary, but paranoia is good! */ - /* Clear timer0 compare to RXEN since we are transmitting */ - NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk; - - /* - * XXX: The TXEN time is 140 usecs but there may be additional delays - * Need to look at this. - */ - if (ble_phy_set_start_time(cputime, rem_usecs) != 0) { - STATS_INC(ble_phy_stats, tx_late); - ble_phy_disable(); - rc = BLE_PHY_ERR_TX_LATE; - } else { - /* Enable PPI to automatically start TXEN */ - NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk; - rc = 0; - } - return rc; -} -/** - * Called to set the start time of a reception - * - * This function acts a bit differently than transmit. If we are late getting - * here we will still attempt to receive. - * - * NOTE: care must be taken when calling this function. The channel should - * already be set. - * - * @param cputime - * - * @return int - */ -int -ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs) -{ - int rc; - - ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_RX, cputime, rem_usecs); - - /* XXX: This should not be necessary, but paranoia is good! */ - /* Clear timer0 compare to TXEN since we are transmitting */ - NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk; - - /* - * XXX: The RXEN time is 138 usecs but there may be additional delays - * Need to look at this. - */ - if (ble_phy_set_start_time(cputime, rem_usecs) != 0) { - STATS_INC(ble_phy_stats, rx_late); - NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk; - NRF_RADIO->TASKS_RXEN = 1; - rc = BLE_PHY_ERR_RX_LATE; - } else { - /* Enable PPI to automatically start RXEN */ - NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk; - - /* Start rx */ - rc = ble_phy_rx(); - } - return rc; -} - -int -ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans) -{ - int rc; - uint8_t *dptr; - uint8_t payload_len; - uint8_t payload_off; - uint8_t hdr_byte; - uint32_t state; - uint32_t shortcuts; - - /* - * This check is to make sure that the radio is not in a state where - * it is moving to disabled state. If so, let it get there. - */ - nrf_wait_disabled(); - - /* - * XXX: Although we may not have to do this here, I clear all the PPI - * that should not be used when transmitting. Some of them are only enabled - * if encryption and/or privacy is on, but I dont care. Better to be - * paranoid, and if you are going to clear one, might as well clear them - * all. - */ - NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH23_Msk | - PPI_CHEN_CH25_Msk; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (g_ble_phy_data.phy_encrypted) { - /* RAM representation has S0, LENGTH and S1 fields. (3 bytes) */ - dptr = (uint8_t *)&g_ble_phy_enc_buf[0]; - payload_off = 3; - - NRF_CCM->SHORTS = 1; - NRF_CCM->INPTR = (uint32_t)&g_ble_phy_enc_buf[0]; - NRF_CCM->OUTPTR = (uint32_t)&g_ble_phy_tx_buf[0]; - NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0]; - NRF_CCM->EVENTS_ERROR = 0; - NRF_CCM->MODE = CCM_MODE_MODE_Encryption; - NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data; - NRF_PPI->CHENSET = PPI_CHEN_CH24_Msk; - } else { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* Reconfigure PCNF0 */ - NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | - (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); - NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; -#endif - /* RAM representation has S0 and LENGTH fields (2 bytes) */ - dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; - payload_off = 2; - } -#else - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* Reconfigure PCNF0 */ - NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | - (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); -#endif - - /* RAM representation has S0 and LENGTH fields (2 bytes) */ - dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; - payload_off = 2; -#endif - - NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_tx_buf[0]; - - /* Clear the ready, end and disabled events */ - NRF_RADIO->EVENTS_READY = 0; - NRF_RADIO->EVENTS_END = 0; - NRF_RADIO->EVENTS_DISABLED = 0; - - /* Enable shortcuts for transmit start/end. */ - shortcuts = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk; - if (end_trans == BLE_PHY_TRANSITION_TX_RX) { - shortcuts |= RADIO_SHORTS_DISABLED_RXEN_Msk; - } - NRF_RADIO->SHORTS = shortcuts; - NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; - - /* Set PDU payload */ - payload_len = pducb(&dptr[payload_off], pducb_arg, &hdr_byte); - - /* Set PDU header */ - dptr[0] = hdr_byte; - dptr[1] = payload_len; - if (payload_off > 2) { - dptr[2] = 0; - } - - /* Set the PHY transition */ - g_ble_phy_data.phy_transition = end_trans; - - /* Set transmitted payload length */ - g_ble_phy_data.phy_tx_pyld_len = payload_len; - - /* If we already started transmitting, abort it! */ - state = NRF_RADIO->STATE; - if (state != RADIO_STATE_STATE_Tx) { - - /* Set phy state to transmitting and count packet statistics */ - g_ble_phy_data.phy_state = BLE_PHY_STATE_TX; - STATS_INC(ble_phy_stats, tx_good); - STATS_INCN(ble_phy_stats, tx_bytes, payload_len + BLE_LL_PDU_HDR_LEN); - rc = BLE_ERR_SUCCESS; - } else { - ble_phy_disable(); - STATS_INC(ble_phy_stats, tx_late); - rc = BLE_PHY_ERR_RADIO_STATE; - } - - return rc; -} - -/** - * ble phy txpwr set - * - * Set the transmit output power (in dBm). - * - * NOTE: If the output power specified is within the BLE limits but outside - * the chip limits, we "rail" the power level so we dont exceed the min/max - * chip values. - * - * @param dbm Power output in dBm. - * - * @return int 0: success; anything else is an error - */ -int -ble_phy_txpwr_set(int dbm) -{ - /* Check valid range */ - assert(dbm <= BLE_PHY_MAX_PWR_DBM); - - /* "Rail" power level if outside supported range */ - if (dbm > NRF_TX_PWR_MAX_DBM) { - dbm = NRF_TX_PWR_MAX_DBM; - } else { - if (dbm < NRF_TX_PWR_MIN_DBM) { - dbm = NRF_TX_PWR_MIN_DBM; - } - } - - NRF_RADIO->TXPOWER = dbm; - g_ble_phy_data.phy_txpwr_dbm = dbm; - - return 0; -} - -/** - * ble phy txpwr round - * - * Get the rounded transmit output power (in dBm). - * - * @param dbm Power output in dBm. - * - * @return int Rounded power in dBm - */ -int ble_phy_txpower_round(int dbm) -{ - /* "Rail" power level if outside supported range */ - if (dbm > NRF_TX_PWR_MAX_DBM) { - dbm = NRF_TX_PWR_MAX_DBM; - } else { - if (dbm < NRF_TX_PWR_MIN_DBM) { - dbm = NRF_TX_PWR_MIN_DBM; - } - } - - return dbm; -} - -/** - * ble phy txpwr get - * - * Get the transmit power. - * - * @return int The current PHY transmit power, in dBm - */ -int -ble_phy_txpwr_get(void) -{ - return g_ble_phy_data.phy_txpwr_dbm; -} - -void -ble_phy_set_rx_pwr_compensation(int8_t compensation) -{ - g_ble_phy_data.rx_pwr_compensation = compensation; -} - -/** - * ble phy setchan - * - * Sets the logical frequency of the transceiver. The input parameter is the - * BLE channel index (0 to 39, inclusive). The NRF frequency register works like - * this: logical frequency = 2400 + FREQ (MHz). - * - * Thus, to get a logical frequency of 2402 MHz, you would program the - * FREQUENCY register to 2. - * - * @param chan This is the Data Channel Index or Advertising Channel index - * - * @return int 0: success; PHY error code otherwise - */ -int -ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit) -{ - uint32_t prefix; - - assert(chan < BLE_PHY_NUM_CHANS); - - /* Check for valid channel range */ - if (chan >= BLE_PHY_NUM_CHANS) { - return BLE_PHY_ERR_INV_PARAM; - } - - /* Get correct frequency */ - if (chan < BLE_PHY_NUM_DATA_CHANS) { - /* Set current access address */ - g_ble_phy_data.phy_access_address = access_addr; - - /* Configure logical address 1 and crcinit */ - prefix = NRF_RADIO->PREFIX0; - prefix &= 0xffff00ff; - prefix |= ((access_addr >> 24) & 0xFF) << 8; - NRF_RADIO->BASE1 = (access_addr << 8) & 0xFFFFFF00; - NRF_RADIO->PREFIX0 = prefix; - NRF_RADIO->TXADDRESS = 1; - NRF_RADIO->RXADDRESSES = (1 << 1); - NRF_RADIO->CRCINIT = crcinit; - } else { - /* Logical adddress 0 preconfigured */ - NRF_RADIO->TXADDRESS = 0; - NRF_RADIO->RXADDRESSES = (1 << 0); - NRF_RADIO->CRCINIT = BLE_LL_CRCINIT_ADV; - - /* Set current access address */ - g_ble_phy_data.phy_access_address = BLE_ACCESS_ADDR_ADV; - } - - /* Set the frequency and the data whitening initial value */ - g_ble_phy_data.phy_chan = chan; - NRF_RADIO->FREQUENCY = g_ble_phy_chan_freq[chan]; - NRF_RADIO->DATAWHITEIV = chan; - - return 0; -} - -/** - * Stop the timer used to count microseconds when using RTC for cputime - */ -static void -ble_phy_stop_usec_timer(void) -{ - NRF_TIMER0->TASKS_STOP = 1; - NRF_TIMER0->TASKS_SHUTDOWN = 1; - NRF_RTC0->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk; -} - -/** - * ble phy disable irq and ppi - * - * This routine is to be called when reception was stopped due to either a - * wait for response timeout or a packet being received and the phy is to be - * restarted in receive mode. Generally, the disable routine is called to stop - * the phy. - */ -static void -ble_phy_disable_irq_and_ppi(void) -{ - NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; - NRF_RADIO->SHORTS = 0; - NRF_RADIO->TASKS_DISABLE = 1; - NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH20_Msk | - PPI_CHEN_CH21_Msk | PPI_CHEN_CH23_Msk | PPI_CHEN_CH24_Msk | - PPI_CHEN_CH25_Msk | PPI_CHEN_CH31_Msk; - NVIC_ClearPendingIRQ(RADIO_IRQn); - g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE; -} - -void -ble_phy_restart_rx(void) -{ - ble_phy_stop_usec_timer(); - ble_phy_disable_irq_and_ppi(); - ble_phy_rx(); -} - -/** - * ble phy disable - * - * Disables the PHY. This should be called when an event is over. It stops - * the usec timer (if used), disables interrupts, disables the RADIO, disables - * PPI and sets state to idle. - */ -void -ble_phy_disable(void) -{ - ble_phy_trace_void(BLE_PHY_TRACE_ID_DISABLE); - - ble_phy_stop_usec_timer(); - ble_phy_disable_irq_and_ppi(); -} - -/* Gets the current access address */ -uint32_t ble_phy_access_addr_get(void) -{ - return g_ble_phy_data.phy_access_address; -} - -/** - * Return the phy state - * - * @return int The current PHY state. - */ -int -ble_phy_state_get(void) -{ - return g_ble_phy_data.phy_state; -} - -/** - * Called to see if a reception has started - * - * @return int - */ -int -ble_phy_rx_started(void) -{ - return g_ble_phy_data.phy_rx_started; -} - -/** - * Return the transceiver state - * - * @return int transceiver state. - */ -uint8_t -ble_phy_xcvr_state_get(void) -{ - uint32_t state; - state = NRF_RADIO->STATE; - return (uint8_t)state; -} - -/** - * Called to return the maximum data pdu payload length supported by the - * phy. For this chip, if encryption is enabled, the maximum payload is 27 - * bytes. - * - * @return uint8_t Maximum data channel PDU payload size supported - */ -uint8_t -ble_phy_max_data_pdu_pyld(void) -{ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - return NRF_MAX_ENCRYPTED_PYLD_LEN; -#else - return BLE_LL_DATA_PDU_MAX_PYLD; -#endif -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -void -ble_phy_resolv_list_enable(void) -{ - NRF_AAR->NIRK = (uint32_t)g_nrf_num_irks; - g_ble_phy_data.phy_privacy = 1; -} - -void -ble_phy_resolv_list_disable(void) -{ - g_ble_phy_data.phy_privacy = 0; -} -#endif - -void -ble_phy_rfclk_enable(void) -{ -#if MYNEWT - nrf51_clock_hfxo_request(); -#else - NRF_CLOCK->TASKS_HFCLKSTART = 1; -#endif -} - -void -ble_phy_rfclk_disable(void) -{ -#if MYNEWT - nrf51_clock_hfxo_release(); -#else - NRF_CLOCK->TASKS_HFCLKSTOP = 1; -#endif -} -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/include/ble/xcvr.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/include/ble/xcvr.h deleted file mode 100644 index fd8e1e898..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/include/ble/xcvr.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) - -#ifndef H_BLE_XCVR_ -#define H_BLE_XCVR_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define XCVR_RX_RADIO_RAMPUP_USECS (40) -#define XCVR_TX_RADIO_RAMPUP_USECS (40) - -/* - * NOTE: we have to account for the RTC output compare issue. We want it to be - * 5 ticks. - */ -#define XCVR_PROC_DELAY_USECS (153) -#define XCVR_RX_START_DELAY_USECS (XCVR_RX_RADIO_RAMPUP_USECS) -#define XCVR_TX_START_DELAY_USECS (XCVR_TX_RADIO_RAMPUP_USECS) -#define XCVR_TX_SCHED_DELAY_USECS \ - (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS) -#define XCVR_RX_SCHED_DELAY_USECS \ - (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS) - -/* - * Define HW whitelist size. This is the total possible whitelist size; - * not necessarily the size that will be used (may be smaller) - */ -#define BLE_HW_WHITE_LIST_SIZE (8) - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_XCVR_ */ -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/pkg.yml deleted file mode 100644 index a1ff457e6..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/pkg.yml +++ /dev/null @@ -1,31 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/drivers/nrf52 -pkg.description: BLE driver for nRF52 systems. -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - -pkg.apis: ble_driver -pkg.deps: - - nimble - - nimble/controller diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_hw.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_hw.c deleted file mode 100644 index 400fddf6f..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_hw.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) - -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "../include/ble/xcvr.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nrf.h" -#include "nimble/nimble/controller/include/controller/ble_hw.h" -#if MYNEWT -#include "mcu/cmsis_nvic.h" -#else -#include "core_cm4.h" -#include "nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h" -#endif -#include "nimble/porting/nimble/include/os/os_trace_api.h" - -/* Total number of resolving list elements */ -#define BLE_HW_RESOLV_LIST_SIZE (16) - -/* We use this to keep track of which entries are set to valid addresses */ -static uint8_t g_ble_hw_whitelist_mask; - -/* Random number generator isr callback */ -ble_rng_isr_cb_t g_ble_rng_isr_cb; - -/* If LL privacy is enabled, allocate memory for AAR */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - -/* The NRF51 supports up to 16 IRK entries */ -#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16) -#define NRF_IRK_LIST_ENTRIES (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)) -#else -#define NRF_IRK_LIST_ENTRIES (16) -#endif - -/* NOTE: each entry is 16 bytes long. */ -uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4]; - -/* Current number of IRK entries */ -uint8_t g_nrf_num_irks; - -#endif - -/* Returns public device address or -1 if not present */ -int -ble_hw_get_public_addr(ble_addr_t *addr) -{ - uint32_t addr_high; - uint32_t addr_low; - - /* Does FICR have a public address */ - if ((NRF_FICR->DEVICEADDRTYPE & 1) != 0) { - return -1; - } - - /* Copy into device address. We can do this because we know platform */ - addr_low = NRF_FICR->DEVICEADDR[0]; - addr_high = NRF_FICR->DEVICEADDR[1]; - memcpy(addr->val, &addr_low, 4); - memcpy(&addr->val[4], &addr_high, 2); - addr->type = BLE_ADDR_PUBLIC; - - return 0; -} - -/* Returns random static address or -1 if not present */ -int -ble_hw_get_static_addr(ble_addr_t *addr) -{ - int rc; - - if ((NRF_FICR->DEVICEADDRTYPE & 1) == 1) { - memcpy(addr->val, (void *)&NRF_FICR->DEVICEADDR[0], 4); - memcpy(&addr->val[4], (void *)&NRF_FICR->DEVICEADDR[1], 2); - addr->val[5] |= 0xc0; - addr->type = BLE_ADDR_RANDOM; - rc = 0; - } else { - rc = -1; - } - - return rc; -} - -/** - * Clear the whitelist - * - * @return int - */ -void -ble_hw_whitelist_clear(void) -{ - NRF_RADIO->DACNF = 0; - g_ble_hw_whitelist_mask = 0; -} - -/** - * Add a device to the hw whitelist - * - * @param addr - * @param addr_type - * - * @return int 0: success, BLE error code otherwise - */ -int -ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type) -{ - int i; - uint32_t mask; - - /* Find first ununsed device address match element */ - mask = 0x01; - for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) { - if ((mask & g_ble_hw_whitelist_mask) == 0) { - NRF_RADIO->DAB[i] = get_le32(addr); - NRF_RADIO->DAP[i] = get_le16(addr + 4); - if (addr_type == BLE_ADDR_RANDOM) { - NRF_RADIO->DACNF |= (mask << 8); - } - g_ble_hw_whitelist_mask |= mask; - return BLE_ERR_SUCCESS; - } - mask <<= 1; - } - - return BLE_ERR_MEM_CAPACITY; -} - -/** - * Remove a device from the hw whitelist - * - * @param addr - * @param addr_type - * - */ -void -ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type) -{ - int i; - uint8_t cfg_addr; - uint16_t dap; - uint16_t txadd; - uint32_t dab; - uint32_t mask; - - /* Find first ununsed device address match element */ - dab = get_le32(addr); - dap = get_le16(addr + 4); - txadd = NRF_RADIO->DACNF >> 8; - mask = 0x01; - for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) { - if (mask & g_ble_hw_whitelist_mask) { - if ((dab == NRF_RADIO->DAB[i]) && (dap == NRF_RADIO->DAP[i])) { - cfg_addr = txadd & mask; - if (addr_type == BLE_ADDR_RANDOM) { - if (cfg_addr != 0) { - break; - } - } else { - if (cfg_addr == 0) { - break; - } - } - } - } - mask <<= 1; - } - - if (i < BLE_HW_WHITE_LIST_SIZE) { - g_ble_hw_whitelist_mask &= ~mask; - NRF_RADIO->DACNF &= ~mask; - } -} - -/** - * Returns the size of the whitelist in HW - * - * @return int Number of devices allowed in whitelist - */ -uint8_t -ble_hw_whitelist_size(void) -{ - return BLE_HW_WHITE_LIST_SIZE; -} - -/** - * Enable the whitelisted devices - */ -void -ble_hw_whitelist_enable(void) -{ - /* Enable the configured device addresses */ - NRF_RADIO->DACNF |= g_ble_hw_whitelist_mask; -} - -/** - * Disables the whitelisted devices - */ -void -ble_hw_whitelist_disable(void) -{ - /* Disable all whitelist devices */ - NRF_RADIO->DACNF &= 0x0000ff00; -} - -/** - * Boolean function which returns true ('1') if there is a match on the - * whitelist. - * - * @return int - */ -int -ble_hw_whitelist_match(void) -{ - return (int)NRF_RADIO->EVENTS_DEVMATCH; -} - -/* Encrypt data */ -int -ble_hw_encrypt_block(struct ble_encryption_block *ecb) -{ - int rc; - uint32_t end; - uint32_t err; - - /* Stop ECB */ - NRF_ECB->TASKS_STOPECB = 1; - /* XXX: does task stop clear these counters? Anyway to do this quicker? */ - NRF_ECB->EVENTS_ENDECB = 0; - NRF_ECB->EVENTS_ERRORECB = 0; - NRF_ECB->ECBDATAPTR = (uint32_t)ecb; - - /* Start ECB */ - NRF_ECB->TASKS_STARTECB = 1; - - /* Wait till error or done */ - rc = 0; - while (1) { - end = NRF_ECB->EVENTS_ENDECB; - err = NRF_ECB->EVENTS_ERRORECB; - if (end || err) { - if (err) { - rc = -1; - } - break; - } - } - - return rc; -} - -/** - * Random number generator ISR. - */ -static void -ble_rng_isr(void) -{ - uint8_t rnum; - - os_trace_isr_enter(); - - /* No callback? Clear and disable interrupts */ - if (g_ble_rng_isr_cb == NULL) { - NRF_RNG->INTENCLR = 1; - NRF_RNG->EVENTS_VALRDY = 0; - (void)NRF_RNG->SHORTS; - os_trace_isr_exit(); - return; - } - - /* If there is a value ready grab it */ - if (NRF_RNG->EVENTS_VALRDY) { - NRF_RNG->EVENTS_VALRDY = 0; - rnum = (uint8_t)NRF_RNG->VALUE; - (*g_ble_rng_isr_cb)(rnum); - } - - os_trace_isr_exit(); -} - -/** - * Initialize the random number generator - * - * @param cb - * @param bias - * - * @return int - */ -int -ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias) -{ - /* Set bias */ - if (bias) { - NRF_RNG->CONFIG = 1; - } else { - NRF_RNG->CONFIG = 0; - } - - /* If we were passed a function pointer we need to enable the interrupt */ - if (cb != NULL) { -#ifndef RIOT_VERSION - NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1); -#endif -#if MYNEWT - NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr); -#else - ble_npl_hw_set_isr(RNG_IRQn, ble_rng_isr); -#endif - NVIC_EnableIRQ(RNG_IRQn); - g_ble_rng_isr_cb = cb; - } - - return 0; -} - -/** - * Start the random number generator - * - * @return int - */ -int -ble_hw_rng_start(void) -{ - os_sr_t sr; - - /* No need for interrupt if there is no callback */ - OS_ENTER_CRITICAL(sr); - NRF_RNG->EVENTS_VALRDY = 0; - if (g_ble_rng_isr_cb) { - NRF_RNG->INTENSET = 1; - } - NRF_RNG->TASKS_START = 1; - OS_EXIT_CRITICAL(sr); - - return 0; -} - -/** - * Stop the random generator - * - * @return int - */ -int -ble_hw_rng_stop(void) -{ - os_sr_t sr; - - /* No need for interrupt if there is no callback */ - OS_ENTER_CRITICAL(sr); - NRF_RNG->INTENCLR = 1; - NRF_RNG->TASKS_STOP = 1; - NRF_RNG->EVENTS_VALRDY = 0; - OS_EXIT_CRITICAL(sr); - - return 0; -} - -/** - * Read the random number generator. - * - * @return uint8_t - */ -uint8_t -ble_hw_rng_read(void) -{ - uint8_t rnum; - - /* Wait for a sample */ - while (NRF_RNG->EVENTS_VALRDY == 0) { - } - - NRF_RNG->EVENTS_VALRDY = 0; - rnum = (uint8_t)NRF_RNG->VALUE; - - return rnum; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -/** - * Clear the resolving list - * - * @return int - */ -void -ble_hw_resolv_list_clear(void) -{ - g_nrf_num_irks = 0; -} - -/** - * Add a device to the hw resolving list - * - * @param irk Pointer to IRK to add - * - * @return int 0: success, BLE error code otherwise - */ -int -ble_hw_resolv_list_add(uint8_t *irk) -{ - uint32_t *nrf_entry; - - /* Find first ununsed device address match element */ - if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) { - return BLE_ERR_MEM_CAPACITY; - } - - /* Copy into irk list */ - nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks]; - memcpy(nrf_entry, irk, 16); - - /* Add to total */ - ++g_nrf_num_irks; - return BLE_ERR_SUCCESS; -} - -/** - * Remove a device from the hw resolving list - * - * @param index Index of IRK to remove - */ -void -ble_hw_resolv_list_rmv(int index) -{ - uint32_t *irk_entry; - - if (index < g_nrf_num_irks) { - --g_nrf_num_irks; - irk_entry = &g_nrf_irk_list[index]; - if (g_nrf_num_irks > index) { - memmove(irk_entry, irk_entry + 4, 16 * (g_nrf_num_irks - index)); - } - } -} - -/** - * Returns the size of the resolving list. NOTE: this returns the maximum - * allowable entries in the HW. Configuration options may limit this. - * - * @return int Number of devices allowed in resolving list - */ -uint8_t -ble_hw_resolv_list_size(void) -{ - return BLE_HW_RESOLV_LIST_SIZE; -} - -/** - * Called to determine if the address received was resolved. - * - * @return int Negative values indicate unresolved address; positive values - * indicate index in resolving list of resolved address. - */ -int -ble_hw_resolv_list_match(void) -{ - uint32_t index; - - if (NRF_AAR->EVENTS_END) { - if (NRF_AAR->EVENTS_RESOLVED) { - index = NRF_AAR->STATUS; - return (int)index; - } - } - - return -1; -} -#endif -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy.c deleted file mode 100644 index 2ee29ab9c..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy.c +++ /dev/null @@ -1,2120 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - #if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) - -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "../include/ble/xcvr.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/include/nimble/nimble_npl.h" -#include "nimble/nimble/controller/include/controller/ble_phy.h" -#include "nimble/nimble/controller/include/controller/ble_phy_trace.h" -#include "nimble/nimble/controller/include/controller/ble_ll.h" -#include "nrf.h" -#if MYNEWT -#include "mcu/nrf52_clock.h" -#include "mcu/cmsis_nvic.h" -#include "hal/hal_gpio.h" -#else -#include "core_cm4.h" -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) -#if !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52840) && !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52811) -#error LE Coded PHY can only be enabled on nRF52811 or nRF52840 -#endif -#endif - -/* - * NOTE: This code uses a couple of PPI channels so care should be taken when - * using PPI somewhere else. - * - * Pre-programmed channels: CH20, CH21, CH23, CH25, CH31 - * Regular channels: CH4, CH5 and optionally CH17, CH18, CH19 - * - CH4 = cancel wfr timer on address match - * - CH5 = disable radio on wfr timer expiry - * - CH17 = (optional) gpio debug for radio ramp-up - * - CH18 = (optional) gpio debug for wfr timer RX enabled - * - CH19 = (optional) gpio debug for wfr timer radio disabled - * - */ - -/* XXX: 4) Make sure RF is higher priority interrupt than schedule */ - -/* - * XXX: Maximum possible transmit time is 1 msec for a 60ppm crystal - * and 16ms for a 30ppm crystal! We need to limit PDU size based on - * crystal accuracy. Look at this in the spec. - */ - -/* XXX: private header file? */ -extern uint8_t g_nrf_num_irks; -extern uint32_t g_nrf_irk_list[]; - -/* To disable all radio interrupts */ -#define NRF_RADIO_IRQ_MASK_ALL (0x34FF) - -/* - * We configure the nrf with a 1 byte S0 field, 8 bit length field, and - * zero bit S1 field. The preamble is 8 bits long. - */ -#define NRF_LFLEN_BITS (8) -#define NRF_S0LEN (1) -#define NRF_S1LEN_BITS (0) -#define NRF_CILEN_BITS (2) -#define NRF_TERMLEN_BITS (3) - -/* Maximum length of frames */ -#define NRF_MAXLEN (255) -#define NRF_BALEN (3) /* For base address of 3 bytes */ - -/* NRF_RADIO->PCNF0 configuration values */ -#define NRF_PCNF0 (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | \ - (RADIO_PCNF0_S1INCL_Msk) | \ - (NRF_S0LEN << RADIO_PCNF0_S0LEN_Pos) | \ - (NRF_S1LEN_BITS << RADIO_PCNF0_S1LEN_Pos) -#define NRF_PCNF0_1M (NRF_PCNF0) | \ - (RADIO_PCNF0_PLEN_8bit << RADIO_PCNF0_PLEN_Pos) -#define NRF_PCNF0_2M (NRF_PCNF0) | \ - (RADIO_PCNF0_PLEN_16bit << RADIO_PCNF0_PLEN_Pos) -#define NRF_PCNF0_CODED (NRF_PCNF0) | \ - (RADIO_PCNF0_PLEN_LongRange << RADIO_PCNF0_PLEN_Pos) | \ - (NRF_CILEN_BITS << RADIO_PCNF0_CILEN_Pos) | \ - (NRF_TERMLEN_BITS << RADIO_PCNF0_TERMLEN_Pos) - -/* BLE PHY data structure */ -struct ble_phy_obj -{ - uint8_t phy_stats_initialized; - int8_t phy_txpwr_dbm; - uint8_t phy_chan; - uint8_t phy_state; - uint8_t phy_transition; - uint8_t phy_transition_late; - uint8_t phy_rx_started; - uint8_t phy_encrypted; - uint8_t phy_privacy; - uint8_t phy_tx_pyld_len; - uint8_t phy_cur_phy_mode; - uint8_t phy_tx_phy_mode; - uint8_t phy_rx_phy_mode; - uint8_t phy_bcc_offset; - int8_t rx_pwr_compensation; - uint32_t phy_aar_scratch; - uint32_t phy_access_address; - struct ble_mbuf_hdr rxhdr; - void *txend_arg; - ble_phy_tx_end_func txend_cb; - uint32_t phy_start_cputime; -}; -struct ble_phy_obj g_ble_phy_data; - -/* XXX: if 27 byte packets desired we can make this smaller */ -/* Global transmit/receive buffer */ -static uint32_t g_ble_phy_tx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; -static uint32_t g_ble_phy_rx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/* Make sure word-aligned for faster copies */ -static uint32_t g_ble_phy_enc_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; -#endif - -/* RF center frequency for each channel index (offset from 2400 MHz) */ -static const uint8_t g_ble_phy_chan_freq[BLE_PHY_NUM_CHANS] = { - 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, /* 0-9 */ - 24, 28, 30, 32, 34, 36, 38, 40, 42, 44, /* 10-19 */ - 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, /* 20-29 */ - 66, 68, 70, 72, 74, 76, 78, 2, 26, 80, /* 30-39 */ -}; - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) -/* packet start offsets (in usecs) */ -static const uint16_t g_ble_phy_mode_pkt_start_off[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 40, - [BLE_PHY_MODE_2M] = 24, - [BLE_PHY_MODE_CODED_125KBPS] = 376, - [BLE_PHY_MODE_CODED_500KBPS] = 376 -}; -#endif - -/* Various radio timings */ -/* Radio ramp-up times in usecs (fast mode) */ -#define BLE_PHY_T_TXENFAST (XCVR_TX_RADIO_RAMPUP_USECS) -#define BLE_PHY_T_RXENFAST (XCVR_RX_RADIO_RAMPUP_USECS) -/* delay between EVENTS_READY and start of tx */ -static const uint8_t g_ble_phy_t_txdelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 4, - [BLE_PHY_MODE_2M] = 3, - [BLE_PHY_MODE_CODED_125KBPS] = 5, - [BLE_PHY_MODE_CODED_500KBPS] = 5 -}; -/* delay between EVENTS_END and end of txd packet */ -static const uint8_t g_ble_phy_t_txenddelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 4, - [BLE_PHY_MODE_2M] = 3, - [BLE_PHY_MODE_CODED_125KBPS] = 9, - [BLE_PHY_MODE_CODED_500KBPS] = 3 -}; -/* delay between rxd access address (w/ TERM1 for coded) and EVENTS_ADDRESS */ -static const uint8_t g_ble_phy_t_rxaddrdelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 6, - [BLE_PHY_MODE_2M] = 2, - [BLE_PHY_MODE_CODED_125KBPS] = 17, - [BLE_PHY_MODE_CODED_500KBPS] = 17 -}; -/* delay between end of rxd packet and EVENTS_END */ -static const uint8_t g_ble_phy_t_rxenddelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 6, - [BLE_PHY_MODE_2M] = 2, - [BLE_PHY_MODE_CODED_125KBPS] = 27, - [BLE_PHY_MODE_CODED_500KBPS] = 22 -}; - -/* Statistics */ -STATS_SECT_START(ble_phy_stats) - STATS_SECT_ENTRY(phy_isrs) - STATS_SECT_ENTRY(tx_good) - STATS_SECT_ENTRY(tx_fail) - STATS_SECT_ENTRY(tx_late) - STATS_SECT_ENTRY(tx_bytes) - STATS_SECT_ENTRY(rx_starts) - STATS_SECT_ENTRY(rx_aborts) - STATS_SECT_ENTRY(rx_valid) - STATS_SECT_ENTRY(rx_crc_err) - STATS_SECT_ENTRY(rx_late) - STATS_SECT_ENTRY(radio_state_errs) - STATS_SECT_ENTRY(rx_hw_err) - STATS_SECT_ENTRY(tx_hw_err) -STATS_SECT_END -STATS_SECT_DECL(ble_phy_stats) ble_phy_stats; - -STATS_NAME_START(ble_phy_stats) - STATS_NAME(ble_phy_stats, phy_isrs) - STATS_NAME(ble_phy_stats, tx_good) - STATS_NAME(ble_phy_stats, tx_fail) - STATS_NAME(ble_phy_stats, tx_late) - STATS_NAME(ble_phy_stats, tx_bytes) - STATS_NAME(ble_phy_stats, rx_starts) - STATS_NAME(ble_phy_stats, rx_aborts) - STATS_NAME(ble_phy_stats, rx_valid) - STATS_NAME(ble_phy_stats, rx_crc_err) - STATS_NAME(ble_phy_stats, rx_late) - STATS_NAME(ble_phy_stats, radio_state_errs) - STATS_NAME(ble_phy_stats, rx_hw_err) - STATS_NAME(ble_phy_stats, tx_hw_err) -STATS_NAME_END(ble_phy_stats) - -/* - * NOTE: - * Tested the following to see what would happen: - * -> NVIC has radio irq enabled (interrupt # 1, mask 0x2). - * -> Set up nrf to receive. Clear ADDRESS event register. - * -> Enable ADDRESS interrupt on nrf5 by writing to INTENSET. - * -> Enable RX. - * -> Disable interrupts globally using OS_ENTER_CRITICAL(). - * -> Wait until a packet is received and the ADDRESS event occurs. - * -> Call ble_phy_disable(). - * - * At this point I wanted to see the state of the cortex NVIC. The IRQ - * pending bit was TRUE for the radio interrupt (as expected) as we never - * serviced the radio interrupt (interrupts were disabled). - * - * What was unexpected was this: without clearing the pending IRQ in the NVIC, - * when radio interrupts were re-enabled (address event bit in INTENSET set to - * 1) and the radio ADDRESS event register read 1 (it was never cleared after - * the first address event), the radio did not enter the ISR! I would have - * expected that if the following were true, an interrupt would occur: - * -> NVIC ISER bit set to TRUE - * -> NVIC ISPR bit reads TRUE, meaning interrupt is pending. - * -> Radio peripheral interrupts are enabled for some event (or events). - * -> Corresponding event register(s) in radio peripheral read 1. - * - * Not sure what the end result of all this is. We will clear the pending - * bit in the NVIC just to be sure when we disable the PHY. - */ - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - -/* - * Per nordic, the number of bytes needed for scratch is 16 + MAX_PKT_SIZE. - * However, when I used a smaller size it still overwrote the scratchpad. Until - * I figure this out I am just going to allocate 67 words so we have enough - * space for 267 bytes of scratch. I used 268 bytes since not sure if this - * needs to be aligned and burning a byte is no big deal. - */ -//#define NRF_ENC_SCRATCH_WORDS (((MYNEWT_VAL(BLE_LL_MAX_PKT_SIZE) + 16) + 3) / 4) -#define NRF_ENC_SCRATCH_WORDS (67) - -uint32_t g_nrf_encrypt_scratchpad[NRF_ENC_SCRATCH_WORDS]; - -struct nrf_ccm_data -{ - uint8_t key[16]; - uint64_t pkt_counter; - uint8_t dir_bit; - uint8_t iv[8]; -} __attribute__((packed)); - -struct nrf_ccm_data g_nrf_ccm_data; -#endif - -static void -ble_phy_apply_errata_102_106_107(void) -{ - /* [102] RADIO: PAYLOAD/END events delayed or not triggered after ADDRESS - * [106] RADIO: Higher CRC error rates for some access addresses - * [107] RADIO: Immediate address match for access addresses containing MSBs 0x00 - */ - *(volatile uint32_t *)0x40001774 = ((*(volatile uint32_t *)0x40001774) & - 0xfffffffe) | 0x01000000; -} - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - -/* Packet start offset (in usecs). This is the preamble plus access address. - * For LE Coded PHY this also includes CI and TERM1. */ -uint32_t -ble_phy_mode_pdu_start_off(int phy_mode) -{ - return g_ble_phy_mode_pkt_start_off[phy_mode]; -} - -#if NRF52840_XXAA -static inline bool -ble_phy_mode_is_coded(uint8_t phy_mode) -{ - return (phy_mode == BLE_PHY_MODE_CODED_125KBPS) || - (phy_mode == BLE_PHY_MODE_CODED_500KBPS); -} - -static void -ble_phy_apply_nrf52840_errata(uint8_t new_phy_mode) -{ - bool new_coded = ble_phy_mode_is_coded(new_phy_mode); - bool cur_coded = ble_phy_mode_is_coded(g_ble_phy_data.phy_cur_phy_mode); - - /* - * Workarounds should be applied only when switching to/from LE Coded PHY - * so no need to apply them every time. - * - * nRF52840 Engineering A Errata v1.2 - * [164] RADIO: Low sensitivity in long range mode - * - * nRF52840 Rev 1 Errata - * [191] RADIO: High packet error rate in BLE Long Range mode - */ - if (new_coded == cur_coded) { - return; - } - - if (new_coded) { -#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_164) - /* [164] */ - *(volatile uint32_t *)0x4000173C |= 0x80000000; - *(volatile uint32_t *)0x4000173C = - ((*(volatile uint32_t *)0x4000173C & 0xFFFFFF00) | 0x5C); -#endif -#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_191) - /* [191] */ - *(volatile uint32_t *) 0x40001740 = - ((*((volatile uint32_t *) 0x40001740)) & 0x7FFF00FF) | - 0x80000000 | (((uint32_t)(196)) << 8); -#endif - } else { -#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_164) - /* [164] */ - *(volatile uint32_t *)0x4000173C &= ~0x80000000; -#endif -#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_191) - /* [191] */ - *(volatile uint32_t *) 0x40001740 = - ((*((volatile uint32_t *) 0x40001740)) & 0x7FFFFFFF); -#endif - } -} -#endif - -static void -ble_phy_mode_apply(uint8_t phy_mode) -{ - if (phy_mode == g_ble_phy_data.phy_cur_phy_mode) { - return; - } - -#if NRF52840_XXAA - ble_phy_apply_nrf52840_errata(phy_mode); -#endif - - switch (phy_mode) { - case BLE_PHY_MODE_1M: - NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit; - NRF_RADIO->PCNF0 = NRF_PCNF0_1M; - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - case BLE_PHY_MODE_2M: - NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_2Mbit; - NRF_RADIO->PCNF0 = NRF_PCNF0_2M; - break; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - case BLE_PHY_MODE_CODED_125KBPS: - NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_LR125Kbit; - NRF_RADIO->PCNF0 = NRF_PCNF0_CODED; - break; - case BLE_PHY_MODE_CODED_500KBPS: - NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_LR500Kbit; - NRF_RADIO->PCNF0 = NRF_PCNF0_CODED; - break; -#endif - default: - assert(0); - } - - g_ble_phy_data.phy_cur_phy_mode = phy_mode; -} - -void -ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode) -{ - g_ble_phy_data.phy_tx_phy_mode = tx_phy_mode; - g_ble_phy_data.phy_rx_phy_mode = rx_phy_mode; -} -#endif - -int -ble_phy_get_cur_phy(void) -{ -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - switch (g_ble_phy_data.phy_cur_phy_mode) { - case BLE_PHY_MODE_1M: - return BLE_PHY_1M; - case BLE_PHY_MODE_2M: - return BLE_PHY_2M; - case BLE_PHY_MODE_CODED_125KBPS: - case BLE_PHY_MODE_CODED_500KBPS: - return BLE_PHY_CODED; - default: - assert(0); - return -1; - } -#else - return BLE_PHY_1M; -#endif -} - -/** - * Copies the data from the phy receive buffer into a mbuf chain. - * - * @param dptr Pointer to receive buffer - * @param rxpdu Pointer to already allocated mbuf chain - * - * NOTE: the packet header already has the total mbuf length in it. The - * lengths of the individual mbufs are not set prior to calling. - * - */ -void -ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu) -{ - uint32_t rem_len; - uint32_t copy_len; - uint32_t block_len; - uint32_t block_rem_len; - void *dst; - void *src; - struct os_mbuf * om; - - /* Better be aligned */ - assert(((uint32_t)dptr & 3) == 0); - - block_len = rxpdu->om_omp->omp_databuf_len; - rem_len = OS_MBUF_PKTHDR(rxpdu)->omp_len; - src = dptr; - - /* - * Setup for copying from first mbuf which is shorter due to packet header - * and extra leading space - */ - copy_len = block_len - rxpdu->om_pkthdr_len - 4; - om = rxpdu; - dst = om->om_data; - - while (true) { - /* - * Always copy blocks of length aligned to word size, only last mbuf - * will have remaining non-word size bytes appended. - */ - block_rem_len = copy_len; - copy_len = min(copy_len, rem_len); - copy_len &= ~3; - - dst = om->om_data; - om->om_len = copy_len; - rem_len -= copy_len; - block_rem_len -= copy_len; - - __asm__ volatile (".syntax unified \n" - " mov r4, %[len] \n" - " b 2f \n" - "1: ldr r3, [%[src], %[len]] \n" - " str r3, [%[dst], %[len]] \n" - "2: subs %[len], #4 \n" - " bpl 1b \n" - " adds %[src], %[src], r4 \n" - " adds %[dst], %[dst], r4 \n" - : [dst] "+r" (dst), [src] "+r" (src), - [len] "+r" (copy_len) - : - : "r3", "r4", "memory" - ); - - if ((rem_len < 4) && (block_rem_len >= rem_len)) { - break; - } - - /* Move to next mbuf */ - om = SLIST_NEXT(om, om_next); - copy_len = block_len; - } - - /* Copy remaining bytes, if any, to last mbuf */ - om->om_len += rem_len; - __asm__ volatile (".syntax unified \n" - " b 2f \n" - "1: ldrb r3, [%[src], %[len]] \n" - " strb r3, [%[dst], %[len]] \n" - "2: subs %[len], #1 \n" - " bpl 1b \n" - : [len] "+r" (rem_len) - : [dst] "r" (dst), [src] "r" (src) - : "r3", "memory" - ); - - /* Copy header */ - memcpy(BLE_MBUF_HDR_PTR(rxpdu), &g_ble_phy_data.rxhdr, - sizeof(struct ble_mbuf_hdr)); -} - -/** - * Called when we want to wait if the radio is in either the rx or tx - * disable states. We want to wait until that state is over before doing - * anything to the radio - */ -static void -nrf_wait_disabled(void) -{ - uint32_t state; - - state = NRF_RADIO->STATE; - if (state != RADIO_STATE_STATE_Disabled) { - if ((state == RADIO_STATE_STATE_RxDisable) || - (state == RADIO_STATE_STATE_TxDisable)) { - /* This will end within a short time (6 usecs). Just poll */ - while (NRF_RADIO->STATE == state) { - /* If this fails, something is really wrong. Should last - * no more than 6 usecs */ - } - } - } -} - -/** - * - * - */ -static int -ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs, bool tx) -{ - uint32_t next_cc; - uint32_t cur_cc; - uint32_t cntr; - uint32_t delta; - - /* - * We need to adjust start time to include radio ramp-up and TX pipeline - * delay (the latter only if applicable, so only for TX). - * - * Radio ramp-up time is 40 usecs and TX delay is 3 or 5 usecs depending on - * phy, thus we'll offset RTC by 2 full ticks (61 usecs) and then compensate - * using TIMER0 with 1 usec precision. - */ - - cputime -= 2; - rem_usecs += 61; - if (tx) { - rem_usecs -= BLE_PHY_T_TXENFAST; - rem_usecs -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; - } else { - rem_usecs -= BLE_PHY_T_RXENFAST; - } - - /* - * rem_usecs will be no more than 2 ticks, but if it is more than single - * tick then we should better count one more low-power tick rather than - * 30 high-power usecs. Also make sure we don't set TIMER0 CC to 0 as the - * compare won't occur. - */ - - if (rem_usecs > 30) { - cputime++; - rem_usecs -= 30; - } - - /* - * Can we set the RTC compare to start TIMER0? We can do it if: - * a) Current compare value is not N+1 or N+2 ticks from current - * counter. - * b) The value we want to set is not at least N+2 from current - * counter. - * - * NOTE: since the counter can tick 1 while we do these calculations we - * need to account for it. - */ - next_cc = cputime & 0xffffff; - cur_cc = NRF_RTC0->CC[0]; - cntr = NRF_RTC0->COUNTER; - - delta = (cur_cc - cntr) & 0xffffff; - if ((delta <= 3) && (delta != 0)) { - return -1; - } - delta = (next_cc - cntr) & 0xffffff; - if ((delta & 0x800000) || (delta < 3)) { - return -1; - } - - /* Clear and set TIMER0 to fire off at proper time */ - NRF_TIMER0->TASKS_CLEAR = 1; - NRF_TIMER0->CC[0] = rem_usecs; - NRF_TIMER0->EVENTS_COMPARE[0] = 0; - - /* Set RTC compare to start TIMER0 */ - NRF_RTC0->EVENTS_COMPARE[0] = 0; - NRF_RTC0->CC[0] = next_cc; - NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; - - /* Enable PPI */ - NRF_PPI->CHENSET = PPI_CHEN_CH31_Msk; - - /* Store the cputime at which we set the RTC */ - g_ble_phy_data.phy_start_cputime = cputime; - - return 0; -} - -static int -ble_phy_set_start_now(void) -{ - os_sr_t sr; - uint32_t now; - - OS_ENTER_CRITICAL(sr); - - /* - * Set TIMER0 to fire immediately. We can't set CC to 0 as compare will not - * occur in such case. - */ - NRF_TIMER0->TASKS_CLEAR = 1; - NRF_TIMER0->CC[0] = 1; - NRF_TIMER0->EVENTS_COMPARE[0] = 0; - - /* - * Set RTC compare to start TIMER0. We need to set it to at least N+2 ticks - * from current value to guarantee triggering compare event, but let's set - * it to N+3 to account for possible extra tick on RTC0 during these - * operations. - */ - now = os_cputime_get32(); - NRF_RTC0->EVENTS_COMPARE[0] = 0; - NRF_RTC0->CC[0] = now + 3; - NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; - - /* Enable PPI */ - NRF_PPI->CHENSET = PPI_CHEN_CH31_Msk; - - /* - * Store the cputime at which we set the RTC - * - * XXX Compare event may be triggered on previous CC value (if it was set to - * less than N+2) so in rare cases actual start time may be 2 ticks earlier - * than what we expect. Since this is only used on RX, it may cause AUX scan - * to be scheduled 1 or 2 ticks too late so we'll miss it - it's acceptable - * for now. - */ - g_ble_phy_data.phy_start_cputime = now + 3; - - OS_EXIT_CRITICAL(sr); - - return 0; -} - -/** - * Function is used to set PPI so that we can time out waiting for a reception - * to occur. This happens for two reasons: we have sent a packet and we are - * waiting for a respons (txrx should be set to ENABLE_TXRX) or we are - * starting a connection event and we are a slave and we are waiting for the - * master to send us a packet (txrx should be set to ENABLE_RX). - * - * NOTE: when waiting for a txrx turn-around, wfr_usecs is not used as there - * is no additional time to wait; we know when we should receive the address of - * the received frame. - * - * @param txrx Flag denoting if this wfr is a txrx turn-around or not. - * @param tx_phy_mode phy mode for last TX (only valid for TX->RX) - * @param wfr_usecs Amount of usecs to wait. - */ -void -ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) -{ - uint32_t end_time; - uint8_t phy; - - phy = g_ble_phy_data.phy_cur_phy_mode; - - if (txrx == BLE_PHY_WFR_ENABLE_TXRX) { - /* RX shall start exactly T_IFS after TX end captured in CC[2] */ - end_time = NRF_TIMER0->CC[2] + BLE_LL_IFS; - /* Adjust for delay between EVENT_END and actual TX end time */ - end_time += g_ble_phy_t_txenddelay[tx_phy_mode]; - /* Wait a bit longer due to allowed active clock accuracy */ - end_time += 2; - /* - * It's possible that we'll capture PDU start time at the end of timer - * cycle and since wfr expires at the beginning of calculated timer - * cycle it can be almost 1 usec too early. Let's compensate for this - * by waiting 1 usec more. - */ - end_time += 1; -#if MYNEWT_VAL(BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN) > 0 - if ((phy == BLE_PHY_MODE_CODED_125KBPS) || - (phy == BLE_PHY_MODE_CODED_500KBPS)) { - /* - * Some controllers exceed T_IFS when transmitting on coded phy - * so let's wait a bit longer to be able to talk to them if this - * workaround is enabled. - */ - end_time += MYNEWT_VAL(BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN); - } -#endif - } else { - /* - * RX shall start no later than wfr_usecs after RX enabled. - * CC[0] is the time of RXEN so adjust for radio ram-up. - * Do not add jitter since this is already covered by LL. - */ - end_time = NRF_TIMER0->CC[0] + BLE_PHY_T_RXENFAST + wfr_usecs; - } - - /* - * Note: on LE Coded EVENT_ADDRESS is fired after TERM1 is received, so - * we are actually calculating relative to start of packet payload - * which is fine. - */ - - /* Adjust for receiving access address since this triggers EVENT_ADDRESS */ - end_time += ble_phy_mode_pdu_start_off(phy); - /* Adjust for delay between actual access address RX and EVENT_ADDRESS */ - end_time += g_ble_phy_t_rxaddrdelay[phy]; - - /* wfr_secs is the time from rxen until timeout */ - NRF_TIMER0->CC[3] = end_time; - NRF_TIMER0->EVENTS_COMPARE[3] = 0; - - /* Enable wait for response PPI */ - NRF_PPI->CHENSET = (PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk); - - /* Enable the disabled interrupt so we time out on events compare */ - NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; - - /* - * It may happen that if CPU is halted for a brief moment (e.g. during flash - * erase or write), TIMER0 already counted past CC[3] and thus wfr will not - * fire as expected. In case this happened, let's just disable PPIs for wfr - * and trigger wfr manually (i.e. disable radio). - * - * Note that the same applies to RX start time set in CC[0] but since it - * should fire earlier than wfr, fixing wfr is enough. - * - * CC[1] is only used as a reference on RX start, we do not need it here so - * it can be used to read TIMER0 counter. - */ - NRF_TIMER0->TASKS_CAPTURE[1] = 1; - if (NRF_TIMER0->CC[1] > NRF_TIMER0->CC[3]) { - NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk; - NRF_RADIO->TASKS_DISABLE = 1; - } -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -static uint32_t -ble_phy_get_ccm_datarate(void) -{ -#if BLE_LL_BT5_PHY_SUPPORTED - switch (g_ble_phy_data.phy_cur_phy_mode) { - case BLE_PHY_MODE_1M: - return CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos; - case BLE_PHY_MODE_2M: - return CCM_MODE_DATARATE_2Mbit << CCM_MODE_DATARATE_Pos; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - case BLE_PHY_MODE_CODED_125KBPS: - return CCM_MODE_DATARATE_125Kbps << CCM_MODE_DATARATE_Pos; - case BLE_PHY_MODE_CODED_500KBPS: - return CCM_MODE_DATARATE_500Kbps << CCM_MODE_DATARATE_Pos; -#endif - } - - assert(0); - return 0; -#else - return CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos; -#endif -} -#endif - -/** - * Setup transceiver for receive. - */ -static void -ble_phy_rx_xcvr_setup(void) -{ - uint8_t *dptr; - - dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; - dptr += 3; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (g_ble_phy_data.phy_encrypted) { - NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_enc_buf[0]; - NRF_CCM->INPTR = (uint32_t)&g_ble_phy_enc_buf[0]; - NRF_CCM->OUTPTR = (uint32_t)dptr; - NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0]; - NRF_CCM->MODE = CCM_MODE_LENGTH_Msk | CCM_MODE_MODE_Decryption | - ble_phy_get_ccm_datarate(); - NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data; - NRF_CCM->SHORTS = 0; - NRF_CCM->EVENTS_ERROR = 0; - NRF_CCM->EVENTS_ENDCRYPT = 0; - NRF_CCM->TASKS_KSGEN = 1; - NRF_PPI->CHENSET = PPI_CHEN_CH25_Msk; - } else { - NRF_RADIO->PACKETPTR = (uint32_t)dptr; - } -#else - NRF_RADIO->PACKETPTR = (uint32_t)dptr; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (g_ble_phy_data.phy_privacy) { - NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Enabled; - NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; - NRF_AAR->SCRATCHPTR = (uint32_t)&g_ble_phy_data.phy_aar_scratch; - NRF_AAR->EVENTS_END = 0; - NRF_AAR->EVENTS_RESOLVED = 0; - NRF_AAR->EVENTS_NOTRESOLVED = 0; - } else { - if (g_ble_phy_data.phy_encrypted == 0) { - NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled; - } - } -#endif - - /* Turn off trigger TXEN on output compare match and AAR on bcmatch */ - NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk | PPI_CHEN_CH23_Msk; - - /* Reset the rx started flag. Used for the wait for response */ - g_ble_phy_data.phy_rx_started = 0; - g_ble_phy_data.phy_state = BLE_PHY_STATE_RX; - -#if BLE_LL_BT5_PHY_SUPPORTED - /* - * On Coded PHY there are CI and TERM1 fields before PDU starts so we need - * to take this into account when setting up BCC. - */ - if (g_ble_phy_data.phy_cur_phy_mode == BLE_PHY_MODE_CODED_125KBPS || - g_ble_phy_data.phy_cur_phy_mode == BLE_PHY_MODE_CODED_500KBPS) { - g_ble_phy_data.phy_bcc_offset = 5; - } else { - g_ble_phy_data.phy_bcc_offset = 0; - } -#else - g_ble_phy_data.phy_bcc_offset = 0; -#endif - - /* I want to know when 1st byte received (after address) */ - NRF_RADIO->BCC = 8 + g_ble_phy_data.phy_bcc_offset; /* in bits */ - NRF_RADIO->EVENTS_ADDRESS = 0; - NRF_RADIO->EVENTS_DEVMATCH = 0; - NRF_RADIO->EVENTS_BCMATCH = 0; - NRF_RADIO->EVENTS_RSSIEND = 0; - NRF_RADIO->EVENTS_CRCOK = 0; - NRF_RADIO->SHORTS = RADIO_SHORTS_END_DISABLE_Msk | - RADIO_SHORTS_READY_START_Msk | - RADIO_SHORTS_ADDRESS_BCSTART_Msk | - RADIO_SHORTS_ADDRESS_RSSISTART_Msk | - RADIO_SHORTS_DISABLED_RSSISTOP_Msk; - - NRF_RADIO->INTENSET = RADIO_INTENSET_ADDRESS_Msk; -} - -/** - * Called from interrupt context when the transmit ends - * - */ -static void -ble_phy_tx_end_isr(void) -{ - uint8_t tx_phy_mode; - uint8_t was_encrypted; - uint8_t transition; - uint32_t rx_time; - uint32_t wfr_time; - - /* Store PHY on which we've just transmitted smth */ - tx_phy_mode = g_ble_phy_data.phy_cur_phy_mode; - - /* If this transmission was encrypted we need to remember it */ - was_encrypted = g_ble_phy_data.phy_encrypted; - (void)was_encrypted; - - /* Better be in TX state! */ - assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX); - - /* Clear events and clear interrupt on disabled event */ - NRF_RADIO->EVENTS_DISABLED = 0; - NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk; - NRF_RADIO->EVENTS_END = 0; - wfr_time = NRF_RADIO->SHORTS; - (void)wfr_time; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - /* - * XXX: not sure what to do. We had a HW error during transmission. - * For now I just count a stat but continue on like all is good. - */ - if (was_encrypted) { - if (NRF_CCM->EVENTS_ERROR) { - STATS_INC(ble_phy_stats, tx_hw_err); - NRF_CCM->EVENTS_ERROR = 0; - } - } -#endif - - /* Call transmit end callback */ - if (g_ble_phy_data.txend_cb) { - g_ble_phy_data.txend_cb(g_ble_phy_data.txend_arg); - } - - transition = g_ble_phy_data.phy_transition; - if (transition == BLE_PHY_TRANSITION_TX_RX) { - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_apply(g_ble_phy_data.phy_rx_phy_mode); -#endif - - /* Packet pointer needs to be reset. */ - ble_phy_rx_xcvr_setup(); - - ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, tx_phy_mode, 0); - - /* Schedule RX exactly T_IFS after TX end captured in CC[2] */ - rx_time = NRF_TIMER0->CC[2] + BLE_LL_IFS; - /* Adjust for delay between EVENT_END and actual TX end time */ - rx_time += g_ble_phy_t_txenddelay[tx_phy_mode]; - /* Adjust for radio ramp-up */ - rx_time -= BLE_PHY_T_RXENFAST; - /* Start listening a bit earlier due to allowed active clock accuracy */ - rx_time -= 2; - - NRF_TIMER0->CC[0] = rx_time; - NRF_TIMER0->EVENTS_COMPARE[0] = 0; - NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk; - } else { - /* - * XXX: not sure we need to stop the timer here all the time. Or that - * it should be stopped here. - */ - NRF_TIMER0->TASKS_STOP = 1; - NRF_TIMER0->TASKS_SHUTDOWN = 1; - NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | - PPI_CHEN_CH20_Msk | PPI_CHEN_CH31_Msk; - assert(transition == BLE_PHY_TRANSITION_NONE); - } -} - -static inline uint8_t -ble_phy_get_cur_rx_phy_mode(void) -{ - uint8_t phy; - - phy = g_ble_phy_data.phy_cur_phy_mode; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - /* - * For Coded PHY mode can be set to either codings since actual coding is - * set in packet header. However, here we need actual coding of received - * packet as this determines pipeline delays so need to figure this out - * using CI field. - */ - if ((phy == BLE_PHY_MODE_CODED_125KBPS) || - (phy == BLE_PHY_MODE_CODED_500KBPS)) { - phy = NRF_RADIO->PDUSTAT & RADIO_PDUSTAT_CISTAT_Msk ? - BLE_PHY_MODE_CODED_500KBPS : - BLE_PHY_MODE_CODED_125KBPS; - } -#endif - - return phy; -} - -static void -ble_phy_rx_end_isr(void) -{ - int rc; - uint8_t *dptr; - uint8_t crcok; - uint32_t tx_time; - struct ble_mbuf_hdr *ble_hdr; - - /* Clear events and clear interrupt */ - NRF_RADIO->EVENTS_END = 0; - NRF_RADIO->INTENCLR = RADIO_INTENCLR_END_Msk; - - /* Disable automatic RXEN */ - NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk; - - /* Set RSSI and CRC status flag in header */ - ble_hdr = &g_ble_phy_data.rxhdr; - assert(NRF_RADIO->EVENTS_RSSIEND != 0); - ble_hdr->rxinfo.rssi = (-1 * NRF_RADIO->RSSISAMPLE) + - g_ble_phy_data.rx_pwr_compensation; - - dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; - dptr += 3; - - /* Count PHY crc errors and valid packets */ - crcok = NRF_RADIO->EVENTS_CRCOK; - if (!crcok) { - STATS_INC(ble_phy_stats, rx_crc_err); - } else { - STATS_INC(ble_phy_stats, rx_valid); - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (g_ble_phy_data.phy_encrypted) { - /* Only set MIC failure flag if frame is not zero length */ - if ((dptr[1] != 0) && (NRF_CCM->MICSTATUS == 0)) { - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_MIC_FAILURE; - } - - /* - * XXX: not sure how to deal with this. This should not - * be a MIC failure but we should not hand it up. I guess - * this is just some form of rx error and that is how we - * handle it? For now, just set CRC error flags - */ - if (NRF_CCM->EVENTS_ERROR) { - STATS_INC(ble_phy_stats, rx_hw_err); - ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; - } - - /* - * XXX: This is a total hack work-around for now but I dont - * know what else to do. If ENDCRYPT is not set and we are - * encrypted we need to not trust this frame and drop it. - */ - if (NRF_CCM->EVENTS_ENDCRYPT == 0) { - STATS_INC(ble_phy_stats, rx_hw_err); - ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; - } - } -#endif - } - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_apply(g_ble_phy_data.phy_tx_phy_mode); -#endif - - /* - * Let's schedule TX now and we will just cancel it after processing RXed - * packet if we don't need TX. - * - * We need this to initiate connection in case AUX_CONNECT_REQ was sent on - * LE Coded S8. In this case the time we process RXed packet is roughly the - * same as the limit when we need to have TX scheduled (i.e. TIMER0 and PPI - * armed) so we may simply miss the slot and set the timer in the past. - * - * When TX is scheduled in advance, we may event process packet a bit longer - * during radio ramp-up - this gives us extra 40 usecs which is more than - * enough. - */ - - /* Schedule TX exactly T_IFS after RX end captured in CC[2] */ - tx_time = NRF_TIMER0->CC[2] + BLE_LL_IFS; - /* Adjust for delay between actual RX end time and EVENT_END */ - tx_time -= g_ble_phy_t_rxenddelay[ble_hdr->rxinfo.phy_mode]; - /* Adjust for radio ramp-up */ - tx_time -= BLE_PHY_T_TXENFAST; - /* Adjust for delay between EVENT_READY and actual TX start time */ - tx_time -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; - - NRF_TIMER0->CC[0] = tx_time; - NRF_TIMER0->EVENTS_COMPARE[0] = 0; - NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk; - - /* - * XXX: Hack warning! - * - * It may happen (during flash erase) that CPU is stopped for a moment and - * TIMER0 already counted past CC[0]. In such case we will be stuck waiting - * for TX to start since EVENTS_COMPARE[0] will not happen any time soon. - * For now let's set a flag denoting that we are late in RX-TX transition so - * ble_phy_tx() will fail - this allows everything to cleanup nicely without - * the need for extra handling in many places. - * - * Note: CC[3] is used only for wfr which we do not need here. - */ - NRF_TIMER0->TASKS_CAPTURE[3] = 1; - if (NRF_TIMER0->CC[3] > NRF_TIMER0->CC[0]) { - NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk; - g_ble_phy_data.phy_transition_late = 1; - } - - /* - * XXX: This is a horrible ugly hack to deal with the RAM S1 byte - * that is not sent over the air but is present here. Simply move the - * data pointer to deal with it. Fix this later. - */ - dptr[2] = dptr[1]; - dptr[1] = dptr[0]; - rc = ble_ll_rx_end(dptr + 1, ble_hdr); - if (rc < 0) { - ble_phy_disable(); - } -} - -static bool -ble_phy_rx_start_isr(void) -{ - int rc; - uint32_t state; - uint32_t usecs; - uint32_t pdu_usecs; - uint32_t ticks; - struct ble_mbuf_hdr *ble_hdr; - uint8_t *dptr; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - int adva_offset; -#endif - - dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; - - /* Clear events and clear interrupt */ - NRF_RADIO->EVENTS_ADDRESS = 0; - - /* Clear wfr timer channels and DISABLED interrupt */ - NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk | RADIO_INTENCLR_ADDRESS_Msk; - NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk; - - /* Initialize the ble mbuf header */ - ble_hdr = &g_ble_phy_data.rxhdr; - ble_hdr->rxinfo.flags = ble_ll_state_get(); - ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan; - ble_hdr->rxinfo.handle = 0; - ble_hdr->rxinfo.phy = ble_phy_get_cur_phy(); - ble_hdr->rxinfo.phy_mode = ble_phy_get_cur_rx_phy_mode(); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - ble_hdr->rxinfo.user_data = NULL; -#endif - - /* - * Calculate accurate packets start time (with remainder) - * - * We may start receiving packet somewhere during preamble in which case - * it is possible that actual transmission started before TIMER0 was - * running - need to take this into account. - */ - ble_hdr->beg_cputime = g_ble_phy_data.phy_start_cputime; - - usecs = NRF_TIMER0->CC[1]; - pdu_usecs = ble_phy_mode_pdu_start_off(ble_hdr->rxinfo.phy_mode) + - g_ble_phy_t_rxaddrdelay[ble_hdr->rxinfo.phy_mode]; - if (usecs < pdu_usecs) { - g_ble_phy_data.phy_start_cputime--; - usecs += 30; - } - usecs -= pdu_usecs; - - ticks = os_cputime_usecs_to_ticks(usecs); - usecs -= os_cputime_ticks_to_usecs(ticks); - if (usecs == 31) { - usecs = 0; - ++ticks; - } - - ble_hdr->beg_cputime += ticks; - ble_hdr->rem_usecs = usecs; - - /* XXX: I wonder if we always have the 1st byte. If we need to wait for - * rx chain delay, it could be 18 usecs from address interrupt. The - nrf52 may be able to get here early. */ - /* Wait to get 1st byte of frame */ - while (1) { - state = NRF_RADIO->STATE; - if (NRF_RADIO->EVENTS_BCMATCH != 0) { - break; - } - - /* - * If state is disabled, we should have the BCMATCH. If not, - * something is wrong! - */ - if (state == RADIO_STATE_STATE_Disabled) { - NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; - NRF_RADIO->SHORTS = 0; - return false; - } - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* - * If privacy is enabled and received PDU has TxAdd bit set (i.e. random - * address) we try to resolve address using AAR. - */ - if (g_ble_phy_data.phy_privacy && (dptr[3] & 0x40)) { - /* - * AdvA is located at 4th octet in RX buffer (after S0, length an S1 - * fields). In case of extended advertising PDU we need to add 2 more - * octets for extended header. - */ - adva_offset = (dptr[3] & 0x0f) == 0x07 ? 2 : 0; - NRF_AAR->ADDRPTR = (uint32_t)(dptr + 3 + adva_offset); - - /* Trigger AAR after last bit of AdvA is received */ - NRF_RADIO->EVENTS_BCMATCH = 0; - NRF_PPI->CHENSET = PPI_CHEN_CH23_Msk; - NRF_RADIO->BCC = (BLE_LL_PDU_HDR_LEN + adva_offset + BLE_DEV_ADDR_LEN) * 8 + - g_ble_phy_data.phy_bcc_offset; - } -#endif - - /* Call Link Layer receive start function */ - rc = ble_ll_rx_start(dptr + 3, - g_ble_phy_data.phy_chan, - &g_ble_phy_data.rxhdr); - if (rc >= 0) { - /* Set rx started flag and enable rx end ISR */ - g_ble_phy_data.phy_rx_started = 1; - NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk; - } else { - /* Disable PHY */ - ble_phy_disable(); - STATS_INC(ble_phy_stats, rx_aborts); - } - - /* Count rx starts */ - STATS_INC(ble_phy_stats, rx_starts); - - return true; -} - -static void -ble_phy_isr(void) -{ - uint32_t irq_en; - - os_trace_isr_enter(); - - /* Read irq register to determine which interrupts are enabled */ - irq_en = NRF_RADIO->INTENCLR; - - /* - * NOTE: order of checking is important! Possible, if things get delayed, - * we have both an ADDRESS and DISABLED interrupt in rx state. If we get - * an address, we disable the DISABLED interrupt. - */ - - /* We get this if we have started to receive a frame */ - if ((irq_en & RADIO_INTENCLR_ADDRESS_Msk) && NRF_RADIO->EVENTS_ADDRESS) { - /* - * wfr timer is calculated to expire at the exact time we should start - * receiving a packet (with 1 usec precision) so it is possible it will - * fire at the same time as EVENT_ADDRESS. If this happens, radio will - * be disabled while we are waiting for EVENT_BCCMATCH after 1st byte - * of payload is received and ble_phy_rx_start_isr() will fail. In this - * case we should not clear DISABLED irq mask so it will be handled as - * regular radio disabled event below. In other case radio was disabled - * on purpose and there's nothing more to handle so we can clear mask. - */ - if (ble_phy_rx_start_isr()) { - irq_en &= ~RADIO_INTENCLR_DISABLED_Msk; - } - } - - /* Check for disabled event. This only happens for transmits now */ - if ((irq_en & RADIO_INTENCLR_DISABLED_Msk) && NRF_RADIO->EVENTS_DISABLED) { - if (g_ble_phy_data.phy_state == BLE_PHY_STATE_RX) { - NRF_RADIO->EVENTS_DISABLED = 0; - ble_ll_wfr_timer_exp(NULL); - } else if (g_ble_phy_data.phy_state == BLE_PHY_STATE_IDLE) { - assert(0); - } else { - ble_phy_tx_end_isr(); - } - } - - /* Receive packet end (we dont enable this for transmit) */ - if ((irq_en & RADIO_INTENCLR_END_Msk) && NRF_RADIO->EVENTS_END) { - ble_phy_rx_end_isr(); - } - - g_ble_phy_data.phy_transition_late = 0; - - /* Ensures IRQ is cleared */ - irq_en = NRF_RADIO->SHORTS; - - /* Count # of interrupts */ - STATS_INC(ble_phy_stats, phy_isrs); - - os_trace_isr_exit(); -} - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 || \ - MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 || \ - MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 -static inline void -ble_phy_dbg_time_setup_gpiote(int index, int pin) -{ - NRF_GPIO_Type *port; - -#if NRF52840_XXAA - port = pin > 31 ? NRF_P1 : NRF_P0; - pin &= 0x1f; -#else - port = NRF_P0; -#endif - - /* Configure GPIO directly to avoid dependency to hal_gpio (for porting) */ - port->DIRSET = (1 << pin); - port->OUTCLR = (1 << pin); - - NRF_GPIOTE->CONFIG[index] = - (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | - ((pin & 0x1F) << GPIOTE_CONFIG_PSEL_Pos) | -#if NRF52840_XXAA - ((port == NRF_P1) << GPIOTE_CONFIG_PORT_Pos); -#else - 0; -#endif -} -#endif - -static void -ble_phy_dbg_time_setup(void) -{ - int gpiote_idx __attribute__((unused)) = 8; - - /* - * We setup GPIOTE starting from last configuration index to minimize risk - * of conflict with GPIO setup via hal. It's not great solution, but since - * this is just debugging code we can live with this. - */ - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 - ble_phy_dbg_time_setup_gpiote(--gpiote_idx, - MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN)); - - NRF_PPI->CH[17].EEP = (uint32_t)&(NRF_RADIO->EVENTS_READY); - NRF_PPI->CH[17].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]); - NRF_PPI->CHENSET = PPI_CHEN_CH17_Msk; - - /* CH[20] and PPI CH[21] are on to trigger TASKS_TXEN or TASKS_RXEN */ - NRF_PPI->FORK[20].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]); - NRF_PPI->FORK[21].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]); -#endif - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 - ble_phy_dbg_time_setup_gpiote(--gpiote_idx, - MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN)); - - /* CH[26] and CH[27] are always on for EVENT_ADDRESS and EVENT_END */ - NRF_PPI->FORK[26].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]); - NRF_PPI->FORK[27].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]); -#endif - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 - ble_phy_dbg_time_setup_gpiote(--gpiote_idx, - MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN)); - -#if NRF52840_XXAA - NRF_PPI->CH[18].EEP = (uint32_t)&(NRF_RADIO->EVENTS_RXREADY); -#else - NRF_PPI->CH[18].EEP = (uint32_t)&(NRF_RADIO->EVENTS_READY); -#endif - NRF_PPI->CH[18].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]); - NRF_PPI->CH[19].EEP = (uint32_t)&(NRF_RADIO->EVENTS_DISABLED); - NRF_PPI->CH[19].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]); - NRF_PPI->CHENSET = PPI_CHEN_CH18_Msk | PPI_CHEN_CH19_Msk; - - /* CH[4] and CH[5] are always on for wfr */ - NRF_PPI->FORK[4].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]); - NRF_PPI->FORK[5].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]); -#endif -} - -/** - * ble phy init - * - * Initialize the PHY. - * - * @return int 0: success; PHY error code otherwise - */ -int -ble_phy_init(void) -{ - int rc; - - /* Default phy to use is 1M */ - g_ble_phy_data.phy_cur_phy_mode = BLE_PHY_MODE_1M; - g_ble_phy_data.phy_tx_phy_mode = BLE_PHY_MODE_1M; - g_ble_phy_data.phy_rx_phy_mode = BLE_PHY_MODE_1M; - - g_ble_phy_data.rx_pwr_compensation = 0; - - /* Set phy channel to an invalid channel so first set channel works */ - g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS; - - /* Toggle peripheral power to reset (just in case) */ - NRF_RADIO->POWER = 0; - NRF_RADIO->POWER = 1; - - /* Disable all interrupts */ - NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; - - /* Set configuration registers */ - NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit; - NRF_RADIO->PCNF0 = NRF_PCNF0; - - /* XXX: should maxlen be 251 for encryption? */ - NRF_RADIO->PCNF1 = NRF_MAXLEN | - (RADIO_PCNF1_ENDIAN_Little << RADIO_PCNF1_ENDIAN_Pos) | - (NRF_BALEN << RADIO_PCNF1_BALEN_Pos) | - RADIO_PCNF1_WHITEEN_Msk; - - /* Enable radio fast ramp-up */ - NRF_RADIO->MODECNF0 |= (RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos) & - RADIO_MODECNF0_RU_Msk; - - /* Set logical address 1 for TX and RX */ - NRF_RADIO->TXADDRESS = 0; - NRF_RADIO->RXADDRESSES = (1 << 0); - - /* Configure the CRC registers */ - NRF_RADIO->CRCCNF = (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos) | RADIO_CRCCNF_LEN_Three; - - /* Configure BLE poly */ - NRF_RADIO->CRCPOLY = 0x0000065B; - - /* Configure IFS */ - NRF_RADIO->TIFS = BLE_LL_IFS; - - /* Captures tx/rx start in timer0 cc 1 and tx/rx end in timer0 cc 2 */ - NRF_PPI->CHENSET = PPI_CHEN_CH26_Msk | PPI_CHEN_CH27_Msk; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - NRF_CCM->INTENCLR = 0xffffffff; - NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; - NRF_CCM->EVENTS_ERROR = 0; - memset(g_nrf_encrypt_scratchpad, 0, sizeof(g_nrf_encrypt_scratchpad)); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - g_ble_phy_data.phy_aar_scratch = 0; - NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; - NRF_AAR->INTENCLR = 0xffffffff; - NRF_AAR->EVENTS_END = 0; - NRF_AAR->EVENTS_RESOLVED = 0; - NRF_AAR->EVENTS_NOTRESOLVED = 0; - NRF_AAR->NIRK = 0; -#endif - - /* TIMER0 setup for PHY when using RTC */ - NRF_TIMER0->TASKS_STOP = 1; - NRF_TIMER0->TASKS_SHUTDOWN = 1; - NRF_TIMER0->BITMODE = 3; /* 32-bit timer */ - NRF_TIMER0->MODE = 0; /* Timer mode */ - NRF_TIMER0->PRESCALER = 4; /* gives us 1 MHz */ - - /* - * PPI setup. - * Channel 4: Captures TIMER0 in CC[3] when EVENTS_ADDRESS occurs. Used - * to cancel the wait for response timer. - * Channel 5: TIMER0 CC[3] to TASKS_DISABLE on radio. This is the wait - * for response timer. - */ - NRF_PPI->CH[4].EEP = (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS); - NRF_PPI->CH[4].TEP = (uint32_t)&(NRF_TIMER0->TASKS_CAPTURE[3]); - NRF_PPI->CH[5].EEP = (uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]); - NRF_PPI->CH[5].TEP = (uint32_t)&(NRF_RADIO->TASKS_DISABLE); - - /* Set isr in vector table and enable interrupt */ -#ifndef RIOT_VERSION - NVIC_SetPriority(RADIO_IRQn, 0); -#endif -#if MYNEWT - NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr); -#else - ble_npl_hw_set_isr(RADIO_IRQn, ble_phy_isr); -#endif - NVIC_EnableIRQ(RADIO_IRQn); - - /* Register phy statistics */ - if (!g_ble_phy_data.phy_stats_initialized) { - rc = stats_init_and_reg(STATS_HDR(ble_phy_stats), - STATS_SIZE_INIT_PARMS(ble_phy_stats, - STATS_SIZE_32), - STATS_NAME_INIT_PARMS(ble_phy_stats), - "ble_phy"); - assert(rc == 0); - - g_ble_phy_data.phy_stats_initialized = 1; - } - - ble_phy_dbg_time_setup(); - - return 0; -} - -/** - * Puts the phy into receive mode. - * - * @return int 0: success; BLE Phy error code otherwise - */ -int -ble_phy_rx(void) -{ - /* - * Check radio state. - * - * In case radio is now disabling we'll wait for it to finish, but if for - * any reason it's just in idle state we proceed with RX as usual since - * nRF52 radio can ramp-up from idle state as well. - * - * Note that TX and RX states values are the same except for 3rd bit so we - * can make a shortcut here when checking for idle state. - */ - nrf_wait_disabled(); - if ((NRF_RADIO->STATE != RADIO_STATE_STATE_Disabled) && - ((NRF_RADIO->STATE & 0x07) != RADIO_STATE_STATE_RxIdle)) { - ble_phy_disable(); - STATS_INC(ble_phy_stats, radio_state_errs); - return BLE_PHY_ERR_RADIO_STATE; - } - - /* Make sure all interrupts are disabled */ - NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; - - /* Clear events prior to enabling receive */ - NRF_RADIO->EVENTS_END = 0; - NRF_RADIO->EVENTS_DISABLED = 0; - - /* Setup for rx */ - ble_phy_rx_xcvr_setup(); - - /* PPI to start radio automatically shall be set here */ - assert(NRF_PPI->CHEN & PPI_CHEN_CH21_Msk); - - return 0; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/** - * Called to enable encryption at the PHY. Note that this state will persist - * in the PHY; in other words, if you call this function you have to call - * disable so that future PHY transmits/receives will not be encrypted. - * - * @param pkt_counter - * @param iv - * @param key - * @param is_master - */ -void -ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, - uint8_t is_master) -{ - memcpy(g_nrf_ccm_data.key, key, 16); - g_nrf_ccm_data.pkt_counter = pkt_counter; - memcpy(g_nrf_ccm_data.iv, iv, 8); - g_nrf_ccm_data.dir_bit = is_master; - g_ble_phy_data.phy_encrypted = 1; - /* Enable the module (AAR cannot be on while CCM on) */ - NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled; - NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled; -} - -void -ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir) -{ - g_nrf_ccm_data.pkt_counter = pkt_counter; - g_nrf_ccm_data.dir_bit = dir; -} - -void -ble_phy_encrypt_disable(void) -{ - NRF_PPI->CHENCLR = PPI_CHEN_CH25_Msk; - NRF_CCM->TASKS_STOP = 1; - NRF_CCM->EVENTS_ERROR = 0; - NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled; - - g_ble_phy_data.phy_encrypted = 0; -} -#endif - -void -ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg) -{ - /* Set transmit end callback and arg */ - g_ble_phy_data.txend_cb = txend_cb; - g_ble_phy_data.txend_arg = arg; -} - -/** - * Called to set the start time of a transmission. - * - * This function is called to set the start time when we are not going from - * rx to tx automatically. - * - * NOTE: care must be taken when calling this function. The channel should - * already be set. - * - * @param cputime This is the tick at which the 1st bit of the preamble - * should be transmitted - * @param rem_usecs This is used only when the underlying timing uses a 32.768 - * kHz crystal. It is the # of usecs from the cputime tick - * at which the first bit of the preamble should be - * transmitted. - * @return int - */ -int -ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs) -{ - int rc; - - ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_TX, cputime, rem_usecs); - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_apply(g_ble_phy_data.phy_tx_phy_mode); -#endif - - /* XXX: This should not be necessary, but paranoia is good! */ - /* Clear timer0 compare to RXEN since we are transmitting */ - NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk; - - if (ble_phy_set_start_time(cputime, rem_usecs, true) != 0) { - STATS_INC(ble_phy_stats, tx_late); - ble_phy_disable(); - rc = BLE_PHY_ERR_TX_LATE; - } else { - /* Enable PPI to automatically start TXEN */ - NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk; - rc = 0; - } - return rc; -} - -/** - * Called to set the start time of a reception - * - * This function acts a bit differently than transmit. If we are late getting - * here we will still attempt to receive. - * - * NOTE: care must be taken when calling this function. The channel should - * already be set. - * - * @param cputime - * - * @return int - */ -int -ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs) -{ - bool late = false; - int rc = 0; - - ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_RX, cputime, rem_usecs); - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_apply(g_ble_phy_data.phy_rx_phy_mode); -#endif - - /* XXX: This should not be necessary, but paranoia is good! */ - /* Clear timer0 compare to TXEN since we are transmitting */ - NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk; - - if (ble_phy_set_start_time(cputime, rem_usecs, false) != 0) { - STATS_INC(ble_phy_stats, rx_late); - - /* We're late so let's just try to start RX as soon as possible */ - ble_phy_set_start_now(); - - late = true; - } - - /* Enable PPI to automatically start RXEN */ - NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk; - - /* Start rx */ - rc = ble_phy_rx(); - - /* - * If we enabled receiver but were late, let's return proper error code so - * caller can handle this. - */ - if (!rc && late) { - rc = BLE_PHY_ERR_RX_LATE; - } - - return rc; -} - -int -ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans) -{ - int rc; - uint8_t *dptr; - uint8_t *pktptr; - uint8_t payload_len; - uint8_t hdr_byte; - uint32_t state; - uint32_t shortcuts; - - if (g_ble_phy_data.phy_transition_late) { - ble_phy_disable(); - STATS_INC(ble_phy_stats, tx_late); - return BLE_PHY_ERR_TX_LATE; - } - - /* - * This check is to make sure that the radio is not in a state where - * it is moving to disabled state. If so, let it get there. - */ - nrf_wait_disabled(); - - /* - * XXX: Although we may not have to do this here, I clear all the PPI - * that should not be used when transmitting. Some of them are only enabled - * if encryption and/or privacy is on, but I dont care. Better to be - * paranoid, and if you are going to clear one, might as well clear them - * all. - */ - NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH23_Msk | - PPI_CHEN_CH25_Msk; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (g_ble_phy_data.phy_encrypted) { - dptr = (uint8_t *)&g_ble_phy_enc_buf[0]; - pktptr = (uint8_t *)&g_ble_phy_tx_buf[0]; - NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; - NRF_CCM->INPTR = (uint32_t)dptr; - NRF_CCM->OUTPTR = (uint32_t)pktptr; - NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0]; - NRF_CCM->EVENTS_ERROR = 0; - NRF_CCM->MODE = CCM_MODE_LENGTH_Msk | ble_phy_get_ccm_datarate(); - NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data; - } else { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; -#endif - dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; - pktptr = dptr; - } -#else - dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; - pktptr = dptr; -#endif - - /* Set PDU payload */ - payload_len = pducb(&dptr[3], pducb_arg, &hdr_byte); - - /* RAM representation has S0, LENGTH and S1 fields. (3 bytes) */ - dptr[0] = hdr_byte; - dptr[1] = payload_len; - dptr[2] = 0; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - /* Start key-stream generation and encryption (via short) */ - if (g_ble_phy_data.phy_encrypted) { - NRF_CCM->TASKS_KSGEN = 1; - } -#endif - - NRF_RADIO->PACKETPTR = (uint32_t)pktptr; - - /* Clear the ready, end and disabled events */ - NRF_RADIO->EVENTS_READY = 0; - NRF_RADIO->EVENTS_END = 0; - NRF_RADIO->EVENTS_DISABLED = 0; - - /* Enable shortcuts for transmit start/end. */ - shortcuts = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk; - NRF_RADIO->SHORTS = shortcuts; - NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; - - /* Set the PHY transition */ - g_ble_phy_data.phy_transition = end_trans; - - /* Set transmitted payload length */ - g_ble_phy_data.phy_tx_pyld_len = payload_len; - - /* If we already started transmitting, abort it! */ - state = NRF_RADIO->STATE; - if (state != RADIO_STATE_STATE_Tx) { - /* Set phy state to transmitting and count packet statistics */ - g_ble_phy_data.phy_state = BLE_PHY_STATE_TX; - STATS_INC(ble_phy_stats, tx_good); - STATS_INCN(ble_phy_stats, tx_bytes, payload_len + BLE_LL_PDU_HDR_LEN); - rc = BLE_ERR_SUCCESS; - } else { - ble_phy_disable(); - STATS_INC(ble_phy_stats, tx_late); - rc = BLE_PHY_ERR_RADIO_STATE; - } - - return rc; -} - -/** - * ble phy txpwr set - * - * Set the transmit output power (in dBm). - * - * NOTE: If the output power specified is within the BLE limits but outside - * the chip limits, we "rail" the power level so we dont exceed the min/max - * chip values. - * - * @param dbm Power output in dBm. - * - * @return int 0: success; anything else is an error - */ -int -ble_phy_txpwr_set(int dbm) -{ - /* "Rail" power level if outside supported range */ - dbm = ble_phy_txpower_round(dbm); - - NRF_RADIO->TXPOWER = dbm; - g_ble_phy_data.phy_txpwr_dbm = dbm; - - return 0; -} - -/** - * ble phy txpwr round - * - * Get the rounded transmit output power (in dBm). - * - * @param dbm Power output in dBm. - * - * @return int Rounded power in dBm - */ -int ble_phy_txpower_round(int dbm) -{ - /* TODO this should be per nRF52XXX */ - - /* "Rail" power level if outside supported range */ - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_0dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm; - } - - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm; -} - -/** - * ble phy set access addr - * - * Set access address. - * - * @param access_addr Access address - * - * @return int 0: success; PHY error code otherwise - */ -static int -ble_phy_set_access_addr(uint32_t access_addr) -{ - NRF_RADIO->BASE0 = (access_addr << 8); - NRF_RADIO->PREFIX0 = (NRF_RADIO->PREFIX0 & 0xFFFFFF00) | (access_addr >> 24); - - g_ble_phy_data.phy_access_address = access_addr; - - ble_phy_apply_errata_102_106_107(); - - return 0; -} - -/** - * ble phy txpwr get - * - * Get the transmit power. - * - * @return int The current PHY transmit power, in dBm - */ -int -ble_phy_txpwr_get(void) -{ - return g_ble_phy_data.phy_txpwr_dbm; -} - -void -ble_phy_set_rx_pwr_compensation(int8_t compensation) -{ - g_ble_phy_data.rx_pwr_compensation = compensation; -} - -/** - * ble phy setchan - * - * Sets the logical frequency of the transceiver. The input parameter is the - * BLE channel index (0 to 39, inclusive). The NRF frequency register works like - * this: logical frequency = 2400 + FREQ (MHz). - * - * Thus, to get a logical frequency of 2402 MHz, you would program the - * FREQUENCY register to 2. - * - * @param chan This is the Data Channel Index or Advertising Channel index - * - * @return int 0: success; PHY error code otherwise - */ -int -ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit) -{ - assert(chan < BLE_PHY_NUM_CHANS); - - /* Check for valid channel range */ - if (chan >= BLE_PHY_NUM_CHANS) { - return BLE_PHY_ERR_INV_PARAM; - } - - /* Set current access address */ - ble_phy_set_access_addr(access_addr); - - /* Configure crcinit */ - NRF_RADIO->CRCINIT = crcinit; - - /* Set the frequency and the data whitening initial value */ - g_ble_phy_data.phy_chan = chan; - NRF_RADIO->FREQUENCY = g_ble_phy_chan_freq[chan]; - NRF_RADIO->DATAWHITEIV = chan; - - return 0; -} - -/** - * Stop the timer used to count microseconds when using RTC for cputime - */ -static void -ble_phy_stop_usec_timer(void) -{ - NRF_TIMER0->TASKS_STOP = 1; - NRF_TIMER0->TASKS_SHUTDOWN = 1; - NRF_RTC0->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk; -} - -/** - * ble phy disable irq and ppi - * - * This routine is to be called when reception was stopped due to either a - * wait for response timeout or a packet being received and the phy is to be - * restarted in receive mode. Generally, the disable routine is called to stop - * the phy. - */ -static void -ble_phy_disable_irq_and_ppi(void) -{ - NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; - NRF_RADIO->SHORTS = 0; - NRF_RADIO->TASKS_DISABLE = 1; - NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH20_Msk | - PPI_CHEN_CH21_Msk | PPI_CHEN_CH23_Msk | - PPI_CHEN_CH25_Msk | PPI_CHEN_CH31_Msk; - NVIC_ClearPendingIRQ(RADIO_IRQn); - g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE; -} - -void -ble_phy_restart_rx(void) -{ - ble_phy_stop_usec_timer(); - ble_phy_disable_irq_and_ppi(); - - ble_phy_set_start_now(); - /* Enable PPI to automatically start RXEN */ - NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk; - - ble_phy_rx(); -} - -/** - * ble phy disable - * - * Disables the PHY. This should be called when an event is over. It stops - * the usec timer (if used), disables interrupts, disables the RADIO, disables - * PPI and sets state to idle. - */ -void -ble_phy_disable(void) -{ - ble_phy_trace_void(BLE_PHY_TRACE_ID_DISABLE); - - ble_phy_stop_usec_timer(); - ble_phy_disable_irq_and_ppi(); -} - -/* Gets the current access address */ -uint32_t ble_phy_access_addr_get(void) -{ - return g_ble_phy_data.phy_access_address; -} - -/** - * Return the phy state - * - * @return int The current PHY state. - */ -int -ble_phy_state_get(void) -{ - return g_ble_phy_data.phy_state; -} - -/** - * Called to see if a reception has started - * - * @return int - */ -int -ble_phy_rx_started(void) -{ - return g_ble_phy_data.phy_rx_started; -} - -/** - * Return the transceiver state - * - * @return int transceiver state. - */ -uint8_t -ble_phy_xcvr_state_get(void) -{ - uint32_t state; - state = NRF_RADIO->STATE; - return (uint8_t)state; -} - -/** - * Called to return the maximum data pdu payload length supported by the - * phy. For this chip, if encryption is enabled, the maximum payload is 27 - * bytes. - * - * @return uint8_t Maximum data channel PDU payload size supported - */ -uint8_t -ble_phy_max_data_pdu_pyld(void) -{ - return BLE_LL_DATA_PDU_MAX_PYLD; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -void -ble_phy_resolv_list_enable(void) -{ - NRF_AAR->NIRK = (uint32_t)g_nrf_num_irks; - g_ble_phy_data.phy_privacy = 1; -} - -void -ble_phy_resolv_list_disable(void) -{ - g_ble_phy_data.phy_privacy = 0; -} -#endif - -#if MYNEWT_VAL(BLE_LL_DTM) -void ble_phy_enable_dtm(void) -{ - /* When DTM is enabled we need to disable whitening as per - * Bluetooth v5.0 Vol 6. Part F. 4.1.1 - */ - NRF_RADIO->PCNF1 &= ~RADIO_PCNF1_WHITEEN_Msk; -} - -void ble_phy_disable_dtm(void) -{ - /* Enable whitening */ - NRF_RADIO->PCNF1 |= RADIO_PCNF1_WHITEEN_Msk; -} -#endif - -void -ble_phy_rfclk_enable(void) -{ -#if MYNEWT - nrf52_clock_hfxo_request(); -#else - NRF_CLOCK->TASKS_HFCLKSTART = 1; -#endif -} - -void -ble_phy_rfclk_disable(void) -{ -#if MYNEWT - nrf52_clock_hfxo_release(); -#else - NRF_CLOCK->TASKS_HFCLKSTOP = 1; -#endif -} - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy_trace.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy_trace.c deleted file mode 100644 index 84dbf4def..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy_trace.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) - -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os_trace_api.h" - -#if MYNEWT_VAL(BLE_PHY_SYSVIEW) - -static os_trace_module_t g_ble_phy_trace_mod; -uint32_t ble_phy_trace_off; - -static void -ble_phy_trace_module_send_desc(void) -{ - os_trace_module_desc(&g_ble_phy_trace_mod, "0 phy_set_tx cputime=%u usecs=%u"); - os_trace_module_desc(&g_ble_phy_trace_mod, "1 phy_set_rx cputime=%u usecs=%u"); - os_trace_module_desc(&g_ble_phy_trace_mod, "2 phy_disable"); -} - -void -ble_phy_trace_init(void) -{ - ble_phy_trace_off = - os_trace_module_register(&g_ble_phy_trace_mod, "ble_phy", 3, - ble_phy_trace_module_send_desc); -} -#endif -#endif \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/syscfg.yml deleted file mode 100644 index ce5123721..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/syscfg.yml +++ /dev/null @@ -1,75 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - BLE_PHY_SYSVIEW: - description: > - Enable SystemView tracing module for radio driver. - value: 0 - - BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN: - description: > - This defines additional margin for T_IFS tolerance while in - RX on coded phy to allow maintaining connections with some - controllers that exceed proper T_IFS (150 usecs) by more - than allowed 2 usecs. - This value shall be only used for debugging purposes. It is - strongly recommended to keep this settings at default value - to ensure compliance with specification. - value: 0 - BLE_PHY_DBG_TIME_TXRXEN_READY_PIN: - description: > - When set to proper GPIO pin number, this pin will be set - to high state when radio is enabled using PPI channels - 20 or 21 and back to low state on radio EVENTS_READY. - This can be used to measure radio ram-up time. - value: -1 - - BLE_PHY_DBG_TIME_ADDRESS_END_PIN: - description: > - When set to proper GPIO pin number, this pin will be set - to high state on radio EVENTS_ADDRESS and back to low state - on radio EVENTS_END. - This can be used to measure radio pipeline delays. - value: -1 - - BLE_PHY_DBG_TIME_WFR_PIN: - description: > - When set to proper GPIO pin number, this pin will be set - to high state on radio EVENTS_RXREADY and back to low - state when wfr timer expires. - This can be used to check if wfr is calculated properly. - value: -1 - - BLE_PHY_NRF52840_ERRATA_164: - description: > - Enable workaround for anomaly 164 found in nRF52840. - "[164] RADIO: Low selectivity in long range mode" - This shall be only enabled for: - - nRF52840 Engineering A - value: 0 - - BLE_PHY_NRF52840_ERRATA_191: - description: > - Enable workaround for anomaly 191 found in nRF52840. - "[191] RADIO: High packet error rate in BLE Long Range mode" - This shall be only enabled for: - - nRF52840 Engineering B - - nRF52840 Engineering C - - nRF52840 Rev 1 (final silicon) - value: 1 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/pkg.yml deleted file mode 100644 index 44cc0c732..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/pkg.yml +++ /dev/null @@ -1,49 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/host/mesh -pkg.description: Bluetooth Mesh -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - - mesh - -pkg.deps: - - "@apache-mynewt-core/kernel/os" - - "@apache-mynewt-core/util/mem" - - "@apache-mynewt-core/crypto/tinycrypt" - - nimble - - nimble/host - -pkg.deps.BLE_MESH_SHELL: - - "@apache-mynewt-core/sys/shell" - -pkg.deps.BLE_MESH_SETTINGS: - - "@apache-mynewt-core/encoding/base64" - - "@apache-mynewt-core/sys/config" - -pkg.req_apis: - - log - - stats - -pkg.init: - bt_mesh_register_gatt: 'MYNEWT_VAL(BLE_MESH_SYSINIT_STAGE)' - ble_mesh_shell_init: 'MYNEWT_VAL(BLE_MESH_SYSINIT_STAGE_SHELL)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/syscfg.yml deleted file mode 100644 index 98632232b..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/syscfg.yml +++ /dev/null @@ -1,661 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - BLE_MESH_PROV: - description: > - Enable provisioning. It is automatically enabled whenever - BLE_MESH_PB_ADV or BLE_MESH_PB_GATT is set. - value: 1 - - BLE_MESH_PB_ADV: - description: > - Enable this option to allow the device to be provisioned over - the advertising bearer. - value: 1 - - BLE_MESH_PROVISIONER: - description: > - Enable this option to have support for provisioning remote devices. - value: 0 - restrictions: - - (BLE_MESH_PROV) - - BLE_MESH_NODE_COUNT: - description: > - This option specifies how many nodes each network can at most - save in the provisioning database. Range 1-4096 - value: 1 - - BLE_MESH_PROXY: - description: > - Enable proxy. This is automatically set whenever BLE_MESH_PB_GATT or - BLE_MESH_GATT_PROXY is set. - value: 0 - - BLE_MESH_PB_GATT: - description: > - Enable this option to allow the device to be provisioned over - the GATT bearer. - value: 1 - - BLE_MESH_GATT_PROXY: - description: > - This option enables support for the Mesh GATT Proxy Service, - i.e. the ability to act as a proxy between a Mesh GATT Client - and a Mesh network. - value: 1 - - BLE_MESH_NODE_ID_TIMEOUT: - description: > - This option determines for how long the local node advertises - using Node Identity. The given value is in seconds. The - specification limits this to 60 seconds, and implies that to - be the appropriate value as well, so just leaving this as the - default is the safest option. - value: 60 - - BLE_MESH_PROXY_FILTER_SIZE: - descryption: > - This option specifies how many Proxy Filter entries the local - node supports. - value: 1 - - BLE_MESH_SUBNET_COUNT: - description: > - This option specifies how many subnets a Mesh network can - participate in at the same time. - value: 1 - - BLE_MESH_APP_KEY_COUNT: - description: > - This option specifies how many application keys the device can - store per network. - value: 1 - - BLE_MESH_MODEL_KEY_COUNT: - description: > - This option specifies how many application keys each model can - at most be bound to. - value: 1 - - BLE_MESH_MODEL_GROUP_COUNT: - description: > - This option specifies how many group addresses each model can - at most be subscribed to. - value: 1 - - BLE_MESH_LABEL_COUNT: - description: > - This option specifies how many Label UUIDs can be stored. - value: 1 - - BLE_MESH_CRPL: - description: > - This options specifies the maximum capacity of the replay - protection list. This option is similar to the network message - cache size, but has a different purpose. - value: 10 - - BLE_MESH_ADV_TASK_PRIO: - description: > - Advertising task prio (FIXME) - type: task_priority - value: 9 - - BLE_MESH_MSG_CACHE_SIZE: - description: > - Number of messages that are cached for the network. This description - prevent unnecessary decryption operations and unnecessary - relays. This option is similar to the replay protection list, - but has a different purpose. - value: 10 - - BLE_MESH_ADV_BUF_COUNT: - description: > - Number of advertising buffers available. This should be chosen - based on what kind of features the local node shoule have. E.g. - a relay will perform better the more buffers it has. Another - thing to consider is outgoing segmented messages. There must - be at least three more advertising buffers than the maximum - supported outgoing segment count (BT_MESH_TX_SEG_MAX). - value: 6 - - BLE_MESH_IVU_DIVIDER: - description: > - When the IV Update state enters Normal operation or IV Update - in Progress, we need to keep track of how many hours has passed - in the state, since the specification requires us to remain in - the state at least for 96 hours (Update in Progress has an - additional upper limit of 144 hours). - - In order to fulfil the above requirement, even if the node might - be powered off once in a while, we need to store persistently - how many hours the node has been in the state. This doesn't - necessarily need to happen every hour (thanks to the flexible - duration range). The exact cadence will depend a lot on the - ways that the node will be used and what kind of power source it - has. - - Since there is no single optimal answer, this configuration - option allows specifying a divider, i.e. how many intervals - the 96 hour minimum gets split into. After each interval the - duration that the node has been in the current state gets - stored to flash. E.g. the default value of 4 means that the - state is saved every 24 hours (96 / 4). - value: 4 - - BLE_MESH_TX_SEG_MSG_COUNT: - description: > - Maximum number of simultaneous outgoing multi-segment and/or - reliable messages. - value: 4 - - BLE_MESH_RX_SEG_MSG_COUNT: - description: > - Maximum number of simultaneous incoming multi-segment and/or - reliable messages. - value: 2 - - BLE_MESH_RX_SDU_MAX: - description: > - Maximum incoming Upper Transport Access PDU length. This - determines also how many segments incoming segmented messages - can have. Each segment can contain 12 bytes, so this value should - be set to a multiple of 12 to avoid wasted memory. The minimum - requirement is 2 segments (24 bytes) whereas the maximum supported - by the Mesh specification is 32 segments (384 bytes). - value: 72 - - BLE_MESH_TX_SEG_MAX: - description: > - Maximum number of segments supported for outgoing messages. - This value should typically be fine-tuned based on what - models the local node supports, i.e. what's the largest - message payload that the node needs to be able to send. - This value affects memory and call stack consumption, which - is why the default is lower than the maximum that the - specification would allow (32 segments). - - The maximum outgoing SDU size is 12 times this number (out of - which 4 or 8 bytes is used for the Transport Layer MIC). For - example, 5 segments means the maximum SDU size is 60 bytes, - which leaves 56 bytes for application layer data using a - 4-byte MIC and 52 bytes using an 8-byte MIC. - - Be sure to specify a sufficient number of advertising buffers - when setting this option to a higher value. There must be at - least three more advertising buffers (BT_MESH_ADV_BUF_COUNT) - as there are outgoing segments. - value: 3 - - BLE_MESH_SEG_RETRANSMIT_ATTEMPTS: - description: > - Number of retransmit attempts (after the initial transmit) per segment - value: 4 - retrictions: 'BLE_MESH_SEG_RETRANSMIT_ATTEMPTS > 1' - - BLE_MESH_RELAY: - description: > - Support for acting as a Mesh Relay Node. - value: 0 - - BLE_MESH_LOW_POWER: - description: > - Enable this option to be able to act as a Low Power Node. - value: 0 - - BLE_MESH_LPN_ESTABLISHMENT: - description: > - Perform the Friendship establishment using low power, with - the help of a reduced scan duty cycle. The downside of this - is that the node may miss out on messages intended for it - until it has successfully set up Friendship with a Friend - node. - value: 1 - - BLE_MESH_LPN_AUTO: - description: > - Automatically enable LPN functionality once provisioned and start - looking for Friend nodes. If this option is disabled LPN mode - needs to be manually enabled by calling bt_mesh_lpn_set(true). - node. - value: 1 - - BLE_MESH_LPN_AUTO_TIMEOUT: - description: > - Time in seconds from the last received message, that the node - will wait before starting to look for Friend nodes. - value: 15 - - BLE_MESH_LPN_RETRY_TIMEOUT: - description: > - Time in seconds between Friend Requests, if a previous Friend - Request did not receive any acceptable Friend Offers. - value: 8 - - BLE_MESH_LPN_RSSI_FACTOR: - description: > - The contribution of the RSSI measured by the Friend node used - in Friend Offer Delay calculations. 0 = 1, 1 = 1.5, 2 = 2, 3 = 2.5. - value: 0 - - BLE_MESH_LPN_RECV_WIN_FACTOR: - description: > - The contribution of the supported Receive Window used in - Friend Offer Delay calculations. 0 = 1, 1 = 1.5, 2 = 2, 3 = 2.5. - value: 0 - - BLE_MESH_LPN_MIN_QUEUE_SIZE: - description: > - The MinQueueSizeLog field is defined as log_2(N), where N is - the minimum number of maximum size Lower Transport PDUs that - the Friend node can store in its Friend Queue. As an example, - MinQueueSizeLog value 1 gives N = 2, and value 7 gives N = 128. - value: 1 - - BLE_MESH_LPN_RECV_DELAY: - description: > - The ReceiveDelay is the time between the Low Power node - sending a request and listening for a response. This delay - allows the Friend node time to prepare the response. The value - is in units of milliseconds. - value: 100 - - BLE_MESH_LPN_POLL_TIMEOUT: - description: > - PollTimeout timer is used to measure time between two - consecutive requests sent by the Low Power node. If no - requests are received by the Friend node before the - PollTimeout timer expires, then the friendship is considered - terminated. The value is in units of 100 milliseconds, so e.g. - a value of 300 means 30 seconds. - value: 300 - - BLE_MESH_LPN_INIT_POLL_TIMEOUT: - description: > - The initial value of the PollTimeout timer when Friendship - gets established for the first time. After this the timeout - will gradually grow toward the actual PollTimeout, doubling - in value for each iteration. The value is in units of 100 - milliseconds, so e.g. a value of 300 means 3 seconds. - value: MYNEWT_VAL_BLE_MESH_LPN_POLL_TIMEOUT - - BLE_MESH_LPN_SCAN_LATENCY: - description: > - Latency in milliseconds that it takes to enable scanning. This - is in practice how much time in advance before the Receive Window - that scanning is requested to be enabled. - value: 10 - - BLE_MESH_LPN_GROUPS: - description: > - Maximum number of groups that the LPN can subscribe to. - value: 10 - - BLE_MESH_FRIEND: - description: > - Enable this option to be able to act as a Friend Node. - value: 0 - - BLE_MESH_FRIEND_RECV_WIN: - description: > - Receive Window in milliseconds supported by the Friend node. - value: 255 - - BLE_MESH_FRIEND_QUEUE_SIZE: - description: > - Minimum number of buffers available to be stored for each - local Friend Queue. - value: 16 - - BLE_MESH_FRIEND_SUB_LIST_SIZE: - description: > - Size of the Subscription List that can be supported by a - Friend node for a Low Power node. - value: 3 - - BLE_MESH_FRIEND_LPN_COUNT: - description: > - Number of Low Power Nodes the Friend can have a Friendship - with simultaneously. - value: 2 - - BLE_MESH_FRIEND_SEG_RX: - description: > - Number of incomplete segment lists that we track for each LPN - that we are Friends for. In other words, this determines how - many elements we can simultaneously be receiving segmented - messages from when the messages are going into the Friend queue. - value: 1 - - BLE_MESH_CFG_CLI: - description: > - Enable support for the configuration client model. - value: 0 - - BLE_MESH_HEALTH_CLI: - description: > - Enable support for the health client model. - value: 0 - - BLE_MESH_SHELL: - description: > - Activate shell module that provides Bluetooth Mesh commands to - the console. - value: 0 - - BLE_MESH_MODEL_EXTENSIONS: - description: > - Enable support for the model extension concept, allowing the Access - layer to know about Mesh model relationships. - value: 0 - - BLE_MESH_IV_UPDATE_TEST: - description: > - This option removes the 96 hour limit of the IV Update - Procedure and lets the state be changed at any time. - value: 0 - - BLE_MESH_TESTING: - description: > - This option enables testing API. - value: 0 - - BLE_MESH_DEV_UUID: - description: > - Device UUID - value: ((uint8_t[16]){0x11, 0x22, 0}) - - BLE_MESH_SHELL_MODELS: - description: > - Include implementation of some demo models. - value: 0 - - BLE_MESH_OOB_OUTPUT_ACTIONS: - description: > - Supported Output OOB Actions - BT_MESH_NO_OUTPUT = 0, - BT_MESH_BLINK = BIT(0) - BT_MESH_BEEP = BIT(1) - BT_MESH_VIBRATE = BIT(2) - BT_MESH_DISPLAY_NUMBER = BIT(3) - BT_MESH_DISPLAY_STRING = BIT(4) - value: ((BT_MESH_DISPLAY_NUMBER)) - - BLE_MESH_OOB_OUTPUT_SIZE: - description: > - Output OOB size - value: 4 - - BLE_MESH_OOB_INPUT_ACTIONS: - description: > - Supported Input OOB Actions - BT_MESH_NO_INPUT = 0, - BT_MESH_PUSH = BIT(0) - BT_MESH_TWIST = BIT(1) - BT_MESH_ENTER_NUMBER = BIT(2) - BT_MESH_ENTER_STRING = BIT(3) - value: ((BT_MESH_NO_INPUT)) - - BLE_MESH_OOB_INPUT_SIZE: - description: > - Input OOB size - value: 4 - - BLE_MESH_SETTINGS: - description: > - This option enables Mesh settings storage. - value: 1 - - BLE_MESH_STORE_TIMEOUT: - description: > - This value defines in seconds how soon any pending changes - are actually written into persistent storage (flash) after - a change occurs. - value: 2 - - BLE_MESH_SEQ_STORE_RATE: - description: > - This value defines how often the local sequence number gets - updated in persistent storage (i.e. flash). E.g. a value of 100 - means that the sequence number will be stored to flash on every - 100th increment. If the node sends messages very frequently a - higher value makes more sense, whereas if the node sends - infrequently a value as low as 0 (update storage for every - increment) can make sense. When the stack gets initialized it - will add this number to the last stored one, so that it starts - off with a value that's guaranteed to be larger than the last - one used before power off. - value: 128 - - BLE_MESH_RPL_STORE_TIMEOUT: - description: > - This value defines in seconds how soon the RPL gets written to - persistent storage after a change occurs. If the node receives - messages frequently it may make sense to have this set to a - large value, whereas if the RPL gets updated infrequently a - value as low as 0 (write immediately) may make sense. Note that - if the node operates a security sensitive use case, and there's - a risk of sudden power loss, it may be a security vulnerability - to set this value to anything else than 0 (a power loss before - writing to storage exposes the node to potential message - replay attacks). - value: 5 - - BLE_MESH_DEVICE_NAME: - description: > - This value defines BLE Mesh device/node name. - value: '"nimble-mesh-node"' - - BLE_MESH_SYSINIT_STAGE: - description: > - Primary sysinit stage for BLE mesh functionality. - value: 500 - - BLE_MESH_SYSINIT_STAGE_SHELL: - description: > - Secondary sysinit stage for BLE mesh functionality. - value: 1000 - - ### Log settings. - - BLE_MESH_LOG_MOD: - description: > - Numeric module ID to use for BLE Mesh log messages. - value: 9 - BLE_MESH_LOG_LVL: - description: > - Minimum level for the BLE Mesh log. - value: 1 - - BLE_MESH_ACCESS_LOG_MOD: - description: > - Numeric module ID to use for BLE Mesh Access-related log messages. - value: 10 - BLE_MESH_ACCESS_LOG_LVL: - description: > - Minimum level for the BLE Mesh Access-related log. - value: 1 - - BLE_MESH_ADV_LOG_MOD: - description: > - Numeric module ID to use for BLE Mesh advertising log messages. - value: 11 - BLE_MESH_ADV_LOG_LVL: - description: > - Minimum level for the BLE Mesh log. - value: 1 - - BLE_MESH_BEACON_LOG_MOD: - description: > - Numeric module ID to use for BLE Mesh Beacon-related log messages. - value: 12 - BLE_MESH_BEACON_LOG_LVL: - description: > - Minimum level for the BLE Mesh Beacon-related log. - value: 1 - - BLE_MESH_CRYPTO_LOG_MOD: - description: > - Numeric module ID to use for BLE Mesh cryptographic log messages. - value: 13 - BLE_MESH_CRYPTO_LOG_LVL: - description: > - Minimum level for the BLE Mesh cryptographic log. - value: 1 - - BLE_MESH_FRIEND_LOG_MOD: - description: > - Numeric module ID to use for BLE Mesh Friend log messages. - value: 14 - BLE_MESH_FRIEND_LOG_LVL: - description: > - Minimum level for the BLE Mesh Friend log. - value: 1 - - BLE_MESH_LOW_POWER_LOG_MOD: - description: > - Numeric module ID to use for BLE Mesh Low Power log messages. - value: 15 - BLE_MESH_LOW_POWER_LOG_LVL: - description: > - Minimum level for the BLE Mesh Low Power log. - value: 1 - - BLE_MESH_MODEL_LOG_MOD: - description: > - Numeric module ID to use for BLE Mesh Foundation Models log messages. - value: 16 - BLE_MESH_MODEL_LOG_LVL: - description: > - Minimum level for the BLE Mesh Foundation Models log. - value: 1 - - BLE_MESH_NET_LOG_MOD: - description: > - Numeric module ID to use for BLE Mesh Network layer log messages. - value: 17 - BLE_MESH_NET_LOG_LVL: - description: > - Minimum level for the BLE Mesh Network layer log. - value: 1 - - BLE_MESH_PROV_LOG_MOD: - description: > - Numeric module ID to use for BLE Mesh Provisioning log messages. - value: 18 - BLE_MESH_PROV_LOG_LVL: - description: > - Minimum level for the BLE Mesh Provisioning log. - value: 1 - - BLE_MESH_PROXY_LOG_MOD: - description: > - Numeric module ID to use for BLE Mesh Proxy protocol log messages. - value: 19 - BLE_MESH_PROXY_LOG_LVL: - description: > - Minimum level for the BLE Mesh Proxy protocol log. - value: 1 - - BLE_MESH_SETTINGS_LOG_MOD: - description: > - Numeric module ID to use for BLE Mesh persistent settings log messages. - value: 20 - BLE_MESH_SETTINGS_LOG_LVL: - description: > - Minimum level for the BLE Mesh persistent settings log. - value: 1 - - BLE_MESH_TRANS_LOG_MOD: - description: > - Numeric module ID to use for BLE Mesh Transport Layer log messages. - value: 21 - BLE_MESH_TRANS_LOG_LVL: - description: > - Minimum level for the BLE Mesh Transport Layer log. - value: 1 - -syscfg.logs: - BLE_MESH_LOG: - module: MYNEWT_VAL(BLE_MESH_LOG_MOD) - level: MYNEWT_VAL(BLE_MESH_LOG_LVL) - - BLE_MESH_ACCESS_LOG: - module: MYNEWT_VAL(BLE_MESH_ACCESS_LOG_MOD) - level: MYNEWT_VAL(BLE_MESH_ACCESS_LOG_LVL) - - BLE_MESH_ADV_LOG: - module: MYNEWT_VAL(BLE_MESH_ADV_LOG_MOD) - level: MYNEWT_VAL(BLE_MESH_ADV_LOG_LVL) - - BLE_MESH_BEACON_LOG: - module: MYNEWT_VAL(BLE_MESH_BEACON_LOG_MOD) - level: MYNEWT_VAL(BLE_MESH_BEACON_LOG_LVL) - - BLE_MESH_CRYPTO_LOG: - module: MYNEWT_VAL(BLE_MESH_CRYPTO_LOG_MOD) - level: MYNEWT_VAL(BLE_MESH_CRYPTO_LOG_LVL) - - BLE_MESH_FRIEND_LOG: - module: MYNEWT_VAL(BLE_MESH_FRIEND_LOG_MOD) - level: MYNEWT_VAL(BLE_MESH_FRIEND_LOG_LVL) - - BLE_MESH_LOW_POWER_LOG: - module: MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_MOD) - level: MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) - - BLE_MESH_MODEL_LOG: - module: MYNEWT_VAL(BLE_MESH_MODEL_LOG_MOD) - level: MYNEWT_VAL(BLE_MESH_MODEL_LOG_LVL) - - BLE_MESH_NET_LOG: - module: MYNEWT_VAL(BLE_MESH_NET_LOG_MOD) - level: MYNEWT_VAL(BLE_MESH_NET_LOG_LVL) - - BLE_MESH_PROV_LOG: - module: MYNEWT_VAL(BLE_MESH_PROV_LOG_MOD) - level: MYNEWT_VAL(BLE_MESH_PROV_LOG_LVL) - - BLE_MESH_PROXY_LOG: - module: MYNEWT_VAL(BLE_MESH_PROXY_LOG_MOD) - level: MYNEWT_VAL(BLE_MESH_PROXY_LOG_LVL) - - BLE_MESH_SETTINGS_LOG: - module: MYNEWT_VAL(BLE_MESH_SETTINGS_LOG_MOD) - level: MYNEWT_VAL(BLE_MESH_SETTINGS_LOG_LVL) - - BLE_MESH_TRANS_LOG: - module: MYNEWT_VAL(BLE_MESH_TRANS_LOG_MOD) - level: MYNEWT_VAL(BLE_MESH_TRANS_LOG_LVL) - -syscfg.vals.BLE_MESH_SHELL: - BLE_MESH_CFG_CLI: 1 - BLE_MESH_HEALTH_CLI: 1 - BLE_MESH_IV_UPDATE_TEST: 1 - -syscfg.vals.BLE_MESH_GATT_PROXY: - BLE_MESH_PROXY: 1 - -syscfg.vals.BLE_MESH_PB_GATT: - BLE_MESH_PROXY: 1 - BLE_MESH_PROV: 1 - -syscfg.vals.BLE_MESH_PB_ADV: - BLE_MESH_PROV: 1 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pkg.yml deleted file mode 100644 index a063a0b63..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pkg.yml +++ /dev/null @@ -1,55 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/host -pkg.description: Host side of the nimble Bluetooth Smart stack. -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - -pkg.deps: - - "@apache-mynewt-core/kernel/os" - - "@apache-mynewt-core/sys/log/modlog" - - "@apache-mynewt-core/util/mem" - - nimble - -pkg.deps.BLE_SM_LEGACY: - - "@apache-mynewt-core/crypto/tinycrypt" - -pkg.deps.BLE_SM_SC: - - "@apache-mynewt-core/crypto/tinycrypt" - -pkg.deps.BLE_MONITOR_RTT: - - "@apache-mynewt-core/hw/drivers/rtt" - -pkg.deps.BLE_MESH: - - nimble/host/mesh - -pkg.req_apis: - - ble_transport - - console - - stats - -pkg.init: - ble_hs_init: 'MYNEWT_VAL(BLE_HS_SYSINIT_STAGE)' - -pkg.down.BLE_HS_STOP_ON_SHUTDOWN: - ble_hs_shutdown: 200 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/README.txt b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/README.txt deleted file mode 100644 index bb03b18ca..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/README.txt +++ /dev/null @@ -1,8 +0,0 @@ -This folder contains qualification tests results against BT SIG Profile Test -Suite. - -pts-FOO.txt files contain result for specific profiles or protocols. This -includes PTS version, test date, enabled tests, results etc. - -In addition to tests results 'tpg' folder constains Test Plang Generator -configuration files that can be imported by PTS for tests configuration. diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-gap.txt b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-gap.txt deleted file mode 100644 index 29ed2446e..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-gap.txt +++ /dev/null @@ -1,367 +0,0 @@ -PTS test results for GAP - -PTS version: 7.5.0 -Tested: 27-Sept-2019 - -Results: -PASS test passed -FAIL test failed -INC test is inconclusive -N/A test is disabled due to PICS setup - -------------------------------------------------------------------------------- -Test Name Result Notes -------------------------------------------------------------------------------- - -GAP/BROB/BCST/BV-01-C PASS advertise-configure legacy=1 connectable=0 scannable=0 -GAP/BROB/BCST/BV-02-C PASS advertise-configure legacy=1 connectable=0 scannable=0 - -GAP/BROB/BCST/BV-03-C PASS set irk= e.g: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:11 - Note: in PTS IXIT please set: - TSPX_iut_device_IRK_for_resolvable_privacy_address_generation_procedure=11000000000000000000000000000000 - set advertise-set-adv-data name= flags=4 - advertise-configure connectable=0 scannable=0 own_addr_type=rpa_pub -GAP/BROB/BCST/BV-04-C PASS TSPX_advertising_data=07086E696D626C65 - advertise-set-adv-data name=nimble - set addr_type=random addr=01:3e:56:f7:46:21 - advertise-configure connectable=0 scannable=0 own_addr_type=random -GAP/BROB/BCST/BV-05-C N/A -GAP/BROB/OBSV/BV-01-C PASS scan passive -GAP/BROB/OBSV/BV-02-C PASS scan -GAP/BROB/OBSV/BV-03-C PASS scan -GAP/BROB/OBSV/BV-04-C PASS connect peer_addr= - security-set-data bonding=1 - security-pair conn= - - -GAP/BROB/OBSV/BV-05-C PASS scan own_addr_type=rpa_pub -GAP/BROB/OBSV/BV-06-C PASS scan own_addr_type=rpa_pub -------------------------------------------------------------------------------- - -GAP/DISC/NONM/BV-01-C PASS advertise-configure connectable=0 legacy=1 adverdise=non -GAP/DISC/NONM/BV-02-C PASS advertise-configure connectable=0 - -GAP/DISC/LIMM/BV-01-C N/A -GAP/DISC/LIMM/BV-02-C N/A -GAP/DISC/LIMM/BV-03-C PASS advertise-configure legacy=1 connectable=0 - advertise-set-adv-data flags=5 - advertise-start duration= e.g.3000 -GAP/DISC/LIMM/BV-04-C PASS advertise-configure legacy=1 connectable=0 - advertise-set-adv-data flags=5 - advertising-start duration= -GAP/DISC/GENM/BV-01-C N/A -GAP/DISC/GENM/BV-02-C N/A -GAP/DISC/GENM/BV-03-C PASS advertise-configure legacy=1 connectable=0 - advertise-set-adv-data flags=6 - advertise-start -GAP/DISC/GENM/BV-04-C PASS advertise-configure legacy=1 connectable=0 - advertise-set-adv-data flags=6 - advertising-start - -GAP/DISC/LIMP/BV-01-C PASS scan limited=1 nodups=1 -GAP/DISC/LIMP/BV-02-C PASS scan limited=1 nodups=1 -GAP/DISC/LIMP/BV-03-C PASS scan limited=1 nodups=1 -GAP/DISC/LIMP/BV-04-C PASS scan limited=1 nodups=1 -GAP/DISC/LIMP/BV-05-C PASS scan limited=1 nodups=1 - -GAP/DISC/GENP/BV-01-C PASS scan nodups=1 -GAP/DISC/GENP/BV-02-C PASS scan nodups=1 -GAP/DISC/GENP/BV-03-C PASS scan nodups=1 - -GAP/DISC/GENP/BV-04-C PASS scan nodups=1 - -GAP/DISC/GENP/BV-05-C PASS scan nodups=1 - -GAP/DISC/RPA/BV-01-C N/A scan nodups=1 -------------------------------------------------------------------------------- - -GAP/IDLE/GIN/BV-01-C N/A -GAP/IDLE/GIN/BV-02-C N/A -GAP/IDLE/NAMP/BV-01-C PASS advertise-configure connectable=1 legacy=1 - advertising-start - gatt-discover-full conn= - gatt-show - - gatt-read conn= uuid=0x2a00 start= end= - disconnect conn= -GAP/IDLE/NAMP/BV-02-C PASS - advertise-configure connectable=1 legacy=1 - advertising-start -GAP/IDLE/DED/BV-01-C N/A -GAP/IDLE/DED/BV-02-C N/A -------------------------------------------------------------------------------- - -GAP/CONN/NCON/BV-01-C PASS advertise-configure connectable=0 legacy=1 - advertising-start -GAP/CONN/NCON/BV-02-C PASS advertise-configure connectable=0 legacy=1 - advertise-set-adv-data flags=6 - advertise-start -GAP/CONN/NCON/BV-03-C PASS advertise-configure connectable=0 legacy=1 - advertise-set-adv-data flags=5 - advertise-start - -GAP/CONN/DCON/BV-01-C PASS advertise-configure connectable=0 directed=1 peer_addr= - advertise-start -GAP/CONN/DCON/BV-02-C N/A -GAP/CONN/DCON/BV-03-C N/A - -GAP/CONN/UCON/BV-01-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=4 - advertise-start -GAP/CONN/UCON/BV-02_C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=5 - advertise-start -GAP/CONN/UCON/BV-03_C PASS adbertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 -GAP/CONN/UCON/BV-04_C N/A -GAP/CONN/UCON/BV-05_C N/A -GAP/CONN/UCON/BV-06_C N/A - -GAP/CONN/ACEP/BV-01-C PASS white-list addr_type=public addr= - connect - disconnect conn= -GAP/CONN/ACEP/BV-02-C N/A - -GAP/CONN/GCEP/BV-01-C PASS connect peer_addr= - disconnect conn= -GAP/CONN/GCEP/BV-02-C PASS connect peer_addr= -GAP/CONN/GCEP/BV-03-C PASS set irk= - connect peer_addr= own_addr_type=rpa_pub - security-set-data bonding=1 our_key_dist=7 their_key_dist=7 - security-pair conn= - connect peer_addr= - disconnect conn=1 -GAP/CONN/GCEP/BV-04-C N/A -GAP/CONN/SCEP/BV-01-C PASS white-list addr_type=public addr= - connect - disconnect conn= -GAP/CONN/SCEP/BV-02-C INC -GAP/CONN/DCEP/BV-01-C PASS connect peer_addr= - disconnect conn= -GAP/CONN/DCEP/BV-02-C INC -GAP/CONN/DCEP/BV-03-C PASS connect peer_addr= - disconnect conn= -GAP/CONN/DCEP/BV-04-C PASS connect peer_addr= - disconnect conn= - -GAP/CONN/CPUP/BV-01-C PASS advertise-start - conn-update-params conn= -GAP/CONN/CPUP/BV-02-C PASS advertise-start - conn-update-params conn= -GAP/CONN/CPUP/BV-03-C PASS advertise-start - conn-update-params conn= -GAP/CONN/CPUP/BV-04-C PASS connect peer_addr= - disconnect conn= -GAP/CONN/CPUP/BV-05-C PASS connect peer_addr= - disconnect conn= -GAP/CONN/CPUP/BV-06-C PASS conect peer_addr= - conn-update-params conn= eg.latency=20 - disconnect conn= -GAP/CONN/CPUP/BV-08-C PASS advertise-configure legacy=1 connectable=1 - advertise-set-data name= - advertise-start - -GAP/CONN/TERM/BV-01-C PASS connect peer_addr= - disconnect conn= -GAP/CONN/PRDA/BV-01-C N/A -GAP/CONN/PRDA/BV-02-C N/A -------------------------------------------------------------------------------- -GAP/BOND/NBON/BV-01-C PASS security-set-data bonding=0 - connect peer_addr= - - connect peer_addr= - -GAP/BOND/NBON/BV-02-C PASS security-set-data bonding=0 - connect peer_addr= - security-pair conn= - - connect peer_addr= - security-pair conn= - -GAP/BOND/NBON/BV-03-C PASS security-set-data bonding=0 - advertise-configure legacy=1 connectable=1 - advertise-set-data name= - advertise-start - - -GAP/BOND/BON/BV-01-C PASS security-set-data bonding=1 sc=1 our_key_dist=7 their_key_dist=7 - advertise-configure legacy=1 connectable=1 - advertise-start - security-start conn= - - advertise-start - -GAP/BOND/BON/BV-02-C PASS security-set-data bonding=1 - connect peer_addr= - security-pair conn= - - connect peer_addr= - seccurity-pair conn= - -GAP/BOND/BON/BV-03-C PASS security-set-sm-data bonding=1 our_key_dist=7 their_key_dist=7 - advertise-configure legacy=1 connectable=1 - advertise-start - - advertise-start - -GAP/BOND/BON/BV-04-C PASS security-set-data bonding=1 - connect-peer_addr= - disconnect conn= - connect peer_addr= - security-pair conn= - disconnect conn= -------------------------------------------------------------------------------- - -GAP/SEC/AUT/BV-11-C PASS security-set-data io_capabilities=1 sc=1 - advertise-configure legacy=1 connectable=1 - advertising-start - Note: in PTS enter handle for characteristics - value which requires encryption for read (gatt-show-local) - auth-passkey conn= action=3 key=123456 - Note: enter '123456' passkey in PTS -GAP/SEC/AUT/BV-12-C PASS security-set-data io_capabilities=1 bonding=1 mitm_flag=1 sc=1 our_key_dist=7 their_key_dist=7 - connect peer_addr= - gatt-show-local - Note: in PTS enter handle for characteristics - value which requires encryption for read - auth-passkey conn= action=3 key=123456 - Note: enter '123456' passkey in PTS -GAP/SEC/AUT/BV-13-C PASS Note: in PTS confirm that IUT supports GATT Server - security-set-data io_capabilities=1 bonding=1 mitm_flag=1 sc=1 our_key_dist=7 their_key_dist=7 - connect peer_addr= - gatt-show-local - Note: in PTS enter handle for characteristics - value which requires authenticated pairing for read - auth-passkey conn= action=3 key=123456 - Note: enter '123456' passkey in PTS -GAP/SEC/AUT/BV-14-C PASS security-set-data io_capabilities=1 - advertise-configure legacy=1 connectable=1 - advertise-start - gatt-show-local - Note: in PTS enter handle for characteristics - value which requires authenticated pairing for read - auth-passkey conn= action=3 key=123456 - Note: enter '123456' passkey in PTS -GAP/SEC/AUT/BV-15-C N/A security-set-data bonding=1 io_capabilities=4 mitm_flag=1 sc=1 our_key_dist=7 their_key_dist=7 - advertise-configure legacy=1 connectable=1 - advertise-start - auth-passkey conn= action=2 key= - advertise-start - gatt-show-local - Note: in PTS enter handle for characteristics - value which requires authenticated pairing for read -GAP/SEC/AUT/BV-16-C N/A security-set-data io_capabilities=1 bonding=1 mitm_flag=1 sc=1 our_key_dist=7 their_key_dist=7 - connect peer_addr= - auth-passkey conn= action=3 key=123456 - Note: enter '123456' passkey in PTS - connect peer_addr= - gatt-show-local - Note: in PTS enter handle for characteristics - value which requires authenticated pairing for read -GAP/SEC/AUT/BV-17-C N/A -GAP/SEC/AUT/BV-18-C N/A -GAP/SEC/AUT/BV-19-C N/A -GAP/SEC/AUT/BV-20-C N/A -GAP/SEC/AUT/BV-21-C N/A -GAP/SEC/AUT/BV-22-C N/A -GAP/SEC/AUT/BV-23-C N/A -GAP/SEC/AUT/BV-24-C N/A - -GAP/SEC/CSIGN/BV-01-C N/A -GAP/SEC/CSIGN/BV-02-C N/A - -GAP/SEC/CSIGN/BI-01-C N/A -GAP/SEC/CSIGN/BI-02-C N/A -GAP/SEC/CSIGN/BI-03-C N/A -GAP/SEC/CSIGN/BI-04-C N/A -------------------------------------------------------------------------------- - -GAP/PRIV/CONN/BV-01-C N/A -GAP/PRIV/CONN/BV-02-C N/A -GAP/PRIV/CONN/BV-03-C N/A -GAP/PRIV/CONN/BV-04-C INC -GAP/PRIV/CONN/BV-05-C N/A -GAP/PRIV/CONN/BV-06-C N/A -GAP/PRIV/CONN/BV-07-C N/A -GAP/PRIV/CONN/BV-08-C N/A -GAP/PRIV/CONN/BV-09-C N/A -GAP/PRIV/CONN/BV-10-C N/A -GAP/PRIV/CONN/BV-11-C N/A -------------------------------------------------------------------------------- - -GAP/ADV/BV-01-C PASS advertise-set-adv_data uuid16=0x1802 - advertise-start - advertise-stop -GAP/ADV/BV-02-C PASS advertise-set-adv_data name= - advertise-start - advertise-stop -GAP/ADV/BV-03-C PASS advertise-set-adv_data flags=6 - advertise-start - advertise-stop -GAP/ADV/BV-04-C PASS advertise-set-adv_data mfg_data=ff:ff - advertise-start - advertise-stop -GAP/ADV/BV-05-C PASS advertise-set-adv_data tx_pwr_lvl=10 - advertise-start - advertise-stop -GAP/ADV/BV-08-C N/A -GAP/ADV/BV-09-C N/A -GAP/ADV/BV-10-C PASS advetrise-set-adv_data service_data_uuid16=18:02:ff:ff - advertise-start - advertise-stop -GAP/ADV/BV-11-C PASS advertise-set -dv_data appearance=12 - advertise-start - advertise-stop -GAP/ADV/BV-12-C N/A -GAP/ADV/BV-13-C N/A -GAP/ADV/BV-14-C N/A -GAP/ADV/BV-15-C N/A -GAP/ADV/BV-16-C N/A -GAP/ADV/BV-17-C PASS In PTS: TSPX_URI= - set-adv-data uri= - advertise-start - advertise-stop -------------------------------------------------------------------------------- - -GAP/GAT/BV-01-C PASS - advertising-start - - connect peer_addr= -GAP/GAT/BV-02-C N/A -GAP/GAT/BV-03-C N/A -GAP/GAT/BV-04-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GAP/GAT/BV-05-C N/A -GAP/GAT/BV-06-C N/A -GAP/GAT/BV-07-C N/A -GAP/GAT/BV-08-C N/A ----------------------------------------------------------------------------- - -GAP/DM/NCON/BV-01-C N/A -GAP/DM/CON/BV-01-C N/A -GAP/DM/NBON/BV-01-C N/A -GAP/DM/BON/BV-01-C N/A -GAP/DM/GIN/BV-01-C N/A -GAP/DM/LIN/BV-01-C N/A -GAP/DM/NAD/BV-01-C N/A -GAP/DM/NAD/BV-02-C N/A -GAP/DM/LEP/BV-01-C N/A -GAP/DM/LEP/BV-02-C N/A -GAP/DM/LEP/BV-04-C N/A -GAP/DM/LEP/BV-05-C N/A -GAP/DM/LEP/BV-06-C N/A -GAP/DM/LEP/BV-07-C N/A -GAP/DM/LEP/BV-08-C N/A -GAP/DM/LEP/BV-09-C N/A -GAP/DM/LEP/BV-10-C N/A -GAP/DM/LEP/BV-11-C N/A -------------------------------------------------------------------------------- - -GAP/MOD/NDIS/BV-01-C N/A -GAP/MOD/LDIS/BV-01-C N/A -GAP/MOD/LDIS/BV-02-C N/A -GAP/MOD/LDIS/BV-03-C N/A -GAP/MOD/GDIS/BV-01-C N/A -GAP/MOD/GDIS/BV-02-C N/A -GAP/MOD/NCON/BV-01-C N/A -GAP/MOD/CON/BV-01-C N/A \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-gatt.txt b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-gatt.txt deleted file mode 100644 index 74c0a2e01..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-gatt.txt +++ /dev/null @@ -1,508 +0,0 @@ -PTS test results for GATT - -PTS version: 7.5.0 -Tested: 27-Sept-2019 - -Results: -PASS test passed -FAIL test failed -INC test is inconclusive -N/A test is disabled due to PICS setup - -------------------------------------------------------------------------------- -Test Name Result Notes -------------------------------------------------------------------------------- -GATT/CL/GAC/BV-01-C PASS connect peer_addr= - gatt-exchanche-mtu conn= - gatt-write conn= long=1 attr= value= - disconnect conn= -------------------------------------------------------------------------------- - -GATT/CL/GAD/BV-01-C PASS connect peer_addr= - gatt-discover-service conn= - gatt-show - - disconnect conn= - -GATT/CL/GAD/BV-02-C PASS connect peer_addr= - gatt-discover-service conn= uuid= - gatt-show - - disconnect conn= - -GATT/CL/GAD/BV-03-C PASS connect peer_addr= - gatt-find-included-services conn= start=1 end=0xffff - - disconnect conn= - -GATT/CL/GAD/BV-04-C PASS connect peer_addr= - gatt-discover-service conn= uuid= - gatt-discover-characteristic conn= start= end= - gatt-show - - disconnect conn= - -GATT/CL/GAD/BV-05-C PASS connect peer_addr= - gatt-discover-service conn= - gatt-discover-characteristic conn= uuid= start= end= - gatt-show - - disconnect conn= - -GATT/CL/GAD/BV-06-C PASS connect peer_addr= - gatt-discover-service conn= - gatt-discover-characteristic conn= start= end= - gatt-discover-descriptor conn= start= end= - - disconnect conn= - -GATT/CL/GAD/BV-07-C N/A -GATT/CL/GAD/BV-08-C N/A -------------------------------------------------------------------------------- - -GATT/CL/GAR/BV-01-C PASS connect peer_addr= - gatt-read conn= attr= - - disconnect conn= -GATT/CL/GAR/BI-01-C PASS connect peer_addr= - gatt-read conn= attr= - - disconnect conn= -GATT/CL/GAR/BI-02-C PASS connect peer_addr= - gatt-read conn= attr= - - disconnect conn= -GATT/CL/GAR/BI-03-C N/A - -GATT/CL/GAR/BI-04-C PASS connect peer_addr= - gatt-read conn= attr= - disconnect conn= - -GATT/CL/GAR/BI-05-C PASS connect peer_addr= - gatt-read conn= attr= - - disconnect conn= -GATT/CL/GAR/BV-03-C PASS connect peer_addr= - gatt-read conn= uuid= start=1 end=0xffff - - - disconnect conn= -GATT/CL/GAR/BI-06-C PASS connect peer_addr= - gatt-read conn= uuid= start= end= - disconnect conn= - -GATT/CL/GAR/BI-07-C PASS connect peer_addr= - gatt-read conn= uuid= start= end= - disconnect conn= - -GATT/CL/GAR/BI-09-C N/A -GATT/CL/GAR/BI-10-C PASS connect peer_addr= - gatt-read conn= uuid= start= end= - disconnect conn= - -GATT/CL/GAR/BI-11-C PASS connect perr_addr= - gatt-read conn= start= end= - disconnect conn= - -GATT/CL/GAR/BV-04-C PASS connect peer_addr= - gatt-read conn= long=1 attr= - - - disconnect conn= -GATT/CL/GAR/BI-12-C PASS connect peer_addr= - gatt-read conn= long=1 attr= - - disconnect conn= -GATT/CL/GAR/BI-13-C PASS connect peer_addr= - gatt-read conn= long=1 attr= offset= - - disconnect conn= -GATT/CL/GAR/BI-14-C PASS connect peer_addr= - gatt-read conn= long=1 attr= - disconnect conn= - -GATT/CL/GAR/BI-15-C N/A - -GATT/CL/GAR/BI-16-C PASS connect peer_addr= - gatt-read conn= long=1 attr= - disconnect conn= - -GATT/CL/GAR/BI-17-C PASS connect peer_addr= - gatt-read conn= long=1 attr= - - disconnect conn= -GATT/CL/GAR/BV-05-C PASS connect peer_addr= - gatt-read conn= attr= attr= - disconnect conn= -GATT/CL/GAR/BI-18-C PASS connect peer_addr= - gatt-read conn= attr= attr= - - disconnect conn= -GATT/CL/GAR/BI-19-C PASS connect peer_addr= - gatt-read conn= attr= attr= - disconnect conn= - -GATT/CL/GAR/BI-20-C N/A - -GATT/CL/GAR/BI-21-C PASS connect peer_addr= - gatt-read conn= attr= attr= - disconnect conn= - -GATT/CL/GAR/BI-22-C PASS connect peer_addr= - gatt-read conn= attr= attr= - - disconnect conn= -GATT/CL/GAR/BV-06-C PASS connect peer_addr= - gatt-read conn= attr= - - disconnect conn= -GATT/CL/GAR/BV-07-C PASS connect peer_addr= - gatt-read conn= long=1 attr= - - - disconnect conn= -GATT/CL/GAR/BI-34-C N/A -GATT/CL/GAR/BI-35-C PASS connect peer_addr= - gatt-read conn= long=1 attr= - - disconnect conn= -------------------------------------------------------------------------------- - -GATT/CL/GAW/BV-01-C PASS connect peer_addr= - gatt-write no_rsp=1 conn= attr= value= - disconnect conn= -GATT/CL/GAW/BV-02-C N/A - -GATT/CL/GAW/BV-03-C PASS connect peer_addr= - gatt-write conn= attr= value= - disconnect conn= -GATT/CL/GAW/BI-02-C PASS connect peer_addr= - gatt-write conn= attr= value= - disconnect conn= -GATT/CL/GAW/BI-03-C PASS connect peer_addr= - gatt-write conn= attr= value= - disconnect conn= -GATT/CL/GAW/BI-04-C N/A - -GATT/CL/GAW/BI-05-C PASS connect peer_addr= - gatt-write conn= attr= value= - disconnect conn= -GATT/CL/GAW/BI-06-C PASS connect peer_addr= - gatt-write conn= attr= value= - disconnect conn= -GATT/CL/GAW/BV-05-C PASS connect peer_addr= - gatt-write long=1 conn= attr= value= - disconnect conn= -GATT/CL/GAW/BI-07-C PASS connect peer_addr= - gatt-write long=1 conn= attr= value= - disocnnect conn= -GATT/CL/GAW/BI-08-C PASS connect peer_addr= - gatt-write long=1 conn= attr= value= - diconnect conn= -GATT/CL/GAW/BI-09-C PASS connect peer_addr= - gatt-write long=1 conn= attr= value= offset= - diconnect conn=1 -GATT/CL/GAW/BI-11-C N/A - -GATT/CL/GAW/BI-12-C PASS connect peer_addr= - gatt-write long=1 conn= attr= value= - disconnect conn= -GATT/CL/GAW/BI-13-C PASS connect peer_addr= - gatt-write long=1 conn= attr= value= - diconnect conn= -GATT/CL/GAW/BV-06-C PASS connect peer_addr= - gatt-write long=1 conn= attr= value= - -GAAT/CL/GAW/BV-08-C PASS connect peer_addr= - gat-write conn= attr= value= - -GATT/CL/GAW/BV-09-C PASS connect peer_addr= - gatt-write long=1 conn= attr= value= - -GATT/CL/GAW/BI-32-C PASS connect peer_addr= - gatt-write conn= attr= value= attr= value= - disconnect conn= -GATT/CL/GAW/BI-33-C PASS connect peer_addr= - gatt-write conn= attr= value= - disconnect conn= -GATT/CL/GAW/BI-34-C PASS connect peer_addr= - gatt-write long=1 conn= attr= value= - disconnect conn= - -------------------------------------------------------------------------------- - -GATT/CL/GAN/BV-01-C PASS connect peer_addr= - gatt-write conn= attr= value=01:00 - Note: verify that the notification was received - disconnect conn= -------------------------------------------------------------------------------- - -GATT/CL/GAI/BV-01-C PASS connect peer_addr= - gatt-write conn= attr= value=01:00 - Note: verify that the notification was received - disconnect conn= -------------------------------------------------------------------------------- - -GATT/CL/GAS/BV-01-C PASS connect peer_addr= - disconnect conn= -------------------------------------------------------------------------------- - -GATT/CL/GAT/BV-01-C PASS connect peer_addr= - gatt-read conn= attr= -GATT/CL/GAT/BV-02-C PASS connect peer_addr= - gatt-write conn= attr= value= -------------------------------------------------------------------------------- - -GATT/CL/GPA/BV-01-C N/A -GATT/CL/GPA/BV-02-C N/A -GATT/CL/GPA/BV-03-C N/A -GATT/CL/GPA/BV-04-C N/A -GATT/CL/GPA/BV-05-C N/A -GATT/CL/GPA/BV-06-C N/A -GATT/CL/GPA/BV-07-C N/A -GATT/CL/GPA/BV-08-C N/A -GATT/CL/GPA/BV-11-C N/A -GATT/CL/GPA/BV-12-C N/A -------------------------------------------------------------------------------- - -GATT/SR/GAC/BV-01-C PASS set mtu=25 - advertise-configure connectable=1 legacy=1 - advertise-start - advertise-start -------------------------------------------------------------------------------- - -GATT/SR/GAD/BV-01-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - gatt-show-local - -GATT/SR/GAD/BV-02-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - gatt-show-local - -GATT/SR/GAD/BV-03-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - gatt-show-local - -GATT/SR/GAD/BV-04-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAD/BV-05-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAD/BV-06-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAD/BV-07-C N/A -GATT/SR/GAD/BV-08-C N/A -------------------------------------------------------------------------------- - -GATT/SR/GAR/BV-01-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BI-01-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BI-02-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAR/BI-03-C N/A -GATT/SR/GAR/BI-04-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BI-05-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BV-03-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BI-06-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - gatt-show-local - - -GATT/SR/GAR/BI-07-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAR/BI-08-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BI-09-C N/A -GATT/SR/GAR/BI-10-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BI-11-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAR/BV-04-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BI-12-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAR/BI-13-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BI-14-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAR/BI-15-C N/A -GATT/SR/GAR/BI-16-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BI-17-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BV-05-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BI-18-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAR/BI-19-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAR/BI-20-C N/A -GATT/SR/GAR/BI-21-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BI-22-C PASS advertise-configure connectable=1 legacy=1 - advertise-startt -GATT/SR/GAR/BV-06-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BI-23-C N/A -GATT/SR/GAR/BI-24-C N/A -GATT/SR/GAR/BI-25-C N/A -GATT/SR/GAR/BI-26-C N/A -GATT/SR/GAR/BI-27-C N/A -GATT/SR/GAR/BV-07-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BV-08-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAR/BI-28-C N/A -GATT/SR/GAR/BI-29-C N/A -GATT/SR/GAR/BI-30-C N/A -GATT/SR/GAR/BI-31-C N/A -GATT/SR/GAR/BI-32-C N/A -GATT/SR/GAR/BI-33-C N/A -GATT/SR/GAR/BI-34-C N/A -GATT/SR/GAR/BI-35-C N/A -------------------------------------------------------------------------------- - -GATT/SR/GAW/BV-01-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BV-02-C N/A -GATT/SR/GAW/BI-01-C N/A -GATT/SR/GAW/BV-03-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-02-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAW/BI-03-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-04-C N/A -GATT/SR/GAW/BI-05-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-06-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BV-05-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-07-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAW/BI-08-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAW/BI-09-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-11-C N/A -GATT/SR/GAW/BI-12-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-13-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BV-06-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BV-10-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-14-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAW/BI-15-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAW/BI-17-C N/A -GATT/SR/GAW/BI-18-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-19-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BV-11-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BV-07-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BV-08-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-20-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAW/BI-21-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAW/BI-22-C N/A -GATT/SR/GAW/BI-23-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-24-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BV-09-C PASS advertise-configure connectable=1 legacy=1q - advertise-start -GATT/SR/GAW/BI-25-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAW/BI-26-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -GATT/SR/GAW/BI-27-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-29-C N/A -GATT/SR/GAW/BI-30-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-31-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-32-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-33-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-34-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/GAW/BI-35-C PASS advertise-configure connectable=1 legacy=1 - advertise-start ------------------------------------------------------------------------------- - -GATT/SR/GAN/BV-01-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - gatt-notify attr= ------------------------------------------------------------------------------- - -GATT/SR/GAI/BV-01-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - gatt-notify attr= -------------------------------------------------------------------------------- - -GATT/SR/GAS/BV-01-C PASS Note: set TSPX_security_enabled to TRUE - security-set-data bonding=1 our_key_dist=7 their_key_dist=7 - advertise-configure connectable=1 legacy=1 - advertise-start - - gatt-service-changed start=1 end=0xffff - advertise-start - security-start conn= -------------------------------------------------------------------------------- - -GATT/SR/GAT/BV-01-C PASS advertise-start - gatt-notify attr=0x0008 ------------------------------------------------------------------------------- - -GATT/SR/GPA/BV-01-C N/A -GATT/SR/GPA/BV-02-C N/A -GATT/SR/GPA/BV-03-C N/A -GATT/SR/GPA/BV-04-C N/A -GATT/SR/GPA/BV-05-C N/A -GATT/SR/GPA/BV-06-C N/A -GATT/SR/GPA/BV-07-C N/A -GATT/SR/GPA/BV-08-C N/A -GATT/SR/GPA/BV-11-C N/A -GATT/SR/GPA/BV-12-C N/A -------------------------------------------------------------------------------- - -GATT/SR/UNS/BI-01-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -GATT/SR/UNS/BI-02-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - --------------------------------------------------------------------------------- - -GATT/SR/GPM/BV-01-C N/A - diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-l2cap.txt b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-l2cap.txt deleted file mode 100644 index c09add916..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-l2cap.txt +++ /dev/null @@ -1,304 +0,0 @@ -PTS test results for L2CAP - -PTS version: 7.5.0 -Tested: 07-Oct-2019 - -syscfg.vals: - BLE_EXT_ADV: 1 - BLE_PUBLIC_DEV_ADDR: "((uint8_t[6]){0x01, 0xff, 0xff, 0xc0, 0xde, 0xc0})" - BLE_SM_LEGACY: 1 - BLE_SM_SC: 1 - BLE_L2CAP_COC_MAX_NUM: 5 - BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL: 9 - BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL: 30 - BLE_SVC_GAP_PPCP_SUPERVISION_TMO: 2000 - CONSOLE_HISTORY_SIZE: 10 - -Results: -PASS test passed -FAIL test failed -INC test is inconclusive -N/A test is disabled due to PICS setup - -------------------------------------------------------------------------------- -Test Name Result Notes -------------------------------------------------------------------------------- - -L2CAP/COS/CED/BV-01-C N/A -L2CAP/COS/CED/BV-03-C N/A -L2CAP/COS/CED/BV-04-C N/A -L2CAP/COS/CED/BV-05-C N/A -L2CAP/COS/CED/BV-07-C N/A -L2CAP/COS/CED/BV-08-C N/A -L2CAP/COS/CED/BV-09-C N/A -L2CAP/COS/CED/BV-10-C N/A -L2CAP/COS/CED/BV-11-C N/A -L2CAP/COS/CED/BI-01-C N/A -------------------------------------------------------------------------------- - -L2CAP/COS/CFD/BV-01-C N/A -L2CAP/COS/CFD/BV-02-C N/A -L2CAP/COS/CFD/BV-03-C N/A -L2CAP/COS/CFD/BV-08-C N/A -L2CAP/COS/CFD/BV-09-C N/A -L2CAP/COS/CFD/BV-10-C N/A -L2CAP/COS/CFD/BV-11-C N/A -L2CAP/COS/CFD/BV-12-C N/A -L2CAP/COS/CFD/BV-13-C N/A -------------------------------------------------------------------------------- - -L2CAP/COS/IEX/BV-01-C N/A -L2CAP/COS/IEX/BV-02-C N/A -------------------------------------------------------------------------------- - -L2CAP/COS/ECH/BV-01-C N/A -L2CAP/COS/ECH/BV-02-C N/A -------------------------------------------------------------------------------- - -L2CAP/COS/CFC/BV-01-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - l2cap-create-server psm= - advertise-start - l2cap-send conn= idx=0 bytes=15 - -L2CAP/COS/CFC/BV-02-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - l2cap-create-server psm= - advertise-start - l2cap-send conn= idx=0 bytes=15 - -L2CAP/COS/CFC/BV-03-C PASS NOTE: #define BTSHELL_COC_MTU = 512 - advertise-configure connectable=1 legacy=1 - l2cap-create-server psm= - advertise-start -L2CAP/COS/CFC/BV-04-C PASS advertise-configure connectable=1 legacy=1 - l2cap-create-server psm= - advertise-start -L2CAP/COS/CFC/BV-05-C PASS advertise-configure connectable=1 legacy=1 - l2cap-create-server psm= - advertise-start - l2cap-connect conn= psm= - l2cap-connect conn= psm=<2nd psm> -------------------------------------------------------------------------------- - -L2CAP/CLS/CLR/BV-01-C N/A -------------------------------------------------------------------------------- - -L2CAP/CLS/UCD/BV-01-C N/A -L2CAP/CLS/UCD/BV-02-C N/A -L2CAP/CLS/UCD/BV-03-C N/A -------------------------------------------------------------------------------- - -L2CAP/EXF/BV-01-C N/A -L2CAP/EXF/BV-02-C N/A -L2CAP/EXF/BV-03-C N/A -L2CAP/EXF/BV-04-C N/A -L2CAP/EXF/BV-05-C N/A -L2CAP/EXF/BV-06-C N/A -------------------------------------------------------------------------------- - -L2CAP/CMC/BV-01-C N/A -L2CAP/CMC/BV-02-C N/A -L2CAP/CMC/BV-03-C N/A -L2CAP/CMC/BV-04-C N/A -L2CAP/CMC/BV-05-C N/A -L2CAP/CMC/BV-06-C N/A -L2CAP/CMC/BV-07-C N/A -L2CAP/CMC/BV-08-C N/A -L2CAP/CMC/BV-09-C N/A -L2CAP/CMC/BV-10-C N/A -L2CAP/CMC/BV-11-C N/A -L2CAP/CMC/BV-12-C N/A -L2CAP/CMC/BV-13-C N/A -L2CAP/CMC/BV-14-C N/A -L2CAP/CMC/BV-15-C N/A -L2CAP/CMC/BI-01-C N/A -L2CAP/CMC/BI-02-C N/A -L2CAP/CMC/BI-03-C N/A -L2CAP/CMC/BI-04-C N/A -L2CAP/CMC/BI-05-C N/A -L2CAP/CMC/BI-06-C N/A -------------------------------------------------------------------------------- - -L2CAP/FOC/BV-01-C N/A -L2CAP/FOC/BV-02-C N/A -L2CAP/FOC/BV-03-C N/A -------------------------------------------------------------------------------- - -L2CAP/OFS/BV-01-C N/A -L2CAP/OFS/BV-02-C N/A -L2CAP/OFS/BV-03-C N/A -L2CAP/OFS/BV-04-C N/A -L2CAP/OFS/BV-05-C N/A -L2CAP/OFS/BV-06-C N/A -L2CAP/OFS/BV-07-C N/A -L2CAP/OFS/BV-08-C N/A -------------------------------------------------------------------------------- - -L2CAP/ERM/BV-01-C N/A -L2CAP/ERM/BV-02-C N/A -L2CAP/ERM/BV-03-C N/A -L2CAP/ERM/BV-05-C N/A -L2CAP/ERM/BV-06-C N/A -L2CAP/ERM/BV-07-C N/A -L2CAP/ERM/BV-08-C N/A -L2CAP/ERM/BV-09-C N/A -L2CAP/ERM/BV-10-C N/A -L2CAP/ERM/BV-11-C N/A -L2CAP/ERM/BV-12-C N/A -L2CAP/ERM/BV-13-C N/A -L2CAP/ERM/BV-14-C N/A -L2CAP/ERM/BV-15-C N/A -L2CAP/ERM/BV-16-C N/A -L2CAP/ERM/BV-17-C N/A -L2CAP/ERM/BV-18-C N/A -L2CAP/ERM/BV-19-C N/A -L2CAP/ERM/BV-20-C N/A -L2CAP/ERM/BV-21-C N/A -L2CAP/ERM/BV-22-C N/A -L2CAP/ERM/BV-23-C N/A -L2CAP/ERM/BI-01-C N/A -L2CAP/ERM/BI-02-C N/A -L2CAP/ERM/BI-03-C N/A -L2CAP/ERM/BI-04-C N/A -L2CAP/ERM/BI-05-C N/A -------------------------------------------------------------------------------- - -L2CAP/STM/BV-01-C N/A -L2CAP/STM/BV-02-C N/A -L2CAP/STM/BV-03-C N/A -L2CAP/STM/BV-11-C N/A -L2CAP/STM/BV-12-C N/A -L2CAP/STM/BV-13-C N/A -------------------------------------------------------------------------------- - -L2CAP/FIX/BV-01-C N/A -L2CAP/FIX/BV-02-C N/A -------------------------------------------------------------------------------- - -L2CAP/EWC/BV-01-C N/A -L2CAP/EWC/BV-02-C N/A -L2CAP/EWC/BV-03-C N/A -------------------------------------------------------------------------------- - -L2CAP/LSC/BV-01-C N/A -L2CAP/LSC/BV-02-C N/A -L2CAP/LSC/BV-03-C N/A -L2CAP/LSC/BI-04-C N/A -L2CAP/LSC/BI-05-C N/A -L2CAP/LSC/BV-06-C N/A -L2CAP/LSC/BV-07-C N/A -L2CAP/LSC/BV-08-C N/A -L2CAP/LSC/BV-09-C N/A -L2CAP/LSC/BI-10-C N/A -L2CAP/LSC/BI-11-C N/A -L2CAP/LSC/BV-12-C N/A -------------------------------------------------------------------------------- - -L2CAP/CCH/BV-01-C N/A -L2CAP/CCH/BV-02-C N/A -L2CAP/CCH/BV-03-C N/A -L2CAP/CCH/BV-04-C N/A -------------------------------------------------------------------------------- - -L2CAP/ECF/BV-01-C N/A -L2CAP/ECF/BV-02-C N/A -L2CAP/ECF/BV-03-C N/A -L2CAP/ECF/BV-04-C N/A -L2CAP/ECF/BV-05-C N/A -L2CAP/ECF/BV-06-C N/A -L2CAP/ECF/BV-07-C N/A -L2CAP/ECF/BV-08-C N/A -------------------------------------------------------------------------------- - -L2CAP/LE/CPU/BV-01-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - advertise-start - l2cap-update conn= -L2CAP/LE/CPU/BV-02-C PASS connect peer_addr= - disconnect conn= -L2CAP/LE/CPU/BI-01-C PASS connect peer_addr= - disconnect conn= -L2CAP/LE/CPU/BI-02-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - advertise-start -------------------------------------------------------------------------------- - -L2CAP/LE/REJ/BI-01-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - advertise-start -L2CAP/LE/REJ/BI-02-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - advertise-start - disconnect conn= -------------------------------------------------------------------------------- - -L2CAP/LE/CFC/BV-01-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - advertise-start -L2CAP/LE/CFC/BV-02-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - advertise-start - l2cap-connect conn= psm=90 -L2CAP/LE/CFC/BV-03-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - l2cap-create-server psm= - advertise-start - l2cap-send conn= idx=0 bytes=15 - -L2CAP/LE/CFC/BV-04-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - advertise-start - l2cap-connect conn= psm= -L2CAP/LE/CFC/BV-05-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - advertise-start -L2CAP/LE/CFC/BV-06-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - l2cap-create-server psm= - advertise-start - l2cap-send conn= idx=0 bytes=15 -L2CAP/LE/CFC/BV-07-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - l2cap-create-server psm= - advertise-start -L2CAP/LE/CFC/BI-01-C PASS advertise-configure connectable=1 legacy=1 - l2cap-create-server psm= - advertise-start -L2CAP/LE/CFC/BV-08-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - l2cap-create-server psm= - advertise-start - l2cap-disconnect conn= idx=0 -L2CAP/LE/CFC/BV-09-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - l2cap-create-server psm= - advertise-start -L2CAP/LE/CFC/BV-16-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - advertise-start - l2cap-connect conn= psm=90 -L2CAP/LE/CFC/BV-17-C N/A -L2CAP/LE/CFC/BV-18-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - advertise-start - l2cap-connect conn= psm=90 -L2CAP/LE/CFC/BV-19-C PASS NOTE: TSPC_L2CAP_3_16 (multiple channel support) must be checked - advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - advertise-start - l2cap-connect conn= psm=90 -L2CAP/LE/CFC/BV-20-C PASS NOTE: TSPC_L2CAP_3_16 (multiple channel support) must be checked - advertise-configure connectable=1 legacy=1 - l2cap-create-server psm= - advertise-start -L2CAP/LE/CFC/BV-21-C PASS advertise-configure connectable=1 legacy=1 - advertise-set-adv-data flags=6 - advertise-start - l2cap-connect conn= psm=90 -------------------------------------------------------------------------------- - -L2CAP/LE/CID/BV-01-C N/A -L2CAP/LE/CID/BV-02-C N/A -------------------------------------------------------------------------------- - diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-sm.txt b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-sm.txt deleted file mode 100644 index ac26db712..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-sm.txt +++ /dev/null @@ -1,310 +0,0 @@ -PTS test results for SM - -PTS version: 7.5.0 -Tested: 07-Oct-2019 - -syscfg.vals: - BLE_EXT_ADV: 1 - BLE_PUBLIC_DEV_ADDR: "((uint8_t[6]){0x01, 0xff, 0xff, 0xc0, 0xde, 0xc0})" - BLE_SM_LEGACY: 1 - BLE_SM_SC: 1 - BLE_L2CAP_COC_MAX_NUM: 5 - BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL: 9 - BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL: 30 - BLE_SVC_GAP_PPCP_SUPERVISION_TMO: 2000 - CONSOLE_HISTORY_SIZE: 10 - -Results: -PASS test passed -FAIL test failed -INC test is inconclusive -N/A test is disabled due to PICS setup -NONE test result is none - -------------------------------------------------------------------------------- -Test Name Result Notes -------------------------------------------------------------------------------- - -SM/MAS/PROT/BV-01-C PASS connect peer_addr= - security-set-data bonding=1 sc=1 our_key_dist=7 their_key_dist=7 - security-pair conn= -------------------------------------------------------------------------------- - -SM/MAS/JW/BV-01-C N/A -SM/MAS/JW/BV-05-C PASS connect peer_addr= - security-pair conn= - disconnect conn= - -SM/MAS/JW/BI-01-C PASS connect peer_addr= - security-pair conn= -SM/MAS/JW/BI-04-C PASS connect peer_addr= - security-set-data bonding=1 sc=1 - security-pair conn= -------------------------------------------------------------------------------- - -SM/MAS/PKE/BV-01-C PASS security-set-data io_capabilities=1 - connect peer_addr= - b sec pair conn= - b passkey conn= action=3 key=123456 - Note: enter '123456' passkey in PTS -SM/MAS/PKE/BV-04-C PASS security-set-data bonding=1 oob_flag=0 - connect peer_addr= - security-pair conn= - disconnect conn= -SM/MAS/PKE/BI-01-C PASS ecurity-set-data io_capabilities=1 oob_flag=0 - connect peer_addr= - security-pair conn= - auth-passkey conn= action=3 key=123456 - Note: enter invalid passkey -SM/MAS/PKE/BI-02-C PASS security-set-data io_capabilities=1 oob_flag=0 - connect peer_addr= - security-pair conn= - auth-passkey conn= action=3 key=123456 - Note: enter '123456' passkey in PTS -------------------------------------------------------------------------------- - -SM/MAS/OOB/BV-01-C N/A -SM/MAS/OOB/BV-03-C N/A -SM/MAS/OOB/BV-05-C PASS security-set-data io_capabilities=1 oob_flag=0 - connect-peer_addr= - security-pair conn= - auth-passkey conn= action=3 key=123456 - Note: enter '123456' passkey in PTS - disconnect conn=1 -SM/MAS/OOB/BV-07-C PASS ecurity-set-data io_capabilities=1 oob_flag=0 - connect-peer_addr= - security-pair conn= - disconnect conn=1 -SM/MAS/OOB/BV-09-C N/A -SM/MAS/OOB/BI-01-C N/A -------------------------------------------------------------------------------- - -SM/MAS/EKS/BV-01-C PASS connect peer_addr= - security-pair conn= - disconnect conn=1 -SM/MAS/EKS/BI-01-C PASS connect peer_addr= - security-pair conn= - disconnect conn=1 -------------------------------------------------------------------------------- - -SM/MAS/SIGN/BV-01-C N/A -SM/MAS/SIGN/BV-03-C N/A -SM/MAS/SIGN/BI-01-C N/A -------------------------------------------------------------------------------- - -SM/MAS/KDU/BV-04-C PASS security-set-data our_key_dist=4 - connect peer_addr= - security-pair conn= - disconnect conn=1 -SM/MAS/KDU/BV-05-C PASS security-set-data our_key_dist=2 - connect peer_addr= - security-pair conn= - disconnect conn=1 -SM/MAS/KDU/BV-06-C PASS security-set-data our_key_dist=1 - connect peer_addr= - security-pair conn= - disconnect conn=1 -SM/MAS/KDU/BV-10-C PASS security-set-data our_key_dist=2 sc=1 - connect peer_addr= - security-pair conn= - disconnect conn=1 -SM/MAS/KDU/BV-11-C PASS security-set-data our_key_dist=2 sc=1 - connect peer_addr= - security-pair conn= - disconnect conn=1 -SM/MAS/KDU/BI-01-C PASS connect peer_addr= - disconnect conn=1 - reset device - - -------------------------------------------------------------------------------- - -SM/MAS/SIP/BV-02-C PASS security-set-data io_capabilities=4 - connect peer_addr= - disconnect conn=1 -------------------------------------------------------------------------------- -SM/MAS/SCJW/BV-01-C PASS security-set-data sc=1 - connect peer_addr= - security-pair conn= - disconnect conn=1 -SM/MAS/SCJW/BV-04-C PASS security-set-data sc=1 io_capabilities=1 our_key_dist=1 - connect peer_addr= - security-pair conn= - disconnect conn=1 -SM/MAS/SCJW/BI-01-C PASS security-set-data sc=1 io_capabilities=4 - connect peer_addr= - security-pair conn= - disconnect conn=1 - - -------------------------------------------------------------------------------- - -SM/MAS/SCPK/BV-01-C PASS security-set-data sc=1 io_capabilities=2 - connect peer_addr= - security-pair conn= - auth_passkey conn=1 action=2 key=123456 - Note: enter '123456' passkey in PTS - disconnect conn=1 -SM/MAS/SCPK/BV-04-C PASS security-set-data io_capabilities=4 oob_flag=0 our_key_dist=1 their_key_dist=1 - connect peer_addr= - security-pair conn= - auth_passkey conn=1 action=2 key=123456 - Note: enter '123456' passkey in PTS - disconnect conn=1 -SM/MAS/SCPK/BI-01-C PASS security-set-data io_capabilities=4 oob_flag=0 sc=1 - connect peer_addr= - security-pair conn= - disconnect conn=1 - - auth_passkey conn=1 action=2 key=123456 - Note: enter '123456' passkey in PTS - disconnect conn=1 -SM/MAS/SCPK/BI-02-C PASS security-set-data io_capabilities=2 oob_flag=0 bonding=1 sc=1 - connect peer_addr= - security-pair conn= - auth_passkey conn=1 action=2 key=123456 - Note: enter '123456' passkey in PTS - disconnect conn=1 -------------------------------------------------------------------------------- - -SM/MAS/SCOB/BV-01-C N/A -SM/MAS/SCOB/BI-04-C N/A -SM/MAS/SCOB/BV-01-C N/A -SM/MAS/SCOB/BI-04-C N/A -------------------------------------------------------------------------------- - -SM/MAS/SCCT/BV-01-C N/A -SM/MAS/SCCT/BV-03-C N/A -SM/MAS/SCCT/BV-05-C N/A -SM/MAS/SCCT/BV-07-C N/A -SM/MAS/SCCT/BV-09-C N/A -------------------------------------------------------------------------------- - -SM/SLA/PROT/BV-02-C PASS advertise-configure connectable=1 legacy=1 - advertise-start - -------------------------------------------------------------------------------- - -SM/MAS/JW/BV-02-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -SM/SLA/JW/BI-02-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -SM/SLA/JW/BI-03-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -------------------------------------------------------------------------------- - -SM/SLA/PKE/BV-02-C PASS security-set-data io_capabilities=4 - advertise-configure connectable=1 legacy=1 - advertise-start - auth-passkey conn= action=2 key= - -SM/SLA/PKE/BV-05-C PASS security-set-data io_capabilities=4 - advertise-configure connectable=1 legacy=1 - advertise-start -SM/SLA/PKE/BI-03-C PASS security-set-data io_capabilities=4 - advertise-configure connectable=1 legacy=1 - advertise-start - auth-passkey conn= action=3 key=123456 - Note: enter invalid passkey -------------------------------------------------------------------------------- - -SM/SLA/OOB/BV-02-C N/A -SM/SLA/OOB/BV-04-C N/A -SM/SLA/OOB/BV-06-C PASS security-set-data io_capabilities=1 - advertise-configure connectable=1 legacy=1 - advertise-start - auth-passkey conn= action=3 key= -SM/SLA/OOB/BV-08-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -SM/SLA/OOB/BV-10-C N/A -SM/SLA/OOB/BI-02-C N/A -------------------------------------------------------------------------------- - -SM/SLA/EKS/BV-02-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -SM/SLA/EKS/BI-02-C PASS advertise-configure connectable=1 legacy=1 - advertise-start -------------------------------------------------------------------------------- - -SM/SLA/KDU/BV-01-C PASS security-set-data io_capabilities=1 - advertise-configure connectable=1 legacy=1 - advertise-start -SM/SLA/KDU/BV-02-C PASS security-set-data io_capabilities=2 - advertise-configure connectable=1 legacy=1 - advertise-start -SM/SLA/KDU/BV-03-C PASS security-set-data io_capabilities=4 - advertise-configure connectable=1 legacy=1 - advertise-start -SM/SLA/KDU/BV-07-C PASS security-set-data our_key_dist=1 bonding=1 - advertise-configure connectable=1 legacy=1 - advertise-start -SM/SLA/KDU/BV-08-C PASS security-set-data our_key_dist=2 sc=1 - advertise-configure connectable=1 legacy=1 - advertise-start -SM/SLA/KDU/BV-09-C PASS security-set-data our_key_dist=4 bonding=0 - advertise-configure connectable=1 legacy=1 - advertise-start -SM/SLA/KDU/BI-01-C PASS advertise-configure connectable=1 legacy=1 - security-set-data sc=1 - advertise-start - - -------------------------------------------------------------------------------- - -SM/SLA/SIP/BV-01-C PASS security-set-data io_capabilities=4 - advertise-configure connectable=1 legacy=1 - advertise-start - security-start conn= -------------------------------------------------------------------------------- - -SM/SLA/SIE/BV-01-C PASS security-set-data io_capabilities=3 bonding=1 our_key_dist=1 their_key_dist=1 - advertise-configure connectable=1 legacy=1 - advertise-start - advertise-start - security-start conn= -------------------------------------------------------------------------------- - -SM/SLA/SCJW/BV-02-C PASS security-set-data io_capabilities=4 oob_flag=0 bonding=0 mitm_flag=0 sc=1 our_key_dist=1 - advertise-configure connectable=1 legacy=1 - advertise-start -SM/SLA/SCJW/BV-03-C PASS security-set-data io_capabilities=1 our_key_dist=1 oob_flag=0 - advertise-configure connectable=1 legacy=1 - advertise-start -SM/SLA/SCJW/BI-02-C PASS security-set-data io_capabilities=1 oob_flag=0 bonding=1 sc=1 - advertise-configure connectable=1 legacy=1 - advertise-start -------------------------------------------------------------------------------- - -SM/SLA/SCPK/BV-02-C PASS security-set-data io_capabilities=1 oob_flag=0 sc=1 - advertise-configure connectable=1 legacy=1 - advertise-start - auth-passkey conn=1 action=4 key=186900 yesno=yy -SM/SLA/SCPK/BV-03-C PASS security-set-data io_capabilities=2 oob_flag=0 our_key_dist=1 their_key_dist=1 sc=1 - advertise-configure connectable=1 legacy=1 - advertise-start - auth-passkey conn=1 action=2 key=123456 - Note: enter '123456' passkey in PTS -SM/SLA/SCPK/BI-03-C PASS security-set-data io_capabilities=2 oob_flag=0 sc=1 - advertise-configure connectable=1 legacy=1 - advertise-start - auth-passkey conn=1 action=2 key=123456 oob= - Note: enter '123456' passkey in PTS -SM/SLA/SCPK/BI-04-C PASS security-set-data io_capabilities=2 oob_flag=0 mitm_flag=1 sc=1 - advertise-configure connectable=1 legacy=1 - advertise-start - - auth-passkey conn=1 action=2 key=123456 - Note: enter '123456' passkey in PTS -------------------------------------------------------------------------------- - -SM/SLA/SCOB/BV-02-C N/A -SM/SLA/SCOB/BI-03-C N/A -SM/SLA/SCOB/BV-02-C N/A -SM/SLA/SCOB/BI-03-C N/A -------------------------------------------------------------------------------- - -SM/SLA/SCCT/BV-02-C N/A -SM/SLA/SCCT/BV-04-C N/A -SM/SLA/SCCT/BV-06-C N/A -SM/SLA/SCCT/BV-08-C N/A -SM/SLA/SCCT/BV-10-C N/A \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/tpg/94654-20170317-085122560.tpg b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/tpg/94654-20170317-085122560.tpg deleted file mode 100644 index 3cc985fab..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/tpg/94654-20170317-085122560.tpg +++ /dev/null @@ -1,1026 +0,0 @@ - -M'&/JP\$+#X83?)"[ M2E=\N*7*U 5)JSKT(5#=>@^/#]IP*[GTZ0%0]$F(/$ -MEK[V7>349??;!JZJNFZ CK=QGD^FOYV^FU>"DK<@0U*##HV\H9&_%["5IK@1 -MA9F,FJO2P^3:4_]04%-0T%9=^XCMWKF"L$[)%)G>_I 0Q?@:H)&1HX)7VY&. -M3 *!JH;^YUJ1[_*7JN2'Z5^*0I&NP+[LAE:>S92BP^T:3+B>IKFJJ8A,4Y^L -MUX+P_C'Z#VN20)A!ANN2@J#!AYY4"KQ\5):1]+[B\TN+BI"AB8NJH ,NZ(() -MG>K?^A\-B,<@/IVC+$#XFXJ<65V*OE'"L]7*OEJ*C]CS^."A/) (K_@0 -ME"&)D)^IP]?+')Q(%NM&7:VL@*6#D!-TU,7.WG SERP(@*R+DH"MPH;@X:Y) -M]X6NG8^EC)N?AH+3[\3SG''R3(?WRGF0NZ#,_4%*E)&>&9R)5[F0OM$A0Y.; -MA8R7%EGBS&\IDPYNR%4ZV$FK^(F[P B/[TU86=H%S^ -MH[H^EYQB:MZ)A:2@IV)4O=//SXNP#%F]5N&<3KZL>(#6'H"D4\DST(O!(![@ -MUYZX#+:1G:V5BE&TGHK]+;@:^JF;;2-&@WD;Z8I9*SB5D+7 &/J8NI6GYGMDGK2(U+_)K!,I$6Q4R% -MAIE9AK#]!JAFCWWD:A8K.9O/I(;D(F2G*6A0YUCMIOQ5M*VD#1: -MG9^)MMZ GIK7,^R0^M"/\%^_B9Y7TLQ/^N?S1 DEF 6XUJU"V_3_U\44H9.; -M6C/PV(36QT(9B9^.C)*YUP?BN>#F%4ST/JM>\*Y;K)J:S+4[O%?G[S[L"^FPVC9/W+).O23U=;?;2EV+G5"5%KG(EED8SLB#Q["2.9YW6IB4DKT QL7P\,%# -MAY^ (+Y+V8GD:B'!S H%G*;=[-\ -M 0+QQ3;G\H21FY_P4-)38+ =K,/38[24B[6W\(N-L/(9[/_LY.X/OLZ%S;A> -MO0TN'._"@/.)DDZ*AGY.V1XW%G7:O+R67U"C@:L%+T\24!11KH^]@[UR\Y\T -M'G.5D/)=H)R"J6R470%+AO24DHF5L -2OV(60>3Z]/#0\HE4<(V%GXBM% 0- -M3X-@G;H%E[2$DL$P-?W&"JI0-EV0AUP(\>] XIW!BI6DO7I9T33VE._FJ(*_ -MKQ6$@E,QFO?! P_#OYFAJ_:"JEF6?]O2PM3:)3"+BYBAK :/H:SLBX.NPOA_3S>U9*&PG[SAU:$=KQR\M>?\!X3 -MZYZ?J;\8N0V1]JOBJ@3;9=L01YQ<:%>>U)-!GAL!T^"]VF8KB/^$EH.ENI:4 -M[(80V,)1T>^'[@;!KIZ5T4.RQW)2M,X;#;8LTO_GV8V[OD6F@JNK JO G$2Q -MH(=0E:GW!3:0E_/T4ZF!M!D-F1F7NI*^QP;A%%V8M*U:R59]QE^+$NONY](% -M28E"K!J#K5N5E8#B_OU9L819J(CL]20ZBF"L4*4D#JV,*& -MYJV<6(JKEZZ4+^NI?%8D<$.P^*4 Z#=7K>XM. -MU3'S/BX/AP [V4*K!EY0C-/CE//ME"./3?_H5OQM$R!7NN&@21#()=Q)MEIG -MU_Y)N7IZ .'V51 ]]L:;LEZ+DI"H^K R=CO:@D2&#^H,PQ!"EDZ>@'"*JK)I -MM9<-XF7"=^(HC+:D156UME\ U?+P=G >A(^3=EW1ZB[7^C_1CZ&R#Y!"F:FH -MHO_0SL+1D%1$55K!?)*MLC?(]!3G_A,(AXY&\M.G+@>5;>6Z]?^Z&KBV:9N< -MBRWP0KI!\#7P]MOC;Y)<5(NN%8*2GEL9'\7/SMD 1Q6PCZ]6;0T*&KK)-^4N -M-OV!3U6TE8(,B;9"K*0WH=?J*<_9J=-(NK)0LY:FO5R)P'*3V.;%;^Z6() 2 -MWEB>F*H-#0RERD0TG[]6I4)#T_26M/[GQ8V5MO]RIY&RN%W_S1G/L829DMR2 -M]('/K/92XJKUML7OR!,>P)J*"H>&-Q0-\]("+'L^-EO>=(036Y>P%.:V&"8V-7ZT139&:(YNN@Z VJQCV=M VOMJ:E/XOE(L[GZ4;QT"H -M$!AY7Y>2^:N K"-$'B0L[FEJN#[Q19:D[2;=9F*>)!$@X/4']#" -M!1&2G)8;"$M&=?M B=+DQ^YQ"-!FB)9'T\^32NDK[68N]-J[6Y^IR:Z(A[.. -M6RG95?0:6^K'2FAK[7\O>>+_9#G(I4O*2=3,_<+@R)UM-9DW*NL+I?DJA^ -M:X8+&-[1=O9MX:R#BIVVVL*?&,-#U928LBR6DI:OR/OQV_;Z"H13GEZ <)J[ -M^8(-)]\+U9V24@V?@HK_A'3=YS&MN]3U&:<&)%JJPHZ6H4 --!,T\L,(ICBY -M$XOXI)]-\^"U_CHZ!52.^"'OK$V=K;>;@,34R_HCW U3FB1#KKV/@Z#_S.'% -M9M 26;U3E76LAFN3DZG5@QO8R.G+!?N(V9N<2;,*E9E2@K&$0L$X+707X.^\ -MT*.^GE""6H$?\19Z=D.11X"6D]CR\RWCD_%?L8JF/FV$&X]!:4**[ -MIJ&85T .P5K[]>8?Q92+TN#S6X[[MHCH"/&KV'J%?' -MDXN2D@L"PEG3X\S?#I9!&(61@+:/6K0YEXK-.ODV/_?'<;&3^)J!2E##A^,3 -M^E;>K7N=]K<"P^$PWC05A%.T7+ 72YJ2?GKS[_#*?9/+D5I=DGF1MKNMU-:; -MTA'SN[>Q@KJ'7 >7QXCJY?#F JZBH%J*TH7WD[S#-.W&]"["KX^N/$.2E8- -M\'OI3>S9)=OP3U7$O"FNK.\J5(+0IC!.XWY;M$\. -M=$Z/KD^-C/1_0?_L_+W"8^N=B7="A8V64I)?G0DOR_KWS/WPQFUSE4C6DDBH -MPJ(PFL.YN.[W]D+^>+I&EEF\EPW'VQA<& I.AD"V5P+ .6_&1:%>-O&=E8%* -M4Z0_F\3GXHI]D-*1FG<:^(&&FQ$__=_Z\-!-I[N#]"^O-VP$ U1GN0\!K]*A/C9:4F99SFM+[ -M[/?CV\*/O(Z#ME:'OC&&?BVA3B31],CN[TF*EE6"FYY(_IXY];+QIY%OQ/?P -MO'*3\1.ABJKLSL+ 7[&CG)>!3%[%>BSWMCX#>%VV+I"SC'*XM%O%*Q$\F$3R -MFPZ16JEA@IM"\L/P^B,0TK:X6KG'%9"W[*C0N>76+Q%7H<_>PHYZHI3A)I%T -M'CJE1J;\5+\;VP%IFYWG(<')6(D;XR:/K)56#*O 5YC#VK;WD_H'2JC>IQI2 -M#Q)4X? :TPVM[5T "L<4HRZ>IZZGK_N#H)Z#!2#PQ>W&P5H#TE6?DII]0?_U -M&*Q64E:.A]I>Y.KMN_K%\W60 9M4G7>#89>?AQ=WP<6$M/BPF(@#DXY8H>HV -M_98"]E%UHB\\ASAPD.K1\^:UE\.K'Z!]6YL*DABNQ='FFM8U\J>$N;^)5E:; -M)HY7P\"EFN02YN[;E$Z.O[U&K 1"I3*7,,8PB6.?)NNE%"<+^?)R\BZB9Z6IC<;N)4W -MEY_GY\JLE%.13J-^"6Q2BLC7\M ,DGJQ)(E!VJ2>JL$T&>X]XL(MD$C9 KM8 -M%Y>>1_Z3H)?PNK"UEQY;MXY:G%GHQVX4[8_K5(P&CO(G'D&LVCKQRXG#YNWUT]23B'FSNANK -M@Z20C[BBQL4UU=+ND/(1D56Y OC->0^5A'RAD:0)&OZ$T.+\%E=K2E)F21L'SG5?CVIO&C8Z+K@7F\3[O\+J% -MK ,6OHYV"U3WZ=%^O_I*[+2LOFNZ'JB&3Z[%X$%9K\/(9II5A+\>CLV44)DG -MY"7V/;KFB)A=4].7@ZASJ'":Q?OL=UEIJBM)BH:'DOQRDJGTL!*[0>HY??Y= -MFH1(OYRWAUJ2T4S+"ZR@FZZRN4&HP\;T]IH2Q9F!DZV225N_C9);$_T!Y9J6 -MB?F&05X*DJ"#A3HS)L?'&@E>::Z$F&OD%;D[>K$/HNT2&C7!VF$ _$SYEG(;VM@7+&[?+^VI-.F;>X -M4$N*I)"B-MC^$ ;YV2@#T;JXA(JZ$ N3WQ-JL"%2M&J##F86WT/BL'P -MY.VZ(+&==J "\H:'QX.LP/#E[>8/BUZF'QI-5Y"0G*"V[S?D9O%'18Y.OQY. -MBN.WELSHV]K#\>(NUEP8;K>_4;:W^HE8]=?]M-" G)V?4[6AJYZ2EEO(SYH. -MTTO,P0*3G@V)GMG/YD6U,L<2Y XGUX) -M5_*33$# Y3?& [B;I:JP:89:E>KG^_6:7=8*G*!8[&^$;(Z@1KQ02XQR>D^[0?W8I/O-HL#UDI)0DZAU -MB0)0^(Z7S,)\T"?Z U#6N@25I]B*U0;.UH2"=%]>6:ZX\2'U/M(5U716I!UU -MAU>VX _/V?RJT)V2DA"&F9I3<(VJ\_9U\.#3L9.F9)JHII.?H+_E_M'N.AC' -MLJ26B+DMEGL&T.?A\O3"2VZZG P?TXM@[/:MS>W.P<\+W$D$U;_/>$NY>I>X -M@7(U+^;^3T^$B;-_E[M7GA&.60E*V?<3XZ;8V;L]]0J6EIF<%& -J5L2]SOF -M)..<4(JK6EB.FR?/*Y/*3^&/#W\G-)F'B? -M_I^'2E1MGHKG[)A4BPP,6SO'#EU2L@8-FX'XNKJJMD?P]A#56)N3GJ:]0(]# -MKQOCD)&4K4(9#][#/G_6O= #>+!255^7FJLR<%C8RX_1K[:$A7N@B;OC]X-8 -MD<#T'M<6O7NCD]Z'?G!;B/,JPSIMY8V7L!]:YYA>@(CT]#ETYC7;3**MC$LL -MGITZ!Y[MV@],Q_+DGQ6>J,^3K(EMA+=-(OW7L//1@8:QI5G:JH(>;!2"QRXJ -M+R[F!=L=DUCVD5J60+I_Q%R+1_*UQG;UV46@EY],D=";@:GC\)J8F)M;W8R; -M*.+3[O8_Q?!5A-&;R((_DEJ? LG"R$Q\%E20$:^YD96)27[S\]/WG8,";9:< -MB\;UOXW--C77[].KC!/_VJ;VMZ.4P+KM^M R]8]67@PGA[R'HA)=V0W=!13! -MY%:R5&I>GJT_;)R Q5/7[);$"[J:>U7SEY&\5B95RW<.4*_2T\;"V(-3OI]Y -M\@__\X:4/1J3QT3^-=.JL]O[I3=Q1GB=J]ISE]AB"MH2U.UFE?U7^,8K))8C=:WBEBA$ISUM_JO# !"7X>:K!ML#X,"_.J= -MG!R4+TY!FAEF5YO2PO$U[*- [4:L7U8]CA>_O)CFP<7;TQ"2IKGZN5>GGPAS -M.;5>5A ;3I:$O*=[#2@N0NZU'H$O7!BZB==5R7@K:4D->IP,'V\CHW@)Z40(>&U;>7 -M1P/+%KBF6Y]?D)!6\L'U->V;]1S=])[\45:#HI67Q LF:<'M@% 1!+V?BN4)3P"-F-18@GM^ -MB*CJ)3+6X,]04)Y;!?R;@V&PFM7.UT&$4!&III5*O9)WV=L2=^YN&LJ[%^V> -M^8,L'!J(D2(FN_1!#SIX%YN/5E^Q;BS"YO_$/\M-5H2=KYR&T+"@GN#,(?G! -M#\A+NYR\%)V%/7N.>R3Q[._&\]JK7Y"+2Y>*JA>IIZE)7I@*XWH6T32[6]6: -MDE";E_',D)?HU"T:YM[A4""1K*)S\ED S^+T6 O:>(>5&_W',OEWT#[C78"> -M&9/2N;T(C;VI#ML)O9.24?.8_!ULCY#%%\3&^]DT8IN UZJHKOWRJB$S^58O -MVTM:L8-\#__SHTK3:?&_L/#V[).5W*:>.9*3O%L"P*T-[H-"IR>MSFR?C*V, -M7@BBPF?DU' *@?*UWU>:HT);D=H.\9>.2TT$P_?4:TX,\+NFJZ@";%6XXS;N -M\O"]VI6&I%N&,+:S)2L3YC&CGJ]R")Y[PR@P[;/_R7I0,$)*=0Y7SNZ"6D_%]Q="M%!&:FJS7 -MEMDR]?W +_V8I>";BHB]UK.,S/(QE??CBZ9@20F__):6I('^/,;W]=B/6Y^, -M@IA>B[!3FPDMXWV\C 9CG6)O96G H-MEHO!3L#FE)82CY>(F8FACI^'F^\P\%K0YJ>( -ML\Z3DHZWO$DPP>+ TPT@28J,F+R&64#!QNR0/]!8CU::O8^>O6>AH$+!S/[- -MY]/4CY#_N8\NCTN@6[?1:OF6]?7%!U>?7UKPC5)"XY*;\,82 ^\%R\-)ZJR9 -M7UK0FZJFL%>MTR9W-<75I9A0@EOP6)^=4-4#Y@^CDZTT45I;R?XY9__P Y!2 -M7D2 ,)(7HJ8:T<,*_863^XETD)J;8I92Y_(E]B_3U(>2X)WV2]:"AIS''MS^ -M-/*(EZQ:@^W7PK6*(.)9Y/8PXI:"! Z?BZMI1I;91/[)R.7"MNN:D Q'^KU<\5$<:<8!WC4$,SLT-V_Z M$U=GJ"^3D?;FF.T@2?V -M/K0[HE"0G'@_UI2;]]COX1F<%%&5CISZ>\3'Y-_Z-/.JEI.MH-,7JJ9VE_%= -M,@YVK@V2V6]?*7-+JUMJ/6I"5IY^5"W.R$^'S^486[]%* -MKI$C6Z9.F*)@GKB'B %&2#&U3&8K:U9&J81DY*05ADDPG'6X$8+D/:8<+Z) -MN-DM1\'<6@O>?07UF%C),M,P]/X*^GR3AU99G .AEBG-[=NPF9+?A(Q=2]N$ -M3Y\"DKTZQN49B(YX&HF'3K:*FG,;O3KG\ZU6A/.I@RV&4(KP^C<\^\>E#*1% -MZ!F/CKJYCIO#QX&,RV;0CZ)=J :>#8N")MLI<]7V+._BGI)]FQ>WD5H(:))7 -M8*(+U0L(Y^-8N0X9$+RF0*I?K,Y7S=0YU/Y$\3CVHKREH,*!P0,*T;BFHXV. -M7;B-1='8T/OGR+F6O@Z65ZFWJ'^;052%R)&@$5_ 9[CIPQ1=7FHV9>NE*HH6="LC/ -M2-'6V$:D7!^]AX]O>HW]\3@9I^;U\Z:8G)M7LHJ*T'"@4L$-^E[3AL[ \8K= -MN;>LF@^KLZF0>MCPEI/0N\=:=C>(EEU*5N4,HN"4G(H=I8D2C -MMJ"?DX&;MP6R*N#-PW:/]WPO6PQ)%,%VJ:ZJ. -MJ*"2@0+#]^_N]@^JAX:?0J:-O'&1SE>@COOE".;#]^9)FKGW"?9##K:3L'JL -M].TPY]##+%);A/H'0EL'W(\0CY&TMU"G^KG"XG3:M";)+'G_E:!=@JNX7)F) -M3T4QOG0#F*7WDZED%C="PC/[_?%4KH^64UAKV%*U0=G'[/04B:N2N,F+GIA& -MB97"X^[TU_971:1]B:=6N)U&NMCPSXOY#\[9O:.=@$,.0:B25[L'/O;%TE+/ -M2:H9@YY7C2QT08^0S2VJQ\<*U4?B/]2=I5NEKPN2\+:+(O+'-^X^YWF@DYN/ -MHKR7)KXL-1;176O#6D!?FKJN&QW^?C\J;DNQV -MBZ'6$*'/'ACJTYYK!F]%LOM)X9&@F;F0,'![/]D:.- -M6@C^ N/$\2PMFL.8!!'UEA&8GN2FGL'#0<05D)X=FJ*[F(&6]PWST-7$\+2K -MCJ2=>EE?E=*\Z?IMU#)+2IK* IQMAX!:O\JJ=<3\]M"+1I'JJYZ]"*2:G5C< -MR*5C0/&/5I")E(RNJ_B5VLT^.6(ZED^'NX]3G_(MC'NZMIG,S_C5_2?9HM&> -MG'BS>O!FBY.LEYW6(OR_.$QA8H!T494B8K,]'35DI1& -MN@@1A)^2_@VAI9E2XLL05! 4W9(U69*P7E+1\/3[E]+@FX6AL]>-#8*!O**Z -M/:S$SS^ZQ!JKC87[B[@)X_R@QOP%N?>IO(*&A<\1LYLA#$S[(<=1CO8-K8,: -M;(J0]XCG'_F@8L2:HKQ]V7J<9T*4:%9;04[J"^.+T<, @5^[HIX7N[N4N_!V -MQ-[O$/_D<)R"D+VDR9Z7 -: AA"$B"R5G9A+!_#@_%;F3PJ<4XZ0E5>KL!(J -M],+:DH_"0]^D=((*H)I?V.@U;<9ET8%0HI>H@Y1T YCU_F?P\@-)L)!6UDM. -M#XLMI\ 3]]HP U[WA)Q/.$'/*%"!]]3!:I[U!@<2^@J$F V0ED19VOXSUN;V -MXKBMJWZLEAN:6*P6F<+"R ,/Q^'W2(C2"4N:$+N"@[B0F_+;Y28:,L"\H)I? -M]ET;B_7,YQVOL91TGE%:FU+K^>YOUE.?D_ %LY/^FTQ3FLW_J39\\EX4S**Z -MF:(&]MGKP/?5Q=C*G*B76&C=IEL:HL(NFB?AJ51RJQKO5C!)O '7T_?@[\*B -MCKR<0UQOBV"F \OL?)D/Y1:#Q/W.@]X.O9)7B4B0+MYR=1DYL)P\??[<[2 -MRU*47U>'#*6@O&5B$?I\V+^3H%=:4K9:GX0!5CCZ\_X/:S9<@:^&5I-PM_O9 -MBERO2_; 1PY?A(,/AJMKG?DG,?]^U"?3XY)5$*S/BOF!IC.XR,C0(J+DR\"< -MQ[(UDU>'AZGX(%:7YSYCYN;>SQ"0B]TV 8NHP0[ \_&6(ATF79>O 3#SKL9O -MSYJ;M/$>]UG^L%Y;&?KS')ZQMJ^FM)):AD87"JOC+/H+,D>4$9J?DUW&4HHG -MX#3:-\F-J0>LSC -ME\";IG1["//YML:23[M=KU5ZSN\6"&6VLR$,Z O'!\S9$"*V>YL C:J=K^=5G>?]\E6\S!0\Y2?DEV" PDYEM?E]CS]_#7391&JIG+ -M4E^5'<<4+3+N;O*.@ER>%(V^@I./NHG$Q,S5P/!'M]P=B_^!;SA63Q+K^3OE -MO\\^EIT?2I:/&DFF#[C!#,"G^\_^Q39JNERS6Y:;@Y^QAE>9__B;_=IK49CS -MK821OX*1 O;1F)&1O7*0F%# T^3"=L"C'8@)M8:S4M/&>YK:R0_!CIB;E7*@ -MJ;:ZD'L(U#EZ1L,1F2:@2UJ-6$WPC$CJ_3KURHN_AJNL1Y)&$HSRPM2ZUBS' -M#I2(3L=:;XUFXC -M.HNR(@->1T^:D(JBY_62- -#6C@!EIM/E:6*23IM?]>20:D&#>F,AI2[#$9^ -MZ,_@^,4#X ]V48P6EX\8H 9:Q_1#-/+N#P*-A8**1D">5BF&@0D"B<\##JW9 -M-=BN!+M65;CYDJ&.ET<^*$X.>LK.*'ZBB+2#*T(95U%2=#(&:@+*@>_,T.?;0(+!+%$&;K&J/CY#* -MHM+QTI(/1_ [O9Q(A)):NL#$^1)GYL6,GK&,5H>/:Q!>6SV/2725PU=[ U>MOEX]2N/^BCG(,M%:DSM'B^X);Q]:]F"RRDI>KL()C -MIE<#,KVWF^XB_[*7KH+QKE?E:X-ACY:1]+ZW6+/9(L7G[+_S"K*FG,>\G'*6 -M<#G'W<>05).VA)^%KE."EACQ/N;UQ"?;O5^P"5@;OY!35='"=O746TJ5E+%3 -MA_;F(" 6>WO#^1'T'((FMD6&\.WL_3B..1& -MQU:MGF&KFDM\3[*GR3+G\!K!8)9F*9F3?9J;O_&S[.6UQ -?5X> C-N>HJV. -M6/' I0"3T>96:O[58O*>HJEN5I)[!OD:2=N G'!!>=(*9KXW5Z0,0CM!SE4^9OI,*]\,Z -M=&?/AG&4G?69 %>QM_O7'JO;K?R^O:;97JFL'?L-T.$_^B+P2:>&.1/95X>B -MH%GT./;BZ9?;OV-D<)]E#M3YRU$YBY61 -M[$^.F)BAI(MQU/4WY_32HH^[VJ/; -MJ:-R_Z4 1;EVI#V&6.S_92M2&V;I'9*R-S!T,;VTYU>K,1)EI];N$>3))'5 -M$!3[\+TLFW*6I:B<0:.20N?B3@\K!F6OT^L/J8B#MX]+>,2/./%T.ZN -M6*1Q'I&^FL?<]M"?H)1WMH&:OUG^_)?F]<"=@#9>II%+^JRFOL46PY;^O<&- -M3I>;O6I:&_<3[=+FPQ"#A$KXEDN;E_&*&SIU^C7/$[:&>YPG)GH.EQEO,Y,$?POKPG-9QO(Z)UXNHPMKC -MK***N194FK<"Z#/ZW^;;K8N7K/>7XKM^^?F -MWB$269JXK1.14E;Q <#^9I+2:U*,AE^;FY)7@L?:PM,>^FS2O_"8A)^^/KF0 -M4AE#1<_(]=5T3(Y_KY2O60O(M%^9M-D2)U*!-/;RT)+C-?(;L9%2L-*;AS^4 -M=8?:P_E[YA6;=+3_$BC=C8#J31.19G#028S_OXY"N%RHI)0+0MZ7XMAS=_\^L;%;Q)( -M>IRG5Y>5O@3CDS[F/I""D%6*CMR52JSUEMD<1OT5V1Q&O[F4:7Z6BZ#RDM/B -M\3;RU\"2GBB3K%YOMYJLGI_-5@OO^0C$4D-7!@T8CUEI.#DT_>BKQ,\.S2 -MNCO6B;JMA>]R:X*J6DT(S\O3]L\1S[11J!:+X8-@1/W3\O/0+OK7 QZ>H9*$ -MSJFGH*>=#5?HP$:CY_]@JA,C992@Y>MV_#PY_ EVU06<+E?E8)3!WVE -M *W3H-"F2KI;9]'YOU -MQOH*UJM.1D.)C01P2.B-_M?FY<,^AFA0JZL&MJ<4<<34T#?6(QE2VFCOAFZ -ML(W]+?H,[UR@Y)>$C8J_FXNGP9I(TQ;WT[ L#Y&8G-JJI(B>T^!6^-'"49\K -MS(KE18J5D2$#CH,(LF!=PU'>U,+:]<-4$YN\D@$"EPS*T[65B8N4AAFJ&1?K -M[)?RP@MY]I:MCZ% DJ&,DJ?)SM*%G(.;F@*^5L)?U^5[T2?&SU1*G^V;@X>] -MU9;%P7)C>CHE2)9!NP&'6YO3*O$S_6XU^O+"A'Y 0JI;:4765Q',R0\' U6' -MEH6437W%1J"6K0=I[7OW]L-*CH2*WE(+F?&H5E*:[M *^(?1Q0B+5)Z@G!:[ -MNH)@7%^A4!6^)B+G** +E-")N9K+!M+DK_K+W7!0@H_G]C3P\K(%_Y&>L?+% -M4[T-NH+EZ440G)12*QH9FIJ5CK<5\O?W\\#)CY:A^U.-J%"EC,#Z-MSR6(>6 -MI:U6RUJ2 X_ UM$F-/?SAQZ,+>^S6@R#J&$;)APO!9DNOKW"?CJNJ6[JEW>CY^77P, "X49I;IZ"3BL#% -M)O11HDN$Q*5:K\+2K?#&QMM<5(.8LB&V2X9PJ2G_ZU&?H(&>GY._@J)/F8+ -M[3HW\N"ZC\&8\8]=OX.^(>'%GJ:A0!DC\^8WU\-71CC825X! -M*J8 D,3J>,7NSMQ)C\Z,'+X50)0WBN^+G*(DJ5VW@H/!V2.)CG 8"L0#T^P,:N+ -MAZ17B<"KM=8N*(G7H/NN37^"7Z#8\<,Z,'K*@XY=X(M22T>26K:CP-7?WI,8 -MBS>L'&FH;4\FLM-,WC?$/!?S!UAVDK86KU>#D*:QR,=J]+,)4PI(6"ZZ1\YFZ2(NHJ' -MF).=8Y>:R.+:P8^;D;ZPD5)W!8RXT/;Q)O;U0ZE>.%S]]!NI^Z&]DRQ -M=IJZBH&B#(W)@@7+QJY;ZT.[MZE;"*)=7Z+CUDNM(N?^P-3BA" 6NQITMBT* -MBO"+_B*0'8R'G'O@]O3N>OKS3$G2^0^(NE<#GGK#S\M02D/Q_W:4RGNBMXG! -M,C#V[%#EPY1F0UKKGJ;?3B7W]?0UD6-WIJN;AQ[%F*7A]#Z:\._5BY><3*O[ -MG3NMEDL- <;HR\?PEH!<5,3RGK^UH(M13\M"4&KJ8@I[[\6/!\^0GF%O[MH.2 -MB+WPLL#W]_4P-!L:D$Q=NX=6!KM!T=XY.G#OVIF:K(V#!ZD9N%K#PQWDR-[% -MY ^F#$SLM[MJN%ZHP4/TYA8P6LB_EK*"?E*:"^@PEV36 G4*_[GW-8 -MCY."H[G4^$BKB, -M5P#4V=/E[E.#>'M56@"Y5X*J@7(/PTF<6 -M[N6FC NQN/>0^9[$PJ75WJ6>65J=BA$A:[E3T/W%6EB G9>5JECAC%?!_0]) -M\* ZA9:AFD*!GYO8\O;V<]K0FI:4B*NY5I1'C%#V=3:V Y*[DML*N)>4DVH( -M].W&-,;PCU8)[9J%Z[BAUBW*S.L%3R+8EW:=C$M5A)"I^I[ NN$0XOK'S;^+ -MH:HFYJNQPEK#$L9)Q*OL!P\VAK);4*Z@K_;1H8X?<,/3.C_@(X1V?H>ZD+J3 -ME2IA^,:IRG\JP'GK;:Y!"#7FQ LY/=EEZ64O(]W^62SX^V>&W/ -M6XV I%^IX,:)R4]#FF,?J8Q##:4T1.FJW"+);'V]R*D$:K -MNJ:6\)<(D_GWQ'XBIIKBB1:=.O(0JJC$)-_V9D^GED3EC(9?3<"0O]G_J,D5 -M6]8I1@^-AYB.B[F0?77^"$HT<:+_=&' -M?@Y+G['&GXD*F<'W]<8*O)""B1X'DIO"_]J9S-02F[>BFA#C\O,_[N;)7[R2 -M'02(GHJFE[K(P_#=J$B;JZ8E>_M,%_T16_#"?O(FL1(FT<%+)S=;+(=B63WN.CXF:F;F0 -M5HL2N^3F)?S(DP>$IK>WDI8@99^;Q>QYT\'_C<\":7^9PRF6NX)0A* )\<#W -M1G'. -M03CN]L8W\X=>7#VO5:UOS .:S-P.S>O'X@J&1-1&CI2;,/#ZS/8M[AW^!Z], -M%5,;\JZV7B , QD(J,>*K#?><\)*;DI 4NO?B>>#WV]5-ED914*'Z -M"\SNP_91D]&-IEU:D\/6N-65_L\=O88?4]2:7;"0EW$'04F9D,I$IYTJ6_AV -M@PW &4?ORV2-6BR:DJJ*IM*IX=0LWI)/ Y*DDHI8BEN53?$Q_Q8N5\6LFE&Z -MAUH%4T9-S2' ZP#2AM"?SYV?BPMEGN%T3S%JO%I>IMHO: -MPX'$V'S)\]P;FK2%EZ9-ED.@6EOB]C]^W_Y!=8F*CO67OG/A(],5K]A*5))3 -M7X.)*B#N0!*+,!S;G*1QEY*CW#U)_X+<&-"6/(ZE_X%[EIW2T?ST=\/+A_PU -MU_N(OH^E;,&X93+0(PN4H9U!FWQVD4QEXY;5YO*!E[I0"9S^H2C!I9+2S(TI -MZ_'+KH2LOX:/O*J4$%/Q,><:WC7' SA0BKHW[KN"#):=T5[!XNH-S:[8D5Z% -M0YN60IBBK8^;I?;DQ=3OHZV6&'B:HJN=$_ZC&;&:4?R7^).1PI(L_>;$*5BQ -MF_"%\5J7::6^@7SQPIQ1HIZ.B/);\HZ9#/#@^A^GUKB'PI] CXN?ATX(PM5& -M-_.Y3A 76X?XU9>7T,'E+9HD"I]4#X'IEXWMQ89]PLP!Q5U%V[NPF!6-/D[- -MJ >8S9(Y,#J[Y6&(3-> GDN;FJP/N>+B"-[1W*7;=(AKLJOI9WJ/7_ -M[3?N%\^>E*>KFDB#D2W4RN"5D'Z,FM"9T,%^P<7$/E,?EEY>FA&(NN&V6Q3# -MP-NX64[FD0H/D^=?PS]!"AFJ/J-M2EE.X4.)LM!7#6Z:ZCZF0K%;7 -M:M+"+5/U]]57''F5BQ>=2[I^KRB**P_CQ]SNM%H-F1:EH(@WJT+P)NX6[/61 -M?:T1 "*"BX)IA*O P_H!Z^A= ]1(F@L@VD:K@@2!AIK'PD7[U]/CM=PCE=*7 -M I<9QO,54R@DBCB1Y'E^4]D'? WJ>9=IJF -MM9TKE^/N-_*;HI.@4H&/N)9)E$/S^,9V!]E08%&SBKW.G^_%T,5_\L/V@U1Z -M:FU&:VF@I+_3^-:OWO/9GU>6KHJ=CQJV_XE2\?F:U\8GXYK.OZARJH)0K Z> -MZ1@M]/Q_S.,3RYZ?MT*ZJ)J2IG")\Y \]O8T 4>\0I66D*B!P4TCT9GX4I". -M49H)V.+T_Y VP)2QDX^6<9Y0DHR=V>?/^:PCE%L0\:GY1!^# L#35A?BLDJ, -M-E/9NI)4'[R-ZM,7N]6? NC_6ZM.)J"_\.@1-_!NYHU/F=6;6%6[(Y>3R_[) -M+0L32@R&6KA#7 5*I%I!*/B3N]KMTXN.6P";CD&:0&RRN^S\V,;("A^CX:N- -MGH&*6H;^D('^7UDQ^4;%Q-NZ2%^6AE*?^L+_#[8&B9:[$'<*N -M_I &V5;(&=.9LI>3KZ4?\304]B>*ICWNOL:N@Y*GK5B,#H3! +0Y39Q.29H; -MBZ&7U^[U'"W>!M#+J#V74Z(;&%.@5OT! -M]"5N1B;BG*!QL3)S@8G#6L,:1Z&+C573EINHXFSWP-> K)*7D:9=2XM@!JC3 -M%P+ESI3T!O9\BIBF6@/-_NUN\"71BPY$]IZ-TA11J!":_)8UVU*^)I>2DP^/ -MH(^-*;SL[; #2869B$6'G;ESFHKPU FM!L/EA7>_P#F:P8^X%?DAXFSZQ>_U -MJ0Z(EKBZ@4NAH%>3".SIALF):P-"H[ROMUIR ZX?DG>"C>K6Q_ILP-_\N@Z% -MI8*ZS=G1UEP1LG:U\*F*S?G&YM(OVKI=MJM[MXG[>)>"T<\@M'Q6DY^46?#Q -M((*HP78W=C?/X$K=Z8/\CH7<%:C%(#/']L6Y>^Y\4&>KT]M26)\S6 -MCXP_+>^M+*:? ^K/$,%8\,*T18^+?HNK@IVZV6@5)\?@((QQ"0($FO -M5H-9D\W^->;U^]5<=O.=1HJ*F*@, _#,UU&_MI&;<'%7F+A>J]4R?; _HMP/ -MI&)"D[J&P%75PN+_[]+6D[7SDU:M59*:O\?$/T;Z)B:.FE2,EXALDRQ4N]C -MUH55#V OCE@4AIP/2*/;_V$0U/Y YL5*F];95Y"]G+.REILBABFBZ?G-PYV( -MK+V F):;7K>@7@O!8D:R[M)GO)*TG(^8BJU!!-O@4/9R_I90UD,G,_,_]^Y& -MD<@+E7+0@=V$A:_K+2\;D=Q4F170BA>[L%GPZGG;[@*6OP>,2*A*A+7>B 'Q -M^,?0 \]6H"J1BIH<0X[T^C:U[/7#1:1VR>/_G;O$G?_(B$]:Z\76B9Q*G$>& -MNY"[IH-U<'FTPD3.ZT>LH-&PQ[I3K(VWP>KZ"L>M_//3D7+57YY>F)HVIE6K -M0O#4]C3EX71TI%$&H[(MD-;;V+FXWE^PT5(ID/INVC)6H*V(?[M6FIF2N!XK -MQ8DI:-B:RI,\;%E_*''8!=5NN2 -M&O\!Q\ W/L>OSHO]D.V-3KZG,/ S"0[>H\OE$%Z?AYR'K$R#,[!XD>G5-#IF -MSQ":A0B,=>J6,[JCF0-*_/4H M_RP9%'C<.,I$:P0OA0BP*D]?XZ.Z:7\!*? -M4@F;JT+OPOR0D+"YMY&L>M?_[,>L=J*P")Z?=H&IDZ8U^^/%X4C\5J*HMG>H -M6*V,347V7)?_YU"=5G*9M@E_EY"\X4'Y.F[78H>0^HAM&J>#+S7!^",7D"\#!VQI)S@^EEUH4FX6'MP$4$SH>E\*[EI674G*XDY8L -M%YT(Q='2QBGJ#U&Z])]>L\:JG+ZLAIOS-CD^-# #F$&P'J" JYN'+0&P.G(* -MFUI94ZCQU/GPX"^#]YA?G/J")PM?G/:]^?9IHY*5^FNE5.&C[K! -MP'U2RR+8XQ:4Z)RR%-BDD%$H\O;%Y?8 JS*=TKF5Y[H>H$8 \0X$2OC+ .76 -MDJZONUKZ2]Q:;81XB>+%0/OR<:Z4AE$2U]J]\*W1BH9)B?T:6)>"Y_OU]?H^ -MUY>A@IU?DI)8ECV[S>L'29&PD)U:HP.;:/:= 7YS?C3OUKM/L%U2'0Y6(0K8 -MP!'D]^>;H&R:ELM?A(- 09^L\C 0VT,0C(KM7^2Y089+]/KNR.=:V$V41DJK -M3;ZYJI29\RO1]K*T0J^>'4#7GXV2DX"&F6<'[,7JK[);=EUV=V&D -MD^C' +)<"%^9#KU#N)*$2-$^9/8^)I!"C$!^F@ZY&-1?00JBWZ-7?GP.V0I%:0AJWP\HG ]#;Z]!): -MGK2'[:_8;-]L]X+8W.'JI\$)AI_>X%Z>K:JYL(,*]^W$V_7PS9*57ZI64)R^ -M,_6N]0+ITOZ'XL$QG8@>M7GTBU9&B*6S8*K&QM#GY7J+H)6F4I/SS,M2X?V( -M.H6UTT#S"1[4QCI]PP0R6_R>5UZXY9Q*]R+2U86BNE6,D8G#>*3]X\+Q_^X% -M$D+R(%/QQKA3GTP PC7V']*)5[.^FH*L3Z&< >+VT/;%B,>-G)Q/CHF-D(V_ -MP/S$S5S VZ_:F$B'TA[J[!?_$_?]PNXTSXJ,51]^!A-RE'(0<.W-Q!;.R\/" -MU$;:!:&7HHU>D\&:NP#S[S8R/>:X@Y^\E%BZGLD-HQ)0E).TP%R6"N?P-9WV -M\@%=D9J-=I*KEY;<7TC/ZH6%G!.,L)":FS > O?R)?;GVLIH]:.#FBV*\+%- -MK3+%DL8!0(>@&];FTX)2E@V6Q-;VE@.6FK:$H'(54W'&MB7D%0: -MZ9R!.L"F"QD2T]?0]"6O"(4UJ@^/0Z1%E9=Q&"A.TLI"6\!+7<6CFG^(D]ZY -MCM+!,>SNOA037(JD?50#O%DMPUNT#(*:$9_53KU%D&;BE:W/79F)K9V$@KBQ -MI)C([VO*=8F6E)H)7JB@A:M(^=DUK\/\3\3$F+N*GX!S'Z7VE1KSVYJ7I B" -M T2$,Z !WD&O]):BB7*$GIZZ#+K&FO?11>WJW=$9BJ7]BD,]ELJYCI*B\Z'Z -ME^7 IU(P0T>K!8ASI_SV8G0;I_+9)BP2!YCP -MD9":$0.(PRK#"9I4@!^.F8+3#70Y,#SZ2KIP6OBU]XB#:;>#!\U%/"^B I2B -M7+*]0):3V?+')G;%&HN%D+U:B(>:DT_9DO4[_ .&FGJ"FI/ZII68U\*L[B[O -MX8=%G[Y4OXNM1C>9)\P$S4OKG!>.E$0\OX22EK*0T.JPD3]?+V+G&X0_>=7IERJ,'?S^"5 -MB!X=A)D%)4M!-3K:.V6Q$)BN @_9SFB[1D/%P,F_:G8J;KYYWJYO1+L_6AZ&V!9."O$-SZ_7& -ML#)"A+&BKYW7?JB3GX]PW=#B7IQ2O( WUYE(LI+AZ\;^==D(JI;AUP(GEGI? -MJ-GT-3>2YTM0^)-[NUPR]I7LZF-F.D:G@Q8NK(*8J\^DO9+,U:L?)O+6NU^6 -MC(<854> #'K!WB[Z-"[BO9B>@SN$DUJFLD2J]_P*)T;2R?;)TH>8@(&0@WI* -M29* S93'5?_T6ZW<5(W?\JN7$8;NX8BV/JE679IXS3)4_<#VCK^D4GR/B8*= -MI9""Y,.EU%^ ]JV. JJJJEY102O?$,7IUCF.N+.^BIB2_[Z'_K;'YHJ=O_A6 -MN9*6=]"\R/'Y;AO$TS\4>DQ9C8U&L#JK@LK\R43S$\] %F@7NKR=0X:SQ\(P -MD#?%K[J<>(%:IXM>"Z&6JZH #J^#NT]2_B)8% -M==SZ@L9?NO>[U>;6Q=2 EZ&ZNH:'GE%, NHU\)X(Y]*2-PF*]EJ11>7R=3?5 -M\,-OE[V=EJYAB6"DN2S*CL%&U1Q?IX?!C*P-2Z&5_\%ZM-;EYD$9N/R1C%R3 -MJYF3IK;8POS1!@J+S_9C?+V;@9N2J'.20YT@YL;V?O8BF+96&9I=&G\55PMF -MA(B3D)>8J[,-]#UT']?.NJ**1[:*LOZT1X,!6<#6C)!>1*0=RD%@FO_:^^;G -M]<+VS="MLO*OCOH I:/R,1?N0XJRI$E+GIZ5FX##/GGVX-#'3X:$/(FLSH>Y -MDC_+ 8Z3SLNV382'BKM,2;MSCE^-<>'BF^?CU>"T#B; -MDL&DD,JS].[2YB&T4G);AAR#J4WCBT6828H%D$JH?W&6],?W]@N>B9.1-X"" -MD+0V4LD#KL#^$ JLH_T;F6RV0N*:]71FKO!GGJ K7$*3IA6DQ]Y6DM?50J:6 -M>]ZM6EZ:G&N4)T=^$ %JKA 10+7ER/YJR\AKFB5P'" -M]II0K *3WDVSK)2IC(.AAIW9Z'HA@X7^P)F3GJM;J ^;_%*DGJT!$'&6^C6% -ME'04J=ZS_ZC@S/"3VHO[KYN(^9[2U/74NM!'^*/2A-I7@EZ"IGOA^0[=WZ8Q -MK=ZQ0EVAI9_A(KG /J"?GIVMOIB S@-8XC,VFN8*KYH$B[F$ -M@MATJ:>HV-7KURX2_J+42\AY\MNPGKN*N).W3<;!;_/WPHFQFGW4L7Z7PJM; -M3Q+8[!;!S[S -M[?8%-HB/D%J#CY00N(6@X!$W]>]+592I5HB'GZ-8$_XU%CI_P,T>?YB7L@EH -MJ W6R0_NVO3U&<*6A[_75>V+HI>;\_[U\#9&X(B^G:""=M#>TJ $6(T-RXJJ -MR\%!F*O^F5&[OD&80LIV8E]3#Y].1D$&M5:?^LT?J -M)SK%L]JNAE^0LA=[NTV&DL<,RM:\T%.-4%RSJ7A'JJC!M?3'RQ.+5J!7";BK -MOI,\P7+U]/?+B\:@@)Q''J23C.6S]2_N]N4>M;S,3YR$@SBRB,'5Q(3U ,&) -MEE^!EYY+4,9^@(CT]V;U]@.M7HUSB)^*LE'!IIW0PO@G RP_(D72$I:N7F1FQH8Z):?[YU#K^ -M IQ3T[E&43.1PHL'T[CP6AZ 0O:0\,;%0KOV HB((927D7RMPMN2Q://M'HV -M%+BD01H]MI8.P?OMQCX#YDJ6K*JHN5^>=X^%*FRR[\5#5B1:NJC\OO4*67OQ -M1Y)RH)Z@1\"&FYZHS%*:]]W/R-_Q,)?R.M2_'8F-+)!8R)O$U_HFVUF.L??9 -M_NM#F9#W^(E&:N7&>M[G5D<$^WM^5A**"I2-F.$PQJ_^%=*L4Y_[5O2^0O+[ -M!V94PS(S8/K:C79DGJJ3J(^5K=KSRRB_\#V-.77W@5M1ICUEH2=*HJHC_J@R@A% -M2%&M\N)M7X6+6(_/?$*B]X+K:J:VML0:^I"PGI(0FH/ JL58?8B7G195+ZK- -M\>W@^CWCE;P1\5>PFJO@IEL#*V?;D9/47T:=EE= 5%W9TMU<$Z;V6- A@IJ" -MDA7RBG$R_336B,. 8)*#V1N&!:P!PO3ZU?(2O[Z<5\KX[5,ACIW*S=?Y7=J8 -MBQ>,[ZD5CHJH3ZK1,\3S\% #1])&9SXIUW3,ZA+W]CXP)52\VJN5 -MB/;SP%.+!=T#286<-E4]B;F)1O"/I_0M/C_#";J&)*FR"+6@(*?E>=-P5L.* -MI[F*_D"6EJ*4V//D\#;_\HR&5^#/Q$$)Z/?3.:JLA(*V,I"*@ZQ=U\,Z,2[M -MVJ:<$%).IO";LL?\RN"%HZ(=18"[@=J2Q)7P1>54MHJVAB":G_I:"PSM#]&* -MG%&[]J>2F:R.2UO^$78OTK@/AY/#>@*2%;J]Y?F5(."@BPX@>HH[+":BE=K@ -M.;0VYO5FGAI,9KB) ZP]JT7.%2CO@]1&MEV 'Q6,B,*Z_P+FE_OR) <-A?M* -MV@Q;DXI&%:O9!, E+@K* P*;>E"2C%O/JDHIFH$A_F3$Q;_&E+#+L:60K'D9 -M*\_D7HBB]7"A?(K7%[SRQ^Q+<;"3^3!;>@\AEI,;#\7P7[!+G7:;0G]LGJN1 -M^I>OP,5<2;9P HB*C]1!3=#RQ>P0 ,MUDD":0W[P@Z'!<>TF[F7+KZ)059]% -MG*DAFYL*W LA%L4^( -M)LH(#HG("H?=@:R>F4""N+>31-+LUA#MY5!85%&02(H#P<*O\9F+H=26F8(" -M\O+Y]BZET=>0E%VTUUA:H/*6VP,*V%2;WI&5V('_0*:JX1*=[Y9B^ K7D%B6 -MJ)H&5:GPT#"0.H"=0*9>D(MR&_.\\L)%-N[MSXT$""J&ADE+,II7 ,[[!*7: -M\LRWF@9/K;FG.;(O*1+EQG;@P6FJCIE*A8V\0::'FT$#JA?1CBLNVKL._55: -MGFJ GI/0>/';N47D8-'5M(J=!=&V?\W9PM.=AK*[U9""K\UB;/3 +\*$6!'\ -MFD&"KKFD5LT% -)_D)@&MA2OQ@*ZD$>7B89-TJR:&QD.?Q'+RO&'=':-B7V%7KI7 -MFR?3[\06/MNYFM"#.)^1B98PFO\E!^[A+@O$]WQ"KHF? B>+J8+#E)[,TOG -M=9/!6 &25I"Q7/T91,'!A;!;N9!;BG+8\_/V0C$^8 ;JV6YO8\G[2/?[!BIB= -M2)J<:ZF7[(Y[P\:IP\S-Z\,!ZHNQBI[&"8RAIE*^Y[CY;CYRCTI1@JR7@+XI -MP8VB]EJ+AJVR1/JW#;;'-]KURX>E^85:5YY8P!:74,M3580 DY\WE5>)<%:_ -M()Y=GNV"UEJ08X-;C9A:N(1(Z]$>)@'/6XB:W$B,L[&, >HYD!#DP5>5K*&I -MFX5JHYY[",0&VM[ FX6D#$&)5YR+$;N8@[&7+]8[PH=]MU$:=&>Z7C1:G2?+ -MZ:\*S^_OX$B5K94<6J]<-( 6 L>K[/00[,56 ";4J"^J\3,X0A4"G9=CG"_ -M@ZE8W78@+L??\%3TDI*:5S*T00+YT=:=HJ*579FKEJ 7M\ -MRM&KGG:EI9(!JR('J\>V.=Y4K<]+E_:?7%7"D[>HDOD+S]C7!LL0\P&(JYRQ -M^E92J+)CH C8\C%_QBX(G$A3\;*!7EK PJ'D+H9^6;"(^D'AWO:B,/K@M+:> -MCUH509.0?ZMBSZ?$6%R:?H^7NAZKMZT4].;>)-KE -MQ8JGJ8W9B(V0Q:H JD5$QA_/3([$%%2M@9*L) -3)@9N0 -MFECQ,?7OT/W"DU71$I.:NUP+L]:7TPV!ZL'+BPOQJX7=FI:T1ZJ4@-Y7:1OG -M\# 663R"DYU0=;J=QX]S/9 (,G7 <7F[<2HVYG9OZKKVH%[P2Y97H'!"YPRC -MV%P001;^O>$&YIIZ9P4#)!=70V8^#C$&NB*R'HY36QV'LU=WWT]*< -MK8>NGJG8^>&GBQC=G)'#K]^NV%N8&;::E::"GI&.>L'JXS?MP-"^$(N5CE%2 -MJ-'#H+&^<(I;@A%_C>?4UMOMU\>?LE1Q=I.NUZ1.*Q/.K_A=N%I_CI6)J4.< -MB/$J9:#G ZS3\T0N4:5^\5E_%7N -M29. DTR0>\35Z_K%!<@/GDQ%S*_%7J"@%^%ITQ8F[N-0LKV@EH^(V)"3E$"M -M"JP+XP''QT/O#G^?2OZ-FI[H!AW9$A'WOE0/+D:QG5?36D/%70/)O8A>K9Q1 -M6:[C*]#PYCY1F%":4;Y5>Y=@FXMQ:H];A\B"4+11G%U!EX'%-O4R/O#82)HP -MG5.]^(6%Q<+P[/(L&U-:D$M^:I:7HI0E.F5MD\;+9J.>6$.>[,?LFJO-SBS/ -M ^'' =\GD%^>7=6ZQ+MZBZ& 4L?V -M/,;2YF".O9^5^C58_H4*[MR0&?J/MX>?^P5 Y.)#\@?%DXN$II*OJ/BV4-C# -MP=)>@J)%&Y+ZJJQ:4?*K\^8UIO&K6CB_%Y&^I:-,0_1TT.WU4J9H0UZ3WY:3 -M;<3IV.S [\.ZH+B8Z:R]DZ6.N(NGSHDD\>9LWYJ 3RBOKTQ:6(KZUJ(P9 J3 -ME'];@?"C@[BH#GL!'<#!X>N@*_9C1I<75\?HC%.RM;O#/YW4T^R@G!N0B3*= -M6%=QXT_#_(*!G1ZTDKM8GA4^)? *_!&@DK+[3^CRE93F6UF:J)<9KOA3GT#3_I&:]Y3NGU". -M1==>0)BL!:[9S?O,U]+0AY>42(*%C8Q-JK -MX2S%YO71$:=2#OI="ZG>BIS0I:>30/(G$&_F*-85D)WUM9J#26_"XM>2/[R: -MD1^?P_.C=9*SPTRPBHTE_5F788Z)UP_*R# 448R5D).:LGY"Y/OU+F[NT>N/ -MJ!T#N890DIA+$N,_Y!NBE ?FU+"U6>D[O"XB(I1=;%3EZT,XPNWL9Z[4L.J]\S7UQ+$.X=] -MG!>^E:4;J,0G@=*NP-&=M;2-5;>V_Z:BCNTSU]3Z&MR.IGFNS!,J-J-$P>0Q -M^_Z3&Y>M@HA)JX23+\36X2;Z]_"NEEB(BQZA2H::/^G]S,KG(=1LC$2_E+B4 -MD*W;K=DW]-;']O-MA?N?JD1+G':3@%;8PM##XOE8[]9OB)BCC%^:GHI!D(K! -M.^?%[\)RV8:>D(V1<@-0R0+:_-0&U)I35@''(\3F$"_;JHAP6)^1"8-B=_F- -M6J,2!;:@NS>AG)UFE@,-^_G\E^_)F Y'UN,:_586&[F.(3TV? -MES_%EC4@-! /.O2IA9V;C8LD#K?HR*S/\?+ "[N,C$Z25)UR>IC!P-CV\'78 -MBI@EZ, 6,+U/O8R)TRD -MGX2/-YWHNZ:=4\PLWXKBT8F7O$ /KY43:+23@-[%;^Y:6H"6]K[3ODMR7D&F -M&\&H"NZA38[#R)E648B9EIVN%ZB/C\'^Q_)SY_$ND*![CX-<6RS/!4*>UIZ% -ME:">GIB3E-9_QHOY?J^!WVZ -MGC""J!C8EE]%A>/%_[;;B5YL6)N'FY92@*CQN7?Z\D;7%Y =HOX B,;/K^T -MU (!\P/.MA7L5?KLN*Q5NLCYYIY +87"EZNPV[:);NAN@SY<#PBT[[=:!4!6AO(81VBG'#O$V>I&QD8Y16H/PX.%%U[;7 -M][:^!9JCG(J@7XK'')/F5=#0"521JENHL%[''O4N5M#P.H[@$I:#]&J;JFE9OQ#M8#].$23WYX5&^> -MO^BLD@O,LNS3[]9W3_Z?2YN>6?ZZJ!8I6:9YQ0ZFJ0[<$TR,L9^2D7):;"13 -M25#VE_ON\)6)H(D0BJF3 M2CPH0+DZMR18*)]W#FEO7MT4J!@964(JJ=^8^X -MH)IZ?C^1,KJS)["6;&NW/XO;:T*^0GF"?K&&3LI1:PN2UE]8R -MTIV-K5Z7MZTKMC'46MGZ$-7)0JO6\IM:F3BIQKBJ=/OV3\'BE/X^U-N<"%ZW -M2OA45R==D(#T"Z(Q%CN6 -MN99V0]FR=J_M\UP FB9:FKJ'O8M H/Z=]<+%480V+WJ-FI"0[,%I]K/T=>., -MDM_HEWQ9B3JZ#4T%_(XA!3 7LIJ!C+CAJ+@&J8WJD1)21:<(N]4BD):*GD*$ -M>X,!SY#?P1;2P].#4JMRG(Z+C+^YG]E(\NT>D"W;3"&2A(8)D__RQ0/(BG61 -MFU^7&9C@\_CR\'"KW[:3A(13L[JEMGK,@]K$FEF4N;I14?JDGGU$\/D^>]?+ -MJH^VNPQM?X8?)N=^126O@-#62'^+GYA6LT_9=!$^-G[UO7()G(*.7NJL5IK! -M#HPMKL/1[HX%O!R2+8JL$%L#U//V;:Q+O08K5II6BOZB1I 7VLY-]P'GKN#0 -M*9)1,K:.4MNV+ Z6Q2OT\&80V_VCLEZUB)ROB-W2X89SN'M0$:NS&S/M]^?T -M+Y63@YU?@5B*JEVKV/]'7%&\4KU66JH#JA>#I^O6L/330$\5L=.,P[6D2I^D -M\.5F?L*8]K&XOD:'EO/L$NOVUM;LSHZ0?KV$F+R3,L) @MP &G4%0X^:1:B/ -MG\T+ME92P>/Q-L8V08N'](N,^EJJE*9SBR"L0O? #T\*X$-2MYM\=B^R0GCW -MO5#S\=1P,.6LH]0;6Z"KJ4T7HP!,G8FH4JFZ -M@D"6%Y.;DHCR/J)OP./'I:.8FHJ.F_<-\,+U'<8"K8_&FY:' -M4HZ#.HUR5VXR!/@%KJ7YY?TZR&0L7S[N8Z -MW?# '/C']ND_^G4(Q13K?F_DE>'2E:LIYD8P>W5K,0E=-!; -ML;N0GIK+QJ,VA'8"AK>:JE,BEO'F0_OG!_&FL82PG)NVGX+-!_48G';_B5N@ -MNGNJ?YO!>]'O]@,PB]N@ UIOBI;S3!L;\77ZP+L&()?(27)66IH!8?;&EM/* -MAX:L1*NN7IF[C;\2W8#B7L\9OX1QG$-2@*Z1TJO2\C3V$MI)BH91=9XF&QIT -M$%.7S*SX$]S6JX\4POI"7@6^<8*XQWG#'+V@ -M"G%:H5I]'C+J:.J^5BL_U%/?@W\5MAZ(3DY+_AG*J ^O%M]7B"QV3NIV^EZF.H9Z* -MU:G4UJ3K8;NZFJA"B)?-@Y[72/*]4E03T)E*?55:WHJV4GF?@P%"S-=-P]H@ -MF8BN!3*IMXF[D+AT4<<6QR[>4"E_]H*QD(*ZGT<74MA0-/*%3EW#OP'@-9W% -M[<*JE(*%I?2[G[C.5]?OQ1B&N &%7%%:$W %JQ,BR'/:AEY;)!O,3D9!PC*!4@E*%TB=OEKX77%W"O9*RNXNL -MWH':C,[*F$.2NW8"B=^039U2XC\4$/&02I )J_R"F$X*KL3B-\1U\UJ I),P -M/ZY;E4W#%[7_W9>!J[.:C$^5OU,2=/_-3(XNH<5$#(ZIE,V&F4UJAE+7(E3G -M]?_+O9_;BHX&8HFC@!(-]>C\T0'9"AL1IH>-F9:.1UZ)QEN;!2HG\!+^Q9&] -MGE_279I7H6M:X$6(D;"0B*Z7 )KXMG_6 IJ@%)5:H7HZLG(=)4;:G/K4$OO. -M 4)#>E"7&+34^M+8\+BGQ +3PI*.$HY;\O,N.B_:G+B;BF*OM?J'X?(YEY?N -M"X,4G,FYNF%(N#:>H:14 DJ(R(>F6@&"GD"+.'*H\-'M%I9WR)F'AWZ#D$T7 -MMF+0&^+8[/3>%NO#"9"5D?::L&N"FZQ: M'Q^>#R$,-YD:&M4L7ZE_%&VS10 -MH8N>W/21M]-VQ9>UM>/\4DH%#8JK@X1.60=+!THOG/ZTDJ/8OZ);@<<>,.^: -MX]*1L*0;@ZN'GDBDA?#Q[C/3CUIXG7F[5:*SED/[L7?E]--7!86J;Z@%4L.@ -MB<%(WE^BJM1O1%B(0IV^V, =@N$T-O[VUX_MEBZ9%Y:M&!I,5=T"S,!"G$G1 -M\/ 2K$6+3X/MJEN@=[W!\GSB,O 'E)"@#Y!9UZCQQR_RA%Q3V98@OZ\8\>3D -M\) +CY*+KO90J).FIZ_'_<>P3*._GY7#K(*LMYO3,_]5L!KUBT+&$XCCGE"% -M1 SC[/;EYPBF8D*RNMV^BQY"PI4E__YU1Q#:;$Z.2+N#I;[BU]1X!T*TCKR' -MX(NZO6NCEE?-Z]3\VO7S3861F,O4C?N_K,2[I]WX$JS4H,5@31R%EZK2Z,H7 -MDY./TIZ3%COFXPBRD'U0EY"_ Q4 PE 6"D7>E5.]Q\&_U>; Q^CMH[[HIR3 -MJ9J?T<[*])1"E%B6N)X3;9"K43+ETMQ%MN<0,+?<2QAZ7Z" _^SP\@^!IX)? -M*I]E,"U64$ ,CI7)MK"8ZK)E -M5<*OCX\NO5"KMAN*4*N/^*/=R@% OS)X^U3GX".^CB6>J.%^O#J[._>=NJ5 -MG;.=VY"6'O+^X]RLMO1'\J**@M?J1?_ZE8_>&$2MM?=3G89UMT=LJ]*)EA)? -MAA*;@JSWFO<3T7WWQ<92M*F:^XJ&7)+ X^I#M<9#D_!JKQ/'?::@G^&6[700 -M%.*O%X67OQ^KO3@GJ5G=W(YG"N OMX6 O)>!AJR?G?,6'T77_]M)+)"3B[*3 -M-HNPT)LG2-)![ @#P_ !7,2PJ99)4Z+F!H#-Y.TFQ\#;7XNCCUI8D[J- Z;# -MO;83CQN0BIC9XZ42QN?#4%B^&[6EMDNP\(+E5_,0';!+O/J7_'^(4+OEZO$N -M[\4V;49&PZI*C%Z3'ZOK[1HV\XD.NDBKDI^FD(C-_^[ZQ_1.@I67K\LHKKJL -M<$L(JBP+Y/$::XR/E+U?G8MFMA$)$+7P+9XIII)&PY:7NZF7H+: P8I: ^SB -MR^,".Y(I4UR"0_JB8!6NR>/%Q>WV#_RED:Z.L+N7K0[ X+I=@$4"LKG](OXP -M]#3%A5QV<9&F77NHJY[["R3O";@2BZN,L9J;)EI#663U]]+ P"L6H)B6GPCW -MLXS:VL7EK@.+7ZA_DH"NEG\%]^K9U_;RRHUZ5;_/F$N[8EN!B4RMAX2GT9\ -MGD2)6BVZD*:+030QY;(ZYQL,K*-8RGN]FCROVX\\FIG-*_9H2=NPW$ -M??;[M/-#7XZ3BO7/0\NX5)N-'=/'UZ_KQ?:&AIZ:G)7'5O^@VGCI_L5O@?V-^^P1P]>^IVL0]8/GX"A-Y75 -MT& FOJ.07$S(;8MXA9<)+-3.(>#:1590C%5:0+MX]GK!LCGPU_)&TY^%BUFC -MIU^2(9Y]"8[+X=K=Y\#FC_.1=Y["NY'2>:!7V.)!\N_VQ[^CFHW>0JJ= OS. -M\GZ)DYVUH5[RI7KL]\74"KF3MENF=SI^N9*]9?GSR(29T;N7U(NX@IRHX39S -MY="+6I.[D8#V1OA;FV0#%C7%]^.O3FJ[6X>'D)#MB<;3/\601\F:^*RCE)ZO -M:9VI&P_\0ES#R8^4^D#FG8U/H82=0_0TW_;6(T=2U5-:I9&II[I%@L<."Z3L -M^LS/&,==OI,2VA"\5K2[GIFA]>P2VH>,49*%\%V[]M*#]='0DCZ1UXD:>5G" -M%1_&$ ^0(%0;6IVL7Y#0?_#90+C]B?!1C#U8BI664R/R-Q 7DU*;6G"H^^J$ -MNE\-P]/E+,7##IN3ETFHKY.# />>_16N%?5E<+KL%JV)8J"7@NG\P.3#PYF, -MG9YDKJZ DJWWD^3J-9?<_]JHQKD2O(>/7A8LI[?JB/OTJ@W[\=:[MZZ@NB93 -MJ[B 7I>BT.Z6>_3S4+944)2*JA=GZ4=1M!)(GOVPJM<(T.4V+!_;7:#?GU07 -MFLBQAM^I#0,P<:6CR()=>K^0E'OMY#74+L7@S89A][J13G^C/?#PV?+UVY*= -MK%=7FP:,6Y7PTY:^>C?0K72/E+E[OH:XCY+RE9W.UL\23Y95C)J_H*J@FHO1 -MP/<2]]!#.WR6DZ^=V/E#R)RB&E%6H:Z;1<8S;L+'PT1&GER2UT.;+!>*R^L)TII" -M]@2PP9:6K/H+P12TQ00[#RIB\G5]8=HG"=$16EPS^M<60%O.Z<$@]5C";@R%? -MP<.YH!YQO%"KJ(G"7)66E@5Z4X>=#A"+K:.0?]'7<,F$UE"[&Z%V2?&,70TQ -M\3?<\/:.D^V"]I.VI@L,&>/%L.V*N*:X75.-!XZ3G C#]S_UPL,75E6$KU^- -MQK!WRUD$),@+T32#\EY*@X9!27GR4J#>^31NY,B+>@U0@Y"3").IFM+W_^X* -M^ASXE1"2^IV?^Z:KNG*@1%WQP?CT%O3%1;.+D=*1]MOG U4*-)2SW;:1FYL5 -M(G,6]O9CO(.PO9:7VX.FG_=!SR=AF+12O9;QOC_B6I[!Z?'T;]-8CZ80@Y)' -MLEJ2I=#V-)HZSXB7EKB"4W^.F8_8U!DUY!3S:8"\A[R:.)*6A@#!_.W.+]CT -MKXV%J*Z:E1.X&I?7(\3 U9)EAUR8@H!TBPA^D"!S -W('/C5 4,UA[Z-L+*V -M"7[^B+)=\O1YTGXPRPJBOXS\6)./0/D/4GA0GXZ2<9(; >)1)!;$$TR;T F2 -ME9.?J/*7F:GJQ%^AFO%UB5R;;'V_HSXNG:;%"DN]P)N6CYR7DHS"T^W"NO6+ -MDI&=JX]65I5J&M;'+]/ $XZ6F$R/GXV8H+6;P1S.[L[7T(G7JDR#F(V(S9J= -MPQ/%\O2Z][B.7;^L=8-X"&VVE_#*! K5S<[%2:,>_9%:UKE:GZ!TDL'JE>XV -MQ>L,G!F>Q)6ZY=J45@!1IA>+@7IR4\,K[P0% -MH))=CKU6FJ"06W%WQ? VPL#M<"Q#G,N+I$N>S?O9]/O/A].BF9P)AEJA0%D4 -M\W?F9>>\E?F 2[N4BK&5F0KY[.Z!'[UKNJZ64N-D_W-+WY!5GM9V9 -M6H_M&K:XE(NAWOA3S=4OR=6.LA6?TY"JJE+VCZKRO\4@<#8"K%B249H=KE;S -MU\?@68+:ET22R/;%(=4V%M8KKHH>7(;9?+Z05ZK#WL<]J)S+E-!]5[\AE?,, -MZBWV_L\4D)20&[:#1YX2UA'PET8]CZN5H+] DIY;DT3-_CCNL/I#%Z!<;:Z& -MZ4>1DJL2U(;7"?C2 -M"_C\J]C82-QTF_Y2XIX)S!J1!>A%P/8L6_QUHKE6L)H9 -M\=/6FI_&YS>=FX6PG9[#N86]=^G%$ZA1GEV5^KN_M!I*P<+C(]?.U%N-K)O# -M@UJ&]^3"]Z,0I@JO%^2;J)L>3:>OF?(W8_KWP1^VAFKD6NKMD9N >0QY/YV^9.E**VDPF2>?07K,%45@G[D+.>JQK^V^ %W!!17HO87\/")-+OP@%$E@'8 -MD+NL<^*7@TSO!=;PF9.0_J*\6H@:6)'!T_)WCN9ID*Q#6^UXEJ:%R>ID]D3" -MB5N!LH.;7H*RO%GF[,6U[>=-I[Y47I>]IWF@@ W1Q6 R$B+N>/)MFEK;1\>;$+_;S.)YY -M7RB2B+Z*I)N;14W%]MP$P<\6FZN;58O[Z(.+D9"Y*3YU(#?"[H664)&>\*J2 -MQ]3%, Q %IDE]Q.2R. L^O??D*_[PIOPD7J;H->_0(_#RY"$$ZV6D1RS)H7+ -MP?/FT)SO4&N5H'V#KQAVDVK'UAG5^L/ID#F-7+]%]I*J!_+L[_;6\Y:VO.R9 -MG;W+('*"P43=V-W W$F?JI86AY6XQEWZP33U+BRVT,KSFZ>3IHF"4L&R%_'* -M @^JW0P+&(>ZK55V]I*^<0U^Z&?F! MIZ%8.QC\A=Q%G".;IHJ( -M6/+^=*XGQ@:><%9\D%U>K6S0]PM[A3.UEEN.H)&7LTB>6\?RU:_U]5"CE&." -MJ(.?D)*?[<'5+OQSP7+DDQZ-CA8>H"T_MS>S]?&)5I0*OKR%JKB:/2<:_Z_F -MVV.O%IIMK7^MJSB6NL4;[/ PUL,=3=E7"E6]=I&@L('U5L##3,7MXM!;OYR* -MO$20F**-MGK1P?S%L/3%7["T5(V1 9C@QH[6G( 4NU^16%O%-!; /O+6E)Q -M'16Q&[VD3D, J>+@&+!*#YYQY):C%I#V7PL!?GHS\J00H>M2HB06QI219*:P7'X -M]9:6=ZZ9AY2:M:I[ ^DC":I8&]BP)U.+P6NTQ[;OU5RJ&3OC:2II>I)S^3C'.M>!8Q#6HD:AO>HQSOFOL(P6J]& -M!9-8NJ>;G[F6LJ#$T,,$RLP#'>JRA5%ZG(>)ENQ'@Z?!\;WZPAJJE"&OHXN\ -M0R7+0L.LF9.$E]N8F<5PQS+Z[<5=H_1-4A26^9&46,U6VV/Z.@J[A?% ?R"6 -MW1LR,_8VP]F3G[I[B8N?GJ=,0/;UT.#32/>SVY['7?>C $RV7O>+EE95DR* -MIXB^B^@7BM$ #LPBV=Q4L+I/UYB-NHB06PF2.?0F-N*JA(5SNXR-=\9QHDL0 -M@BG'S" 3H;2BUIU36\Q/&A*L$E_!*!W0]_X Q(B:K)8+?[L"CQ,<++">JZ>2 -M@YG+\C_B/.Q%F!:BC5Z(D[F67Y]-#U,3L9.0JWN8J?-@%XB-]M7P)A/R#9N& -MFQF9K%#?O-':;R(WYT]&<-*:DQY=WQ12ZO30%_?JEH^>7+_<3HNX59T#($ . -MW*?DOIKX'H^^U0;,6MOG$O%WY!K"N9;=5;>7BWN!J96RH,_XH^:H^\#\K[V] -M7ZG/BJFV; 73!7+%%\;LR,?4@(>GD7N#PJ/3"8>\BZ]&EY8"U?#M]G8O]X:@ -M]@6:4I.=N' =R:V768IQBY\2"+I(P)K_3=/Y\A8"PX\$;;>^1X2:@8S),\4T -MHV5%DV[C)":B87^SZ;;W8F2O(2^AZ4' -MAO +TNG%_A OVHV6/)#VD&"6H;.UB=FN"&'IS=L%]*V$E=B\IKBNP8&0>,,9 -MU/RZ8 5Z@*.%C@E"B,?[QP&:7+9B,AJ-%V?;LG^#/ PV2G7R-1[3( -M[-%IE77<$,^"FCQ)C9Y+:>R/MP5,ZJCA3_9/3;^,!+NM0I!5D/%K]?JV?]F# -MOY&8K)_+"8F,1EK-K_JOP$CDZO)ME[U>B:>-%D.YAXC'%$;&T#>9D9.*GJ77 -M@HK9%0/CW:(R>W)#EIG)$L;VYJ[1NER?NY;=5JK %9K!"U"24%147+8+F@.5 -MC[GQ=M7G^J4 '0_#W5N8N'*73-C^-Y;Z$P>7K!U!NYV0P4RJX/3R<];3[K2> -M#9N.'4=F<+K8[OJ,]M=<9/JJ5%3-U9J,DEL9\?;%\N^2NYA5BTH635.29%H! -MT(P8!Q[%PJM/$R[0PEYYEAV2!UF?YC2#P/YVFA +$FUZ -MN:J*6]>0EXK'(&SP\G.8G;B9<;J,ME6N&?KY,E R#J*5FFQ%C9N+XZ>K94AN -MS@[8]8>Z3^_CDI2+:9Z:X//6YI8_PP-/ELB,](:IUI/V^,C^:$>!K\7N\$== -MW)&NMH,7RB95TTCSV-:@Q=NV4Y:;GO=(5X'Y3Q&Z&))PEYB>N(X -M5%:>];?06I!$O\/KV-F$%E^%I'*(CHQ$6RO"P3ID\]!(D[A;F;V>ODL-U?'E -M]+_ONW:KDII&NK.9@%DR=Q3&&B*[7Y^\"4?/T;BZVLKZS_Q#"T&<^IJ*C):7 -M4H&V6*#JQI#N\@K-_*^52I)8W@@2?;K)U$FGS,76IG8^=NT7_;PG(V13D+8]&\VQG[K5!B0GO6PN(JJ6AL1 -M+O,!NG8@G1I;5ET@FH'G%C<]YL"P!U:2J?Q+DG>UK!/E$V<3V_ $)#E"$[MQ.?X0]:T2::X@1*L!H+;WBS_MWY//' BVK8,;NOO:59S)).RV\!KND$*"J.NNGM% :9_W-NWOXS]W -MFH /&XRHC:776LX [^JJT[Z&A+WC'I4'*'IRP/+^Y&&!2?E9*>D_G/^PE?\>**@)"_M8B"?WN5J*3$/27"+["[ -MEK:]@8=.L).<22(\Q_X#AUN6?IH0A;*3#,KJ%K?VIL=K5=KL7X8-1R.G@//H -MSZ(&XN/OCZ^NBZV4H( 6TYT%5QL#V)0^%0Z)7E\#.M7_P+N. -MFE0>KYZG2HVRC],"CP,06 /".[2GEAUH-@/LZ!$Z-G'&6I;YJ4 /=::?/-GR -M8S?@\TM&H!^[AU.4@X^A.\SN"M/3O5OP;9V& -MGHMZEK=)0<;Z-_#"C7N>^JKPYYFB8/:+R,( Y*K]RL"YNJB4@WF>1X*VL9"_ -M$V@Y9N7@<*^0EYN/^IFK <\E2'R8HY%6DJF"\=[99.[V UZ 7YU?D8#2LAN] -MPLO%XI;XI![UT/R#D$X3\NO],]0EM;B?DEDKZ)>?E0Q1GCSZU\N2E+F2D&:' -MA9E Y-9M?O;Z0VZ6D>@/G>E(QG:?Q\S Q@?"D9^0$:J&GYR#J9J# _OO[<#R -M&KF'JUM:>KM:GD"05^/"# ?ITL<'' ]WG)-:!ZV?WGF?G0/:Q=96%-M07!I5 -M1AVV*.*?U/;5@Q"?G&!7N8E^MY>4V-8]U_8FNUI&GP*/*Y21;DT2%2WWY<]# -M6ZJZA[_=#6@V@>3WI8 78^)T_*L%9K![I=4HY3 $R;=80!6UWZ9"YDIB0IC(,(ZVUF<_+ -MS P>W\.]A96\3XR.A:F $*[@EG;'K[I:[9B-O<^G 6+IBV(OV@V5*+=(V.; \'SQ@:UWD0)[>(R#V4 U/#_2PZ^@89^:457&"\XB -MTL7VQ]CI7X.96H#>)DKI\3;UE^X^T(FCA(A&FZ^-YDZ7Q50DX]_U$8L4+;V? -M5H'C)/93$I8V]^7Z4.<8B9DIE8U:GGJ.B]%]&?\_KD%\^:5(IQVA>#@:RE -M^.D7&L15B+>;4AB<'4.^6>/0%/*RHA_13<,;V ]6H=:8BS?S)E04HX23UER$"OP;.+?VY1<;U+Z#TH=:01I#=!Y[0-03[BZ0 -MV8:4[)*NJU^'BTI9$YW$,%M"HX2!.X?R?=.*H30NYD;ZP[JF4$P6_82+(K8? -MQWQ S_8.X<:5EE6/$FW8AH2[\3X\QC)[\)"^/I,7I&NIFK)ZF2W]Q/;8_ K! -MUI-3AP&V]$J^)B060PSC_6;DUD5&G$N'AH=)NM++H\/>D%Z,HY$8_\+;W18V -M1_?<$]F]1XB3VN& ER4<\M+>]EI$O[#WN,9/BUB2\\;_PQ2'D'236N\&I9*- -MQ2GU->7%2J2DGI^2J)H?/LSQ[/8T):B+4L6^;[A-NW.[^]'4_-@FPM!>M?R\ -M3XV,AX(.DL3S[;I%OEB#5ER N)>HCE>0=KTAR.F/J,)8 - Y>HRPK(8ZJJ*Q -MC$B%/C,T\!:E?).R57)2JAW YL+CCZ99KI80@[CQP<;NXM/%5?"P7PZA')*@ -M5'W;RQ""M=#!E]6EF]BLI%V8D_40_<]A[59B6W?/1J>2BA%Q]KOZB.LGIGVV -MFZQRGTG0Z^TZEG!Q;J2^1KZ_E(JXI%/JB/WXPY'2EX(%G8F3G5-LAI^2L_;^ -M5^_#IQ>9VTP&4JN3I9 !U\VH%,7"#X\QNUX50*F:HIQ9K!W7 3O\EA?UIIQP -M4:T 2:H]PPM%X;B4]@:F6X/_"7 9[/J0(1S4&JRGHIQZH-^=)^*F\!6&D9:? -MD99.P%8#2/3TTO?8X:UP1E.Q7DD"KK)6*V,[-SG;Q'"T"A8I.DKV"I/+8VSNU%^^2$U%XD0/\7DN7 -MDF*EVL+]RJ?H$\#GR*J*'Z62>@]^0F!: P50+,+7L!OWU/*QP'.[D\EJRS20 -M!!XKG;&[K8#R53+F.D+00+.;7*48N62_^L"*XN):I9:1-X>)F6V44Z/9[6[F -MVS&/4$R"L=L^1%2LFIL*V\0YB@DZVEDMOFM.WV=D*3J*\5@J22F8*1CGCC+>KDZ=U' -M:L@15;BSUHQOJ*&@DHK9XF;6]E/E#;1+J9;4FEW"_Z/2=! !K9Y4FHM:\_?0 -M+-;1O9/R+I>BFXCKCA<(SL#9A*3&"492V;^Y@)N$X[,^+?#8B/K[OQ^*C982 -ME-CC_[?R0[Q[HNC!=,/7X/?C;YI01$,2A9*IEJO-#'K8W"<4G)"M -MC:(_AH[WBQ\7FQ\(!BU0(*^ -ME/"?QW_/&'RF2YR.TX*]899:V5/$D.:ORYU/DXB/AQ>22Y7,]#<7[_&G$JP" -MJ*BNI*%M\\3&K[K^4ZV0$8RBF#BI=/.+V?W,U\?NU$.3JF2+KXD/K Z3TSHE -MNKH?SY"8GK&O_[J#BZJ. ('X^<,'^_\/W*EW^Y*)IDM2N*1>D]"0U/[F-I,% -MB8NTC9*KJP.O4]P:H;.'7_*"G:5KQ.W&^^4<7%*$E9.>NJ >J,+O]YRTB=ZM -M$(GY@S.:G2B08]OL4KSMFJV;*HM.-8642/*1O"X#$5!-FW^]#MVS:L7V]/?P -M9\6#2<4# -MG:!;FZ2)?Y?1$!5ME]/:AE&@10.7>H"H=%KS+LM06'7:488T]IZ-EZB1%#7F -M-B.P@U>@O;*"E91^AL>^Q930VY".E9:+DH>%V8@7L]5&]BXA'UN8:.^2H5M# -MDC[J[-@.)";(CYZ4E-:?E(NVG:V ^G7G[E(2NMA=GP./J7NCDG*=Q,H.]2HJ -MF_72:FWLI8#"7_XP#;&VMY:^I64<8.) 5\"L*^4GE^&71N3\RHE -M?(X#T0/'% J(M%O_B?Q];8Y)S3_Y5/9:XF?6:*BJAU;> -MBI1:P^7Z^DE>ZT\Q^!O#+$K]6 -M7,:?'"LFJ9?:P-03QO9ORPU6FU^:MY_V2,Q4B\3^Y,2MRP8#$[J?E7]<58\3 -MN[CSJ.34;91VM<+=H%&TEB5;@Z+"V[9\$%.'=;R[@Z#"+1:0]^]46%H4MAV< -M.I&@20FL\1*0H;*56Y.\TVQ:FQCB.,3 UQ"K=&2_]D.^SD=J!^CNK?I"HU[L -M2*J.CD#70-/JT)3_[_"[5X^\1IAKJZ&;@R??UD[""\)K5=>43YR!9J.FC0SR -MX1_PU,>'5IN(ED^^D-YPOY+2U<@75@K%]1RXKE[S7@6[BY@F<-MMGF_B6L3) -M?HF>7(:=J@/M"R\V1Y/^1KYPK%;2\.7WP-9SC:(2GZ 56XJMII['UV;!Q89R -MD:.*^OZ0A9/:L;;P].#:A[>DMU*9N ^+'@L^<._MPS]48)U867)7DKW!Z]7O -MM9?*KX^-C8F\JVJBI'LE*%>"WZ, 3(^$C9M7GVJP3Y_!'G-@$I#KGIY?HYZU -MJ=F3[ ^:\OS[[LI*[LOPK9X%"/B;CQCR+$2-4\/A;L VY9GYWD5V4IB-$0_" -MXYGVMMVEH9B?X6HF_N;V6U6P&9Z:%1JZX'7_36D!TGJ!VD:F65"3.X[=Q30W -M^_#%&%*V>8]7AP>WTH3-*,$F/\_(I&!:JKJ2,@.\$93Y;_KT#[G4NF0,\KT3 -M.;^:I\#4H@H/$)Z.3%6*GLTZP\Y*YW[A\,+>&UN+G[,HC+J6"L&=M_$'K@M& -M#02KRFJ;G=NN7KM;H8&7DP3^.:XV/\#1M!A%1[6*^<'6PK)=@Z:OEAW\ Q?: -M.38;[F=1H%[[LY$9VH"GEP,.SQ*L5+0ISYU>_K1: L$^&3_@%="-1H/[?HO> -ME9>ET;'T[O6BJ)W"=IF;FJ2)2-+T[L+$,\;NAM6-B9>4BKHUEQG:@ P=HM 4 -MIEKHZ5*+8[".32BS]/3P-"N CX7!7@:[N_Y$M%T3%.#JRB*@<1")%EN#FI^' -MFA>Z4']!ZFSV(/(#?)G6D;97DYM"W?6'UN3A)W* -MZN7^!>+ OX8#OSIK1=&ZIBMUMQ7JTQ)QE?ZP,#L_O;N -M)40<2D2Z49H"TL2EPYS0FIZ.@*J2P3[\T/I%]Y"@D8VV5YJ[>E:RTPU0T800 -M5IM:45I=;*)7YQ03__(3XIVWDIJKNWQSL3K9]&% >_.'5B69FKV8E+"_S2+Y -M;.(N R2VF:>>G$5*LY6:\P0,:M?#'(N5CYQNVXF[A)^JZ233U[WN(VK?C5M# -MCKBWB+&.4H$/R_=Z! %0M,L]O:*ZEIC27F)^6\'CYL9EU^>8S[L%45EZ=7@B>F*6^B\E_(LB&T9X<^E2"6JQ.LL7J -MK,8?]M*3H&P#BXU>&XJ\[<'5(##S4)83@MN3D@QWA*%!E/_%^L"CLMP9C)(, -MOVQZ6L+ _'XI.4FEZ5RH9=3N3WC>$Z)Q(E]:BC4["@F[9-FX)XCH,'!,A= -M7LOJ%>"KKHE*F9I+3J&CT)FJ_N5ZTCO"KI6+^UPW2'K1+<[;G))V>Z1 EY?! -MD]-T/_ KG)V4K[912GN@4$F3AZ#;G/92/*8=*'F@59WCE&WR.LK=D*)MDY:3 -MDEI[C #1L3?EVIND@JJYA]9,D>IE:.S2>L#3UI:5C"*8GX/@D(O-W^BH0 /= -MF8"\'FU8B:V1]YT#'O__K]H%2).9L=J06+Y#NKH/0?[!X=7\$\?3ZI^5RQHF -M[?:+DYI!P\/G/C[E\8QT6AT$>7Q:U0SWV)!1B?[RB?NK\SIF]9?\C[V<@9&D -MPH""RK[9VN+9R8>06YLD$9S>N(YQ03+36D+0\+ORIIJ"ZI*/EVP9ZC-EX-*" -M\K@8_&^4A%D, SOM[I1V KF?O$!6AH]-J%>7)\HJS>I/0NM?K8ZI -M)2/QM#6UAPM/AK;VI)&^/J:/B<#?[$<-V^G3RBNFFG=#]'+'O% -M?IN9%IX@E%KRULOCU"C/HM([CO]U>J!#4E;Q@)C%^>;$%,73^HF4\:)TJA;0 -MR_,"OMR41II(T'\!/C\TUA##E%"!WO97FIUYEOL0RQ?0E)B;E5^Q&IBG4*<9 ?2 -MK(# IHB:B!A7P,]3HY.&C9F-CY.XAI$%U!D^;A+(B).IE5Y2JI)0.)JY QN: -M8?Q\V\ZT2YZ? 9[UZTH2H)*7*)[1K_;V&XX0VZ\0D9.7\>_0D)!#H8>%DW)[ -MT?!Y/N9MPKR!BZ]&21*70:*:S5VKY;Q1DM%?G5S;:X29P/;#.C7U] M>N:EZ -MF)I?H^[)\?3B>IO-):N96XJX:F%J>G<&M1EY_@3OGQF(VX)K_G2%:=H4\4,@L!JU'I($40+'5%O?S -MG79FKTO+DG>5EAKT%_> 1&6GEA O8>[N.RFW:LFY)2OKFPPD7]U. 4]F9"4)Q3DXFE\9:8 -M\P_C1!264YR3MUA#S3/%+K RHQ!&@YG22)./;':I"WL+YG2#G_R6D=R?D?>2 -MP??L]9>GXFVFH9L>6P>V18SSY].7]\N[D.:95^J+@I%&#?[U/OOFVXF;G$&? -M$E6_H_+[(0HD_\K/ [LF^81&AZU&H$^7T,3UE>;ZY5*($9E\H(*ZM+&F^_?M -MSL\(5L/:R:]&>*>.$@**EFRVER+6;_#TQ Z?W%:?@H4:6L#YPL*-@*"'IE%; -MJ/?&^3HT,D#^D8I96J-^F6+ -MFZJJCJ".2.KS[C?&C86(&K.9NE(!*-+-W _B -MHLF_%GC@O_VNAI(7O1#@V7NZ],N'2(^ E@:]KIZF58-)3='#U<34U0GG\K>^ -MDZ7+FEIXC+;E>O7^9CKRG*/RGW"W<\+9RW,0A(:2A9+TFZK9\E5O]_90U9!6 -MOW"#CYJ@^X$IZ='(BI22U/HU'*NYEGUG\\;\/J+0:YJX,IN2AY7SF-K2<);7 -MRZVFP;^*0W>R7M0MU\4G[_ CBQI03BQH-*S@">OH.N%ZOS -MI9< P\3[[N;W1K9[5T(0AKQ2>Z1:\M? =5Z:\E6#TL;%;N;/-D.VQ$M:;Y.VLIP(]\4P^J-=M+ 9K$=7T)Z> -M6RIL]]0P&P]PF8CM6X;KD%6#&6K8!J80ME2GO;Y5$D6=H#6"\?XXU^[_]IB. -MOQ"3CXE*F^)>?U'?R\\4Y>90(N! -MJH<# -S1EO&5\+V?LMF0;._2%$^\EH0=E:27WV" 6L',QM)>B%>=^K"3O[.% -M^L$4GQ(FA;R=%!8;DB\/FH,-P?G%\D/O4Z"AF9R)59YRC!#JX<7'[]574E1* -MI(J'B+GT?MM<' W*]MP/D#ZAHTRORY!?@\,Z$.06VO.KEE&0F+N&F]Y@1E<# -MJM'C7-]")IQ3BYT0J R^FO;AI9OR\?:BGN7OFH)2732'>AMRJ^- >DF:!?:' -M6(KR]K[OUM?U=YA?D*)2WIMD!@O-'L[PNA9#BU>2\8N0)E?'UL7EUA+_3605XM/IKB^2)X6D(G3/OC&^_;5SYY>BK^=GLOX7E,L_-A( -MS^*6GU9?E8U604+H-D+E?NS\]^?%O[7$AUN/D4^+H'NJF0[(H0'!S4#&B_[? -M$((,NYHR<9_1 L#U-?X_UUV DD'G' -M]O"9EFA7*%N83;6.VO+E_O7"P6O6JHH)F(Z->(X8S=_@U\K3"ZU]C!^6QEWK -MAI!0S69EGFWPHHM2G)=7I*U\H:S6")&CZ!\%UMPAN^\@B+JTU=P+&LECZO<)>+DL$3[>8:^]DUEG.1C**"FT.UJ0TB -MD1"*H\F38VE -MTEORSQ'P6E9031"7LY$'._$@=93'6EP;KYJ=T+F0)ZD#Q.;<,%V+O873LJB@ -MFY-SJ]3?UL+"1X^AJ*J[E%)*B,GJ9?7PXL=:,'VXAQI$LY_)-\=PQ?!SETVX -M#+[&#H>-EKL3V@H"2M/\GU"6N+L7C4-Y\ZKQ8MF64$6BPJB$GJF66IB+N:6H -MQ5[84Z#+7L+8ZL^\BON6./^:+%_941(\Q-HOPQC3LX2?D5N)(PL'" 1P"AR' -MN+R]96H\QC VTIR3FZT025J];).ZQU=:T9P05DF.%?*_N8^K IYX__Y/<$ZF -MN8U64,Y;GS_%P^7V+ME#I9&/VHL/E9CO@V+VNYZB]TOVD(^_6F] -MG56HIJN6I"0647%D__02[]-<0!2M4+-*.P>"]4NN>Y11AIGXF<6I3?F,%'0-R$@Y95D$>I@I.:7P4J-/8GHYS I")2JX*N=!.?R^ M -M._OBB_!&JJ@-&!1#G-JJU.?^-<4+CM6F0PQO:+&WJ<'-B@/)OEKYLA7NM -M"Z"%W<#RL3;TY$#KQY&3EYY(@K/$EGKE)E&&_ ?.]U62F(T%K)>/N%K$#Y<) -MY-C:Q<7"A$2CA9.72JE5PRC(C9R*K9K;EBN,W^/2\#X'A%"?E[255X,UEJB@ -MIRMTG_!3AHV5%XMFCY?5M-%R,_?QD(YYL)!3+J !;_+2\3>0RXKWH-.KOZJ0 -MT0WG$9V:ME %GW90E&SRO4*RWAWD_M1>IO&SHPZ>U8.HBYZ GIUQ(''@-A;8 -MC[J8L)R:2():>AZ](O_:%(?"I-#Z.9W^E7.ZKIK2PZ#;46OL]IKEX712BI#W -M@)R*VNL/\%A#ODMTD5X2X=[Q9OIN$/24<962BI&+AGY(\>'YDD*4PH^/ -MNKY.J%VOH_J Q=S4_D8AP82$F9YCBFM2EKY8T_#SDO8G]]FOOJ6ZFMLJ2(&U -MM\,&0<'6=]PC4E[2.YJWC(=2DKI4FJ/7[?:4TM,QMJ* -MHG&L7_'6,S8W[\&7M!Z']@"6MV!P>LT7(1FO@[.6I+R+BL97FH?T[>?_PQ.Z -MCX&/6B:ZI'+!P^KD]F7;XYY%V*AK6%I5@=%^^>)T)8&#\$S5E*V/.L.4^5C( -M5,+=R+!BQKV E?WM1Z 25TSJ$48UG\:;A*M[OZ:36 J1UAK'PD1WK:KJXO&3 -M5YZW6?Y/7O1J]XG1,:/3P#9PK )T_YDH'$QO7A_HFV_:8=MM#"#9"H\&:\FL\0!Y20FP)-KD!3'@' -M9QS&TPJ6.YUZOIAT4JS9T>7&.L"BOT>N0$D5ZT$Y@(,IS?W^R@/&0Q8&K$F> -M36U@6A" P96FL/KO@UY]5U9'DUF ?9)+:)1X7_%VDO2#5@=BZ^%P)B@M!9W -M\?/Y.F?0PHA0E%F^68(!\<[)6;V#GHZVI5^-I.H8_\9URI!0>G']G)Q^I-93 -M)]\%@*V)@\Z]]*^"@ 690?(M\"? UJN6DYV(3PVRDZ?QP=4N5J.(E[)]JBV3 -ME@-6"<0Y),?WVT]5G>VS [L[S]E;PE9:-$DRGHHY7\<)D[C8Z -M\4Z^1)\L4XB(GB:&T]KOX$\J*@# Q@V;AP"Z\$*?BLF&FL?S_>XR;L%_L%N% -M0%>6F-K>PO"YB9(KCZ-;JZ#B=/ P%H%R: -ME[:Z7\TBY?0R\,6#]I.;JB:65]M4HO.=TC_+K87TGY:3F >>ZL7 W-9R/\"& -MGDP\#-:!HV9P4MC]^DP Y32"G)!%B:^[2V!0>,GVP3WT_\J3._U>FY!#=HN@ -M6KMQ" 76P, 1SM*Y/JLA4E93>::0MI,1,=_&1E;"SLF4CHXA&GLD_P*!B8)0 -M?I6GN@/3_N^?@IJ$T2OW-/3F!UZ,FI1+'[\O.9H9TP %Q\I#XYR@G*6I -M6HT=.*:=PV+C-C 6\(J/<"H#WXD>XE4B#\[M"H8&E -MNJG ]1YN/ML:LY.4I%5: N#6V3!7D#0,E]&"@Z#RDQ8R]AM4"+25C@BZ66)T -M^DBVBS!0"<&6/3/EKQF'E*))LYNJ7Z>)PO)E[G?3"W+&E_I" -MKE6*CZS">+YV>_%ICII 3K96BVP"D]&L!(_& T 76K!$'\;ANJRZ\\U^,]6] -MQ9M:F([&_'"+EE1H7YO-2LG3^,/(@)"&K*Z@FEN_&Y_&7%W%]$7DQO;8O=!6 -MKOJ0G*K"[*"(K)P6.4^1*Z\BDH.4 -MDYHJ\L@)RP%&U-LXJ(?%E5P%DQ;T>DZ[YQ+&Q;O&PU@1AA^6E9A*\03:T)!0 -MHDL'E)*:S?O5_X:P@8/H+-W*[8>* -MO8F\F7JWD&NKL997O\#A]6S0^J,DE6L=XW'Q?0/\9._DE&QB1G6-] T -MQ@%=E*.QQ?F^$Y/^2I;>9_3"=VTE$\<;NQ=Q!#L&ZJH=?VEN/ -MTOY$\.X%:Q>3@K:XVZ7:@)F1E,?&]ZZ>\(V439X,DK)?^.MV4^// 0-L]-G_M2@IJ-"%J CKZ [MC#QLT/QQ_DY"MX"D -M)%%QP/3L+L CG;VBD9"PFITEP\K0,8F2K773NAMB\BT:,- ++%.TF[#W0%ML -M5 . YU/3GKP*VW2%JH*MMMTEN^UO]D\02H6KGKZ3A_>9O(73]O_ZY1-?I:E_ -MDXQ42TW9YO7^-Y>K2;2>+4FTE*K1^_:= -MTO6:ZIX$@IHZAY?RP,R?T0+,SY/O*@L(3XBU&W:_AUP&)J)RTV'0U^; )?22 -M%EU&4)99P-WS\:B$H[7;@WGS)]/1Y_07VZV*6;U45UY?*8Z:]PE%2:X*KR7OM-O0JU9U%LAN6@MR@DJP!^_'^4.-/?J&="D*=\HBJ1?''\#9Z -M\HZRFJ^'=_(ZPH*8<)5>AX\H -ME*2/@NTHZ>,C@P4'$DB7E0&[M@-#B^VGD0C#[J#@]8%0$(&[EZ"9@P%/HU&( -M5D&K@)*Z?0OO=EPJ'R].\D*"=$A$6FZ&.GLCS[,;V -M=M*O1:2+GIM25K%,6? 55/K.J8>ADQ^3!A/^H,R4)^_ZQ=..E9R5A4^^BT:@ -MFPK@U)A=;QX95L[_8EG9:>A8>)BYL(ZP44#Z:1])"*D8]A]/W5 -MFL2GKX">6W>BB(GH!9G2[L<6#YN1E+?$CDF&VOTGX/3&^EK=IWVX'_JJCXZ@ -MB?5\*VR@+NFF+F-K8+:M82(7[> M:Y*A3GUQ-_7VWVFEIZ B,&? -M;%Z_07SOUH_PH]'V$WR=$9 #K/OM9?K/XX>:D$J#JJRR!TIST<77PHOCHJ8O -MNE&5I+=, 3YYY\0Z$4*W_8VYA;MKH)03&,^,3<_B_$S&6HIOGE^-8;H+"?+M -ME_HV15">F5:#H%O\^7UZ.Z -MO#9$E%22B/+_VK2H&%H&DI6*P^23Y=6V18*5DE;VAG264O*'KT%^+1N':Q;I? -MNN:/U*BX7Q]Y6SQP3AZVCUO^'&Y20\)?UZFWEPL#Q^8@+N5(R_BB9@U/8 -M>9Q4?867FG[(WK6Z9CK'C%P!K;:@DL,YLE?9YZKZK:"+K-^=F:ZLFJ[1.9,N -M\,*XGQ8PDY.#&(ZPC-/ T1O4 -V:P?U**T9.FX ,TKFW_.93[Z:,.$*2/)D@ -M6J[##:Q4YMOQ@Z2]@$^3SU*( "TG/B7^IO)#BZZ0HIN.BYO4N\":U,[;XLK& -MUL/<0-^="H)>BY::2+>ZV7+P]:_P)8_)@)U4B;^Z\9><@UA_ -MB6RA:_<67Z.-GZ*_>(F=U8*4), O_/?P%6=.G,V7C V2J)7_4L#$R:E#\9^T -M?DS%CHBHJZ7XQ;05QKWN\*&J^QO6$Y*!EZF7K:-OPB]/G_SJU$=^SK> -MT[.2FM'[Y.V4^BN$$%&],J*J6Q5.TO0=EA.IAE*RG>TVE3__K=/P78G/O8D: -M]S!RFU%58S %G/*%59%8$\PPGN<^\7YEV_#+FL&]>^^<=B.EZ?XU=>X%CW"L -MET.G2"!?G_#DU1+0]MM-< YL2Q*-0)&0>T5O_\U/%<.&]]^,5W^!/6:.70$6 -MQ^_FTE#M?9DFD9"0JI>YE]WRSCB9C0_PLTO?P)SKHP@@ML_^SWMN^)6!!1GY"AJI'CO9U'(T#PK=S3 -MF4;7@KUAH(CJZL<0$,7!C;:YJIJO7;!Q1\7$-;_DQHJ:*/NJ.QS5H)G2]GFE -MY!#BF51_G#L83+TAM[;GR$C5U_=XCI!)GDD.BXULEXM(U/-W[Y;;4HA?BUI/ -MB9PRK+(-40V+Q#*O!)&\UB^?V*^"ADM.L(+2H4OQ -MT(P"HYU7@M.;\L*C.N_NVORP5ID$45F8P25*.WD(Z:4'A%@PSZ->_7UZ?XL_Y-M'B!DN4#PM94=DH,M_>87XGF -M+,?NU@5.?9:<\'U6J,!>BUG#QMQ?H90\E;$(@VP 5]*2967E]=&=ID7RF -M5$MH0,#$]'/'DI*X]H.#';)1O:"V\5 UDNZ]&Y>\KY>/JZP:&,*T?%G>/G)K!LX+(_ YUSPH'X\N(KMO!6)9M -MGO)*3E,BDC[&)&;/4=A6A10)@ZODV=CX_9(B'YN5JHKRPC5M[_Y0N(NCA5H) -M\C&CIJW7QO+"FI19K(^ASEVTAD+8H9;UT-'&F\:KJ]@0TM10K$6C]1 ?T6>R -M;%\*FX>/DT 1'K3NUL;E8Q"]B@V'[1LAVD$)"@ 6!-K(AY;0/)RX9:MLEY_- -M]-$P]B?;[YQY?H.62*BPI(^:P*I2*M$.2?. NYZ<@U9 FI&2H(_-Q^NN[O;^ -MRY!6K.18**7H:Z#Q+RC -MG_F<69ZY0 _#R//F]\6K$HF/D[J2CPA7@HA8T]76U\J[TBP?LI&H=8FO\.'D -M]^SZ)KM/C> ]<@%3EI(70.W>"N;"Q!22N)P4JX"3N*0^P-;U1L:N0ZB&F?#8 -MC[N6)NR<0LW]J8JHC8J:%^+5@M&C\S?O]'51H%I&FO"+F]D= -M$_6X0GY=D%F"6\-R-?+FQ8^=G*2M,(M""V/7FR+V -M-,6:_ZK^>6IMV_OUHK -MAK&2TT$/ZLCF5SF5=GF4N:C,ZI!T@N+DQS"^,E6_%?&UEC!B@')P3H+9#LCW -M6LC?&4"+3[=>J?J#FJ)LEI['\#7P;C;2EYRRD9HQEX+Q2O72?IB6G(Q0F8*C -M,A/P]/( J(.*O)^8B+MIH(+S[84<+_)X6U8(O\.CUE<@\OGW^LBUJ/:D6_'/ -MG[>3O<+V'>0^Q1*2(_*;N(:&G[ZA0/U]_?ONNQ*0+]Z:JXNML B@Z ?H!LN( -MJ:><@(SZ3IUSEI]!-^<;[O[#:9O=DIO6CU86@))?\?[KYNO(@&_5ARP1D7Q^ -MRISSD86:P/C&NB7D\_2)EM64>KFY@,+:X+PV4;BD=Y?;)_;S-OWPSZQ6RAF> -M5WFY0]HXRP.NN'JCF)TSE5JIQHR#X1 \]C!7-8U6:9J;HU):GTJ@QL%]XB5& -M_8R)K@_7L%.-US_NI]8VPI:6OHV]AXV3X%NZVJK4SXH"TKL5K]2)N)5'ME>= -MPO1%)'_^"KNRK4.)H$U2LF.?B6Y1%#9/;G?&)X-2N,_!6DEO,>0+QLS8R_\+^7-N]?;$*W2*$77##\1@J -M@8&;=Z>06^R"0^#1\;?_T^ 2I&P)2CBJ.J%,R/&VUO("BZ>D0WJA%);U9%+_ -MQ>;\QO.&E!BHETV.JR10\P/^#,%+43VILDF.HWN^BZQ6BQ?6]_;ZUO#K+ASS -MB;J-J9G!CIW)HAQ?(M_!0N&"GM\+GI)#5X.B-YCQOCE"_\8C68 6G8ZRB:CC -M52G0/AP+A;"0G/?EP>?6_/IS+!:)KL*7NAEF0#O SN=45""6G0ZALD#CEE/) -M%#3O]_'3DX!I@U&#OX1WG.S3P20ZP)*7H!.HK[.<%;C:GCSO_G/S ]91G\FH -M0;ML(%?-R@\:QHK0EUX1CXN+C:]F_XJ#%L7^P&Z(AU97]Y>>J)^F\+Y[2._D -M0]31 G$(N9/]&H!^F8A8L%.KP/XS.OXZY1J1^["0E*H+@O_STLQ0 Y$WEUJ> -M\JOLGN64X[Q<@;6>4*^+S');(-L'W*Y;^Y"0DU:"J::9XT(W\,+CP^<7J8BO -M@T:2D9H$P?COQNNFGY.#6AV2$HL:VI?V^A)'X3T:'$_M1HL.H8Y;%^0)_^?B -MXH./E$1>4X",V3;%=J+: -MDY>V5S9;K@Y3K,#0[])OUE.-O97MOU^)BL:$5_$*'N/' ,B4M%14G_8@CY:. -M4Q$V-7OE^EJYAY"UJ:>]=A*[LX.E!EC/S\@LSO&KJ)[SL?62B?*2AYK#*A7N -MTE?U?G >5:#1]I\%Z8'(#Y."T2 PO(#(T\"VKNB5Y+0L;/O]O-29YHJTI9+C%^5ZB#"/-#^R4:")9?ZJKX5HX!, -MH?37^BY/G19>FF2N()MMAL*IR$VHWO,<3I:L3;D&[U-F=K;A,A#OYF6A@Y+Y -MFP+R@7N*:80?AP)*S,\*5,J#JIN,B*FFDII3Q+!WPSKD]N7N\)J3E(MR@,.K -M$7\5V*YR7@Z:\-B6\^GJJDJ&"':%6;%SO%]L7_\,N&G:.>]XJ:,J16T*XV;).IO7\'T3)V^(:M?8[1YRL -MJR22D?0N=>M%EHN+Q -M4].#G@9@KYJ(G:P&EW'V-.+'^O/*EM%:T+Z?RJ'YDAOWB*ZG1) OTN6C2O&; -MC'^/ I!ACA+1X_?UTM.%4));FU:E3$/EUX-AD)#0^Q(3U@W',;\5L+O VI ? -MG+18F*DXA /'_,\+L+!3JX19J%OD$%W-,!&7]:L<&;V$@JGIE;K;X$F>EWK$ -MVP^>>8-3NHN=I5;EL";WYMK#UU^,; >]C4UCOG?HU"D9Q5LREIN?S R7N4TY -MI9,%,\3V5A &DH^,VX.5AIX&:;>0D0*LU\>-QL661T^-DT.=JH!*IEZ:PI#E -MEM>:P7^(0%U.2H*X[1G/\Y0+GBV7E192UZO\^O/N"YIQB\5&M+9;XM:M\1O/ -M'(6V,@2GDIZZH+>"QSO7+/J^/>"T>(JNCDB\ -MCZ5*X;6:Q_4>1T[_#QO"C_!6 -ME\4B-.X[RW#GIG1= X:MCHM/A^ 3];9PCJ7L0QB37Y33Z*USESO[^]B/4*Q( -MZ9N;CX7<\7$/VMT6P\F/W+F:2_I-K::"@,SD^?ODTH_HEJRS>O>'4[8%MZV@ -M_H1QR\_$CL&'GYV0J;6)3A& EYKG_O/D]NW%A$B(J5J1'*GKWZ<07)7[D1QS -M29+ ]G&6/I/+?(N3L0^=_)*4$-L(SP]D.)Q?A5>2FH%AI)<94;7FU@+(4H^@ -M5T.[#Z971@TPY^__SI*,H(M3@HCPA83 T_;2,!0!G)99KY:HJYUCAJ[#5I1\ -MK*4(OW2:1YFXC(:*5[_HU#WMM=;S0K95LUO5COI*;+9#$-@ X_]BRR>T4U>; -M1Q&0II821I.;)Z%%'"@%*^R6))6PYN_A"MY^@NVJ_08HFF&8R]GI]!1D^7P,#.;<\HYH] '8B/7LVK -M8$1;F9KL\C?Z3XJ2A7=U[6LR3C$]MY"PYH0>0F+?XRC -M3<#^;>[P9AJ)5 9-@IRE( !D,STJ>@(YJ75YHNKG[FM'S[/3P,@-) -MOME;5J1(G[N OXF% ONCRX_"CKR!E'V%J//GDY3!EY[-,A9G_:*3_>(DXLH -MAX#;:&SN,O<84)6 FM.I=HR5JL'B_/+D]5*VDIJYNPI&DHW17\=V=C[15W:( -MO#^&#HZXCDC-#?^O#=/27B_'RI6MPPI&NH.QEIJ* -M\,9" 5+,Q]K)F7@YFI9:+?R?H)^-I.(]%>[WCSV T;$Z,9:9!=SE$)B2$ECW -MD1J0P])O^[;$PKP*7H22H)NM0I/=*,-*_)"[FJF5]UH>IHY33>)6_;XK.X*C -MK;BS@OI&=8X TB&6VD^[GD&7^CV8SZ:M]-XNQ?Y@PVR6GZJ\VH]=H+79V\[* -MS0;2RK^RNHRL^Z6BK!X;K7*YQ].ZX^>!&)7O1KSG<;POB.\B()UL'2^6]+*V?*4D9.%4%37@<'F[,)O[\.. -M\(.;EG>"@SF7MJ7)V1 .B+*MFB%<@TR^B,/3D3!4TM!'Q[*=%\<(C[<&X./U -M^I;6DIV%@MJ2UH9(K:'P_ZEYX%EY_ -MU-SN>O+:])R$FP!QB8/1^87 A(A?FU2C?%+"PCCR$.6CNHBSK5H$KH/!WD'9 -M(P/R7"2&B38128FR]YK,\_E %^5)IX_#FKB-?I91@:+D%6[WU4_2;).L;Y^7 -MVK[-UM5VFL8;KJ2. 8FOKI,$L(K)5EP; L7REH_PK+V>1-*[EBG)$N\5R+E9:*T->.QAJ5L*5TRJO$O 6X4^0 -ME)2'7EZ;I8"!TJ * ]G?*\B>0M(- -M6MF1FM+ ?,?3[N*1EI"$AXF#@6P-FU/4\QF?O!&%CE5*6J2'@QDYV?_04-O) -M7Z 6N;C7E_4 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/tpg/94654-20170317-085441153.pts b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/tpg/94654-20170317-085441153.pts deleted file mode 100644 index 6760d5ec6..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/tpg/94654-20170317-085441153.pts +++ /dev/null @@ -1,289 +0,0 @@ - -94654mynewt-Updated - - - L2CAP - 0
2
- 1
3
- 1
4
- 1
5
- 1
6
- 2
40
- 2
41
- 2
42
- 2
43
- 2
45
- 2
46
- 2
47
- 3
1
- 3
12
- 3
16
-
- - GAP - 0
2
- 0a
4
- 10
1
- 12
1
- 13
1
- 13
2
- 14
1
- 15
1
- 16
1
- 18
1
- 18
2
- 19
1
- 19
2
- 19
3
- 20
1
- 20
2
- 20
3
- 20
4
- 20A
1
- 20A
10
- 20A
11
- 20A
12
- 20A
13
- 20A
14
- 20A
15
- 20A
16
- 20A
17
- 20A
2
- 20A
3
- 20A
4
- 20A
5
- 20A
7
- 20A
8
- 20A
9
- 21
1
- 21
2
- 21
3
- 21
4
- 21
5
- 21
6
- 21
7
- 21
8
- 21
9
- 22
1
- 22
2
- 22
3
- 22
4
- 23
1
- 23
2
- 23
3
- 23
4
- 23
5
- 24
1
- 24
2
- 24
3
- 24
4
- 25
1
- 25
2
- 25
3
- 25
4
- 25
7
- 25
8
- 25
9
- 26
1
- 26
2
- 26
3
- 26
4
- 27
1
- 27
2
- 28
1
- 28
2
- 29
1
- 29
2
- 29
3
- 29
4
- 30
1
- 30
2
- 31
1
- 31
2
- 31
3
- 31
4
- 31
5
- 31
6
- 31
7
- 31
8
- 31
9
- 32
1
- 32
2
- 32
3
- 33
1
- 33
2
- 33
3
- 33
4
- 33
5
- 33
6
- 34
1
- 34
2
- 34
3
- 35
1
- 35
2
- 35
3
- 35
4
- 35
5
- 35
7
- 35
8
- 35
9
- 37
1
- 37
2
- 37
3
- 5
1
- 5
2
- 5
3
- 5
4
- 6
1
- 7
1
- 7
2
- 8
1
- 8
2
- 8a
3
- 9
1
-
- - SUM ICS - - - PROD - - - GATT - 1
1
- 1
2
- 2
2
- 3
1
- 3
10
- 3
11
- 3
12
- 3
14
- 3
15
- 3
16
- 3
17
- 3
18
- 3
19
- 3
2
- 3
20
- 3
21
- 3
22
- 3
23
- 3
3
- 3
4
- 3
5
- 3
6
- 3
7
- 3
8
- 3
9
- 4
1
- 4
10
- 4
11
- 4
12
- 4
14
- 4
15
- 4
16
- 4
17
- 4
18
- 4
19
- 4
2
- 4
20
- 4
21
- 4
22
- 4
23
- 4
3
- 4
4
- 4
5
- 4
6
- 4
7
- 4
8
- 4
9
- 7
2
- 7
3
- 7
4
-
- - ATT - 1
1
- 1
2
- 2
2
- 3
1
- 3
10
- 3
11
- 3
12
- 3
13
- 3
14
- 3
15
- 3
16
- 3
17
- 3
18
- 3
19
- 3
2
- 3
20
- 3
22
- 3
23
- 3
24
- 3
25
- 3
26
- 3
27
- 3
28
- 3
29
- 3
3
- 3
4
- 3
5
- 3
6
- 3
7
- 3
8
- 3
9
- 4
1
- 4
10
- 4
11
- 4
12
- 4
13
- 4
14
- 4
15
- 4
16
- 4
17
- 4
18
- 4
19
- 4
2
- 4
20
- 4
22
- 4
23
- 4
24
- 4
25
- 4
26
- 4
27
- 4
28
- 4
29
- 4
3
- 4
4
- 4
5
- 4
6
- 4
7
- 4
8
- 4
9
- 5
2
- 5
3
- 5
4
-
- - SM - 1
1
- 1
2
- 2
1
- 2
2
- 2
3
- 2
5
- 3
1
- 4
1
- 4
2
- 5
1
- 5
2
- 5
3
- 5
4
- 7
1
- 7
2
- 7
3
-
-
-
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/pkg.yml deleted file mode 100644 index 691e566e1..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/pkg.yml +++ /dev/null @@ -1,34 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/host/services/ans -pkg.description: Alert Notification Service Server. -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - - ans - - nimble - -pkg.deps: - - nimble/host - -pkg.init: - ble_svc_ans_init: 'MYNEWT_VAL(BLE_SVC_ANS_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/syscfg.yml deleted file mode 100644 index 74de8d963..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/syscfg.yml +++ /dev/null @@ -1,30 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -syscfg.defs: - BLE_SVC_ANS_NEW_ALERT_CAT: - description: "Initial supported new alert category bitmask." - value: 0 - - BLE_SVC_ANS_UNR_ALERT_CAT: - description: "Initial supported unread alert category bitmask." - value: 0 - - BLE_SVC_ANS_SYSINIT_STAGE: - description: > - Sysinit stage for the alert notification service. - value: 303 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/pkg.yml deleted file mode 100644 index afdc69421..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/pkg.yml +++ /dev/null @@ -1,34 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/host/services/bas -pkg.description: Battery Service -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - - bas - - nimble - -pkg.deps: - - nimble/host - -pkg.init: - ble_svc_bas_init: 'MYNEWT_VAL(BLE_SVC_BAS_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/syscfg.yml deleted file mode 100644 index 279930f14..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/syscfg.yml +++ /dev/null @@ -1,34 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -syscfg.defs: - BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM: - description: > - Defines permissions for reading "Battery Level" characteristics. Can - be zero to allow read without extra permissions or combination of: - BLE_GATT_CHR_F_READ_ENC - BLE_GATT_CHR_F_READ_AUTHEN - BLE_GATT_CHR_F_READ_AUTHOR - value: 0 - BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE: - description: > - Set to 1 to support notification or 0 to disable it. - value: 1 - BLE_SVC_BAS_SYSINIT_STAGE: - description: > - Sysinit stage for the battery level service. - value: 303 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/include/services/dis/ble_svc_dis.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/include/services/dis/ble_svc_dis.h deleted file mode 100644 index d095e959a..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/include/services/dis/ble_svc_dis.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_SVC_DIS_ -#define H_BLE_SVC_DIS_ - -/** - * Example: - * - * char firmware_revision[20] = '?.?.?'; - * struct image_version iv; - * if (!imgr_my_version(&iv)) { - * snprintf(firmware_revision, sizeof(firmware_revision), - * "%u.%u.%u", iv.iv_major, iv.iv_minor, iv.iv_revision); - * } - * ble_svc_dis_manufacturer_name_set("MyNewt"); - * ble_svc_dis_firmware_revision_set(firmware_revision); - * - */ - -#define BLE_SVC_DIS_UUID16 0x180A -#define BLE_SVC_DIS_CHR_UUID16_SYSTEM_ID 0x2A23 -#define BLE_SVC_DIS_CHR_UUID16_MODEL_NUMBER 0x2A24 -#define BLE_SVC_DIS_CHR_UUID16_SERIAL_NUMBER 0x2A25 -#define BLE_SVC_DIS_CHR_UUID16_FIRMWARE_REVISION 0x2A26 -#define BLE_SVC_DIS_CHR_UUID16_HARDWARE_REVISION 0x2A27 -#define BLE_SVC_DIS_CHR_UUID16_SOFTWARE_REVISION 0x2A28 -#define BLE_SVC_DIS_CHR_UUID16_MANUFACTURER_NAME 0x2A29 - -/** - * Structure holding data for the main characteristics - */ -struct ble_svc_dis_data { - /** - * Model number. - * Represent the model number that is assigned by the device vendor. - */ - const char *model_number; - /** - * Serial number. - * Represent the serial number for a particular instance of the device. - */ - const char *serial_number; - /** - * Firmware revision. - * Represent the firmware revision for the firmware within the device. - */ - const char *firmware_revision; - /** - * Hardware revision. - * Represent the hardware revision for the hardware within the device. - */ - const char *hardware_revision; - /** - * Software revision. - * Represent the software revision for the software within the device. - */ - const char *software_revision; - /** - * Manufacturer name. - * Represent the name of the manufacturer of the device. - */ - const char *manufacturer_name; - /** - * System ID. - * Represent the System Id of the device. - */ - const char *system_id; -}; - -/** - * Variable holding data for the main characteristics. - */ -extern struct ble_svc_dis_data ble_svc_dis_data; - -/** - * Service initialisation. - * Automatically called during package initialisation. - */ -void ble_svc_dis_init(void); - -const char *ble_svc_dis_model_number(void); -int ble_svc_dis_model_number_set(const char *value); -const char *ble_svc_dis_serial_number(void); -int ble_svc_dis_serial_number_set(const char *value); -const char *ble_svc_dis_firmware_revision(void); -int ble_svc_dis_firmware_revision_set(const char *value); -const char *ble_svc_dis_hardware_revision(void); -int ble_svc_dis_hardware_revision_set(const char *value); -const char *ble_svc_dis_software_revision(void); -int ble_svc_dis_software_revision_set(const char *value); -const char *ble_svc_dis_manufacturer_name(void); -int ble_svc_dis_manufacturer_name_set(const char *value); -const char *ble_svc_dis_system_id(void); -int ble_svc_dis_system_id_set(const char *value); - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/pkg.yml deleted file mode 100644 index b914ca90a..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/pkg.yml +++ /dev/null @@ -1,34 +0,0 @@ - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/host/services/dis -pkg.description: Device Information Service Implementation. -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - - dis - - nimble - -pkg.deps: - - nimble/host - -pkg.init: - ble_svc_dis_init: 'MYNEWT_VAL(BLE_SVC_DIS_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/src/ble_svc_dis.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/src/ble_svc_dis.c deleted file mode 100644 index 55c6f1d56..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/src/ble_svc_dis.c +++ /dev/null @@ -1,331 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/services/dis/ble_svc_dis.h" - -/* Device information */ -struct ble_svc_dis_data ble_svc_dis_data = { - .model_number = MYNEWT_VAL(BLE_SVC_DIS_MODEL_NUMBER_DEFAULT), - .serial_number = MYNEWT_VAL(BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT), - .firmware_revision = MYNEWT_VAL(BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT), - .hardware_revision = MYNEWT_VAL(BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT), - .software_revision = MYNEWT_VAL(BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT), - .manufacturer_name = MYNEWT_VAL(BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT), - .system_id = MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_DEFAULT), -}; - -/* Access function */ -#if (MYNEWT_VAL(BLE_SVC_DIS_MODEL_NUMBER_READ_PERM) >= 0) || \ - (MYNEWT_VAL(BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM) >= 0) || \ - (MYNEWT_VAL(BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM) >= 0) || \ - (MYNEWT_VAL(BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM) >= 0) || \ - (MYNEWT_VAL(BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM) >= 0) || \ - (MYNEWT_VAL(BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM) >= 0) || \ - (MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_READ_PERM) >= 0) -static int -ble_svc_dis_access(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg); -#endif - -static const struct ble_gatt_svc_def ble_svc_dis_defs[] = { - { /*** Service: Device Information Service (DIS). */ - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_UUID16), - .characteristics = (struct ble_gatt_chr_def[]) { { -#if (MYNEWT_VAL(BLE_SVC_DIS_MODEL_NUMBER_READ_PERM) >= 0) - /*** Characteristic: Model Number String */ - .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_MODEL_NUMBER), - .access_cb = ble_svc_dis_access, - .flags = BLE_GATT_CHR_F_READ | - MYNEWT_VAL(BLE_SVC_DIS_MODEL_NUMBER_READ_PERM), - }, { -#endif -#if (MYNEWT_VAL(BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM) >= 0) - /*** Characteristic: Serial Number String */ - .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_SERIAL_NUMBER), - .access_cb = ble_svc_dis_access, - .flags = BLE_GATT_CHR_F_READ | - MYNEWT_VAL(BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM), - }, { -#endif -#if (MYNEWT_VAL(BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM) >= 0) - /*** Characteristic: Hardware Revision String */ - .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_HARDWARE_REVISION), - .access_cb = ble_svc_dis_access, - .flags = BLE_GATT_CHR_F_READ | - MYNEWT_VAL(BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM), - }, { -#endif -#if (MYNEWT_VAL(BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM) >= 0) - /*** Characteristic: Firmware Revision String */ - .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_FIRMWARE_REVISION), - .access_cb = ble_svc_dis_access, - .flags = BLE_GATT_CHR_F_READ | - MYNEWT_VAL(BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM), - }, { -#endif -#if (MYNEWT_VAL(BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM) >= 0) - /*** Characteristic: Software Revision String */ - .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_SOFTWARE_REVISION), - .access_cb = ble_svc_dis_access, - .flags = BLE_GATT_CHR_F_READ | - MYNEWT_VAL(BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM), - }, { -#endif -#if (MYNEWT_VAL(BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM) >= 0) - /*** Characteristic: Manufacturer Name */ - .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_MANUFACTURER_NAME), - .access_cb = ble_svc_dis_access, - .flags = BLE_GATT_CHR_F_READ | - MYNEWT_VAL(BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM), - }, { -#endif -#if (MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_READ_PERM) >= 0) - /*** Characteristic: System Id */ - .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_SYSTEM_ID), - .access_cb = ble_svc_dis_access, - .flags = BLE_GATT_CHR_F_READ | - MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_READ_PERM), - }, { -#endif - - 0, /* No more characteristics in this service */ - }, } - }, - - { - 0, /* No more services. */ - }, -}; - -/** - * Simple read access callback for the device information service - * characteristic. - */ -#if (MYNEWT_VAL(BLE_SVC_DIS_MODEL_NUMBER_READ_PERM) >= 0) || \ - (MYNEWT_VAL(BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM) >= 0) || \ - (MYNEWT_VAL(BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM) >= 0) || \ - (MYNEWT_VAL(BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM) >= 0) || \ - (MYNEWT_VAL(BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM) >= 0) || \ - (MYNEWT_VAL(BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM) >= 0) || \ - (MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_READ_PERM) >= 0) -static int -ble_svc_dis_access(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg) -{ - uint16_t uuid = ble_uuid_u16(ctxt->chr->uuid); - const char *info = NULL; - - switch(uuid) { -#if (MYNEWT_VAL(BLE_SVC_DIS_MODEL_NUMBER_READ_PERM) >= 0) - case BLE_SVC_DIS_CHR_UUID16_MODEL_NUMBER: - info = ble_svc_dis_data.model_number; -#ifdef MYNEWT_VAL_BLE_SVC_DIS_MODEL_NUMBER_NAME_DEFAULT - if (info == NULL) { - info = MYNEWT_VAL(BLE_SVC_DIS_MODEL_NUMBER_DEFAULT); - } -#endif - break; -#endif -#if (MYNEWT_VAL(BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM) >= 0) - case BLE_SVC_DIS_CHR_UUID16_SERIAL_NUMBER: - info = ble_svc_dis_data.serial_number; -#ifdef MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT - if (info == NULL) { - info = MYNEWT_VAL(BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT); - } -#endif - break; -#endif -#if (MYNEWT_VAL(BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM) >= 0) - case BLE_SVC_DIS_CHR_UUID16_FIRMWARE_REVISION: - info = ble_svc_dis_data.firmware_revision; -#ifdef MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT - if (info == NULL) { - info = MYNEWT_VAL(BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT); - } -#endif - break; -#endif -#if (MYNEWT_VAL(BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM) >= 0) - case BLE_SVC_DIS_CHR_UUID16_HARDWARE_REVISION: - info = ble_svc_dis_data.hardware_revision; -#ifdef MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT - if (info == NULL) { - info = MYNEWT_VAL(BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT); - } -#endif - break; -#endif -#if (MYNEWT_VAL(BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM) >= 0) - case BLE_SVC_DIS_CHR_UUID16_SOFTWARE_REVISION: - info = ble_svc_dis_data.software_revision; -#ifdef MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT - if (info == NULL) { - info = MYNEWT_VAL(BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT); - } -#endif - break; -#endif -#if (MYNEWT_VAL(BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM) >= 0) - case BLE_SVC_DIS_CHR_UUID16_MANUFACTURER_NAME: - info = ble_svc_dis_data.manufacturer_name; -#ifdef MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT - if (info == NULL) { - info = MYNEWT_VAL(BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT); - } -#endif - break; -#endif -#if (MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_READ_PERM) >= 0) - case BLE_SVC_DIS_CHR_UUID16_SYSTEM_ID: - info = ble_svc_dis_data.system_id; -#ifdef MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_DEFAULT - if (info == NULL) { - info = MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_DEFAULT); - } -#endif - break; -#endif - default: - assert(0); - return BLE_ATT_ERR_UNLIKELY; - } - - if (info != NULL) { - int rc = os_mbuf_append(ctxt->om, info, strlen(info)); - return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; - } - - return 0; -} -#endif - -const char * -ble_svc_dis_model_number(void) -{ - return ble_svc_dis_data.model_number; -} - -int -ble_svc_dis_model_number_set(const char *value) -{ - ble_svc_dis_data.model_number = value; - return 0; -} - -const char * -ble_svc_dis_serial_number(void) -{ - return ble_svc_dis_data.serial_number; -} - -int -ble_svc_dis_serial_number_set(const char *value) -{ - ble_svc_dis_data.serial_number = value; - return 0; -} - -const char * -ble_svc_dis_firmware_revision(void) -{ - return ble_svc_dis_data.firmware_revision; -} - -int -ble_svc_dis_firmware_revision_set(const char *value) -{ - ble_svc_dis_data.firmware_revision = value; - return 0; -} - -const char * -ble_svc_dis_hardware_revision(void) -{ - return ble_svc_dis_data.hardware_revision; -} - -int -ble_svc_dis_hardware_revision_set(const char *value) -{ - ble_svc_dis_data.hardware_revision = value; - return 0; -} - -const char * -ble_svc_dis_software_revision(void) -{ - return ble_svc_dis_data.software_revision; -} - -int -ble_svc_dis_software_revision_set(const char *value) -{ - ble_svc_dis_data.software_revision = value; - return 0; -} - -const char * -ble_svc_dis_manufacturer_name(void) -{ - return ble_svc_dis_data.manufacturer_name; -} - -int -ble_svc_dis_manufacturer_name_set(const char *value) -{ - ble_svc_dis_data.manufacturer_name = value; - return 0; -} - -const char * -ble_svc_dis_system_id(void) -{ - return ble_svc_dis_data.system_id; -} - -int -ble_svc_dis_system_id_set(const char *value) -{ - ble_svc_dis_data.system_id = value; - return 0; -} - -/** - * Initialize the DIS package. - */ -void -ble_svc_dis_init(void) -{ - int rc; - - /* Ensure this function only gets called by sysinit. */ - SYSINIT_ASSERT_ACTIVE(); - - rc = ble_gatts_count_cfg(ble_svc_dis_defs); - SYSINIT_PANIC_ASSERT(rc == 0); - - rc = ble_gatts_add_svcs(ble_svc_dis_defs); - SYSINIT_PANIC_ASSERT(rc == 0); -} diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/syscfg.yml deleted file mode 100644 index b306d3bb5..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/syscfg.yml +++ /dev/null @@ -1,109 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - BLE_SVC_DIS_DEFAULT_READ_PERM: - description: > - Defines default permissions for reading characteristics. Can be - zero to allow read without extra permissions or combination of: - BLE_GATT_CHR_F_READ_ENC - BLE_GATT_CHR_F_READ_AUTHEN - BLE_GATT_CHR_F_READ_AUTHOR - Set to '-1' to remove this characteristic. - value: -1 - BLE_SVC_DIS_MODEL_NUMBER_READ_PERM: - description: > - Defines permissions for reading "Model Number" characteristics. - Can be set to BLE_SVC_DIS_DEFAULT_READ_PERM or use any of the - possible values defined for that setting. - value: 0 - BLE_SVC_DIS_MODEL_NUMBER_DEFAULT: - description: > - Defines a default value for "Model number" if not set with - 'ble_svc_dis_model_number_set'. - value: '"Apache Mynewt NimBLE"' - BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM: - description: > - Defines permissions for reading "Serial Number" characteristics. - Can be set to BLE_SVC_DIS_DEFAULT_READ_PERM or use any of the - possible values defined for that setting. - value: MYNEWT_VAL(BLE_SVC_DIS_DEFAULT_READ_PERM) - BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT: - description: > - Defines a default value for "Serial number" if not set with - 'ble_svc_dis_serial_number_set'. - value: NULL - BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM: - description: > - Defines permissions for reading "Hardware Revision" characteristics. - Can be set to BLE_SVC_DIS_DEFAULT_READ_PERM or use any of the - possible values defined for that setting. - value: MYNEWT_VAL(BLE_SVC_DIS_DEFAULT_READ_PERM) - BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT: - description: > - Defines a default value for "Hardware revision" if not set with - 'ble_svc_dis_hardware_revision_set'. - value: NULL - BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM: - description: > - Defines permissions for reading "Firmware Revision" characteristics. - Can be set to BLE_SVC_DIS_DEFAULT_READ_PERM or use any of the - possible values defined for that setting. - value: MYNEWT_VAL(BLE_SVC_DIS_DEFAULT_READ_PERM) - BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT: - description: > - Defines a default value for "Software revision" if not set with - 'ble_svc_dis_firmware_revision_set'. - value: NULL - BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM: - description: > - Defines permissions for reading "Software Revision" characteristics. - Can be set to BLE_SVC_DIS_DEFAULT_READ_PERM or use any of the - possible values defined for that setting. - value: MYNEWT_VAL(BLE_SVC_DIS_DEFAULT_READ_PERM) - BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT: - description: > - Defines a default value for "Software revision" if not set with - 'ble_svc_dis_software_revision_set'. - value: NULL - BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM: - description: > - Defines permissions for reading "Manufacturer name" characteristics. - Can be set to BLE_SVC_DIS_DEFAULT_READ_PERM or use any of the - possible values defined for that setting. - value: MYNEWT_VAL(BLE_SVC_DIS_DEFAULT_READ_PERM) - BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT: - description: > - Defines a default value for "Manufacturer name" if not set with - 'ble_svc_dis_manufacturer_name_set'. - value: NULL - BLE_SVC_DIS_SYSTEM_ID_READ_PERM: - description: > - Defines permissions for reading "System ID" characteristics. - Can be set to BLE_SVC_DIS_DEFAULT_READ_PERM or use any of the - possible values defined for that setting. - value: MYNEWT_VAL(BLE_SVC_DIS_DEFAULT_READ_PERM) - BLE_SVC_DIS_SYSTEM_ID_DEFAULT: - description: > - Defines a default value for "System ID" if not set with - 'ble_svc_dis_manufacturer_name_set'. - value: NULL - BLE_SVC_DIS_SYSINIT_STAGE: - description: > - Sysinit stage for the device information BLE service. - value: 303 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/pkg.yml deleted file mode 100644 index a2ef756e3..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/pkg.yml +++ /dev/null @@ -1,34 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/host/services/gap -pkg.description: Implements the GAP Service. -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - - nimble - - gap - -pkg.deps: - - nimble/host - -pkg.init: - ble_svc_gap_init: 'MYNEWT_VAL(BLE_SVC_GAP_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/syscfg.yml deleted file mode 100644 index ad6aa7ef3..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/syscfg.yml +++ /dev/null @@ -1,83 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - BLE_SVC_GAP_DEVICE_NAME: - description: > - Default value for "Device Name" characteristics, unless overwritten - by application. - value: '"nimble"' - BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM: - description: > - Defines permissions for writing "Device Name" characteristics. Can - be zero to allow write without extra permissions or combination of: - BLE_GATT_CHR_F_WRITE_ENC - BLE_GATT_CHR_F_WRITE_AUTHEN - BLE_GATT_CHR_F_WRITE_AUTHOR - Set to '-1' to make characteristic read only. - value: -1 - BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH: - description: Maximum length for "Device Name" characteristics - value: 31 - BLE_SVC_GAP_APPEARANCE: - description: 'Device appearance' - value: 0 - BLE_SVC_GAP_APPEARANCE_WRITE_PERM: - description: > - Defines permissions for writing "Appearance" characteristics. Can - be zero to allow write without extra permissions or combination of: - BLE_GATT_CHR_F_WRITE_ENC - BLE_GATT_CHR_F_WRITE_AUTHEN - BLE_GATT_CHR_F_WRITE_AUTHOR - Set to '-1' to make characteristic read only. - value: -1 - - # Setting all values for PPCP to '0' will disable characteristic! - BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL: - description: > - Value of "minimum connection interval" of PPCP characteristic as - defined by Core specification 5.0, Vol 3, Part C, section 12.3. - value: 0 - BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL: - description: > - Value of "maximum connection interval" of PPCP characteristic as - defined by Core specification 5.0, Vol 3, Part C, section 12.3. - value: 0 - BLE_SVC_GAP_PPCP_SLAVE_LATENCY: - description: > - Value of "slave latency" of PPCP characteristic as defined by Core - specification 5.0, Vol 3, Part C, section 12.3. - value: 0 - BLE_SVC_GAP_PPCP_SUPERVISION_TMO: - description: > - Value of "connection supervision timeout multiplier" of PPCP - characteristic as defined by Core specification 5.0, Vol 3, Part C, - section 12.3. - value: 0 - - BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION: - description: > - Value of "Central Address Resolution" characteristics, as defined - by Core specification 5.0, Vol 3, Part C, section 12. - Set to '-1' to disable. - value: -1 - - BLE_SVC_GAP_SYSINIT_STAGE: - description: > - Sysinit stage for the GAP BLE service. - value: 301 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/pkg.yml deleted file mode 100644 index e3704bc18..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/pkg.yml +++ /dev/null @@ -1,34 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/host/services/gatt -pkg.description: Implements the GATT service. -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - - nimble - - gatt - -pkg.deps: - - nimble/host - -pkg.init: - ble_svc_gatt_init: 'MYNEWT_VAL(BLE_SVC_GATT_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/syscfg.yml deleted file mode 100644 index 6ba1b333e..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/syscfg.yml +++ /dev/null @@ -1,24 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - BLE_SVC_GATT_SYSINIT_STAGE: - description: > - Sysinit stage for the GATT BLE service - value: 302 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/pkg.yml deleted file mode 100644 index 3b0ca0745..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/pkg.yml +++ /dev/null @@ -1,34 +0,0 @@ - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/host/services/ias -pkg.description: Immediate Alert Service Implementation. -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - - ias - - nimble - -pkg.deps: - - nimble/host - -pkg.init: - ble_svc_ias_init: 'MYNEWT_VAL(BLE_SVC_IAS_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/syscfg.yml deleted file mode 100644 index 2cbed3ab4..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/syscfg.yml +++ /dev/null @@ -1,23 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - BLE_SVC_IAS_SYSINIT_STAGE: - description: > - Sysinit stage for the immediate alert BLE service. - value: 303 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/pkg.yml deleted file mode 100644 index 55be157d9..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/pkg.yml +++ /dev/null @@ -1,35 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/host/services/ipss -pkg.description: Implements the IPSS service for IPSP suppoort. -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - - nimble - - ipsp - - ipss - -pkg.deps: - - nimble/host - -pkg.init: - ble_svc_ipss_init: 'MYNEWT_VAL(BLE_SVC_IPSS_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/syscfg.yml deleted file mode 100644 index dd89608e3..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/syscfg.yml +++ /dev/null @@ -1,24 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - BLE_SVC_IPSS_SYSINIT_STAGE: - description: > - Sysinit stage for the IPSS BLE service - value: 303 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/pkg.yml deleted file mode 100644 index 6160f020e..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/pkg.yml +++ /dev/null @@ -1,34 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/host/services/lls -pkg.description: Link Loss Service Implementation. -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - - lls - - nimble - -pkg.deps: - - nimble/host - -pkg.init: - ble_svc_lls_init: 'MYNEWT_VAL(BLE_SVC_LLS_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/syscfg.yml deleted file mode 100644 index 312b08a2f..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/syscfg.yml +++ /dev/null @@ -1,22 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -syscfg.defs: - BLE_SVC_LLS_SYSINIT_STAGE: - description: > - Sysinit stage for the link loss BLE service. - value: 303 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/pkg.yml deleted file mode 100644 index 3d4c5e98e..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/pkg.yml +++ /dev/null @@ -1,34 +0,0 @@ - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/host/services/tps -pkg.description: Tx Power Service adopted specification. -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - - tps - - nimble - -pkg.deps: - - nimble/host - -pkg.init: - ble_svc_tps_init: 'MYNEWT_VAL(BLE_SVC_TPS_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/syscfg.yml deleted file mode 100644 index 0391e8b1d..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/syscfg.yml +++ /dev/null @@ -1,23 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -syscfg.defs: - BLE_SVC_TPS_SYSINIT_STAGE: - description: > - Sysinit stage for the transmit power BLE service. - value: 303 - diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/pkg.yml deleted file mode 100644 index db80d1df8..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/pkg.yml +++ /dev/null @@ -1,38 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/host/store/config -pkg.description: sys/config-based persistence layer for the NimBLE host. -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - - nimble - - persistence - -pkg.deps: - - "@apache-mynewt-core/encoding/base64" - - nimble/host - -pkg.deps.BLE_STORE_CONFIG_PERSIST: - - "@apache-mynewt-core/sys/config" - -pkg.init: - ble_store_config_init: 'MYNEWT_VAL(BLE_STORE_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config_conf.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config_conf.c deleted file mode 100644 index c492c59bc..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config_conf.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/* - * Modified work Copyright (c) 2021 Ryan Powell. - */ - -#ifndef ESP_PLATFORM - -#include "nimble/porting/nimble/include/syscfg/syscfg.h" - -#if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) - -#include -//#include - -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "../../../include/host/ble_hs.h" -//#include "config/config.h" -#include "base64/base64.h" -#include "../include/store/config/ble_store_config.h" -#include "ble_store_config_priv.h" -#include "ble_bond_nvs.h" - -/* -static int -ble_store_config_conf_set(int argc, char **argv, char *val); -static int -ble_store_config_conf_export(void (*func)(char *name, char *val), - enum conf_export_tgt tgt); - -static struct conf_handler ble_store_config_conf_handler = { - .ch_name = "ble_hs", - .ch_get = NULL, - .ch_set = ble_store_config_conf_set, - .ch_commit = NULL, - .ch_export = ble_store_config_conf_export -}; -*/ -#define BLE_STORE_CONFIG_SEC_ENCODE_SZ \ - BASE64_ENCODE_SIZE(sizeof (struct ble_store_value_sec)) - -#define BLE_STORE_CONFIG_SEC_SET_ENCODE_SZ \ - (MYNEWT_VAL(BLE_STORE_MAX_BONDS) * BLE_STORE_CONFIG_SEC_ENCODE_SZ + 1) - -#define BLE_STORE_CONFIG_CCCD_ENCODE_SZ \ - BASE64_ENCODE_SIZE(sizeof (struct ble_store_value_cccd)) - -#define BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ \ - (MYNEWT_VAL(BLE_STORE_MAX_CCCDS) * BLE_STORE_CONFIG_CCCD_ENCODE_SZ + 1) - -static void -ble_store_config_serialize_arr(const void *arr, int obj_sz, int num_objs, - char *out_buf, int buf_sz) -{ - int arr_size; - - arr_size = obj_sz * num_objs; - assert(arr_size <= buf_sz); - - base64_encode(arr, arr_size, out_buf, 1); -} - -static int -ble_store_config_deserialize_arr(const char *enc, - void *out_arr, - int obj_sz, - int *out_num_objs) -{ - int len; - - len = base64_decode(enc, out_arr); - if (len < 0) { - return OS_EINVAL; - } - - *out_num_objs = len / obj_sz; - return 0; -} -/* -static int -ble_store_config_conf_set(int argc, char **argv, char *val) -{ - int rc; - - if (argc == 1) { - if (strcmp(argv[0], "our_sec") == 0) { - rc = ble_store_config_deserialize_arr( - val, - ble_store_config_our_secs, - sizeof *ble_store_config_our_secs, - &ble_store_config_num_our_secs); - printf("\nloading: %s %s rc=%d\n", *argv, val, rc); - return rc; - } else if (strcmp(argv[0], "peer_sec") == 0) { - rc = ble_store_config_deserialize_arr( - val, - ble_store_config_peer_secs, - sizeof *ble_store_config_peer_secs, - &ble_store_config_num_peer_secs); - printf("\nloading: %s %s rc=%d\n", *argv, val, rc); - return rc; - } else if (strcmp(argv[0], "cccd") == 0) { - rc = ble_store_config_deserialize_arr( - val, - ble_store_config_cccds, - sizeof *ble_store_config_cccds, - &ble_store_config_num_cccds); - printf("\nloading: %s %s rc=%d\n", *argv, val, rc); - return rc; - } - } - return OS_ENOENT; -} - -static int -ble_store_config_conf_export(void (*func)(char *name, char *val), - enum conf_export_tgt tgt) -{ - union { - char sec[BLE_STORE_CONFIG_SEC_SET_ENCODE_SZ]; - char cccd[BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ]; - } buf; - - ble_store_config_serialize_arr(ble_store_config_our_secs, - sizeof *ble_store_config_our_secs, - ble_store_config_num_our_secs, - buf.sec, - sizeof buf.sec); - func("ble_hs/our_sec", buf.sec); - - ble_store_config_serialize_arr(ble_store_config_peer_secs, - sizeof *ble_store_config_peer_secs, - ble_store_config_num_peer_secs, - buf.sec, - sizeof buf.sec); - func("ble_hs/peer_sec", buf.sec); - - ble_store_config_serialize_arr(ble_store_config_cccds, - sizeof *ble_store_config_cccds, - ble_store_config_num_cccds, - buf.cccd, - sizeof buf.cccd); - func("ble_hs/cccd", buf.cccd); - - return 0; -} -*/ -static int -ble_store_config_persist_sec_set(uint32_t setting_name, - const struct ble_store_value_sec *secs, - int num_secs) -{ - char buf[BLE_STORE_CONFIG_SEC_SET_ENCODE_SZ]; - int rc; - - ble_store_config_serialize_arr(secs, sizeof *secs, num_secs, - buf, sizeof buf); - - rc = ble_bond_nvs_save_entry(setting_name, buf); - if (rc != 0) { - return BLE_HS_ESTORE_FAIL; - } - - return 0; -} - -int -ble_store_config_persist_our_secs(void) -{ - int rc; - - rc = ble_store_config_persist_sec_set(our_sec, - ble_store_config_our_secs, - ble_store_config_num_our_secs); - if (rc != 0) { - return rc; - } - - return 0; -} - -int -ble_store_config_persist_peer_secs(void) -{ - int rc; - - rc = ble_store_config_persist_sec_set(peer_sec, - ble_store_config_peer_secs, - ble_store_config_num_peer_secs); - if (rc != 0) { - return rc; - } - - return 0; -} - -int -ble_store_config_persist_cccds(void) -{ - char buf[BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ]; - int rc; - - ble_store_config_serialize_arr(ble_store_config_cccds, - sizeof *ble_store_config_cccds, - ble_store_config_num_cccds, - buf, - sizeof buf); - - rc = ble_bond_nvs_save_entry(cccd, buf); - if (rc != 0) { - return BLE_HS_ESTORE_FAIL; - } - - return 0; -} - -void -ble_store_config_conf_init(void) -{ - uint32_t val_addr = 0; - int rc = 0; - - rc = ble_bond_nvs_get_entry(our_sec, &val_addr); - if (rc == 0) { - rc = ble_store_config_deserialize_arr( - (char*)val_addr, - ble_store_config_our_secs, - sizeof *ble_store_config_our_secs, - &ble_store_config_num_our_secs); - if (rc != 0) { - BLE_HS_LOG(ERROR, "our_sec restore error rc=%d\n", rc); - return; - } - - rc = ble_bond_nvs_get_entry(peer_sec, &val_addr); - if (rc == 0) { - rc = ble_store_config_deserialize_arr( - (char*)val_addr, - ble_store_config_peer_secs, - sizeof *ble_store_config_peer_secs, - &ble_store_config_num_peer_secs); - if (rc != 0) { - BLE_HS_LOG(ERROR, "peer_sec restore error rc=%d\n", rc); - return; - } - - } else { - /* If we have a security entry for our security but not a peer - * we should assume something wrong with the store so delete it. - */ - BLE_HS_LOG(ERROR, "peer info not found\n"); - ble_store_clear(); - return; - } - - rc = ble_bond_nvs_get_entry(cccd, &val_addr); - if (rc == 0) { - rc = ble_store_config_deserialize_arr( - (char*)val_addr, - ble_store_config_cccds, - sizeof *ble_store_config_cccds, - &ble_store_config_num_cccds); - if (rc != 0) { - BLE_HS_LOG(ERROR, "cccd restore error rc=%d\n", rc); - return; - } - } - } - - /* int rc; - - rc = conf_register(&ble_store_config_conf_handler); - SYSINIT_PANIC_ASSERT_MSG(rc == 0, - "Failed to register ble_store_config conf"); - */ -} - -#endif /* MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) */ -#endif /* ESP_PLATFORM */ \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/syscfg.yml deleted file mode 100644 index ff0689c6d..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/syscfg.yml +++ /dev/null @@ -1,27 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - BLE_STORE_CONFIG_PERSIST: - description: > - Whether to save data to sys/config, or just keep it in RAM. - value: 1 - BLE_STORE_SYSINIT_STAGE: - description: > - Sysinit stage for BLE host store. - value: 500 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/syscfg.yml deleted file mode 100644 index e72e8d529..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/syscfg.yml +++ /dev/null @@ -1,471 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - BLE_HOST: - description: 'Indicates that a BLE host is present.' - value: 1 - - BLE_HS_AUTO_START: - description: > - Causes the BLE host to automatically start during system - initialization. - value: 1 - - # Debug settings. - BLE_HS_DEBUG: - description: 'Enables extra runtime assertions.' - value: 0 - BLE_HS_PHONY_HCI_ACKS: - description: > - Rather than wait for HCI acknowledgements from a controller, the - host simulates incoming acks. Only recommended for test code - running in the simulator. - value: 0 - BLE_HS_REQUIRE_OS: - description: > - Specifies whether the host can depend on the kernel being present. - This should only be disabled for unit tests running in the - simulator. - value: 1 - - # Monitor interface settings - BLE_MONITOR_UART: - description: Enables monitor interface over UART - value: 0 - BLE_MONITOR_UART_DEV: - description: Monitor interface UART device - value: '"uart0"' - BLE_MONITOR_UART_BAUDRATE: - description: Baudrate for monitor interface UART - value: 1000000 - BLE_MONITOR_UART_BUFFER_SIZE: - description: > - Monitor interface ringbuffer size for UART. - This value should be a power of 2. - value: 64 - BLE_MONITOR_RTT: - description: Enables monitor interface over RTT - value: 0 - BLE_MONITOR_RTT_BUFFER_NAME: - description: Monitor interface upstream buffer name - value: '"btmonitor"' - BLE_MONITOR_RTT_BUFFER_SIZE: - description: Monitor interface upstream buffer size - value: 256 - BLE_MONITOR_RTT_BUFFERED: - description: > - Enables buffering when using monitor interface over RTT. The data - are written to RTT once complete packet is created in intermediate - buffer. This allows to skip complete packet if there is not enough - space in RTT buffer (e.g. there is no reader connected). If disabled, - monitor will simply block waiting for RTT to free space in buffer. - value: 1 - BLE_MONITOR_CONSOLE_BUFFER_SIZE: - description: > - Size of internal buffer for console output. Any line exceeding this - length value will be split. - value: 128 - - # L2CAP settings. - BLE_L2CAP_MAX_CHANS: - description: > - The number of L2CAP channels to allocate. The default value allows - for the signal, ATT, and SM channels for each connection. - value: '3*MYNEWT_VAL_BLE_MAX_CONNECTIONS' - BLE_L2CAP_SIG_MAX_PROCS: - description: > - The maximum number of concurrent L2CAP signal procedures. - value: 1 - BLE_L2CAP_JOIN_RX_FRAGS: - description: > - Whether to collapse incoming L2CAP fragments into a minimal set of - mbufs. - 1: Slower, more memory efficient. - 0: Faster, less memory efficient. - value: 1 - BLE_L2CAP_RX_FRAG_TIMEOUT: - description: > - Expiry time for incoming data packets (ms). If this much time - passes since the previous fragment was received, the connection is - terminated. A value of 0 means no timeout. - value: 30000 - BLE_L2CAP_COC_MAX_NUM: - description: > - Defines maximum number of LE Connection Oriented Channels channels. - When set to (0), LE COC is not compiled in. - value: 0 - BLE_L2CAP_COC_MPS: - description: > - Defines the MPS of L2CAP COC module. This is actually NimBLE's internal - L2CAP MTU. The default MPS size is chosen in a way, that the MPS plus - the required HCI and L2CAP headers fit into the smallest available - MSYS blocks. - value: 'MYNEWT_VAL_MSYS_1_BLOCK_SIZE-8' - - BLE_L2CAP_ENHANCED_COC: - description: > - Enables LE Enhanced CoC mode. - value: 0 - restrictions: - - '(BLE_L2CAP_COC_MAX_NUM > 0) && (BLE_VERSION >= 52) if 1' - - # Security manager settings. - BLE_SM_LEGACY: - description: 'Security manager legacy pairing.' - value: 1 - BLE_SM_SC: - description: 'Security manager secure connections (4.2).' - value: 0 - - BLE_SM_MAX_PROCS: - description: > - The maximum number of concurrent security manager procedures. - value: 1 - BLE_SM_IO_CAP: - description: > - The IO capabilities to report during pairing. Valid values are: - BLE_HS_IO_DISPLAY_ONLY - BLE_HS_IO_DISPLAY_YESNO - BLE_HS_IO_KEYBOARD_ONLY - BLE_HS_IO_NO_INPUT_OUTPUT - BLE_HS_IO_KEYBOARD_DISPLAY - value: 'BLE_HS_IO_NO_INPUT_OUTPUT' - BLE_SM_OOB_DATA_FLAG: - description: > - Whether the out-of-band pairing algorithm is advertised. (0/1) - value: 0 - BLE_SM_BONDING: - description: > - Enables bonding (persistence and restoration of secure links). (0/1) - value: 0 - BLE_SM_MITM: - description: > - Whether man-in-the-middle protection is advertised during - pairing. (0/1) - value: 0 - BLE_SM_KEYPRESS: - description: > - Whether keypress support is advertised during pairing. (0/1) - value: 0 - BLE_SM_OUR_KEY_DIST: - description: > - A bitmap indicating which keys to distribute during pairing. The - bits are defined as follows: - 0x01: BLE_SM_PAIR_KEY_DIST_ENC - 0x02: BLE_SM_PAIR_KEY_DIST_ID - 0x04: BLE_SM_PAIR_KEY_DIST_SIGN - 0x08: BLE_SM_PAIR_KEY_DIST_LINK - value: 0 - BLE_SM_THEIR_KEY_DIST: - description: > - A bitmap indicating which keys to accept during pairing. The - bits are defined as follows: - 0x01: BLE_SM_PAIR_KEY_DIST_ENC - 0x02: BLE_SM_PAIR_KEY_DIST_ID - 0x04: BLE_SM_PAIR_KEY_DIST_SIGN - 0x08: BLE_SM_PAIR_KEY_DIST_LINK - value: 0 - BLE_SM_SC_DEBUG_KEYS: - description: > - Enable SM debug mode. In this mode SM uses predefined DH key pair as - described in Core Specification 5.0, Vol. 3, Part H, 2.3.5.6.1. This - allows to decrypt air traffic easily and thus should be only used - for debugging. - value: 0 - - # GAP options. - BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE: - description: > - Controls the number of connection parameter updates that can be pending - simultaneously. Devices with many concurrent connections may need - to increase this value. - value: 1 - - # Supported GATT procedures. By default: - # o Notify and indicate are enabled; - # o All other procedures are enabled for centrals. - BLE_GATT_DISC_ALL_SVCS: - description: > - Enables the Discover All Primary Services GATT procedure. (0/1) - value: MYNEWT_VAL_BLE_ROLE_CENTRAL - BLE_GATT_DISC_SVC_UUID: - description: > - Enables the Discover Primary Services by Service UUID GATT - procedure. (0/1) - value: MYNEWT_VAL_BLE_ROLE_CENTRAL - BLE_GATT_FIND_INC_SVCS: - description: > - Enables the Find Included Services GATT procedure. (0/1) - value: MYNEWT_VAL_BLE_ROLE_CENTRAL - BLE_GATT_DISC_ALL_CHRS: - description: > - Enables the Discover All Characteristics of a Service GATT - procedure. (0/1) - value: MYNEWT_VAL_BLE_ROLE_CENTRAL - BLE_GATT_DISC_CHR_UUID: - description: > - Enables the Discover Characteristics by UUID GATT procedure. (0/1) - value: MYNEWT_VAL_BLE_ROLE_CENTRAL - BLE_GATT_DISC_ALL_DSCS: - description: > - Enables the Discover All Primary Services GATT procedure. (0/1) - value: MYNEWT_VAL_BLE_ROLE_CENTRAL - BLE_GATT_READ: - description: > - Enables the Read Characteristic Value GATT procedure. (0/1) - (0/1) - value: MYNEWT_VAL_BLE_ROLE_CENTRAL - BLE_GATT_READ_UUID: - description: > - Enables the Read Using Characteristic UUID GATT procedure. (0/1) - value: MYNEWT_VAL_BLE_ROLE_CENTRAL - BLE_GATT_READ_LONG: - description: > - Enables the Read Long Characteristic Values GATT procedure. (0/1) - value: MYNEWT_VAL_BLE_ROLE_CENTRAL - BLE_GATT_READ_MULT: - description: > - Enables the Read Multiple Characteristic Values GATT procedure. - (0/1) - value: MYNEWT_VAL_BLE_ROLE_CENTRAL - BLE_GATT_WRITE_NO_RSP: - description: > - Enables the Write Without Response GATT procedure. (0/1) - value: MYNEWT_VAL_BLE_ROLE_CENTRAL - BLE_GATT_SIGNED_WRITE: - description: > - Enables the Signed Write Without Response GATT procedure. (0/1) - value: MYNEWT_VAL_BLE_ROLE_CENTRAL - BLE_GATT_WRITE: - description: > - Enables the Write Characteristic Value GATT procedure. (0/1) - value: MYNEWT_VAL_BLE_ROLE_CENTRAL - BLE_GATT_WRITE_LONG: - description: > - Enables the Write Long Characteristic Values GATT procedure. (0/1) - value: MYNEWT_VAL_BLE_ROLE_CENTRAL - BLE_GATT_WRITE_RELIABLE: - description: > - Enables the Reliable Writes GATT procedure. (0/1) - value: MYNEWT_VAL_BLE_ROLE_CENTRAL - BLE_GATT_NOTIFY: - description: > - Enables sending and receiving of GATT notifications. (0/1) - value: 1 - BLE_GATT_INDICATE: - description: > - Enables sending and receiving of GATT indications. (0/1) - value: 1 - - # GATT options. - BLE_GATT_READ_MAX_ATTRS: - description: > - The maximum number of attributes that can be read with a single - GATT Read Multiple Characteristic Values procedure. (0/1) - value: 8 - BLE_GATT_WRITE_MAX_ATTRS: - description: > - The maximum number of attributes that can be written with a single - GATT Reliable Write procedure. (0/1) - value: 4 - BLE_GATT_MAX_PROCS: - description: > - The maximum number of concurrent client GATT procedures. (0/1) - value: 4 - BLE_GATT_RESUME_RATE: - description: > - The rate to periodically resume GATT procedures that have stalled - due to memory exhaustion. (0/1) Units are milliseconds. (0/1) - value: 1000 - - # Supported server ATT commands. (0/1) - BLE_ATT_SVR_FIND_INFO: - description: > - Enables processing of incoming Find Information Request ATT - commands. (0/1) - value: 1 - BLE_ATT_SVR_FIND_TYPE: - description: > - Enables processing of incoming Find By Type Value Request ATT - commands. (0/1) - value: 1 - BLE_ATT_SVR_READ_TYPE: - description: > - Enables processing of incoming Read By Type Request ATT commands. - (0/1) - value: 1 - BLE_ATT_SVR_READ: - description: > - Enables processing of incoming Read Request ATT commands. (0/1) - value: 1 - BLE_ATT_SVR_READ_BLOB: - description: > - Enables processing of incoming Read Blob Request ATT commands. - (0/1) - value: 1 - BLE_ATT_SVR_READ_MULT: - description: > - Enables processing of incoming Read Multiple Request ATT commands. - (0/1) - value: 1 - BLE_ATT_SVR_READ_GROUP_TYPE: - description: > - Enables processing of incoming Read by Group Type Request ATT - commands. (0/1) - value: 1 - BLE_ATT_SVR_WRITE: - description: > - Enables processing of incoming Write Request ATT commands. (0/1) - value: 1 - BLE_ATT_SVR_WRITE_NO_RSP: - description: > - Enables processing of incoming Write Command ATT commands. (0/1) - value: 1 - BLE_ATT_SVR_SIGNED_WRITE: - description: > - Enables processing of incoming Signed Write Command ATT commands. - (0/1) - value: 1 - BLE_ATT_SVR_QUEUED_WRITE: - description: > - Enables processing of incoming Prepare Write Request and Execute - Write Request ATT commands. (0/1) - value: 1 - BLE_ATT_SVR_NOTIFY: - description: > - Enables processing of incoming Handle Value Notification ATT - commands. (0/1) - value: 1 - BLE_ATT_SVR_INDICATE: - description: > - Enables processing of incoming Handle Value Indication ATT - commands. (0/1) - value: 1 - - # ATT options. - BLE_ATT_PREFERRED_MTU: - description: The preferred MTU to indicate in MTU exchange commands. - value: 256 - - BLE_ATT_SVR_MAX_PREP_ENTRIES: - description: > - A GATT server uses these when a peer performs a "write long - characteristic values" or "write long characteristic descriptors" - procedure. One of these resources is consumed each time a peer - sends a partial write. - value: 64 - - BLE_ATT_SVR_QUEUED_WRITE_TMO: - description: > - Expiry time for incoming ATT queued writes (ms). If this much - time passes since the previous prepared write was received, the - connection is terminated. A value of 0 means no timeout. - value: 30000 - - # Privacy options. - BLE_RPA_TIMEOUT: - description: > - The rate that new random addresses should be generated (seconds). - value: 300 - - # Store settings. - BLE_STORE_MAX_BONDS: - description: > - Maximum number of bonds that can be persisted. Note: increasing - this value may also require increasing the capacity of the - underlying storage mechanism. - value: 3 - BLE_STORE_MAX_CCCDS: - description: > - Maximum number of client characteristic configuration descriptors - that can be persisted. Note: increasing this value may also - require increasing the capacity of the underlying storage - mechanism. - - value: 8 - - BLE_MESH: - description: > - This option enables Bluetooth Mesh support. The specific - features that are available may depend on other features - that have been enabled in the stack, such as GATT support. - value: 0 - - # Flow control settings. - BLE_HS_FLOW_CTRL: - description: > - Whether to enable host-side flow control. This should only be - enabled in host-only setups (i.e., not combined-host-controller). - value: 0 - - BLE_HS_FLOW_CTRL_ITVL: - description: > - The interval, in milliseconds, that the host should provide - number-of-completed-packets updates to the controller. - value: 1000 - - BLE_HS_FLOW_CTRL_THRESH: - description: > - If the number of data buffers available to the controller falls to - this number, immediately send a number-of-completed-packets event. - The free buffer count is calculated as follows: - (total-acl-bufs - bufs-freed-since-last-num-completed-event). - value: 2 - - BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT: - description: > - If enabled, the host will immediately transmit a - host-number-of-completed-packets command whenever a connection - terminates. This behavior is not required by the standard, but is - a necessary workaround when interfacing with some controllers. - value: 0 - - BLE_HS_STOP_ON_SHUTDOWN: - description: > - Stops the Bluetooth host when the system shuts down. Stopping - entails aborting all GAP procedures and terminating open - connections. - value: 1 - - BLE_HS_STOP_ON_SHUTDOWN_TIMEOUT: - description: > - Timeout used in NimBLE's host stop procedure in ms. - value: 2000 - - BLE_HS_SYSINIT_STAGE: - description: > - Sysinit stage for the NimBLE host. - value: 200 - - ### Log settings. - - BLE_HS_LOG_MOD: - description: 'Numeric module ID to use for BLE host log messages.' - value: 4 - BLE_HS_LOG_LVL: - description: 'Minimum level for the BLE host log.' - value: 1 - -syscfg.logs: - BLE_HS_LOG: - module: MYNEWT_VAL(BLE_HS_LOG_MOD) - level: MYNEWT_VAL(BLE_HS_LOG_LVL) - -syscfg.vals.BLE_MESH: - BLE_SM_SC: 1 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/tools/log2smtest.rb b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/tools/log2smtest.rb deleted file mode 100644 index e253e69f0..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/tools/log2smtest.rb +++ /dev/null @@ -1,1029 +0,0 @@ -#!/usr/bin/env ruby - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -### This script converts a bletiny log into a security manager unit test. The -### input log must contain the connection establishment and complete pairing -### procedure. -### -### Arguments: None -### Stdin: bletiny log file - -$PAIR_ALG_STRINGS = { - 0 => [ 'BLE_SM_PAIR_ALG_JW', 'just works', 'jw' ], - 1 => [ 'BLE_SM_PAIR_ALG_PASSKEY', 'passkey entry', 'pk' ], - 2 => [ 'BLE_SM_PAIR_ALG_OOB', 'out of band', 'ob' ], - 3 => [ 'BLE_SM_PAIR_ALG_NUMCMP', 'numeric comparison', 'nc' ] -} - -$ADDR_TYPE_STRINGS = { - 0 => 'BLE_ADDR_TYPE_PUBLIC', - 1 => 'BLE_ADDR_TYPE_RANDOM', - 2 => 'BLE_ADDR_TYPE_RPA_PUB_DEFAULT', - 3 => 'BLE_ADDR_TYPE_RPA_RND_DEFAULT', -} - -$ACTION_STRINGS = { - 0 => 'BLE_SM_IOACT_NONE', - 1 => 'BLE_SM_IOACT_OOB', - 2 => 'BLE_SM_IOACT_INPUT', - 3 => 'BLE_SM_IOACT_DISP', - 4 => 'BLE_SM_IOACT_NUMCMP', -} - -$prev_idx = 0 -$ctxt = {} - -def test_case_name - type_str = $ctxt[:sc] ? "sc" : "lgcy" - init_str = $ctxt[:we_are_init] ? "us" : "peer" - alg_str = $PAIR_ALG_STRINGS[$ctxt[:pair_alg]][2] - iio_cap_str = "iio#{$ctxt[:pair_req][:io_cap]}" - rio_cap_str = "rio#{$ctxt[:pair_rsp][:io_cap]}" - bonding_str = "b#{$ctxt[:bonding] ? 1 : 0}" - iat_str = "iat#{$ctxt[:addrs][:init_type]}" - rat_str = "rat#{$ctxt[:addrs][:resp_type]}" - ikey_str = "ik#{$ctxt[:pair_rsp][:init_key_dist]}" - rkey_str = "rk#{$ctxt[:pair_rsp][:resp_key_dist]}" - - "ble_sm_" + - "#{type_str}_#{init_str}_#{alg_str}_#{iio_cap_str}_#{rio_cap_str}_" + - "#{bonding_str}_#{iat_str}_#{rat_str}_#{ikey_str}_#{rkey_str}" -end - -def test_case_comment -<<-eos -/** - * #{$ctxt[:sc] ? 'Secure connections' : 'Legacy'} pairing - * Master: #{$ctxt[:we_are_init] ? "us" : "peer"} - * Pair algorithm: #{$PAIR_ALG_STRINGS[$ctxt[:pair_alg]][1]} - * Initiator IO capabilities: #{$ctxt[:pair_req][:io_cap]} - * Responder IO capabilities: #{$ctxt[:pair_rsp][:io_cap]} - * Bonding: #{$ctxt[:bonding]} - * Initiator address type: #{$ADDR_TYPE_STRINGS[$ctxt[:addrs][:init_type]]} - * Responder address type: #{$ADDR_TYPE_STRINGS[$ctxt[:addrs][:resp_type]]} - * Initiator key distribution: #{$ctxt[:pair_rsp][:init_key_dist]} - * Responder key distribution: #{$ctxt[:pair_rsp][:resp_key_dist]} - */ -eos -end - -def to_hex_s(byte) - if byte.is_a?(String) - byte = s_to_i(byte) - end - - "0x#{byte.to_s(16).rjust(2, '0')}" -end - -# to_i(0) but interpret leading zeros as decimal. -def s_to_i(s) - if s[0..1] == "0x" - return s.to_i(16) - else - return s.to_i(10) - end -end - -def invalid_byte_line(msg, line) - str = "invalid byte line" - if msg != nil - str += ": #{msg}" - end - - str += "; line=#{line}" - - raise str -end - -def token_string_to_bytes(line, delim = ' ') - tokens = line.split(delim) - bytes = [] - tokens.each do |token| - begin - byte = token.to_i(16) - bytes << byte - rescue - invalid_byte_line("token=#{token}", line) - end - end - - return bytes -end - -def txrx_prefix(is_tx) - if is_tx - return "tx" - else - return "rx" - end -end - -def reqrsp_s(is_req) - reqrsp = nil - if is_req - return "req" - else - return "rsp" - end -end - -def bytes_to_arr_body(bytes, indent) - lines = [] - - idx = 0 - while idx < bytes.size - slice_len = nil - if bytes.size - idx >= 8 - slice_len = 8 - else - slice_len = bytes.size - idx - end - - slice = bytes[idx...(idx + slice_len)] - line = ' ' * indent + - slice.map{|b| to_hex_s(b)}.join(", ") + "," - lines << line - - idx += slice_len - end - - return lines.join("\n") << "\n" -end - -def bytes_to_arr(bytes, name, indent) - str = "#{' ' * indent}.#{name} = {\n" - str << bytes_to_arr_body(bytes, indent + 4) - str << "#{' ' * indent}}," - - return str -end - -def addr_string_to_bytes(addr_string) - token_string_to_bytes(addr_string, ':').reverse -end - -def parse_pair_cmd(line, is_req) - suffix = reqrsp_s(is_req) - re = %r{ - pair\s#{suffix}; - \s - conn=\d+ - \s - io_cap=(?\d+) - \s - oob_data_flag=(?\d+) - \s - authreq=(?0x[0-9a-f]+) - \s - mac_enc_key_size=(?\d+) - \s - init_key_dist=(?\d+) - \s - resp_key_dist=(?\d+) - }x - - m = re.match(line) - if m == nil - return nil - end - - cmd = {} - cmd[:io_cap] = s_to_i(m[:io_cap]) - cmd[:oob_data_flag] = s_to_i(m[:oob_data_flag]) - cmd[:authreq] = s_to_i(m[:authreq]) - cmd[:max_enc_key_size] = s_to_i(m[:max_enc_key_size]) - cmd[:init_key_dist] = s_to_i(m[:init_key_dist]) - cmd[:resp_key_dist] = s_to_i(m[:resp_key_dist]) - - return cmd -end - -def parse_privkey(line) - if !(line =~ /our privkey=(.+)/) - return nil - end - return token_string_to_bytes($1) -end - -def parse_public_key(line, is_tx) - prefix = txrx_prefix(is_tx) - if !(line =~ /#{prefix}ed sm command: public key; conn=\d+ x=(.+) y=(.+)/) - return nil - end - - pubkey = {} - pubkey[:x] = token_string_to_bytes($1) - pubkey[:y] = token_string_to_bytes($2) - - if pubkey[:x].size != 32 - raise "invalid public key: x length incorrect; line=#{line}" - end - - if pubkey[:y].size != 32 - raise "invalid public key: y length incorrect; line=#{line}" - end - - return pubkey -end - -def parse_confirm(line, is_tx) - prefix = txrx_prefix(is_tx) - if !(line =~ /#{prefix}ed sm command: confirm; conn=\d+ value=(.+)/) - return nil - end - - bytes = token_string_to_bytes($1) - if bytes.size != 16 - raise "invalid confirm line (length mismatch): #{line}" - end - - return { :value => bytes } -end - -def parse_random(line, is_tx) - prefix = txrx_prefix(is_tx) - if !(line =~ /#{prefix}ed sm command: random; conn=\d+ value=(.+)/) - return nil - end - - bytes = token_string_to_bytes($1) - if bytes.size != 16 - raise "invalid random line (length mismatch): #{line}" - end - - return { :value => bytes } -end - -def parse_stk(line) - if !(line =~ /^ out=(.+)/) - return nil - end - - bytes = token_string_to_bytes($1) - if bytes.size != 16 - raise "invalid stk line (length mismatch): #{line}" - end - - return bytes -end - -def parse_dhkey_check(line, is_tx) - prefix = txrx_prefix(is_tx) - if !(line =~ /#{prefix}ed sm command: dhkey check; conn=\d+ value=(.+)/) - return nil - end - - bytes = token_string_to_bytes($1) - if bytes.size != 16 - raise "invalid dhkey_check line (length mismatch): #{line}" - end - - return { :value => bytes } -end - -def parse_ltk(line) - if !(line =~ /persisting.+ltk=([^ ]+)/) - return nil - end - - bytes = $1.split(":") - if bytes.size != 16 - raise "invalid ltk line (length mismatch): exp=16 got=#{bytes.size} " + - "line=#{line}" - end - - return bytes -end - -def parse_enc_info(line, is_tx) - prefix = txrx_prefix(is_tx) - if !(line =~ /#{prefix}ed sm command: enc info; conn=\d+ ltk=(.+)/) - return nil - end - - bytes = token_string_to_bytes($1) - if bytes.size != 16 - raise "invalid enc info line (length mismatch): #{line}" - end - - return { :ltk => bytes } -end - -def parse_master_id(line, is_tx) - prefix = txrx_prefix(is_tx) - if !(line =~ /#{prefix}ed sm command: master id; conn=\d+ ediv=(.+) rand=(.+)/) - return nil - end - - return { - :ediv => s_to_i($1), - :rand => s_to_i($2), - } -end - -def parse_id_info(line, is_tx) - prefix = txrx_prefix(is_tx) - if !(line =~ /#{prefix}ed sm command: id info; conn=\d+ irk=(.+)/) - return nil - end - - bytes = token_string_to_bytes($1) - if bytes.size != 16 - raise "invalid id info line (length mismatch): #{line}" - end - - return { :irk => bytes } -end - -def parse_id_addr_info(line, is_tx) - prefix = txrx_prefix(is_tx) - if !(line =~ /#{prefix}ed sm command: id addr info; conn=\d+ addr_type=(\d+) addr=(.+)/) - return nil - end - - bytes = addr_string_to_bytes($2) - if bytes.size != 6 - raise "invalid id addr info line (length mismatch): #{line}" - end - - return { - :addr_type => s_to_i($1), - :addr => bytes, - } -end - -def parse_sign_info(line, is_tx) - prefix = txrx_prefix(is_tx) - if !(line =~ /#{prefix}ed sm command: sign info; conn=\d+ sig_key=(.+)/) - return nil - end - - bytes = token_string_to_bytes($1) - if bytes.size != 16 - raise "invalid sign info line (length mismatch): #{line}" - end - - return { - :sig_key => bytes, - } -end - -def parse_passkey_info(line) - passkey_info = {} - - case line - when /passkey action event; action=4 numcmp=(\d+)/ - passkey_info[:action] = 4 - passkey_info[:numcmp] = $1.to_i(10) - when /^b passkey conn=\d+ action=1 oob=(\S+)/ - passkey_info[:action] = 1 - passkey_info[:oob] = token_string_to_bytes($1, ':') - when /^b passkey conn=\d+ action=2 key=(\d+)/ - passkey_info[:action] = 2 - passkey_info[:key] = $1.to_i(10) - when /b passkey conn=\d+ action=3 key=(\d+)/ - passkey_info[:action] = 3 - passkey_info[:key] = $1.to_i(10) - else - return nil - end - - return passkey_info -end - -def parse_addrs(line) - if !(line =~ /our_ota_addr_type=(\d+) our_ota_addr=(\S+) our_id_addr_type=(\d+) our_id_addr=(\S+) peer_ota_addr_type=(\d+) peer_ota_addr=(\S+) peer_id_addr_type=(\d+) peer_id_addr=(\S+)/) - return nil - end - - our_ota_addr_bytes = addr_string_to_bytes($2) - our_id_addr_bytes = addr_string_to_bytes($4) - peer_ota_addr_bytes = addr_string_to_bytes($6) - peer_id_addr_bytes = addr_string_to_bytes($8) - - if $ctxt[:we_are_init] - init_id_bytes = our_id_addr_bytes - init_ota_bytes = our_ota_addr_bytes - resp_id_bytes = peer_id_addr_bytes - resp_ota_bytes = peer_ota_addr_bytes - init_addr_type = s_to_i($1) - resp_addr_type = s_to_i($5) - else - init_id_bytes = peer_id_addr_bytes - init_ota_bytes = peer_ota_addr_bytes - resp_id_bytes = our_id_addr_bytes - resp_ota_bytes = our_ota_addr_bytes - init_addr_type = s_to_i($5) - resp_addr_type = s_to_i($1) - end - - if init_id_bytes == init_ota_bytes - init_ota_bytes = [0] * 6 - end - if resp_id_bytes == resp_ota_bytes - resp_ota_bytes = [0] * 6 - end - - return { - :init_type => init_addr_type, - :resp_type => resp_addr_type, - :init_id_addr => init_id_bytes, - :resp_id_addr => resp_id_bytes, - :init_rpa => init_ota_bytes, - :resp_rpa => resp_ota_bytes, - } -end - -def detect_initiator(lines) - lines.each do |line| - if line =~ /txed sm command: pair req/ - $ctxt[:we_are_init] = true - elsif line =~ /txed sm command: pair rsp/ - $ctxt[:we_are_init] = false - end - end - - if $ctxt[:we_are_init] == nil - raise "could not detect which peer is the initiator" - end -end - -def pair_cmd_to_s(cmd, is_req) - suffix = reqrsp_s(is_req) - return <<-eos - .pair_#{suffix} = { - .io_cap = #{to_hex_s(cmd[:io_cap])}, - .oob_data_flag = #{to_hex_s(cmd[:oob_data_flag])}, - .authreq = #{to_hex_s(cmd[:authreq])}, - .max_enc_key_size = #{to_hex_s(cmd[:max_enc_key_size])}, - .init_key_dist = #{to_hex_s(cmd[:init_key_dist])}, - .resp_key_dist = #{to_hex_s(cmd[:resp_key_dist])}, - }, - eos -end - -def privkey_to_s(privkey) - return bytes_to_arr(privkey, "our_priv_key", 8) -end - -def public_key_to_s(public_key, is_req) - suffix = reqrsp_s(is_req) - return <<-eos - .public_key_#{suffix} = { -#{bytes_to_arr(public_key[:x], "x", 12)} -#{bytes_to_arr(public_key[:y], "y", 12)} - }, - eos -end - -def confirm_to_s(confirm, is_req, idx) - return <<-eos - .confirm_#{reqrsp_s(is_req)}[#{idx}] = { -#{bytes_to_arr(confirm[:value], "value", 12)} - }, - eos -end - -def random_to_s(random, is_req, idx) - return <<-eos - .random_#{reqrsp_s(is_req)}[#{idx}] = { -#{bytes_to_arr(random[:value], "value", 12)} - }, - eos -end - -def ltk_to_s(ltk) - return bytes_to_arr(ltk, "ltk", 8) -end - -def stk_to_s(stk) - return bytes_to_arr(stk, "stk", 8) -end - -def enc_info_to_s(id_info, is_req) - return <<-eos - .enc_info_#{reqrsp_s(is_req)} = { -#{bytes_to_arr(id_info[:ltk], "ltk", 12)} - }, - eos -end - -def master_id_to_s(master_id, is_req) - return <<-eos - .master_id_#{reqrsp_s(is_req)} = { - .ediv = 0x#{master_id[:ediv].to_s(16)}, - .rand_val = 0x#{master_id[:rand].to_s(16)}, - }, - eos -end - -def id_info_to_s(id_info, is_req) - return <<-eos - .id_info_#{reqrsp_s(is_req)} = { -#{bytes_to_arr(id_info[:irk], "irk", 12)} - }, - eos -end - -def id_addr_info_to_s(id_addr_info, is_req) - return <<-eos - .id_addr_info_#{reqrsp_s(is_req)} = { - .addr_type = #{id_addr_info[:addr_type]}, -#{bytes_to_arr(id_addr_info[:addr], "bd_addr", 12)} - }, - eos -end - -def sign_info_to_s(sign_info, is_req) - return <<-eos - .sign_info_#{reqrsp_s(is_req)} = { -#{bytes_to_arr(sign_info[:sig_key], "sig_key", 12)} - }, - eos -end - -def passkey_info_fill(passkey_info) - case passkey_info[:action] - # None - when 0 - $ctxt[:pair_alg] = 0 - $ctxt[:authenticated] = false - - # OOB - when 1 - $ctxt[:pair_alg] = 2 - $ctxt[:authenticated] = true - - # Input - when 2 - $ctxt[:pair_alg] = 1 - $ctxt[:authenticated] = true - - # Display - when 3 - $ctxt[:pair_alg] = 1 - $ctxt[:authenticated] = true - - # Numeric comparison - when 4 - $ctxt[:pair_alg] = 3 - $ctxt[:authenticated] = true - - else - raise "invalid MITM action: #{passkey_info[:action]}" - end -end - -def passkey_info_s - passkey_info = $ctxt[:passkey_info] - action_str = $ACTION_STRINGS[passkey_info[:action]] - - result = <<-eos - .pair_alg = #{$ctxt[:pair_alg]}, - .authenticated = #{$ctxt[:authenticated]}, - .passkey_info = { - .passkey = { - .action = #{action_str}, - eos - - if passkey_info[:key] != nil - result << <<-eos - .passkey = #{passkey_info[:key].to_i}, - eos - end - if passkey_info[:oob] != nil - result << <<-eos -#{bytes_to_arr(passkey_info[:oob], "oob", 16)} - eos - end - if passkey_info[:numcmp] != nil - result << <<-eos - .numcmp_accept = 1, - eos - end - - result << <<-eos - }, - eos - - if passkey_info[:numcmp] != nil - result << <<-eos - .exp_numcmp = #{passkey_info[:numcmp].to_i}, - eos - end - - result << <<-eos - }, - eos -end - -def addrs_to_s(addrs) - s = '' - - init_type = addrs[:init_type] - resp_type = addrs[:resp_type] - - if init_type != 0 - s += " .init_addr_type = #{$ADDR_TYPE_STRINGS[init_type]},\n" - end - s += bytes_to_arr(addrs[:init_id_addr], "init_id_addr", 8) + "\n" - if init_type >= 2 - s += bytes_to_arr(addrs[:init_rpa], "init_rpa", 8) + "\n" - end - - if resp_type != 0 - s += " .resp_addr_type = #{$ADDR_TYPE_STRINGS[resp_type]},\n" - end - s += bytes_to_arr(addrs[:resp_id_addr], "resp_id_addr", 8) + "\n" - if resp_type >= 2 - s += bytes_to_arr(addrs[:resp_rpa], "resp_rpa", 8) + "\n" - end - - return s -end - -def dhkey_check_to_s(dhkey_check, is_req) - return <<-eos - .dhkey_check_#{reqrsp_s(is_req)} = { -#{bytes_to_arr(dhkey_check[:value], "value", 12)} - }, - eos -end - -def extract_one(lines, ignore_prev = false) - if ignore_prev - start = 0 - else - start = $prev_idx - end - - (start...lines.size).each do |idx| - line = lines[idx] - result = yield(line) - if result != nil - if !ignore_prev - $prev_idx = idx - end - return result - end - end - - return nil -end - -def extract_pair_req(lines) - return extract_one(lines) {|line| parse_pair_cmd(line, true)} -end - -def extract_pair_rsp(lines) - return extract_one(lines) {|line| parse_pair_cmd(line, false)} -end - -def extract_privkey(lines) - return extract_one(lines) {|line| parse_privkey(line)} -end - -def extract_public_key_req(lines) - return extract_one(lines) do |line| - parse_public_key(line, $ctxt[:we_are_init]) - end -end - -def extract_public_key_rsp(lines) - return extract_one(lines) do |line| - parse_public_key(line, !$ctxt[:we_are_init]) - end -end - -def extract_confirm_req(lines) - return extract_one(lines) do |line| - parse_confirm(line, $ctxt[:we_are_init]) - end -end - -def extract_confirm_rsp(lines) - return extract_one(lines) do |line| - parse_confirm(line, !$ctxt[:we_are_init]) - end -end - -def extract_random_req(lines) - return extract_one(lines) do |line| - parse_random(line, $ctxt[:we_are_init]) - end -end - -def extract_random_rsp(lines) - return extract_one(lines) do |line| - parse_random(line, !$ctxt[:we_are_init]) - end -end - -def extract_confirm_random(lines) - confirm_reqs = [] - confirm_rsps = [] - random_reqs = [] - random_rsps = [] - - idx = 0 - loop do - confirm_req = extract_confirm_req(lines) - if confirm_req != nil - confirm_reqs << confirm_req - end - - confirm_rsp = extract_confirm_rsp(lines) - break if confirm_rsp == nil - if idx >= 20 - raise "too many confirm rsps (>20)" - end - confirm_rsps << confirm_rsp - - random_req = extract_random_req(lines) - break if random_req == nil - random_reqs << random_req - - random_rsp = extract_random_rsp(lines) - break if random_rsp == nil - random_rsps << random_rsp - - idx += 1 - end - - return confirm_reqs, confirm_rsps, random_reqs, random_rsps -end - -def extract_stk(lines) - return extract_one(lines, true) do |line| - parse_stk(line) - end -end - -def extract_dhkey_check_req(lines) - return extract_one(lines) do |line| - parse_dhkey_check(line, $ctxt[:we_are_init]) - end -end - -def extract_dhkey_check_rsp(lines) - return extract_one(lines) do |line| - parse_dhkey_check(line, !$ctxt[:we_are_init]) - end -end - -def extract_enc_info_req(lines) - return extract_one(lines) do |line| - parse_enc_info(line, !$ctxt[:we_are_init]) - end -end - -def extract_enc_info_rsp(lines) - return extract_one(lines) do |line| - parse_enc_info(line, $ctxt[:we_are_init]) - end -end - -def extract_master_id_req(lines) - return extract_one(lines) do |line| - parse_master_id(line, !$ctxt[:we_are_init]) - end -end - -def extract_master_id_rsp(lines) - return extract_one(lines) do |line| - parse_master_id(line, $ctxt[:we_are_init]) - end -end - -def extract_id_info_req(lines) - return extract_one(lines) do |line| - parse_id_info(line, !$ctxt[:we_are_init]) - end -end - -def extract_id_info_rsp(lines) - return extract_one(lines) do |line| - parse_id_info(line, $ctxt[:we_are_init]) - end -end - -def extract_id_addr_info_req(lines) - return extract_one(lines) do |line| - parse_id_addr_info(line, !$ctxt[:we_are_init]) - end -end - -def extract_id_addr_info_rsp(lines) - return extract_one(lines) do |line| - parse_id_addr_info(line, $ctxt[:we_are_init]) - end -end - -def extract_sign_info_req(lines) - return extract_one(lines) do |line| - parse_sign_info(line, !$ctxt[:we_are_init]) - end -end - -def extract_sign_info_rsp(lines) - return extract_one(lines) do |line| - parse_sign_info(line, $ctxt[:we_are_init]) - end -end - -def extract_ltk(lines) - return extract_one(lines) do |line| - parse_ltk(line) - end -end - -def extract_passkey_info(lines) - passkey_info = extract_one(lines, true) do |line| - parse_passkey_info(line) - end - - if passkey_info == nil - passkey_info = { :action => 0 } - end - - return passkey_info -end - -def extract_addrs(lines) - return extract_one(lines) do |line| - parse_addrs(line) - end -end - - -lines = STDIN.readlines - -detect_initiator(lines) -$ctxt[:pair_req] = extract_pair_req(lines) -$ctxt[:pair_rsp] = extract_pair_rsp(lines) -$ctxt[:privkey] = extract_privkey(lines) -$ctxt[:public_key_req] = extract_public_key_req(lines) -$ctxt[:public_key_rsp] = extract_public_key_rsp(lines) -$ctxt[:confirm_reqs], $ctxt[:confirm_rsps], $ctxt[:random_reqs], $ctxt[:random_rsps] = extract_confirm_random(lines) -$ctxt[:passkey_info] = extract_passkey_info(lines) -$ctxt[:dhkey_check_req] = extract_dhkey_check_req(lines) -$ctxt[:dhkey_check_rsp] = extract_dhkey_check_rsp(lines) -$ctxt[:enc_info_req] = extract_enc_info_req(lines) -$ctxt[:master_id_req] = extract_master_id_req(lines) -$ctxt[:id_info_req] = extract_id_info_req(lines) -$ctxt[:id_addr_info_req] = extract_id_addr_info_req(lines) -$ctxt[:sign_info_req] = extract_sign_info_req(lines) -$ctxt[:enc_info_rsp] = extract_enc_info_rsp(lines) -$ctxt[:master_id_rsp] = extract_master_id_rsp(lines) -$ctxt[:id_info_rsp] = extract_id_info_rsp(lines) -$ctxt[:id_addr_info_rsp] = extract_id_addr_info_rsp(lines) -$ctxt[:sign_info_rsp] = extract_sign_info_rsp(lines) -$ctxt[:addrs] = extract_addrs(lines) -$ctxt[:ltk] = extract_ltk(lines) -$ctxt[:stk] = extract_stk(lines) - -expected_confirm_rsps = nil -expected_random_reqs = nil -expected_random_rsps = nil -if $ctxt[:confirm_reqs].size == 0 - expected_confirm_rsps = 1 - expected_random_reqs = 1 - expected_random_rsps = 1 -else - expected_confirm_rsps = $ctxt[:confirm_reqs].size - expected_random_reqs = $ctxt[:random_reqs].size - expected_random_rsps = $ctxt[:random_rsps].size -end - -if $ctxt[:confirm_rsps].size != expected_confirm_rsps - raise "wrong number of confirm responses " + - "(exp=#{expected_confirm_rsps}; got=#{$ctxt[:confirm_rsps].size}" -end - -if $ctxt[:random_reqs].size != expected_random_reqs - raise "wrong number of random requests " + - "(exp=#{expected_random_reqs}; got=#{$ctxt[:random_reqs].size}" -end - -if $ctxt[:random_rsps].size != expected_random_rsps - raise "wrong number of random responses " + - "(exp=#{expected_random_rsps}; got=#{$ctxt[:random_rsps].size}" -end - -passkey_info_fill($ctxt[:passkey_info]) - -$ctxt[:sc] = $ctxt[:public_key_req] != nil -$ctxt[:bonding] = $ctxt[:pair_req][:authreq] & 1 == 1 && - $ctxt[:pair_rsp][:authreq] & 1 == 1 - -puts test_case_comment() -puts <<-eos -TEST_CASE(#{test_case_name()}) -{ - struct ble_sm_test_params params; - - params = (struct ble_sm_test_params) { -eos - -puts addrs_to_s($ctxt[:addrs]) - -puts pair_cmd_to_s($ctxt[:pair_req], true) -puts pair_cmd_to_s($ctxt[:pair_rsp], false) - -if $ctxt[:sc] - puts privkey_to_s($ctxt[:privkey]) - puts public_key_to_s($ctxt[:public_key_req], true) - puts public_key_to_s($ctxt[:public_key_req], false) -end - -$ctxt[:confirm_rsps].size.times do |i| - confirm_req = $ctxt[:confirm_reqs][i] - confirm_rsp = $ctxt[:confirm_rsps][i] - random_req = $ctxt[:random_reqs][i] - random_rsp = $ctxt[:random_rsps][i] - - if confirm_req != nil - puts confirm_to_s(confirm_req, true, i) - end - - puts confirm_to_s(confirm_rsp, false, i) - puts random_to_s(random_req, true, i) - puts random_to_s(random_rsp, false, i) -end - -if $ctxt[:sc] - puts dhkey_check_to_s($ctxt[:dhkey_check_req], true) - puts dhkey_check_to_s($ctxt[:dhkey_check_rsp], false) -end - -if $ctxt[:enc_info_req] != nil - puts enc_info_to_s($ctxt[:enc_info_req], true) -end -if $ctxt[:master_id_req] != nil - puts master_id_to_s($ctxt[:master_id_req], true) -end -if $ctxt[:id_info_req] != nil - puts id_info_to_s($ctxt[:id_info_req], true) -end -if $ctxt[:id_addr_info_req] != nil - puts id_addr_info_to_s($ctxt[:id_addr_info_req], true) -end -if $ctxt[:sign_info_req] != nil - puts sign_info_to_s($ctxt[:sign_info_req], true) -end -if $ctxt[:enc_info_rsp] != nil - puts enc_info_to_s($ctxt[:enc_info_rsp], false) -end -if $ctxt[:master_id_rsp] != nil - puts master_id_to_s($ctxt[:master_id_rsp], false) -end -if $ctxt[:id_info_rsp] != nil - puts id_info_to_s($ctxt[:id_info_rsp], false) -end -if $ctxt[:id_addr_info_rsp] != nil - puts id_addr_info_to_s($ctxt[:id_addr_info_rsp], false) -end -if $ctxt[:sign_info_rsp] != nil - puts sign_info_to_s($ctxt[:sign_info_rsp], false) -end -if $ctxt[:sc] - puts ltk_to_s($ctxt[:ltk]) -else - puts stk_to_s($ctxt[:stk]) -end -puts passkey_info_s() - -puts ' };' - -if $ctxt[:sc] - if $ctxt[:we_are_init] - puts ' ble_sm_test_util_us_sc_good(¶ms);' - else - puts ' ble_sm_test_util_peer_sc_good(¶ms);' - end -else - if $ctxt[:we_are_init] - puts ' ble_sm_test_util_us_lgcy_good(¶ms);' - else - puts ' ble_sm_test_util_peer_lgcy_good(¶ms);' - end -end -puts '}' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/pkg.yml deleted file mode 100644 index 0f5f3a5de..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/pkg.yml +++ /dev/null @@ -1,29 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/host/util -pkg.description: Supplementary utilities for the NimBLE host -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - -pkg.deps: - - nimble/host diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/syscfg.yml deleted file mode 100644 index 2cdd57468..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/syscfg.yml +++ /dev/null @@ -1,19 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/pkg.yml deleted file mode 100644 index 8b6058e11..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/pkg.yml +++ /dev/null @@ -1,30 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble -pkg.description: Generic functionality for the nimble Bluetooth Smart stack; used by both the controller and the host. -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - -pkg.deps: - - porting/npl/mynewt - - "@apache-mynewt-core/kernel/os" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/syscfg.yml deleted file mode 100644 index 537fd9ba5..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/syscfg.yml +++ /dev/null @@ -1,83 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - # Supported GAP roles. By default, all four roles are enabled. - BLE_ROLE_CENTRAL: - description: 'Enables the Central bluetooth role. (0/1)' - value: 1 - BLE_ROLE_PERIPHERAL: - description: 'Enables the Peripheral bluetooth role. (0/1)' - value: 1 - BLE_ROLE_BROADCASTER: - description: 'Enables the Broadcaster bluetooth role. (0/1)' - value: 1 - BLE_ROLE_OBSERVER: - description: 'Enables the Observer bluetooth role. (0/1)' - value: 1 - - BLE_MAX_CONNECTIONS: - description: 'The maximum number of concurrent connections.' - value: 1 - BLE_MAX_PERIODIC_SYNCS: - description: > - The maximum number of concurrent periodic syncs that can - be created - value: 1 - BLE_WHITELIST: - description: > - Enables the BLE whitelist for controlling who to connect to or - accept a connection from. (0/1) - value: 1 - BLE_MULTI_ADV_INSTANCES: - description: > - This is the number of multi-advertising instances. This is NOT the - total number of advertising instances. The total number of - advertising instances is this number plus 1 (assuming the device - supports advertising). - value: 0 - BLE_EXT_ADV: - description: > - This enables extended advertising feature. - value: 0 - BLE_PERIODIC_ADV: - description: > - This enables periodic advertising feature. - value: 0 - BLE_PERIODIC_ADV_SYNC_TRANSFER: - description: > - This enables Periodic Advertising Sync Transfer Feature. - value: 0 - - BLE_EXT_ADV_MAX_SIZE: - description: > - This allows to configure maximum size of advertising data and - scan response data used in LE Advertising Extensions. - Valid range 31-1650. - value: 31 - BLE_VERSION: - description: > - This allows to configure supported Bluetooth Core version. Some - features may not be available if version is too low. Version is - integer for easy comparison. - range: 50, 51, 52 - value: 50 - -# Allow periodic sync transfer only if 5.1 or higher -syscfg.restrictions: - - "'BLE_PERIODIC_ADV_SYNC_TRANSFER == 0' || 'BLE_VERSION >= 51'" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/pkg.yml deleted file mode 100644 index 2bc4ac293..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/pkg.yml +++ /dev/null @@ -1,45 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/transport -pkg.description: Meta-package for NimBLE HCI transport -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - -pkg.deps.'BLE_HCI_TRANSPORT == "builtin"': - - nimble/transport/ram - - nimble/controller - -pkg.deps.'BLE_HCI_TRANSPORT == "emspi"': - - nimble/transport/emspi - -pkg.deps.'BLE_HCI_TRANSPORT == "ram"': - - nimble/transport/ram - -pkg.deps.'BLE_HCI_TRANSPORT == "socket"': - - nimble/transport/socket - -pkg.deps.'BLE_HCI_TRANSPORT == "uart"': - - nimble/transport/uart - -pkg.deps.'BLE_HCI_TRANSPORT == "da1469x"': - - nimble/transport/da1469x diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/pkg.yml deleted file mode 100644 index bb8397bf3..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/pkg.yml +++ /dev/null @@ -1,36 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/transport/ram -pkg.description: XXX -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - ble - - bluetooth - -pkg.deps: - - "@apache-mynewt-core/kernel/os" - - nimble - -pkg.apis: - - ble_transport - -pkg.init: - ble_hci_ram_init: 'MYNEWT_VAL(BLE_TRANS_RAM_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/src/ble_hci_ram.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/src/ble_hci_ram.c deleted file mode 100644 index 9eaa1d866..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/src/ble_hci_ram.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include -#include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/porting/nimble/include/mem/mem.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/ble_hci_trans.h" -#include "../include/transport/ram/ble_hci_ram.h" - -static ble_hci_trans_rx_cmd_fn *ble_hci_ram_rx_cmd_hs_cb; -static void *ble_hci_ram_rx_cmd_hs_arg; - -static ble_hci_trans_rx_cmd_fn *ble_hci_ram_rx_cmd_ll_cb; -static void *ble_hci_ram_rx_cmd_ll_arg; - -static ble_hci_trans_rx_acl_fn *ble_hci_ram_rx_acl_hs_cb; -static void *ble_hci_ram_rx_acl_hs_arg; - -static ble_hci_trans_rx_acl_fn *ble_hci_ram_rx_acl_ll_cb; -static void *ble_hci_ram_rx_acl_ll_arg; - -static struct os_mempool ble_hci_ram_cmd_pool; -static os_membuf_t ble_hci_ram_cmd_buf[ - OS_MEMPOOL_SIZE(1, BLE_HCI_TRANS_CMD_SZ) -]; - -static struct os_mempool ble_hci_ram_evt_hi_pool; -static os_membuf_t ble_hci_ram_evt_hi_buf[ - OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT), - MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)) -]; - -static struct os_mempool ble_hci_ram_evt_lo_pool; -static os_membuf_t ble_hci_ram_evt_lo_buf[ - OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT), - MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)) -]; - -void -ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb, - void *cmd_arg, - ble_hci_trans_rx_acl_fn *acl_cb, - void *acl_arg) -{ - ble_hci_ram_rx_cmd_hs_cb = cmd_cb; - ble_hci_ram_rx_cmd_hs_arg = cmd_arg; - ble_hci_ram_rx_acl_hs_cb = acl_cb; - ble_hci_ram_rx_acl_hs_arg = acl_arg; -} - -void -ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb, - void *cmd_arg, - ble_hci_trans_rx_acl_fn *acl_cb, - void *acl_arg) -{ - ble_hci_ram_rx_cmd_ll_cb = cmd_cb; - ble_hci_ram_rx_cmd_ll_arg = cmd_arg; - ble_hci_ram_rx_acl_ll_cb = acl_cb; - ble_hci_ram_rx_acl_ll_arg = acl_arg; -} - -int -ble_hci_trans_hs_cmd_tx(uint8_t *cmd) -{ - int rc; - - assert(ble_hci_ram_rx_cmd_ll_cb != NULL); - - rc = ble_hci_ram_rx_cmd_ll_cb(cmd, ble_hci_ram_rx_cmd_ll_arg); - return rc; -} - -int -ble_hci_trans_ll_evt_tx(uint8_t *hci_ev) -{ - int rc; - - assert(ble_hci_ram_rx_cmd_hs_cb != NULL); - - rc = ble_hci_ram_rx_cmd_hs_cb(hci_ev, ble_hci_ram_rx_cmd_hs_arg); - return rc; -} - -int -ble_hci_trans_hs_acl_tx(struct os_mbuf *om) -{ - int rc; - - assert(ble_hci_ram_rx_acl_ll_cb != NULL); - - rc = ble_hci_ram_rx_acl_ll_cb(om, ble_hci_ram_rx_acl_ll_arg); - return rc; -} - -int -ble_hci_trans_ll_acl_tx(struct os_mbuf *om) -{ - int rc; - - assert(ble_hci_ram_rx_acl_hs_cb != NULL); - - rc = ble_hci_ram_rx_acl_hs_cb(om, ble_hci_ram_rx_acl_hs_arg); - return rc; -} - -uint8_t * -ble_hci_trans_buf_alloc(int type) -{ - uint8_t *buf; - - switch (type) { - case BLE_HCI_TRANS_BUF_CMD: - buf = os_memblock_get(&ble_hci_ram_cmd_pool); - break; - - case BLE_HCI_TRANS_BUF_EVT_HI: - buf = os_memblock_get(&ble_hci_ram_evt_hi_pool); - if (buf == NULL) { - /* If no high-priority event buffers remain, try to grab a - * low-priority one. - */ - buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); - } - break; - - case BLE_HCI_TRANS_BUF_EVT_LO: - buf = os_memblock_get(&ble_hci_ram_evt_lo_pool); - break; - - default: - assert(0); - buf = NULL; - } - - return buf; -} - -void -ble_hci_trans_buf_free(uint8_t *buf) -{ - int rc; - - /* XXX: this may look a bit odd, but the controller uses the command - * buffer to send back the command complete/status as an immediate - * response to the command. This was done to insure that the controller - * could always send back one of these events when a command was received. - * Thus, we check to see which pool the buffer came from so we can free - * it to the appropriate pool - */ - if (os_memblock_from(&ble_hci_ram_evt_hi_pool, buf)) { - rc = os_memblock_put(&ble_hci_ram_evt_hi_pool, buf); - assert(rc == 0); - } else if (os_memblock_from(&ble_hci_ram_evt_lo_pool, buf)) { - rc = os_memblock_put(&ble_hci_ram_evt_lo_pool, buf); - assert(rc == 0); - } else { - assert(os_memblock_from(&ble_hci_ram_cmd_pool, buf)); - rc = os_memblock_put(&ble_hci_ram_cmd_pool, buf); - assert(rc == 0); - } -} - -/** - * Unsupported; the RAM transport does not have a dedicated ACL data packet - * pool. - */ -int -ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg) -{ - return BLE_ERR_UNSUPPORTED; -} - -int -ble_hci_trans_reset(void) -{ - /* No work to do. All allocated buffers are owned by the host or - * controller, and they will get freed by their owners. - */ - return 0; -} - -void -ble_hci_ram_init(void) -{ - int rc; - - /* Ensure this function only gets called by sysinit. */ - SYSINIT_ASSERT_ACTIVE(); - - /* - * Create memory pool of HCI command buffers. NOTE: we currently dont - * allow this to be configured. The controller will only allow one - * outstanding command. We decided to keep this a pool in case we allow - * allow the controller to handle more than one outstanding command. - */ - rc = os_mempool_init(&ble_hci_ram_cmd_pool, - 1, - BLE_HCI_TRANS_CMD_SZ, - ble_hci_ram_cmd_buf, - "ble_hci_ram_cmd_pool"); - SYSINIT_PANIC_ASSERT(rc == 0); - - rc = os_mempool_init(&ble_hci_ram_evt_hi_pool, - MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT), - MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE), - ble_hci_ram_evt_hi_buf, - "ble_hci_ram_evt_hi_pool"); - SYSINIT_PANIC_ASSERT(rc == 0); - - rc = os_mempool_init(&ble_hci_ram_evt_lo_pool, - MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT), - MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE), - ble_hci_ram_evt_lo_buf, - "ble_hci_ram_evt_lo_pool"); - SYSINIT_PANIC_ASSERT(rc == 0); -} - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/syscfg.yml deleted file mode 100644 index 3b822fcc6..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/syscfg.yml +++ /dev/null @@ -1,48 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - BLE_HCI_EVT_HI_BUF_COUNT: - description: 'Number of high-priority event buffers.' - value: 2 - - BLE_HCI_EVT_LO_BUF_COUNT: - description: 'Number of low-priority event buffers.' - value: 8 - - BLE_HCI_EVT_BUF_SIZE: - description: 'Size of each event buffer, in bytes.' - value: 70 - - BLE_ACL_BUF_COUNT: - description: 'The number of ACL data buffers' - value: 4 - - BLE_ACL_BUF_SIZE: - description: > - This is the maximum size of the data portion of HCI ACL data - packets. It does not include the HCI data header (of 4 bytes). - value: 255 - - BLE_TRANS_RAM_SYSINIT_STAGE: - description: > - Sysinit stage for the RAM BLE transport. - value: 100 - -syscfg.vals.BLE_EXT_ADV: - BLE_HCI_EVT_BUF_SIZE: 257 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/syscfg.yml deleted file mode 100644 index 137d6e94f..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/syscfg.yml +++ /dev/null @@ -1,68 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - BLE_HCI_TRANSPORT: - description: > - Selects HCI transport to be included in build. - This has virtually the same effect as including package dependency - manually, but it allows to easily override HCI transport package in - application or target settings. - value: builtin - restrictions: $notnull - choices: - - builtin # Built-in NimBLE controller and RAM transport - - custom # Custom transport, has to be included manually by user - - ram # RAM transport - - uart # UART HCI H4 transport - - socket # Socket transport (for native builds) - - emspi # SPI transport for EM Microelectionic controllers - - da1469x # Dialog DA1469x integrated controller - -# Deprecated settings - BLE_HCI_TRANSPORT_NIMBLE_BUILTIN: - description: Use BLE_HCI_TRANSPORT instead. - value: 0 - deprecated: 1 - BLE_HCI_TRANSPORT_EMSPI: - description: Use BLE_HCI_TRANSPORT instead. - value: 0 - deprecated: 1 - BLE_HCI_TRANSPORT_RAM: - description: Use BLE_HCI_TRANSPORT instead. - value: 0 - deprecated: 1 - BLE_HCI_TRANSPORT_SOCKET: - description: Use BLE_HCI_TRANSPORT instead. - value: 0 - deprecated: 1 - BLE_HCI_TRANSPORT_UART: - description: Use BLE_HCI_TRANSPORT instead. - value: 0 - deprecated: 1 - -syscfg.vals.BLE_HCI_TRANSPORT_NIMBLE_BUILTIN: - BLE_HCI_TRANSPORT: builtin -syscfg.vals.BLE_HCI_TRANSPORT_RAM: - BLE_HCI_TRANSPORT: ram -syscfg.vals.BLE_HCI_TRANSPORT_UART: - BLE_HCI_TRANSPORT: uart -syscfg.vals.BLE_HCI_TRANSPORT_SOCKET: - BLE_HCI_TRANSPORT: socket -syscfg.vals.BLE_HCI_TRANSPORT_EMSPI: - BLE_HCI_TRANSPORT: emspi diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_npl.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl.h similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_npl.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl.h index 091cbea59..883832289 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_npl.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl.h @@ -23,6 +23,7 @@ #include #include #include +#include "nimconfig.h" #ifdef __cplusplus extern "C" { @@ -50,7 +51,7 @@ enum ble_npl_error { typedef enum ble_npl_error ble_npl_error_t; /* Include OS-specific definitions */ -#include "nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h" +#include "nimble/nimble_npl_os.h" /* * Generic @@ -163,7 +164,7 @@ void ble_npl_time_delay(ble_npl_time_t ticks); #if NIMBLE_CFG_CONTROLLER -void ble_npl_hw_set_isr(int irqn, void (*addr)(void)); +void ble_npl_hw_set_isr(int irqn, uint32_t addr); #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl_os.h similarity index 89% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl_os.h index 7321cd27a..1525d8228 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl_os.h @@ -37,13 +37,6 @@ extern "C" { #define BLE_NPL_TIME_FOREVER portMAX_DELAY -#ifndef ESP_PLATFORM -#define NIMBLE_CFG_CONTROLLER 1 -#define NIMBLE_EVT_QUEUE_SIZE 4 -#else -#define NIMBLE_EVT_QUEUE_SIZE 32 -#endif - /* This should be compatible with TickType_t */ typedef uint32_t ble_npl_time_t; typedef int32_t ble_npl_stime_t; @@ -59,11 +52,7 @@ struct ble_npl_eventq { }; struct ble_npl_callout { -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - esp_timer_handle_t handle; -#else TimerHandle_t handle; -#endif struct ble_npl_eventq *evq; struct ble_npl_event ev; }; @@ -99,7 +88,7 @@ ble_npl_get_current_task_id(void) static inline void ble_npl_eventq_init(struct ble_npl_eventq *evq) { - evq->q = xQueueCreate(NIMBLE_EVT_QUEUE_SIZE, sizeof(struct ble_npl_eventq *)); + evq->q = xQueueCreate(32, sizeof(struct ble_npl_eventq *)); } static inline void @@ -225,7 +214,6 @@ ble_npl_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq, { npl_freertos_callout_init(co, evq, ev_cb, ev_arg); } - static inline void ble_npl_callout_deinit(struct ble_npl_callout *co) { @@ -241,19 +229,23 @@ ble_npl_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) static inline void ble_npl_callout_stop(struct ble_npl_callout *co) { - npl_freertos_callout_stop(co); + xTimerStop(co->handle, portMAX_DELAY); } static inline bool ble_npl_callout_is_active(struct ble_npl_callout *co) { - return npl_freertos_callout_is_active(co); + /* Workaround for bug in xTimerIsTimerActive with FreeRTOS V10.2.0, fixed in V10.4.4 + * See: https://github.com/FreeRTOS/FreeRTOS-Kernel/pull/305 + * Sometimes xTimerIsTimerActive returns pdTRUE even though the timer has expired, so we double check. + */ + return xTimerIsTimerActive(co->handle) == pdTRUE && xTimerGetExpiryTime(co->handle) > xTaskGetTickCountFromISR(); } static inline ble_npl_time_t ble_npl_callout_get_ticks(struct ble_npl_callout *co) { - return npl_freertos_callout_get_ticks(co); + return xTimerGetExpiryTime(co->handle); } static inline uint32_t @@ -307,20 +299,13 @@ ble_npl_time_delay(ble_npl_time_t ticks) #if NIMBLE_CFG_CONTROLLER static inline void -ble_npl_hw_set_isr(int irqn, void (*addr)(void)) +ble_npl_hw_set_isr(int irqn, uint32_t addr) { npl_freertos_hw_set_isr(irqn, addr); } - -static inline bool -ble_npl_hw_is_in_critical(void) -{ - return (uxGetCriticalNestingDepth() > 0); -} #endif -#ifdef ESP_PLATFORM -extern portMUX_TYPE ble_port_mutex; +extern portMUX_TYPE ble_port_mutex; //critical section static inline uint32_t ble_npl_hw_enter_critical(void) @@ -333,24 +318,9 @@ static inline void ble_npl_hw_exit_critical(uint32_t ctx) { portEXIT_CRITICAL(&ble_port_mutex); -} -#else -static inline uint32_t -ble_npl_hw_enter_critical(void) -{ - vPortEnterCritical(); - return 0; } -static inline void -ble_npl_hw_exit_critical(uint32_t ctx) -{ - (void)ctx; - vPortExitCritical(); -} -#endif - #ifdef __cplusplus } #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_opt.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt.h similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_opt.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt.h index 7de55d668..f0e988b27 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_opt.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt.h @@ -25,7 +25,7 @@ extern "C" { #endif /* Include automatically-generated settings. */ -#include "nimble_opt_auto.h" +#include "nimble/nimble_opt_auto.h" #ifdef __cplusplus } diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_opt_auto.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt_auto.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_opt_auto.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt_auto.h index 056eb1b02..33a1e2aac 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_opt_auto.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt_auto.h @@ -20,7 +20,7 @@ #ifndef H_NIMBLE_OPT_AUTO_ #define H_NIMBLE_OPT_AUTO_ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "syscfg/syscfg.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/nimble/nimble_port.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port.h similarity index 88% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/nimble/nimble_port.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port.h index 68e7cdbb8..e8996a666 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/nimble/nimble_port.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port.h @@ -20,16 +20,11 @@ #ifndef _NIMBLE_PORT_H #define _NIMBLE_PORT_H -#include "nimble/nimble/include/nimble/nimble_npl.h" - -#ifdef ESP_PLATFORM +#include "nimble/nimble_npl.h" #include "nimconfig.h" + #define NIMBLE_CORE (CONFIG_BT_NIMBLE_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_NIMBLE_PINNED_TO_CORE : tskNO_AFFINITY) #define NIMBLE_STACK_SIZE CONFIG_BT_NIMBLE_TASK_STACK_SIZE -#else -#include "../syscfg/syscfg.h" -#define NIMBLE_HS_TASK_STACK_SIZE (CONFIG_BT_NIMBLE_TASK_STACK_SIZE / 4) -#endif #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port_freertos.h similarity index 85% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port_freertos.h index 94d75f5a5..ddeefc71c 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port_freertos.h @@ -20,7 +20,7 @@ #ifndef _NIMBLE_PORT_FREERTOS_H #define _NIMBLE_PORT_FREERTOS_H -#include "nimble/nimble/include/nimble/nimble_npl.h" +#include "nimble/nimble_npl.h" #ifdef __cplusplus extern "C" { @@ -28,10 +28,6 @@ extern "C" { void nimble_port_freertos_init(TaskFunction_t host_task_fn); void nimble_port_freertos_deinit(void); -#ifndef ESP_PLATFORM -UBaseType_t nimble_port_freertos_get_ll_hwm(void); -#endif -UBaseType_t nimble_port_freertos_get_hs_hwm(void); #ifdef __cplusplus } diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/npl_freertos.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/npl_freertos.h similarity index 91% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/npl_freertos.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/npl_freertos.h index 69942773f..2bf7b3d23 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/npl_freertos.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/npl_freertos.h @@ -57,12 +57,6 @@ void npl_freertos_callout_init(struct ble_npl_callout *co, void npl_freertos_callout_deinit(struct ble_npl_callout *co); -void npl_freertos_callout_stop(struct ble_npl_callout *co); - -bool npl_freertos_callout_is_active(struct ble_npl_callout *co); - -ble_npl_time_t npl_freertos_callout_get_ticks(struct ble_npl_callout *co); - ble_npl_error_t npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks); @@ -75,7 +69,7 @@ ble_npl_error_t npl_freertos_time_ms_to_ticks(uint32_t ms, ble_npl_error_t npl_freertos_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms); -void npl_freertos_hw_set_isr(int irqn, void (*addr)(void)); +void npl_freertos_hw_set_isr(int irqn, uint32_t addr); uint32_t npl_freertos_hw_enter_critical(void); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimconfig.h b/lib/libesp32_div/NimBLE-Arduino/src/nimconfig.h index b66993ef7..49b81ae29 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimconfig.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimconfig.h @@ -1,11 +1,6 @@ #pragma once -#ifdef ESP_PLATFORM #include "sdkconfig.h" -#else -#include "ext_nimble_config.h" -#endif - #include "nimconfig_rename.h" /*********************************************** @@ -21,17 +16,16 @@ /** @brief Un-comment to change default device name */ // #define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble" -/** @brief Un-comment to set the debug log messages level from the NimBLE host stack.\n - * Values: 0 = DEBUG, 1 = INFO, 2 = WARNING, 3 = ERROR, 4 = CRITICAL, 5+ = NONE\n +/** @brief Un-comment to see debug log messages from the NimBLE host * Uses approx. 32kB of flash memory. */ - // #define CONFIG_BT_NIMBLE_LOG_LEVEL 5 +// #define CONFIG_BT_NIMBLE_DEBUG /** @brief Un-comment to set the debug log messages level from the NimBLE CPP Wrapper.\n * Values: 0 = NONE, 1 = ERROR, 2 = WARNING, 3 = INFO, 4+ = DEBUG\n * Uses approx. 32kB of flash memory. */ - // #define NIMBLE_CPP_DEBUG_LEVEL 0 + // #define CONFIG_NIMBLE_CPP_DEBUG_LEVEL 0 /** @brief Un-comment to see NimBLE host return codes as text debug log messages. * Uses approx. 7kB of flash memory. @@ -162,10 +156,6 @@ #define CONFIG_BT_NIMBLE_RPA_TIMEOUT 900 #endif -#ifndef CONFIG_BT_NIMBLE_LOG_LEVEL -#define CONFIG_BT_NIMBLE_LOG_LEVEL 5 -#endif - /** @brief Set if CCCD's and bond data should be stored in NVS */ #define CONFIG_BT_NIMBLE_NVS_PERSIST 1 @@ -208,7 +198,6 @@ #define CONFIG_BT_ENABLED #endif -#ifdef ESP_PLATFORM #ifndef CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY #define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY #endif @@ -228,7 +217,6 @@ #if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) #define CONFIG_IDF_TARGET_ESP32 1 #endif -#endif /* Cannot use client without scan */ #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/endian.h b/lib/libesp32_div/NimBLE-Arduino/src/os/endian.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/endian.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/endian.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os.h b/lib/libesp32_div/NimBLE-Arduino/src/os/os.h similarity index 89% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/os.h index d4f6101b7..f7a7ef9c5 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/os/os.h @@ -34,8 +34,8 @@ extern "C" { #define max(a, b) ((a)>(b)?(a):(b)) #endif -#include "../syscfg/syscfg.h" -#include "nimble/nimble/include/nimble/nimble_npl.h" +#include "syscfg/syscfg.h" +#include "nimble/nimble_npl.h" #define OS_ALIGN(__n, __a) ( \ (((__n) & ((__a) - 1)) == 0) ? \ @@ -50,11 +50,11 @@ typedef uint32_t os_sr_t; #define OS_ASSERT_CRITICAL() assert(ble_npl_hw_is_in_critical()) /* Mynewt components (not abstracted in NPL) */ -#include "endian.h" -#include "queue.h" -#include "os_error.h" -#include "os_mbuf.h" -#include "os_mempool.h" +#include "os/endian.h" +#include "os/queue.h" +#include "os/os_error.h" +#include "os/os_mbuf.h" +#include "os/os_mempool.h" #ifdef __cplusplus } diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_cputime.h b/lib/libesp32_div/NimBLE-Arduino/src/os/os_cputime.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_cputime.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/os_cputime.h index 9002ca56a..20124b574 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_cputime.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/os/os_cputime.h @@ -31,9 +31,9 @@ extern "C" { #endif -#include "../syscfg/syscfg.h" -#include "../hal/hal_timer.h" -#include "os.h" +#include "syscfg/syscfg.h" +#include "hal/hal_timer.h" +#include "os/os.h" /* * NOTE: these definitions allow one to override the cputime frequency used. diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_error.h b/lib/libesp32_div/NimBLE-Arduino/src/os/os_error.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_error.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/os_error.h index f2213bdf9..15cc62282 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_error.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/os/os_error.h @@ -20,7 +20,7 @@ #ifndef H_OS_ERROR_ #define H_OS_ERROR_ -#include "os.h" +#include "os/os.h" enum os_error { OS_OK = 0, diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mbuf.h b/lib/libesp32_div/NimBLE-Arduino/src/os/os_mbuf.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mbuf.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/os_mbuf.h index 0775556d2..f3857fe46 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mbuf.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/os/os_mbuf.h @@ -29,7 +29,7 @@ #ifndef _OS_MBUF_H #define _OS_MBUF_H -#include "os.h" +#include "os/os.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mempool.h b/lib/libesp32_div/NimBLE-Arduino/src/os/os_mempool.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mempool.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/os_mempool.h index a01d34ded..251858742 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mempool.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/os/os_mempool.h @@ -29,8 +29,8 @@ #define _OS_MEMPOOL_H_ #include -#include "os.h" -#include "queue.h" +#include "os/os.h" +#include "os/queue.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_trace_api.h b/lib/libesp32_div/NimBLE-Arduino/src/os/os_trace_api.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_trace_api.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/os_trace_api.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/queue.h b/lib/libesp32_div/NimBLE-Arduino/src/os/queue.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/queue.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/queue.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/util.h b/lib/libesp32_div/NimBLE-Arduino/src/os/util.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/util.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/util.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.c b/lib/libesp32_div/NimBLE-Arduino/src/port/src/esp_nimble_mem.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.c rename to lib/libesp32_div/NimBLE-Arduino/src/port/src/esp_nimble_mem.c index 21e22fd26..a26e9b2f4 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/port/src/esp_nimble_mem.c @@ -18,12 +18,11 @@ * specific language governing permissions and limitations * under the License. */ -#ifdef ESP_PLATFORM #include "esp_attr.h" #include "esp_heap_caps.h" #include "nimconfig.h" -#include "../include/esp_nimble_mem.h" +#include "esp_nimble_mem.h" IRAM_ATTR void *nimble_platform_mem_malloc(size_t size) { @@ -55,4 +54,3 @@ IRAM_ATTR void nimble_platform_mem_free(void *ptr) { heap_caps_free(ptr); } -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/include/nimble/nimble_port.h b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/include/nimble/nimble_port.h new file mode 100644 index 000000000..fe9592764 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/include/nimble/nimble_port.h @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _NIMBLE_PORT_H +#define _NIMBLE_PORT_H + +#include "nimble/nimble_npl.h" + +#define NIMBLE_CORE (CONFIG_BT_NIMBLE_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_NIMBLE_PINNED_TO_CORE : tskNO_AFFINITY) +#define NIMBLE_STACK_SIZE CONFIG_BT_NIMBLE_TASK_STACK_SIZE + +#ifdef __cplusplus +extern "C" { +#endif + +void nimble_port_init(void); +void nimble_port_deinit(void); + +void nimble_port_run(void); +int nimble_port_stop(void); + +struct ble_npl_eventq *nimble_port_get_dflt_eventq(void); + +#if NIMBLE_CFG_CONTROLLER +void nimble_port_ll_task_func(void *arg); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _NIMBLE_PORT_H */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/endian.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/endian.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/endian.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/endian.c index c1b181dfe..2afd6a22e 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/endian.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/endian.c @@ -17,7 +17,7 @@ * under the License. */ -#include "../include/os/endian.h" +#include "os/endian.h" void put_le16(void *buf, uint16_t x) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/hal_timer.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/hal_timer.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/hal_timer.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/hal_timer.c index 93dfc8df3..14f746e85 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/hal_timer.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/hal_timer.c @@ -16,15 +16,14 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM - +#if 0 #include #include #include #include -#include "../include/os/os.h" -#include "nrf.h" -#include "../include/hal/hal_timer.h" +#include "os/os.h" +#include "nrfx.h" +#include "hal/hal_timer.h" /* IRQ prototype */ typedef void (*hal_timer_irq_handler_t)(void); @@ -487,7 +486,9 @@ hal_timer_init(int timer_num, void *cfg) /* Disable IRQ, set priority and set vector in table */ NVIC_DisableIRQ(irq_num); +#ifndef RIOT_VERSION NVIC_SetPriority(irq_num, (1 << __NVIC_PRIO_BITS) - 1); +#endif #if MYNEWT NVIC_SetVector(irq_num, (uint32_t)irq_isr); #else diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/mem.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/mem.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/mem.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/mem.c index bf1ae7ee3..256632333 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/mem.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/mem.c @@ -18,12 +18,9 @@ */ #include -#include "../include/os/os.h" -#include "../include/mem/mem.h" - -#ifdef ESP_PLATFORM -#include "nimble/esp_port/port/include/esp_nimble_mem.h" -#endif +#include "os/os.h" +#include "mem/mem.h" +#include "esp_nimble_mem.h" /** * Generic mempool allocation function. Used with basic and extended mempools. @@ -35,11 +32,7 @@ mem_malloc_mempool_gen(uint16_t num_blocks, uint32_t block_size, block_size = OS_ALIGN(block_size, OS_ALIGNMENT); if (num_blocks > 0) { -#ifdef ESP_PLATFORM *out_buf = nimble_platform_mem_malloc(OS_MEMPOOL_BYTES(num_blocks, block_size)); -#else - *out_buf = malloc(OS_MEMPOOL_BYTES(num_blocks, block_size)); -#endif if (*out_buf == NULL) { return OS_ENOMEM; } @@ -80,11 +73,7 @@ mem_malloc_mempool(struct os_mempool *mempool, uint16_t num_blocks, rc = os_mempool_init(mempool, num_blocks, block_size, buf, name); if (rc != 0) { -#ifdef ESP_PLATFORM nimble_platform_mem_free(buf); -#else - free(buf); -#endif return rc; } @@ -125,11 +114,7 @@ mem_malloc_mempool_ext(struct os_mempool_ext *mpe, uint16_t num_blocks, rc = os_mempool_ext_init(mpe, num_blocks, block_size, buf, name); if (rc != 0) { -#ifdef ESP_PLATFORM nimble_platform_mem_free(buf); -#else - free(buf); -#endif return rc; } @@ -176,11 +161,7 @@ mem_malloc_mbuf_pool(struct os_mempool *mempool, rc = os_mbuf_pool_init(mbuf_pool, mempool, block_size, num_blocks); if (rc != 0) { -#ifdef ESP_PLATFORM nimble_platform_mem_free(buf); -#else - free(buf); -#endif return rc; } diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/nimble_port.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/nimble_port.c similarity index 90% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/nimble_port.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/nimble_port.c index 98902ce60..5cd377582 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/nimble_port.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/nimble_port.c @@ -18,13 +18,12 @@ */ #include -#include "../include/os/os.h" -#include "../include/sysinit/sysinit.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/nimble/nimble_port.h" - +#include "os/os.h" +#include "sysinit/sysinit.h" +#include "host/ble_hs.h" +#include "nimble/nimble_port.h" #if NIMBLE_CFG_CONTROLLER -#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "controller/ble_ll.h" #endif #ifdef ESP_PLATFORM #include "esp_log.h" @@ -39,9 +38,12 @@ void nimble_port_init(void) { void os_msys_init(void); - + void ble_store_ram_init(void); #if NIMBLE_CFG_CONTROLLER void ble_hci_ram_init(void); +#endif +#ifdef ESP_PLATFORM + esp_log_level_set("NimBLE", LOG_LOCAL_LEVEL); #endif /* Initialize default event queue */ ble_npl_eventq_init(&g_eventq_dflt); @@ -50,13 +52,13 @@ nimble_port_init(void) ble_hs_init(); + /* XXX Need to have template for store */ + ble_store_ram_init(); + #if NIMBLE_CFG_CONTROLLER hal_timer_init(5, NULL); - os_cputime_init(32768); - ble_ll_init(); - ble_hci_ram_init(); #endif } diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime.c index 5c418c6a8..6c95c4f19 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime.c @@ -20,9 +20,9 @@ #include #include #include -#include "../include/syscfg/syscfg.h" -#include "../include/os/os_cputime.h" -#include "../include/hal/hal_timer.h" +#include "syscfg/syscfg.h" +#include "os/os_cputime.h" +#include "hal/hal_timer.h" #if defined(OS_CPUTIME_FREQ_HIGH) struct os_cputime_data g_os_cputime; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime_pwr2.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime_pwr2.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime_pwr2.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime_pwr2.c index 7a17aabc5..1567070ae 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime_pwr2.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime_pwr2.c @@ -17,7 +17,7 @@ * under the License. */ -#include "../include/os/os_cputime.h" +#include "os/os_cputime.h" /** * This module implements cputime functionality for timers for which: diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mbuf.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mbuf.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mbuf.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mbuf.c index 426bd47d8..ed18405b8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mbuf.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mbuf.c @@ -33,7 +33,7 @@ * */ -#include "../include/os/os.h" +#include "os/os.h" #include #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mempool.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mempool.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mempool.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mempool.c index a26099ef0..ba837e7d6 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mempool.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mempool.c @@ -17,7 +17,7 @@ * under the License. */ -#include "../include/os/os.h" +#include "os/os.h" #include #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_msys_init.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_msys_init.c similarity index 90% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_msys_init.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_msys_init.c index 180e18d60..905e7bd09 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_msys_init.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_msys_init.c @@ -18,12 +18,9 @@ */ #include -#include "../include/os/os.h" -#include "../include/mem/mem.h" - -#ifdef ESP_PLATFORM -#include "nimble/esp_port/port/include/esp_nimble_mem.h" -#endif +#include "os/os.h" +#include "mem/mem.h" +#include "esp_nimble_mem.h" #if MYNEWT_VAL(MSYS_1_BLOCK_COUNT) > 0 #define SYSINIT_MSYS_1_MEMBLOCK_SIZE \ @@ -31,11 +28,7 @@ #define SYSINIT_MSYS_1_MEMPOOL_SIZE \ OS_MEMPOOL_SIZE(MYNEWT_VAL(MSYS_1_BLOCK_COUNT), \ SYSINIT_MSYS_1_MEMBLOCK_SIZE) -#ifdef ESP_PLATFORM static os_membuf_t *os_msys_init_1_data; -#else -static os_membuf_t os_msys_init_1_data[SYSINIT_MSYS_1_MEMPOOL_SIZE]; -#endif static struct os_mbuf_pool os_msys_init_1_mbuf_pool; static struct os_mempool os_msys_init_1_mempool; #endif @@ -46,11 +39,7 @@ static struct os_mempool os_msys_init_1_mempool; #define SYSINIT_MSYS_2_MEMPOOL_SIZE \ OS_MEMPOOL_SIZE(MYNEWT_VAL(MSYS_2_BLOCK_COUNT), \ SYSINIT_MSYS_2_MEMBLOCK_SIZE) -#ifdef ESP_PLATFORM static os_membuf_t *os_msys_init_2_data; -#else -static os_membuf_t os_msys_init_2_data[SYSINIT_MSYS_2_MEMPOOL_SIZE]; -#endif static struct os_mbuf_pool os_msys_init_2_mbuf_pool; static struct os_mempool os_msys_init_2_mempool; #endif @@ -70,7 +59,6 @@ os_msys_init_once(void *data, struct os_mempool *mempool, assert(rc == 0); } -#ifdef ESP_PLATFORM int os_msys_buf_alloc(void) { @@ -105,7 +93,6 @@ os_msys_buf_free(void) #endif } -#endif void os_msys_init(void) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/nimble_port_freertos.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/nimble_port_freertos.c similarity index 61% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/nimble_port_freertos.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/nimble_port_freertos.c index a674e2a56..f0f80561f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/nimble_port_freertos.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/nimble_port_freertos.c @@ -20,24 +20,11 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "../../../nimble/include/nimble/nimble_port.h" +#include "nimble/nimble_port.h" #if NIMBLE_CFG_CONTROLLER -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#define NIMBLE_LL_TASK_STACK_SIZE (120) -#else -#define NIMBLE_LL_TASK_STACK_SIZE (90) -#endif -static StackType_t ll_xStack[ NIMBLE_LL_TASK_STACK_SIZE ]; -static StaticTask_t ll_xTaskBuffer; static TaskHandle_t ll_task_h; #endif - -#ifndef ESP_PLATFORM -static StackType_t hs_xStack[ NIMBLE_HS_TASK_STACK_SIZE ]; -static StaticTask_t hs_xTaskBuffer; -#endif - static TaskHandle_t host_task_h; void @@ -50,8 +37,8 @@ nimble_port_freertos_init(TaskFunction_t host_task_fn) * provided by NimBLE and in case of FreeRTOS it does not need to be wrapped * since it has compatible prototype. */ - ll_task_h = xTaskCreateStatic(nimble_port_ll_task_func, "ll", NIMBLE_LL_TASK_STACK_SIZE, - NULL, configMAX_PRIORITIES, ll_xStack, &ll_xTaskBuffer); + xTaskCreate(nimble_port_ll_task_func, "ll", configMINIMAL_STACK_SIZE + 400, + NULL, configMAX_PRIORITIES - 1, &ll_task_h); #endif /* @@ -59,13 +46,8 @@ nimble_port_freertos_init(TaskFunction_t host_task_fn) * have separate task for NimBLE host, but since something needs to handle * default queue it is just easier to make separate task which does this. */ -#ifdef ESP_PLATFORM xTaskCreatePinnedToCore(host_task_fn, "ble", NIMBLE_STACK_SIZE, - NULL, (configMAX_PRIORITIES - 4), &host_task_h, NIMBLE_CORE); -#else - host_task_h = xTaskCreateStatic(host_task_fn, "ble", NIMBLE_HS_TASK_STACK_SIZE, - NULL, (configMAX_PRIORITIES - 1), hs_xStack, &hs_xTaskBuffer); -#endif + NULL, (configMAX_PRIORITIES - 4), &host_task_h, NIMBLE_CORE); } void @@ -75,17 +57,3 @@ nimble_port_freertos_deinit(void) vTaskDelete(host_task_h); } } - -#if NIMBLE_CFG_CONTROLLER -UBaseType_t -nimble_port_freertos_get_ll_hwm(void) -{ - return uxTaskGetStackHighWaterMark(ll_task_h); -} -#endif - -UBaseType_t -nimble_port_freertos_get_hs_hwm(void) -{ - return uxTaskGetStackHighWaterMark(host_task_h); -} diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/npl_os_freertos.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/npl_os_freertos.c similarity index 67% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/npl_os_freertos.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/npl_os_freertos.c index 3f9c530e4..458180f83 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/npl_os_freertos.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/npl_os_freertos.c @@ -20,22 +20,11 @@ #include #include #include - -#include "nimble/nimble/include/nimble/nimble_npl.h" - -#ifdef ESP_PLATFORM +#include "nimble/nimble_npl.h" #include "freertos/portable.h" + portMUX_TYPE ble_port_mutex = portMUX_INITIALIZER_UNLOCKED; -#else -#include "nrf.h" - -static void *radio_isr_addr; -static void *rng_isr_addr; -static void *rtc0_isr_addr; -#endif - -#ifdef ESP_PLATFORM static inline bool in_isr(void) { @@ -43,50 +32,6 @@ in_isr(void) return xPortInIsrContext() != 0; } -#else -static inline bool -in_isr(void) -{ - /* XXX hw specific! */ - return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0; -} - -void -RADIO_IRQHandler(void) -{ - ((void (*)(void))radio_isr_addr)(); -} - -void -RNG_IRQHandler(void) -{ - ((void (*)(void))rng_isr_addr)(); -} - -void -RTC0_IRQHandler(void) -{ - ((void (*)(void))rtc0_isr_addr)(); -} - -/* This is called by NimBLE radio driver to set interrupt handlers */ -void -npl_freertos_hw_set_isr(int irqn, void (*addr)(void)) -{ - switch (irqn) { - case RADIO_IRQn: - radio_isr_addr = addr; - break; - case RNG_IRQn: - rng_isr_addr = addr; - break; - case RTC0_IRQn: - rtc0_isr_addr = addr; - break; - } -} -#endif - struct ble_npl_event * npl_freertos_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) { @@ -97,13 +42,9 @@ npl_freertos_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) if (in_isr()) { assert(tmo == 0); ret = xQueueReceiveFromISR(evq->q, &ev, &woken); -#ifdef ESP_PLATFORM if( woken == pdTRUE ) { portYIELD_FROM_ISR(); } -#else - portYIELD_FROM_ISR(woken); -#endif } else { ret = xQueueReceive(evq->q, &ev, tmo); } @@ -130,13 +71,9 @@ npl_freertos_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev) if (in_isr()) { ret = xQueueSendToBackFromISR(evq->q, &ev, &woken); -#ifdef ESP_PLATFORM if( woken == pdTRUE ) { portYIELD_FROM_ISR(); } -#else - portYIELD_FROM_ISR(woken); -#endif } else { ret = xQueueSendToBack(evq->q, &ev, portMAX_DELAY); } @@ -183,20 +120,13 @@ npl_freertos_eventq_remove(struct ble_npl_eventq *evq, woken |= woken2; } -#ifdef ESP_PLATFORM if( woken == pdTRUE ) { portYIELD_FROM_ISR(); } -#else - portYIELD_FROM_ISR(woken); -#endif } else { -#ifdef ESP_PLATFORM portMUX_TYPE ble_npl_mut = portMUX_INITIALIZER_UNLOCKED; portENTER_CRITICAL(&ble_npl_mut); -#else - vPortEnterCritical(); -#endif + count = uxQueueMessagesWaiting(evq->q); for (i = 0; i < count; i++) { ret = xQueueReceive(evq->q, &tmp_ev, 0); @@ -209,11 +139,8 @@ npl_freertos_eventq_remove(struct ble_npl_eventq *evq, ret = xQueueSendToBack(evq->q, &tmp_ev, 0); assert(ret == pdPASS); } -#ifdef ESP_PLATFORM + portEXIT_CRITICAL(&ble_npl_mut); -#else - vPortExitCritical(); -#endif } ev->queued = 0; @@ -329,13 +256,9 @@ npl_freertos_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout) if (in_isr()) { assert(timeout == 0); ret = xSemaphoreTakeFromISR(sem->handle, &woken); -#ifdef ESP_PLATFORM if( woken == pdTRUE ) { portYIELD_FROM_ISR(); } -#else - portYIELD_FROM_ISR(woken); -#endif } else { ret = xSemaphoreTake(sem->handle, timeout); } @@ -357,13 +280,10 @@ npl_freertos_sem_release(struct ble_npl_sem *sem) if (in_isr()) { ret = xSemaphoreGiveFromISR(sem->handle, &woken); -#ifdef ESP_PLATFORM + if( woken == pdTRUE ) { portYIELD_FROM_ISR(); } -#else - portYIELD_FROM_ISR(woken); -#endif } else { ret = xSemaphoreGive(sem->handle); } @@ -372,38 +292,6 @@ npl_freertos_sem_release(struct ble_npl_sem *sem) return BLE_NPL_OK; } - -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER -static void -ble_npl_event_fn_wrapper(void *arg) -{ - struct ble_npl_callout *co = (struct ble_npl_callout *)arg; - - if (co->evq) { - ble_npl_eventq_put(co->evq, &co->ev); - } else { - co->ev.fn(&co->ev); - } -} - -static -ble_npl_error_t esp_err_to_npl_error(esp_err_t err) -{ - switch(err) { - case ESP_ERR_INVALID_ARG: - return BLE_NPL_INVALID_PARAM; - - case ESP_ERR_INVALID_STATE: - return BLE_NPL_EINVAL; - - case ESP_OK: - return BLE_NPL_OK; - - default: - return BLE_NPL_ERROR; - } -} -#else static void os_callout_timer_cb(TimerHandle_t timer) { @@ -418,64 +306,31 @@ os_callout_timer_cb(TimerHandle_t timer) co->ev.fn(&co->ev); } } -#endif void npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq, - ble_npl_event_fn *ev_cb, void *ev_arg) + ble_npl_event_fn *ev_cb, void *ev_arg) { -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - co->ev.fn = ev_cb; - co->ev.arg = ev_arg; - co->evq = evq; - - esp_timer_create_args_t create_args = { - .callback = ble_npl_event_fn_wrapper, - .arg = co, - .name = "nimble_timer" - }; - - ESP_ERROR_CHECK(esp_timer_create(&create_args, &co->handle)); -#else if (co->handle == NULL) { co->handle = xTimerCreate("co", 1, pdFALSE, co, os_callout_timer_cb); } - co->evq = evq; ble_npl_event_init(&co->ev, ev_cb, ev_arg); -#endif } - void npl_freertos_callout_deinit(struct ble_npl_callout *co) { -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_timer_stop(co->handle)); - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_timer_delete(co->handle)); -#else if (co->handle) { xTimerDelete(co->handle, portMAX_DELAY); co->handle = NULL; } -#endif } ble_npl_error_t npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) { -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - esp_timer_stop(co->handle); - - return esp_err_to_npl_error(esp_timer_start_once(co->handle, ticks*1000)); -#else - BaseType_t woken1, woken2, woken3; - if (co->handle == NULL) { - co->handle = xTimerCreate("co", 1, pdFALSE, co, os_callout_timer_cb); - assert(co->handle); - } - if (ticks == 0) { ticks = 1; } @@ -484,13 +339,10 @@ npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) xTimerStopFromISR(co->handle, &woken1); xTimerChangePeriodFromISR(co->handle, ticks, &woken2); xTimerResetFromISR(co->handle, &woken3); -#ifdef ESP_PLATFORM + if( woken1 == pdTRUE || woken2 == pdTRUE || woken3 == pdTRUE) { portYIELD_FROM_ISR(); } -#else - portYIELD_FROM_ISR(woken1 || woken2 || woken3); -#endif } else { xTimerStop(co->handle, portMAX_DELAY); xTimerChangePeriod(co->handle, ticks, portMAX_DELAY); @@ -498,49 +350,6 @@ npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) } return BLE_NPL_OK; -#endif -} - -void -npl_freertos_callout_stop(struct ble_npl_callout *co) -{ -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - esp_timer_stop(co->handle); -#else - xTimerStop(co->handle, portMAX_DELAY); -#endif -} - -bool -npl_freertos_callout_is_active(struct ble_npl_callout *co) -{ -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - return esp_timer_is_active(co->handle); -#else - /* Workaround for bug in xTimerIsTimerActive with FreeRTOS V10.2.0, fixed in V10.4.4 - * See: https://github.com/FreeRTOS/FreeRTOS-Kernel/pull/305 - * Sometimes xTimerIsTimerActive returns pdTRUE even though the timer has expired, so we double check. - */ - return xTimerIsTimerActive(co->handle) == pdTRUE && xTimerGetExpiryTime(co->handle) > xTaskGetTickCountFromISR(); -#endif -} - -ble_npl_time_t -npl_freertos_callout_get_ticks(struct ble_npl_callout *co) -{ -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - /* Currently, esp_timer does not support an API which gets the expiry time for - * current timer. - * Returning 0 from here should not cause any effect. - * Drawback of this approach is that existing code to reset timer would be called - * more often (since the if condition to invoke reset timer would always succeed if - * timer is active). - */ - - return 0; -#else - return xTimerGetExpiryTime(co->handle); -#endif } ble_npl_time_t diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/include/services/ans/ble_svc_ans.h b/lib/libesp32_div/NimBLE-Arduino/src/services/ans/ble_svc_ans.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/include/services/ans/ble_svc_ans.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/ans/ble_svc_ans.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h b/lib/libesp32_div/NimBLE-Arduino/src/services/bas/ble_svc_bas.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/bas/ble_svc_bas.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h b/lib/libesp32_div/NimBLE-Arduino/src/services/gap/ble_svc_gap.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/gap/ble_svc_gap.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h b/lib/libesp32_div/NimBLE-Arduino/src/services/gatt/ble_svc_gatt.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/gatt/ble_svc_gatt.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/include/services/ias/ble_svc_ias.h b/lib/libesp32_div/NimBLE-Arduino/src/services/ias/ble_svc_ias.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/include/services/ias/ble_svc_ias.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/ias/ble_svc_ias.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/include/services/ipss/ble_svc_ipss.h b/lib/libesp32_div/NimBLE-Arduino/src/services/ipss/ble_svc_ipss.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/include/services/ipss/ble_svc_ipss.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/ipss/ble_svc_ipss.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/include/services/lls/ble_svc_lls.h b/lib/libesp32_div/NimBLE-Arduino/src/services/lls/ble_svc_lls.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/include/services/lls/ble_svc_lls.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/lls/ble_svc_lls.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/include/services/tps/ble_svc_tps.h b/lib/libesp32_div/NimBLE-Arduino/src/services/tps/ble_svc_tps.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/include/services/tps/ble_svc_tps.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/tps/ble_svc_tps.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/src/ble_hs_hci_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/src/ble_hs_hci_priv.h new file mode 100644 index 000000000..362f12cbd --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/src/ble_hs_hci_priv.h @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_HS_HCI_PRIV_ +#define H_BLE_HS_HCI_PRIV_ + +#include "nimble/hci_common.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_hs_conn; +struct os_mbuf; + +#define BLE_HS_HCI_LE_FEAT_ENCRYPTION (0x00000001) +#define BLE_HS_HCI_LE_FEAT_CONN_PARAM_REQUEST (0x00000002) +#define BLE_HS_HCI_LE_FEAT_EXT_REJECT (0x00000004) +#define BLE_HS_HCI_LE_FEAT_SLAVE_FEAT_EXCHANGE (0x00000008) +#define BLE_HS_HCI_LE_FEAT_PING (0x00000010) +#define BLE_HS_HCI_LE_FEAT_DATA_PACKET_LENGTH_EXT (0x00000020) +#define BLE_HS_HCI_LE_FEAT_LL_PRIVACY (0x00000040) +#define BLE_HS_HCI_LE_FEAT_EXT_SCANNER_FILTER_POLICIES (0x00000080) +#define BLE_HS_HCI_LE_FEAT_2M_PHY (0x00000100) +#define BLE_HS_HCI_LE_FEAT_STABLE_MOD_INDEX_TX (0x00000200) +#define BLE_HS_HCI_LE_FEAT_STABLE_MOD_INDEX_RX (0x00000400) +#define BLE_HS_HCI_LE_FEAT_CODED_PHY (0x00000800) +#define BLE_HS_HCI_LE_FEAT_EXT_ADV (0x00001000) +#define BLE_HS_HCI_LE_FEAT_PERIODIC_ADV (0x00002000) +#define BLE_HS_HCI_LE_FEAT_CSA2 (0x00004000) +#define BLE_HS_HCI_LE_FEAT_POWER_CLASS_1 (0x00008000) +#define BLE_HS_HCI_LE_FEAT_MIN_NUM_USED_CHAN (0x00010000) + +struct ble_hs_hci_ack { + int bha_status; /* A BLE_HS_E<...> error; NOT a naked HCI code. */ + const uint8_t *bha_params; + int bha_params_len; + uint16_t bha_opcode; + uint8_t bha_hci_handle; +}; + +#if MYNEWT_VAL(BLE_EXT_ADV) +struct ble_hs_hci_ext_scan_param { + uint8_t scan_type; + uint16_t scan_itvl; + uint16_t scan_window; +}; + +struct ble_hs_hci_ext_conn_params { + uint16_t scan_itvl; + uint16_t scan_window; + uint16_t conn_itvl; + uint16_t conn_windows; +}; + +#if MYNEWT_VAL(BLE_PERIODIC_ADV) +/* Periodic Advertising Parameters */ +struct hci_periodic_adv_params +{ + uint16_t min_interval; + uint16_t max_interval; + uint16_t properties; +}; +#endif +#endif + +extern uint16_t ble_hs_hci_avail_pkts; + +int ble_hs_hci_cmd_tx(uint16_t opcode, const void *cmd, uint8_t cmd_len, + void *rsp, uint8_t rsp_len); +void ble_hs_hci_init(void); +void ble_hs_hci_deinit(void); + +void ble_hs_hci_set_le_supported_feat(uint32_t feat); +uint32_t ble_hs_hci_get_le_supported_feat(void); +void ble_hs_hci_set_hci_version(uint8_t hci_version); +uint8_t ble_hs_hci_get_hci_version(void); + +#if MYNEWT_VAL(BLE_HS_PHONY_HCI_ACKS) +typedef int ble_hs_hci_phony_ack_fn(uint8_t *ack, int ack_buf_len); +void ble_hs_hci_set_phony_ack_cb(ble_hs_hci_phony_ack_fn *cb); +#endif + +int ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_pwr); +int ble_hs_hci_util_rand(void *dst, int len); +int ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi); +int ble_hs_hci_util_set_random_addr(const uint8_t *addr); +int ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om, + struct hci_data_hdr *out_hdr); +int ble_hs_hci_evt_process(const struct ble_hci_ev *ev); + +int ble_hs_hci_cmd_send_buf(uint16_t opcode, const void *buf, uint8_t buf_len); +int ble_hs_hci_set_buf_sz(uint16_t pktlen, uint16_t max_pkts); +void ble_hs_hci_add_avail_pkts(uint16_t delta); + +uint16_t ble_hs_hci_util_handle_pb_bc_join(uint16_t handle, uint8_t pb, + uint8_t bc); + +int ble_hs_hci_acl_tx_now(struct ble_hs_conn *conn, struct os_mbuf **om); +int ble_hs_hci_acl_tx(struct ble_hs_conn *conn, struct os_mbuf **om); + +int ble_hs_hci_frag_num_mbufs(void); +int ble_hs_hci_frag_num_mbufs_free(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/src/ble_sm_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/src/ble_sm_priv.h new file mode 100644 index 000000000..def0a32f5 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/src/ble_sm_priv.h @@ -0,0 +1,428 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_SM_PRIV_ +#define H_BLE_SM_PRIV_ + +#include +#include "syscfg/syscfg.h" +#include "os/queue.h" +#include "nimble/nimble_opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_gap_sec_state; +struct hci_le_lt_key_req; +struct hci_encrypt_change; + +#define BLE_SM_MTU 65 + +#define BLE_SM_OP_PAIR_REQ 0x01 +#define BLE_SM_OP_PAIR_RSP 0x02 +#define BLE_SM_OP_PAIR_CONFIRM 0x03 +#define BLE_SM_OP_PAIR_RANDOM 0x04 +#define BLE_SM_OP_PAIR_FAIL 0x05 +#define BLE_SM_OP_ENC_INFO 0x06 +#define BLE_SM_OP_MASTER_ID 0x07 +#define BLE_SM_OP_IDENTITY_INFO 0x08 +#define BLE_SM_OP_IDENTITY_ADDR_INFO 0x09 +#define BLE_SM_OP_SIGN_INFO 0x0a +#define BLE_SM_OP_SEC_REQ 0x0b +#define BLE_SM_OP_PAIR_PUBLIC_KEY 0x0c +#define BLE_SM_OP_PAIR_DHKEY_CHECK 0x0d +#define BLE_SM_OP_PAIR_KEYPRESS_NOTIFY 0x0e + +struct ble_sm_hdr { + uint8_t opcode; + uint8_t data[0]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x01/0x02 [req/rsp]) | 1 | + * | IO Capability | 1 | + * | OOB data flag | 1 | + * | AuthReq | 1 | + * | Maximum Encryption Key Size | 1 | + * | Initiator Key Distribution | 1 | + * | Responder Key Distribution | 1 | + */ + +struct ble_sm_pair_cmd { + uint8_t io_cap; + uint8_t oob_data_flag; + uint8_t authreq; + uint8_t max_enc_key_size; + uint8_t init_key_dist; + uint8_t resp_key_dist; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x03) | 1 | + * | Confirm Value | 16 | + */ + +struct ble_sm_pair_confirm { + uint8_t value[16]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x04) | 1 | + * | Random Value | 16 | + */ +struct ble_sm_pair_random { + uint8_t value[16]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x05) | 1 | + * | Reason | 1 | + */ +struct ble_sm_pair_fail { + uint8_t reason; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x06) | 1 | + * | ltk | 16 | + */ +struct ble_sm_enc_info { + uint8_t ltk[16]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x07) | 1 | + * | EDIV | 2 | + * | RAND | 8 | + */ +struct ble_sm_master_id { + uint16_t ediv; + uint64_t rand_val; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x08) | 1 | + * | irk | 16 | + */ +struct ble_sm_id_info { + uint8_t irk[16]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x09) | 1 | + * | addr_type | 1 | + * | address | 6 | + */ +struct ble_sm_id_addr_info { + uint8_t addr_type; + uint8_t bd_addr[6]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x0A) | 1 | + * | csrk | 16 | + */ +struct ble_sm_sign_info { + uint8_t sig_key[16]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x0B) | 1 | + * | authreq | 1 | + */ +struct ble_sm_sec_req { + uint8_t authreq; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x0c) | 1 | + * | Public Key X | 32 | + * | Public Key Y | 32 | + */ +struct ble_sm_public_key { + uint8_t x[32]; + uint8_t y[32]; +} __attribute__((packed)); + +/** + * | Parameter | Size (octets) | + * +------------------------------------+-------------------+ + * | (Code=0x0d) | 1 | + * | DHKey Check | 16 | + */ +struct ble_sm_dhkey_check { + uint8_t value[16]; +} __attribute__((packed)); + +#if NIMBLE_BLE_SM + +#define BLE_SM_PROC_STATE_NONE ((uint8_t)-1) + +#define BLE_SM_PROC_STATE_PAIR 0 +#define BLE_SM_PROC_STATE_CONFIRM 1 +#define BLE_SM_PROC_STATE_RANDOM 2 +#define BLE_SM_PROC_STATE_LTK_START 3 +#define BLE_SM_PROC_STATE_LTK_RESTORE 4 +#define BLE_SM_PROC_STATE_ENC_START 5 +#define BLE_SM_PROC_STATE_ENC_RESTORE 6 +#define BLE_SM_PROC_STATE_KEY_EXCH 7 +#define BLE_SM_PROC_STATE_SEC_REQ 8 +#define BLE_SM_PROC_STATE_PUBLIC_KEY 9 +#define BLE_SM_PROC_STATE_DHKEY_CHECK 10 +#define BLE_SM_PROC_STATE_CNT 11 + +#define BLE_SM_PROC_F_INITIATOR 0x01 +#define BLE_SM_PROC_F_IO_INJECTED 0x02 +#define BLE_SM_PROC_F_ADVANCE_ON_IO 0x04 +#define BLE_SM_PROC_F_AUTHENTICATED 0x08 +#define BLE_SM_PROC_F_SC 0x10 +#define BLE_SM_PROC_F_BONDING 0x20 + +#define BLE_SM_KE_F_ENC_INFO 0x01 +#define BLE_SM_KE_F_MASTER_ID 0x02 +#define BLE_SM_KE_F_ID_INFO 0x04 +#define BLE_SM_KE_F_ADDR_INFO 0x08 +#define BLE_SM_KE_F_SIGN_INFO 0x10 + +typedef uint8_t ble_sm_proc_flags; + +struct ble_sm_keys { + unsigned ltk_valid:1; + unsigned ediv_rand_valid:1; + unsigned irk_valid:1; + unsigned csrk_valid:1; + unsigned addr_valid:1; + uint16_t ediv; + uint64_t rand_val; + uint8_t addr_type; + uint8_t key_size; + uint8_t ltk[16]; /* Little endian. */ + uint8_t irk[16]; /* Little endian. */ + uint8_t csrk[16]; /* Little endian. */ + uint8_t addr[6]; /* Little endian. */ +}; + +struct ble_sm_proc { + STAILQ_ENTRY(ble_sm_proc) next; + + ble_npl_time_t exp_os_ticks; + ble_sm_proc_flags flags; + uint16_t conn_handle; + uint8_t pair_alg; + uint8_t state; + uint8_t rx_key_flags; + uint8_t key_size; + + uint8_t pair_req[sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_cmd)]; + uint8_t pair_rsp[sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_cmd)]; + uint8_t tk[16]; + uint8_t confirm_peer[16]; + uint8_t randm[16]; + uint8_t rands[16]; + uint8_t ltk[16]; /* Little endian. */ + struct ble_sm_keys our_keys; + struct ble_sm_keys peer_keys; + +#if MYNEWT_VAL(BLE_SM_SC) + /* Secure connections. */ + uint8_t passkey_bits_exchanged; + uint8_t ri; + struct ble_sm_public_key pub_key_peer; + uint8_t mackey[16]; + uint8_t dhkey[32]; + const struct ble_sm_sc_oob_data *oob_data_local; + const struct ble_sm_sc_oob_data *oob_data_remote; +#endif +}; + +struct ble_sm_result { + int app_status; + uint8_t sm_err; + struct ble_gap_passkey_params passkey_params; + void *state_arg; + unsigned execute : 1; + unsigned enc_cb : 1; + unsigned bonded : 1; + unsigned restore : 1; +}; + +#if MYNEWT_VAL(BLE_HS_DEBUG) +void ble_sm_dbg_set_next_pair_rand(uint8_t *next_pair_rand); +void ble_sm_dbg_set_next_ediv(uint16_t next_ediv); +void ble_sm_dbg_set_next_master_id_rand(uint64_t next_master_id_rand); +void ble_sm_dbg_set_next_ltk(uint8_t *next_ltk); +void ble_sm_dbg_set_next_csrk(uint8_t *next_csrk); +void ble_sm_dbg_set_sc_keys(uint8_t *pubkey, uint8_t *privkey); +#endif + +int ble_sm_num_procs(void); + +int ble_sm_alg_s1(const uint8_t *k, const uint8_t *r1, const uint8_t *r2, + uint8_t *out); +int ble_sm_alg_c1(const uint8_t *k, const uint8_t *r, + const uint8_t *preq, const uint8_t *pres, + uint8_t iat, uint8_t rat, + const uint8_t *ia, const uint8_t *ra, + uint8_t *out_enc_data); +int ble_sm_alg_f4(const uint8_t *u, const uint8_t *v, const uint8_t *x, + uint8_t z, uint8_t *out_enc_data); +int ble_sm_alg_g2(const uint8_t *u, const uint8_t *v, const uint8_t *x, + const uint8_t *y, uint32_t *passkey); +int ble_sm_alg_f5(const uint8_t *w, const uint8_t *n1, const uint8_t *n2, + uint8_t a1t, const uint8_t *a1, uint8_t a2t, + const uint8_t *a2, uint8_t *mackey, uint8_t *ltk); +int ble_sm_alg_f6(const uint8_t *w, const uint8_t *n1, const uint8_t *n2, + const uint8_t *r, const uint8_t *iocap, uint8_t a1t, + const uint8_t *a1, uint8_t a2t, const uint8_t *a2, + uint8_t *check); +int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, + const uint8_t *peer_pub_key_y, + const uint8_t *our_priv_key, uint8_t *out_dhkey); +int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv); +void ble_sm_alg_ecc_init(void); + +void ble_sm_enc_change_rx(const struct ble_hci_ev_enrypt_chg *ev); +void ble_sm_enc_key_refresh_rx(const struct ble_hci_ev_enc_key_refresh *ev); +int ble_sm_ltk_req_rx(const struct ble_hci_ev_le_subev_lt_key_req *ev); + +#if MYNEWT_VAL(BLE_SM_LEGACY) +int ble_sm_lgcy_io_action(struct ble_sm_proc *proc, uint8_t *action); +void ble_sm_lgcy_confirm_exec(struct ble_sm_proc *proc, + struct ble_sm_result *res); +void ble_sm_lgcy_random_exec(struct ble_sm_proc *proc, + struct ble_sm_result *res); +void ble_sm_lgcy_random_rx(struct ble_sm_proc *proc, + struct ble_sm_result *res); +#else +#define ble_sm_lgcy_io_action(proc, action) (BLE_HS_ENOTSUP) +#define ble_sm_lgcy_confirm_exec(proc, res) +#define ble_sm_lgcy_random_exec(proc, res) +#define ble_sm_lgcy_random_rx(proc, res) +#endif + +#if MYNEWT_VAL(BLE_SM_SC) +int ble_sm_sc_io_action(struct ble_sm_proc *proc, uint8_t *action); +void ble_sm_sc_confirm_exec(struct ble_sm_proc *proc, + struct ble_sm_result *res); +void ble_sm_sc_random_exec(struct ble_sm_proc *proc, + struct ble_sm_result *res); +void ble_sm_sc_random_rx(struct ble_sm_proc *proc, struct ble_sm_result *res); +void ble_sm_sc_public_key_exec(struct ble_sm_proc *proc, + struct ble_sm_result *res, + void *arg); +void ble_sm_sc_public_key_rx(uint16_t conn_handle, struct os_mbuf **rxom, + struct ble_sm_result *res); +void ble_sm_sc_dhkey_check_exec(struct ble_sm_proc *proc, + struct ble_sm_result *res, void *arg); +void ble_sm_sc_dhkey_check_rx(uint16_t conn_handle, struct os_mbuf **rxom, + struct ble_sm_result *res); +bool ble_sm_sc_oob_data_check(struct ble_sm_proc *proc, + bool oob_data_local_present, + bool oob_data_remote_present); +void ble_sm_sc_oob_confirm(struct ble_sm_proc *proc, struct ble_sm_result *res); +void ble_sm_sc_init(void); +#else +#define ble_sm_sc_io_action(proc, action) (BLE_HS_ENOTSUP) +#define ble_sm_sc_confirm_exec(proc, res) +#define ble_sm_sc_random_exec(proc, res) +#define ble_sm_sc_random_rx(proc, res) +#define ble_sm_sc_public_key_exec(proc, res, arg) +#define ble_sm_sc_public_key_rx(conn_handle, op, om, res) +#define ble_sm_sc_dhkey_check_exec(proc, res, arg) +#define ble_sm_sc_dhkey_check_rx(conn_handle, op, om, res) +#define ble_sm_sc_init() + +#endif + +struct ble_sm_proc *ble_sm_proc_find(uint16_t conn_handle, uint8_t state, + int is_initiator, + struct ble_sm_proc **out_prev); +int ble_sm_gen_pair_rand(uint8_t *pair_rand); +uint8_t *ble_sm_our_pair_rand(struct ble_sm_proc *proc); +uint8_t *ble_sm_peer_pair_rand(struct ble_sm_proc *proc); +int ble_sm_ioact_state(uint8_t action); +int ble_sm_proc_can_advance(struct ble_sm_proc *proc); +void ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res); +void ble_sm_confirm_advance(struct ble_sm_proc *proc); +void ble_sm_ia_ra(struct ble_sm_proc *proc, + uint8_t *out_iat, uint8_t *out_ia, + uint8_t *out_rat, uint8_t *out_ra); + +int32_t ble_sm_timer(void); +void ble_sm_connection_broken(uint16_t conn_handle); +int ble_sm_pair_initiate(uint16_t conn_handle); +int ble_sm_slave_initiate(uint16_t conn_handle); +int ble_sm_enc_initiate(uint16_t conn_handle, uint8_t key_size, + const uint8_t *ltk, uint16_t ediv, + uint64_t rand_val, int auth); +int ble_sm_alg_encrypt(const uint8_t *key, const uint8_t *plaintext, + uint8_t *enc_data); +int ble_sm_init(void); +#else + +#define ble_sm_enc_change_rx(evt) ((void)(evt)) +#define ble_sm_ltk_req_rx(evt) ((void)(evt)) +#define ble_sm_enc_key_refresh_rx(evt) ((void)(evt)) + +#define ble_sm_timer() BLE_HS_FOREVER +#define ble_sm_connection_broken(conn_handle) +#define ble_sm_pair_initiate(conn_handle) BLE_HS_ENOTSUP +#define ble_sm_slave_initiate(conn_handle) BLE_HS_ENOTSUP +#define ble_sm_enc_initiate(conn_handle, keysize, ltk, ediv, rand_val, auth) \ + BLE_HS_ENOTSUP + +#define ble_sm_init() 0 + +#define ble_sm_alg_encrypt(key, plaintext, enc_data) \ + BLE_HS_ENOTSUP + +#endif + +struct ble_l2cap_chan *ble_sm_create_chan(uint16_t handle); +void *ble_sm_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom); +int ble_sm_tx(uint16_t conn_handle, struct os_mbuf *txom); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/stats/stats.h b/lib/libesp32_div/NimBLE-Arduino/src/stats/stats.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/stats/stats.h rename to lib/libesp32_div/NimBLE-Arduino/src/stats/stats.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/include/store/config/ble_store_config.h b/lib/libesp32_div/NimBLE-Arduino/src/store/config/ble_store_config.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/include/store/config/ble_store_config.h rename to lib/libesp32_div/NimBLE-Arduino/src/store/config/ble_store_config.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/store/ram/ble_store_ram.h b/lib/libesp32_div/NimBLE-Arduino/src/store/ram/ble_store_ram.h new file mode 100644 index 000000000..842fb5f3f --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/store/ram/ble_store_ram.h @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_STORE_RAM_ +#define H_BLE_STORE_RAM_ + +#ifdef __cplusplus +extern "C" { +#endif + +union ble_store_key; +union ble_store_value; + +int ble_store_ram_read(int obj_type, const union ble_store_key *key, + union ble_store_value *value); +int ble_store_ram_write(int obj_type, const union ble_store_value *val); +int ble_store_ram_delete(int obj_type, const union ble_store_key *key); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/syscfg/syscfg.h b/lib/libesp32_div/NimBLE-Arduino/src/syscfg/syscfg.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/syscfg/syscfg.h rename to lib/libesp32_div/NimBLE-Arduino/src/syscfg/syscfg.h index 3cb2b14ba..8dccca5eb 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/syscfg/syscfg.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/syscfg/syscfg.h @@ -6,12 +6,8 @@ #define H_MYNEWT_SYSCFG_ #ifdef ESP_PLATFORM -#include "nimble/esp_port/port/include/esp_nimble_cfg.h" +#include "esp_nimble_cfg.h" #else -#include "ext_nimble_config.h" -#endif - -#if 0 /** * This macro exists to ensure code includes this header when needed. If code diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/sysflash/sysflash.h b/lib/libesp32_div/NimBLE-Arduino/src/sysflash/sysflash.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/sysflash/sysflash.h rename to lib/libesp32_div/NimBLE-Arduino/src/sysflash/sysflash.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/sysinit/sysinit.h b/lib/libesp32_div/NimBLE-Arduino/src/sysinit/sysinit.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/sysinit/sysinit.h rename to lib/libesp32_div/NimBLE-Arduino/src/sysinit/sysinit.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/AUTHORS b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/AUTHORS new file mode 100644 index 000000000..0a8e9f806 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/AUTHORS @@ -0,0 +1,15 @@ +Architect: +Rafael Misoczki + +Open Source Maintainer: +Constanza Heath +Rafael Misoczki + +Contributors: +Constanza Heath +Rafael Misoczki +Flavio Santes +Jarkko Sakkinen +Chris Morrison +Marti Bolivar +Colin Ian King diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/LICENSE b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/LICENSE new file mode 100644 index 000000000..2e1db516a --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/LICENSE @@ -0,0 +1,61 @@ + +================================================================================ + + TinyCrypt Cryptographic Library + +================================================================================ + + Copyright (c) 2017, Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + - Neither the name of the Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +================================================================================ +Copyright (c) 2014, Kenneth MacKay +All rights reserved. + +https://github.com/kmackay/micro-ecc + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +================================================================================ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/README b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/README new file mode 100644 index 000000000..fb52c196a --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/README @@ -0,0 +1,71 @@ + +================================================================================ + + TinyCrypt Cryptographic Library + +================================================================================ + + Copyright (c) 2017, Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + - Neither the name of the Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +================================================================================ + +Overview: + +The TinyCrypt Library provides an implementation for constrained devices of a +minimal set of standard cryptography primitives. + +Please, ***SEE THE DOCUMENTATION*** folder for more information on the supported +cryptographic primitives and the limitations of TinyCrypt library. For usage, +security and technicalities, please see the corresponding header file of each +cryptographic primitive. + +================================================================================ + +Organization: + +/lib: C source code of the cryptographic primitives. +/lib/include/tinycrypt: C header files of the cryptographic primitives. +/tests: Test vectors of the cryptographic primitives. +/doc: Documentation of TinyCrypt. + +================================================================================ + +Building: + +1) In Makefile.conf set: + - CFLAGS for compiler flags. + - CC for compiler. + - ENABLE_TESTS for enabling (true) or disabling (false) tests compilation. +2) In lib/Makefile select the primitives required by your project. +3) In tests/Makefile select the corresponding tests of the selected primitives. +4) make +5) run tests in tests/ + +================================================================================ + diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/VERSION b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/VERSION new file mode 100644 index 000000000..a45be4627 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/VERSION @@ -0,0 +1 @@ +0.2.8 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/aes.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/aes.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/aes.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/aes.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/cbc_mode.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cbc_mode.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/cbc_mode.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cbc_mode.h index a53318eed..4a837fd01 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/cbc_mode.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cbc_mode.h @@ -74,7 +74,7 @@ #ifndef __TC_CBC_MODE_H__ #define __TC_CBC_MODE_H__ -#include "aes.h" +#include #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ccm_mode.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ccm_mode.h index c22ac08d4..69c798e2f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ccm_mode.h @@ -74,7 +74,7 @@ #ifndef __TC_CCM_MODE_H__ #define __TC_CCM_MODE_H__ -#include "aes.h" +#include #include #ifdef __cplusplus diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cmac_mode.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cmac_mode.h index 327097026..f44b0a53c 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cmac_mode.h @@ -97,7 +97,7 @@ #ifndef __TC_CMAC_MODE_H__ #define __TC_CMAC_MODE_H__ -#include "aes.h" +#include #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/constants.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/constants.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/constants.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/constants.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_mode.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_mode.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_mode.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_mode.h index e2da5b43b..dc221f9ee 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_mode.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_mode.h @@ -67,8 +67,8 @@ #ifndef __TC_CTR_MODE_H__ #define __TC_CTR_MODE_H__ -#include "aes.h" -#include "constants.h" +#include +#include #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_prng.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_prng.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_prng.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_prng.h index bff7f9726..9be06dbb1 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_prng.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_prng.h @@ -59,7 +59,7 @@ #ifndef __TC_CTR_PRNG_H__ #define __TC_CTR_PRNG_H__ -#include "aes.h" +#include #define TC_CTR_PRNG_RESEED_REQ -1 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst new file mode 100644 index 000000000..356c099a0 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst @@ -0,0 +1,352 @@ + +TinyCrypt Cryptographic Library +############################### +Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + +Overview +******** +The TinyCrypt Library provides an implementation for targeting constrained devices +with a minimal set of standard cryptography primitives, as listed below. To better +serve applications targeting constrained devices, TinyCrypt implementations differ +from the standard specifications (see the Important Remarks section for some +important differences). Certain cryptographic primitives depend on other +primitives, as mentioned in the list below. + +Aside from the Important Remarks section below, valuable information on the usage, +security and technicalities of each cryptographic primitive are found in the +corresponding header file. + +* SHA-256: + + * Type of primitive: Hash function. + * Standard Specification: NIST FIPS PUB 180-4. + * Requires: -- + +* HMAC-SHA256: + + * Type of primitive: Message authentication code. + * Standard Specification: RFC 2104. + * Requires: SHA-256 + +* HMAC-PRNG: + + * Type of primitive: Pseudo-random number generator (256-bit strength). + * Standard Specification: NIST SP 800-90A. + * Requires: SHA-256 and HMAC-SHA256. + +* AES-128: + + * Type of primitive: Block cipher. + * Standard Specification: NIST FIPS PUB 197. + * Requires: -- + +* AES-CBC mode: + + * Type of primitive: Encryption mode of operation. + * Standard Specification: NIST SP 800-38A. + * Requires: AES-128. + +* AES-CTR mode: + + * Type of primitive: Encryption mode of operation. + * Standard Specification: NIST SP 800-38A. + * Requires: AES-128. + +* AES-CMAC mode: + + * Type of primitive: Message authentication code. + * Standard Specification: NIST SP 800-38B. + * Requires: AES-128. + +* AES-CCM mode: + + * Type of primitive: Authenticated encryption. + * Standard Specification: NIST SP 800-38C. + * Requires: AES-128. + +* CTR-PRNG: + + * Type of primitive: Pseudo-random number generator (128-bit strength). + * Standard Specification: NIST SP 800-90A. + * Requires: AES-128. + +* ECC-DH: + + * Type of primitive: Key exchange based on curve NIST p-256. + * Standard Specification: RFC 6090. + * Requires: ECC auxiliary functions (ecc.h/c). + +* ECC-DSA: + + * Type of primitive: Digital signature based on curve NIST p-256. + * Standard Specification: RFC 6090. + * Requires: ECC auxiliary functions (ecc.h/c). + +Design Goals +************ + +* Minimize the code size of each cryptographic primitive. This means minimize + the size of a platform-independent implementation, as presented in TinyCrypt. + Note that various applications may require further features, optimizations with + respect to other metrics and countermeasures for particular threats. These + peculiarities would increase the code size and thus are not considered here. + +* Minimize the dependencies among the cryptographic primitives. This means + that it is unnecessary to build and allocate object code for more primitives + than the ones strictly required by the intended application. In other words, + one can select and compile only the primitives required by the application. + + +Important Remarks +***************** + +The cryptographic implementations in TinyCrypt library have some limitations. +Some of these limitations are inherent to the cryptographic primitives +themselves, while others are specific to TinyCrypt. These limitations were accepted +in order to meet its design goals (in special, minimal code size) and to better +serve applications targeting constrained devices in general. Some of these +limitations are discussed in-depth below. + +General Remarks +*************** + +* TinyCrypt does **not** intend to be fully side-channel resistant. Due to the + variety of side-channel attacks, many of them only relevant to certain + platforms. In this sense, instead of penalizing all library users with + side-channel countermeasures such as increasing the overall code size, + TinyCrypt only implements certain generic timing-attack countermeasures. + +Specific Remarks +**************** + +* SHA-256: + + * The number of bits_hashed in the state is not checked for overflow. Note + however that this will only be a problem if you intend to hash more than + 2^64 bits, which is an extremely large window. + +* HMAC: + + * The HMAC verification process is assumed to be performed by the application. + This compares the computed tag with some given tag. + Note that conventional memory-comparison methods (such as memcmp function) + might be vulnerable to timing attacks; thus be sure to use a constant-time + memory comparison function (such as compare_constant_time + function provided in lib/utils.c). + + * The tc_hmac_final function, responsible for computing the message tag, + cleans the state context before exiting. Thus, applications do not need to + clean the TCHmacState_t ctx after calling tc_hmac_final. This should not + be changed in future versions of the library as there are applications + currently relying on this good-practice/feature of TinyCrypt. + +* HMAC-PRNG: + + * Before using HMAC-PRNG, you *must* find an entropy source to produce a seed. + PRNGs only stretch the seed into a seemingly random output of arbitrary + length. The security of the output is exactly equal to the + unpredictability of the seed. + + * NIST SP 800-90A requires three items as seed material in the initialization + step: entropy seed, personalization and a nonce (which is not implemented). + TinyCrypt requires the personalization byte array and automatically creates + the entropy seed using a mandatory call to the re-seed function. + +* AES-128: + + * The current implementation does not support other key-lengths (such as 256 + bits). Note that if you need AES-256, it doesn't sound as though your + application is running in a constrained environment. AES-256 requires keys + twice the size as for AES-128, and the key schedule is 40% larger. + +* CTR mode: + + * The AES-CTR mode limits the size of a data message they encrypt to 2^32 + blocks. If you need to encrypt larger data sets, your application would + need to replace the key after 2^32 block encryptions. + +* CTR-PRNG: + + * Before using CTR-PRNG, you *must* find an entropy source to produce a seed. + PRNGs only stretch the seed into a seemingly random output of arbitrary + length. The security of the output is exactly equal to the + unpredictability of the seed. + +* CBC mode: + + * TinyCrypt CBC decryption assumes that the iv and the ciphertext are + contiguous (as produced by TinyCrypt CBC encryption). This allows for a + very efficient decryption algorithm that would not otherwise be possible. + +* CMAC mode: + + * AES128-CMAC mode of operation offers 64 bits of security against collision + attacks. Note however that an external attacker cannot generate the tags + him/herself without knowing the MAC key. In this sense, to attack the + collision property of AES128-CMAC, an external attacker would need the + cooperation of the legal user to produce an exponentially high number of + tags (e.g. 2^64) to finally be able to look for collisions and benefit + from them. As an extra precaution, the current implementation allows to at + most 2^48 calls to tc_cmac_update function before re-calling tc_cmac_setup + (allowing a new key to be set), as suggested in Appendix B of SP 800-38B. + +* CCM mode: + + * There are a few tradeoffs for the selection of the parameters of CCM mode. + In special, there is a tradeoff between the maximum number of invocations + of CCM under a given key and the maximum payload length for those + invocations. Both things are related to the parameter 'q' of CCM mode. The + maximum number of invocations of CCM under a given key is determined by + the nonce size, which is: 15-q bytes. The maximum payload length for those + invocations is defined as 2^(8q) bytes. + + To achieve minimal code size, TinyCrypt CCM implementation fixes q = 2, + which is a quite reasonable choice for constrained applications. The + implications of this choice are: + + The nonce size is: 13 bytes. + + The maximum payload length is: 2^16 bytes = 65 KB. + + The mac size parameter is an important parameter to estimate the security + against collision attacks (that aim at finding different messages that + produce the same authentication tag). TinyCrypt CCM implementation + accepts any even integer between 4 and 16, as suggested in SP 800-38C. + + * TinyCrypt CCM implementation accepts associated data of any length between + 0 and (2^16 - 2^8) = 65280 bytes. + + * TinyCrypt CCM implementation accepts: + + * Both non-empty payload and associated data (it encrypts and + authenticates the payload and only authenticates the associated data); + + * Non-empty payload and empty associated data (it encrypts and + authenticates the payload); + + * Non-empty associated data and empty payload (it degenerates to an + authentication-only mode on the associated data). + + * RFC-3610, which also specifies CCM, presents a few relevant security + suggestions, such as: it is recommended for most applications to use a + mac size greater than 8. Besides, it is emphasized that the usage of the + same nonce for two different messages which are encrypted with the same + key obviously destroys the security properties of CCM mode. + +* ECC-DH and ECC-DSA: + + * TinyCrypt ECC implementation is based on micro-ecc (see + https://github.com/kmackay/micro-ecc). In the original micro-ecc + documentation, there is an important remark about the way integers are + represented: + + "Integer representation: To reduce code size, all large integers are + represented using little-endian words - so the least significant word is + first. You can use the 'ecc_bytes2native()' and 'ecc_native2bytes()' + functions to convert between the native integer representation and the + standardized octet representation." + + Note that the assumed bit layout is: {31, 30, ..., 0}, {63, 62, ..., 32}, + {95, 94, ..., 64}, {127, 126, ..., 96} for a very-long-integer (vli) + consisting of 4 unsigned integers (as an example). + + * A cryptographically-secure PRNG function must be set (using uECC_set_rng()) + before calling uECC_make_key() or uECC_sign(). + +Examples of Applications +************************ +It is possible to do useful cryptography with only the given small set of +primitives. With this list of primitives it becomes feasible to support a range +of cryptography usages: + + * Measurement of code, data structures, and other digital artifacts (SHA256); + + * Generate commitments (SHA256); + + * Construct keys (HMAC-SHA256); + + * Extract entropy from strings containing some randomness (HMAC-SHA256); + + * Construct random mappings (HMAC-SHA256); + + * Construct nonces and challenges (HMAC-PRNG, CTR-PRNG); + + * Authenticate using a shared secret (HMAC-SHA256); + + * Create an authenticated, replay-protected session (HMAC-SHA256 + HMAC-PRNG); + + * Authenticated encryption (AES-128 + AES-CCM); + + * Key-exchange (EC-DH); + + * Digital signature (EC-DSA); + +Test Vectors +************ + +The library provides a test program for each cryptographic primitive (see 'test' +folder). Besides illustrating how to use the primitives, these tests evaluate +the correctness of the implementations by checking the results against +well-known publicly validated test vectors. + +For the case of the HMAC-PRNG, due to the necessity of performing an extensive +battery test to produce meaningful conclusions, we suggest the user to evaluate +the unpredictability of the implementation by using the NIST Statistical Test +Suite (see References). + +For the case of the EC-DH and EC-DSA implementations, most of the test vectors +were obtained from the site of the NIST Cryptographic Algorithm Validation +Program (CAVP), see References. + +References +********** + +* `NIST FIPS PUB 180-4 (SHA-256)`_ + +.. _NIST FIPS PUB 180-4 (SHA-256): + http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf + +* `NIST FIPS PUB 197 (AES-128)`_ + +.. _NIST FIPS PUB 197 (AES-128): + http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + +* `NIST SP800-90A (HMAC-PRNG)`_ + +.. _NIST SP800-90A (HMAC-PRNG): + http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf + +* `NIST SP 800-38A (AES-CBC and AES-CTR)`_ + +.. _NIST SP 800-38A (AES-CBC and AES-CTR): + http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + +* `NIST SP 800-38B (AES-CMAC)`_ + +.. _NIST SP 800-38B (AES-CMAC): + http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf + +* `NIST SP 800-38C (AES-CCM)`_ + +.. _NIST SP 800-38C (AES-CCM): + http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + +* `NIST Statistical Test Suite (useful for testing HMAC-PRNG)`_ + +.. _NIST Statistical Test Suite (useful for testing HMAC-PRNG): + http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html + +* `NIST Cryptographic Algorithm Validation Program (CAVP) site`_ + +.. _NIST Cryptographic Algorithm Validation Program (CAVP) site: + http://csrc.nist.gov/groups/STM/cavp/ + +* `RFC 2104 (HMAC-SHA256)`_ + +.. _RFC 2104 (HMAC-SHA256): + https://www.ietf.org/rfc/rfc2104.txt + +* `RFC 6090 (ECC-DH and ECC-DSA)`_ + +.. _RFC 6090 (ECC-DH and ECC-DSA): + https://www.ietf.org/rfc/rfc6090.txt diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dh.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dh.h index 930e9162e..b828e195d 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dh.h @@ -69,7 +69,7 @@ #ifndef __TC_ECC_DH_H__ #define __TC_ECC_DH_H__ -#include "ecc.h" +#include #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dsa.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dsa.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dsa.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dsa.h index 8cb421b7a..aca00bc95 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dsa.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dsa.h @@ -78,7 +78,7 @@ #ifndef __TC_ECC_DSA_H__ #define __TC_ECC_DSA_H__ -#include "ecc.h" +#include #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_platform_specific.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_platform_specific.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_platform_specific.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_platform_specific.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/hmac.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/hmac.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac.h index cfa7d38cd..3a081494a 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/hmac.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac.h @@ -63,7 +63,7 @@ #ifndef __TC_HMAC_H__ #define __TC_HMAC_H__ -#include "sha256.h" +#include #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/hmac_prng.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac_prng.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/hmac_prng.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac_prng.h index 24f417e6b..ad12cbbf0 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/hmac_prng.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac_prng.h @@ -68,8 +68,8 @@ #ifndef __TC_HMAC_PRNG_H__ #define __TC_HMAC_PRNG_H__ -#include "sha256.h" -#include "hmac.h" +#include +#include #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/sha256.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/sha256.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/sha256.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/sha256.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/utils.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/utils.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/utils.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/utils.h diff --git a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/Adafruit_LvGL_Glue.cpp b/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/Adafruit_LvGL_Glue.cpp index cc64444a0..75f6baa0a 100755 --- a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/Adafruit_LvGL_Glue.cpp +++ b/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/Adafruit_LvGL_Glue.cpp @@ -1,5 +1,6 @@ #include "Adafruit_LvGL_Glue.h" #include +#include "lv_berry.h" // ARCHITECTURE-SPECIFIC TIMER STUFF --------------------------------------- @@ -12,29 +13,22 @@ static void lv_tick_handler(void) { lv_tick_inc(lv_tick_interval_ms); } // TOUCHSCREEN STUFF ------------------------------------------------------- -// STMPE610 calibration for raw touch data -#define TS_MINX 100 -#define TS_MAXX 3800 -#define TS_MINY 100 -#define TS_MAXY 3750 -// Same, for ADC touchscreen -#define ADC_XMIN 325 -#define ADC_XMAX 750 -#define ADC_YMIN 240 -#define ADC_YMAX 840 - - - -uint32_t Touch_Status(uint32_t sel); +uint32_t Touch_Status(int32_t sel); static void touchscreen_read(lv_indev_drv_t *indev_drv, lv_indev_data_t *data) { - //lv_coord_t last_x = 0, last_y = 0; - //static uint8_t release_count = 0; data->point.x = Touch_Status(1); // Last-pressed coordinates data->point.y = Touch_Status(2); data->state = Touch_Status(0) ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; data->continue_reading = false; /*No buffering now so no more data read*/ + // keep data for TS calibration + lv_ts_calibration.state = data->state; + if (data->state == LV_INDEV_STATE_PRESSED) { // if not pressed, the data may be invalid + lv_ts_calibration.x = data->point.x; + lv_ts_calibration.y = data->point.y; + lv_ts_calibration.raw_x = Touch_Status(-1); + lv_ts_calibration.raw_y = Touch_Status(-2); + } } // OTHER LITTLEVGL VITALS -------------------------------------------------- diff --git a/lib/libesp32_lvgl/LVGL8/README.md b/lib/libesp32_lvgl/LVGL8/README.md deleted file mode 100644 index 340995a68..000000000 --- a/lib/libesp32_lvgl/LVGL8/README.md +++ /dev/null @@ -1,165 +0,0 @@ -**The master branch now contains the test version of v8. For the last v7 version use the release/v7 branch.** - - -

LVGL - Light and Versatile Graphics Library

- -

- -

- -

-LVGL provides everything you need to create embedded GUI with easy-to-use graphical elements, beautiful visual effects and low memory footprint. -

- -

-Website · -Online demo · -Nightly demos · -Docs · -Forum -

- ---- - -## Features -* Powerful [building blocks](https://docs.lvgl.io/latest/en/html/widgets/index.html): buttons, charts, lists, sliders, images, etc. -* Advanced graphics: animations, anti-aliasing, opacity, smooth scrolling -* Use [various input devices](https://docs.lvgl.io/latest/en/html/overview/indev.html): touchscreen, mouse, keyboard, encoder, buttons, etc. -* Use [multiple displays](https://docs.lvgl.io/latest/en/html/overview/display.html): e.g. monochrome and color display -* Hardware independent to use with any microcontroller or display -* Scalable to operate with little memory (64 kB Flash, 10 kB RAM) -* Multi-language support with UTF-8 handling, Bidirectional and Arabic script support -* Fully customizable graphical elements via [CSS-like styles](https://docs.lvgl.io/latest/en/html/overview/style.html) -* OS, External memory and GPU are supported but not required -* Smooth rendering even with a [single frame buffer](https://docs.lvgl.io/latest/en/html/porting/display.html) -* Written in C for maximal compatibility (C++ compatible) -* Micropython Binding exposes [LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings) -* [Simulator](https://docs.lvgl.io/latest/en/html/get-started/pc-simulator.html) to develop on PC without embedded hardware -* [Examples](lv_examples) and tutorials for rapid development -* [Documentation](http://docs.lvgl.io/) and API references - -## Requirements -Basically, every modern controller (which is able to drive a display) is suitable to run LVGL. The minimal requirements are: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Name MinimalRecommended
Architecture16, 32 or 64 bit microcontroller or processor
Clock > 16 MHz > 48 MHz
Flash/ROM > 64 kB > 180 kB
Static RAM > 2 kB > 4 kB
Stack > 2 kB > 8 kB
Heap > 2 kB > 8 kB
Display buffer > 1 × hor. res. pixels > 10 × hor. res. pixels
Compiler C99 or newer
- -*Note that the memory usage might vary depending on the architecture, compiler and build options.* - -Just to mention some platforms: -- STM32F1, STM32F3, STM32F4, STM32F7, STM32L4, STM32L5, STM32H7 -- Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ -- NXP: Kinetis, LPC, iMX, iMX RT -- [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb) -- [Raspberry Pi](http://www.vk3erw.com/index.php/16-software/63-raspberry-pi-official-7-touchscreen-and-littlevgl) -- [Espressif ESP32](https://github.com/lvgl/lv_port_esp32) -- [Infineon Aurix](https://github.com/lvgl/lv_port_aurix) -- Nordic NRF52 Bluetooth modules -- Quectel modems - -## Get started -This list shows the recommended way of learning the library: -1. Check the [Online demos](https://lvgl.io/demos) to see LVGL in action (3 minutes) -2. Read the [Introduction](https://docs.lvgl.io/latest/en/html/intro/index.html) page of the documentation (5 minutes) -3. Get familiar with the basics on the [Quick overview](https://docs.lvgl.io/latest/en/html/get-started/quick-overview.html) page (15 minutes) -4. Set up a [Simulator](https://docs.lvgl.io/latest/en/html/get-started/pc-simulator.html) (10 minutes) -5. Try out some [Examples](https://github.com/lvgl/lv_examples/) -6. Port LVGL to a board. See the [Porting](https://docs.lvgl.io/latest/en/html/porting/index.html) guide or check the ready to use [Projects](https://github.com/lvgl?q=lv_port_&type=&language=) -7. Read the [Overview](https://docs.lvgl.io/latest/en/html/overview/index.html) page to get a better understanding of the library (2-3 hours) -8. Check the documentation of the [Widgets](https://docs.lvgl.io/latest/en/html/widgets/index.html) to see their features and usage -9. If you have questions go to the [Forum](http://forum.lvgl.io/) -10. Read the [Contributing](https://docs.lvgl.io/latest/en/html/contributing/index.html) guide to see how you can help to improve LVGL (15 minutes) - -## Examples - -For more examples see the [lv_examples](https://github.com/lvgl/lv_examples) repository. - -### Button with label -```c -lv_obj_t * btn = lv_btn_create(lv_scr_act(), NULL); /*Add a button to the current screen*/ -lv_obj_set_pos(btn, 10, 10); /*Set its position*/ -lv_obj_set_size(btn, 100, 50); /*Set its size*/ -lv_obj_set_event_cb(btn, btn_event_cb); /*Assign a callback to the button*/ - -lv_obj_t * label = lv_label_create(btn, NULL); /*Add a label to the button*/ -lv_label_set_text(label, "Button"); /*Set the labels text*/ - -... - -void btn_event_cb(lv_obj_t * btn, lv_event_t event) -{ - if(event == LV_EVENT_CLICKED) { - printf("Clicked\n"); - } -} -``` -![LVGL button with label example](https://raw.githubusercontent.com/lvgl/docs/latest/misc/simple_button_example.gif) - -### LVGL from Micropython -Learn more about [Micropython](https://docs.lvgl.io/latest/en/html/get-started/micropython.html). -```python -# Create a Button and a Label -scr = lv.obj() -btn = lv.btn(scr) -btn.align(lv.scr_act(), lv.ALIGN.CENTER, 0, 0) -label = lv.label(btn) -label.set_text("Button") - -# Load the screen -lv.scr_load(scr) -``` - -## Contributing -LVGL is an open project and contribution is very welcome. There are many ways to contribute from simply speaking about your project, through writing examples, improving the documentation, fixing bugs to hosing your own project under in LVGL. - -For a detailed description of contribution opportunities visit the [Contributing](https://docs.lvgl.io/latest/en/html/contributing/index.html) section of the documentation. - diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_rect.c b/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_rect.c deleted file mode 100644 index 59953ac70..000000000 --- a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_rect.c +++ /dev/null @@ -1,1441 +0,0 @@ -/** - * @file lv_draw_rect.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_draw_rect.h" -#include "lv_draw_blend.h" -#include "lv_draw_mask.h" -#include "../misc/lv_math.h" -#include "../misc/lv_txt_ap.h" -#include "../core/lv_refr.h" -#include "../misc/lv_assert.h" - -/********************* - * DEFINES - *********************/ -#define SHADOW_UPSCALE_SHIFT 6 -#define SHADOW_ENHANCE 1 -#define SPLIT_LIMIT 50 - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -LV_ATTRIBUTE_FAST_MEM static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, - const lv_draw_rect_dsc_t * dsc); -LV_ATTRIBUTE_FAST_MEM static void draw_bg_img(const lv_area_t * coords, const lv_area_t * clip, - const lv_draw_rect_dsc_t * dsc); -LV_ATTRIBUTE_FAST_MEM static void draw_border(const lv_area_t * coords, const lv_area_t * clip, - const lv_draw_rect_dsc_t * dsc); - -static void draw_outline(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc); - -#if LV_DRAW_COMPLEX -LV_ATTRIBUTE_FAST_MEM static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, - const lv_draw_rect_dsc_t * dsc); -LV_ATTRIBUTE_FAST_MEM static void shadow_draw_corner_buf(const lv_area_t * coords, uint16_t * sh_buf, lv_coord_t s, - lv_coord_t r); -LV_ATTRIBUTE_FAST_MEM static void shadow_blur_corner(lv_coord_t size, lv_coord_t sw, uint16_t * sh_ups_buf); - -static void draw_full_border(const lv_area_t * area_inner, const lv_area_t * area_outer, const lv_area_t * clip, - lv_coord_t radius, bool radius_is_in, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode); -#else -static void draw_simple_border(const lv_area_t * clip, const lv_area_t * area_inner, const lv_area_t * area_outer, - lv_color_t color, lv_opa_t opa, lv_border_side_t side); -#endif - -#if LV_DRAW_COMPLEX -LV_ATTRIBUTE_FAST_MEM static inline lv_color_t grad_get(const lv_draw_rect_dsc_t * dsc, lv_coord_t s, lv_coord_t i); -#endif - -/********************** - * STATIC VARIABLES - **********************/ -#if defined(LV_SHADOW_CACHE_SIZE) && LV_SHADOW_CACHE_SIZE > 0 - static uint8_t sh_cache[LV_SHADOW_CACHE_SIZE * LV_SHADOW_CACHE_SIZE]; - static int32_t sh_cache_size = -1; - static int32_t sh_cache_r = -1; -#endif - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -LV_ATTRIBUTE_FAST_MEM void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc) -{ - lv_memset_00(dsc, sizeof(lv_draw_rect_dsc_t)); - dsc->bg_color = lv_color_white(); - dsc->bg_grad_color = lv_color_black(); - dsc->border_color = lv_color_black(); - dsc->shadow_color = lv_color_black(); - dsc->bg_grad_color_stop = 0xFF; - dsc->bg_img_symbol_font = LV_FONT_DEFAULT; - dsc->bg_opa = LV_OPA_COVER; - dsc->bg_img_opa = LV_OPA_COVER; - dsc->outline_opa = LV_OPA_COVER; - dsc->border_opa = LV_OPA_COVER; - dsc->shadow_opa = LV_OPA_COVER; - dsc->border_side = LV_BORDER_SIDE_FULL; -} - -/** - * Draw a rectangle - * @param coords the coordinates of the rectangle - * @param mask the rectangle will be drawn only in this mask - * @param dsc pointer to an initialized `lv_draw_rect_dsc_t` variable - */ -void lv_draw_rect(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc) -{ - if(lv_area_get_height(coords) < 1 || lv_area_get_width(coords) < 1) return; -#if LV_DRAW_COMPLEX - draw_shadow(coords, clip, dsc); -#endif - - draw_bg(coords, clip, dsc); - draw_bg_img(coords, clip, dsc); - - draw_border(coords, clip, dsc); - - draw_outline(coords, clip, dsc); - - LV_ASSERT_MEM_INTEGRITY(); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -LV_ATTRIBUTE_FAST_MEM static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, - const lv_draw_rect_dsc_t * dsc) -{ - if(dsc->bg_opa <= LV_OPA_MIN) return; - - lv_area_t coords_bg; - lv_area_copy(&coords_bg, coords); - - /*If the border fully covers make the bg area 1px smaller to avoid artifacts on the corners*/ - if(dsc->border_width > 1 && dsc->border_opa >= LV_OPA_MAX && dsc->radius != 0) { - coords_bg.x1 += (dsc->border_side & LV_BORDER_SIDE_LEFT) ? 1 : 0; - coords_bg.y1 += (dsc->border_side & LV_BORDER_SIDE_TOP) ? 1 : 0; - coords_bg.x2 -= (dsc->border_side & LV_BORDER_SIDE_RIGHT) ? 1 : 0; - coords_bg.y2 -= (dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? 1 : 0; - } - - lv_opa_t opa = dsc->bg_opa; - - if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; - - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp); - - /*Get clipped fill area which is the real draw area. - *It is always the same or inside `fill_area`*/ - lv_area_t draw_area; - bool is_common; - is_common = _lv_area_intersect(&draw_area, &coords_bg, clip); - if(is_common == false) return; - - const lv_area_t * disp_area = &draw_buf->area; - - /*Now `draw_area` has absolute coordinates. - *Make it relative to `disp_area` to simplify draw to `disp_buf`*/ - draw_area.x1 -= disp_area->x1; - draw_area.y1 -= disp_area->y1; - draw_area.x2 -= disp_area->x1; - draw_area.y2 -= disp_area->y1; - - - lv_grad_dir_t grad_dir = dsc->bg_grad_dir; - if(dsc->bg_color.full == dsc->bg_grad_color.full) grad_dir = LV_GRAD_DIR_NONE; - - uint16_t other_mask_cnt = lv_draw_mask_get_cnt(); - bool simple_mode = true; - if(other_mask_cnt) simple_mode = false; - else if(grad_dir == LV_GRAD_DIR_HOR) simple_mode = false; - - - int32_t coords_w = lv_area_get_width(&coords_bg); - int32_t coords_h = lv_area_get_height(&coords_bg); - - /*Get the real radius*/ - int32_t rout = dsc->radius; - int32_t short_side = LV_MIN(coords_w, coords_h); - if(rout > short_side >> 1) rout = short_side >> 1; - - /*Most simple case: just a plain rectangle*/ - if(simple_mode && rout == 0 && (grad_dir == LV_GRAD_DIR_NONE)) { - _lv_blend_fill(clip, &coords_bg, - dsc->bg_color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, - dsc->blend_mode); - } - -#if LV_DRAW_COMPLEX - /*More complex case: there is a radius, gradient or other mask.*/ - else { - int32_t draw_area_w = lv_area_get_width(&draw_area); - int16_t mask_rout_id = LV_MASK_ID_INV; - lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w); - lv_draw_mask_radius_param_t mask_rout_param; - if(rout > 0) { - lv_draw_mask_radius_init(&mask_rout_param, &coords_bg, rout, false); - mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); - } - - /*Draw the background line by line*/ - int32_t h; - lv_draw_mask_res_t mask_res = LV_DRAW_MASK_RES_FULL_COVER; - lv_color_t grad_color = dsc->bg_color; - - /*In case of horizontal gradient pre-compute a line with a gradient*/ - lv_color_t * grad_map = NULL; - if(grad_dir == LV_GRAD_DIR_HOR) { - grad_map = lv_mem_buf_get(coords_w * sizeof(lv_color_t)); - - int32_t i; - for(i = 0; i < coords_w; i++) { - grad_map[i] = grad_get(dsc, coords_w, i); - } - } - - bool split = false; - if(lv_area_get_width(&coords_bg) - 2 * rout > SPLIT_LIMIT) split = true; - - lv_opa_t opa2; - - lv_area_t fill_area; - fill_area.x1 = coords_bg.x1; - fill_area.x2 = coords_bg.x2; - fill_area.y1 = disp_area->y1 + draw_area.y1; - fill_area.y2 = fill_area.y1; - for(h = draw_area.y1; h <= draw_area.y2; h++) { - int32_t y = h + draw_buf->area.y1; - - opa2 = opa; - - /*In not corner areas apply the mask only if required*/ - if(y > coords_bg.y1 + rout + 1 && - y < coords_bg.y2 - rout - 1) { - mask_res = LV_DRAW_MASK_RES_FULL_COVER; - if(simple_mode == false) { - lv_memset(mask_buf, opa, draw_area_w); - mask_res = lv_draw_mask_apply(mask_buf, draw_buf->area.x1 + draw_area.x1, draw_buf->area.y1 + h, draw_area_w); - } - } - /*In corner areas apply the mask anyway*/ - else { - lv_memset(mask_buf, opa, draw_area_w); - mask_res = lv_draw_mask_apply(mask_buf, draw_buf->area.x1 + draw_area.x1, draw_buf->area.y1 + h, draw_area_w); - } - - /*If mask will taken into account its base opacity was already set by memset above*/ - if(mask_res == LV_DRAW_MASK_RES_CHANGED) { - opa2 = LV_OPA_COVER; - } - - /*Get the current line color*/ - if(grad_dir == LV_GRAD_DIR_VER) { - grad_color = grad_get(dsc, lv_area_get_height(&coords_bg), y - coords_bg.y1); - } - - /*If there is not other mask and drawing the corner area split the drawing to corner and middle areas - *because it the middle mask shouldn't be taken into account (therefore its faster)*/ - if(simple_mode && split && - (y < coords_bg.y1 + rout + 1 || - y > coords_bg.y2 - rout - 1)) { - - /*Left part*/ - lv_area_t fill_area2; - fill_area2.x1 = coords_bg.x1; - fill_area2.x2 = coords_bg.x1 + rout - 1; - fill_area2.y1 = fill_area.y1; - fill_area2.y2 = fill_area.y2; - - _lv_blend_fill(clip, &fill_area2, - grad_color, mask_buf, mask_res, opa2, dsc->blend_mode); - - /*Center part*/ - if(grad_dir == LV_GRAD_DIR_VER) { - fill_area2.x1 = coords_bg.x1 + rout; - fill_area2.x2 = coords_bg.x2 - rout; - _lv_blend_fill(clip, &fill_area2, - grad_color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, dsc->blend_mode); - } - - /*Right part*/ - fill_area2.x1 = coords_bg.x2 - rout + 1; - fill_area2.x2 = coords_bg.x2; - - int32_t mask_ofs = (coords_bg.x2 - rout + 1) - (draw_buf->area.x1 + draw_area.x1); - if(mask_ofs < 0) mask_ofs = 0; - _lv_blend_fill(clip, &fill_area2, - grad_color, mask_buf + mask_ofs, mask_res, opa2, dsc->blend_mode); - - } - else { - if(grad_dir == LV_GRAD_DIR_HOR) { - _lv_blend_map(clip, &fill_area, grad_map, mask_buf, mask_res, opa2, dsc->blend_mode); - } - else if(grad_dir == LV_GRAD_DIR_VER) { - _lv_blend_fill(clip, &fill_area, - grad_color, mask_buf, mask_res, opa2, dsc->blend_mode); - } - else if(other_mask_cnt != 0 || !split) { - _lv_blend_fill(clip, &fill_area, - grad_color, mask_buf, mask_res, opa2, dsc->blend_mode); - } - } - fill_area.y1++; - fill_area.y2++; - } - - if(grad_dir == LV_GRAD_DIR_NONE && other_mask_cnt == 0 && split) { - /*Central part*/ - fill_area.x1 = coords_bg.x1 + rout; - fill_area.x2 = coords_bg.x2 - rout; - fill_area.y1 = coords_bg.y1; - fill_area.y2 = coords_bg.y1 + rout; - - _lv_blend_fill(clip, &fill_area, - dsc->bg_color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, dsc->blend_mode); - - fill_area.y1 = coords_bg.y2 - rout; - if(fill_area.y1 <= fill_area.y2) fill_area.y1 = fill_area.y2 + 1; /*Avoid overdrawing the last line*/ - fill_area.y2 = coords_bg.y2; - - _lv_blend_fill(clip, &fill_area, - dsc->bg_color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, dsc->blend_mode); - - fill_area.x1 = coords_bg.x1; - fill_area.x2 = coords_bg.x2; - fill_area.y1 = coords_bg.y1 + rout + 1; - fill_area.y2 = coords_bg.y2 - rout - 1; - - _lv_blend_fill(clip, &fill_area, - dsc->bg_color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, dsc->blend_mode); - - } - - if(grad_map) lv_mem_buf_release(grad_map); - if(mask_buf) lv_mem_buf_release(mask_buf); - lv_draw_mask_remove_id(mask_rout_id); - } - -#endif -} - -LV_ATTRIBUTE_FAST_MEM static void draw_bg_img(const lv_area_t * coords, const lv_area_t * clip, - const lv_draw_rect_dsc_t * dsc) -{ - if(dsc->bg_img_src == NULL) return; - if(dsc->bg_img_opa <= LV_OPA_MIN) return; - - lv_img_src_t src_type = lv_img_src_get_type(dsc->bg_img_src); - if(src_type == LV_IMG_SRC_SYMBOL) { - lv_point_t size; - lv_txt_get_size(&size, dsc->bg_img_src, dsc->bg_img_symbol_font, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); - lv_area_t a; - a.x1 = coords->x1 + lv_area_get_width(coords) / 2 - size.x / 2; - a.x2 = a.x1 + size.x - 1; - a.y1 = coords->y1 + lv_area_get_height(coords) / 2 - size.y / 2; - a.y2 = a.y1 + size.y - 1; - - lv_draw_label_dsc_t label_draw_dsc; - lv_draw_label_dsc_init(&label_draw_dsc); - label_draw_dsc.font = dsc->bg_img_symbol_font; - label_draw_dsc.color = dsc->bg_img_recolor; - label_draw_dsc.opa = dsc->bg_img_opa; - lv_draw_label(&a, clip, &label_draw_dsc, dsc->bg_img_src, NULL); - } - else { - lv_img_header_t header; - lv_res_t res = lv_img_decoder_get_info(dsc->bg_img_src, &header); - if(res != LV_RES_OK) { - LV_LOG_WARN("Coudn't read the background image"); - return; - } - - lv_draw_img_dsc_t img_dsc; - lv_draw_img_dsc_init(&img_dsc); - img_dsc.blend_mode = dsc->blend_mode; - img_dsc.recolor = dsc->bg_img_recolor; - img_dsc.recolor_opa = dsc->bg_img_recolor_opa; - img_dsc.opa = dsc->bg_img_opa; - - /*Center align*/ - if(dsc->bg_img_tiled == false) { - lv_area_t area; - area.x1 = coords->x1 + lv_area_get_width(coords) / 2 - header.w / 2; - area.y1 = coords->y1 + lv_area_get_height(coords) / 2 - header.h / 2; - area.x2 = area.x1 + header.w - 1; - area.y2 = area.y1 + header.h - 1; - - lv_draw_img(&area, clip, dsc->bg_img_src, &img_dsc); - } else { - lv_area_t area; - area.y1 = coords->y1; - area.y2 = area.y1 + header.h - 1; - - for(; area.y1 <= coords->y2; area.y1 += header.h, area.y2 += header.h) { - - area.x1 = coords->x1; - area.x2 = area.x1 + header.w - 1; - for(; area.x1 <= coords->x2; area.x1 += header.w, area.x2 += header.w) { - lv_draw_img(&area, clip, dsc->bg_img_src, &img_dsc); - } - } - } - } -} - -LV_ATTRIBUTE_FAST_MEM static void draw_border(const lv_area_t * coords, const lv_area_t * clip, - const lv_draw_rect_dsc_t * dsc) -{ - if(dsc->border_opa <= LV_OPA_MIN) return; - if(dsc->border_width == 0) return; - if(dsc->border_side == LV_BORDER_SIDE_NONE) return; - if(dsc->border_post) return; - - int32_t coords_w = lv_area_get_width(coords); - int32_t coords_h = lv_area_get_height(coords); - - /*Get the real radius*/ - int32_t rout = dsc->radius; - int32_t short_side = LV_MIN(coords_w, coords_h); - if(rout > short_side >> 1) rout = short_side >> 1; - - /*Get the inner area*/ - lv_area_t area_inner; - lv_area_copy(&area_inner, coords); - area_inner.x1 += ((dsc->border_side & LV_BORDER_SIDE_LEFT) ? dsc->border_width : - (dsc->border_width + rout)); - area_inner.x2 -= ((dsc->border_side & LV_BORDER_SIDE_RIGHT) ? dsc->border_width : - (dsc->border_width + rout)); - area_inner.y1 += ((dsc->border_side & LV_BORDER_SIDE_TOP) ? dsc->border_width : - (dsc->border_width + rout)); - area_inner.y2 -= ((dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? dsc->border_width : - (dsc->border_width + rout)); - -#if LV_DRAW_COMPLEX - if(dsc->border_side == LV_BORDER_SIDE_FULL) { - draw_full_border(&area_inner, coords, clip, dsc->radius, false, dsc->border_color, dsc->border_opa, - dsc->blend_mode); - } - else { - lv_opa_t opa = dsc->border_opa; - if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; - - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp); - - /*Get clipped fill area which is the real draw area. - *It is always the same or inside `fill_area`*/ - lv_area_t draw_area; - bool is_common; - is_common = _lv_area_intersect(&draw_area, coords, clip); - if(is_common == false) return; - - const lv_area_t * disp_area = &draw_buf->area; - - /*Now `draw_area` has absolute coordinates. - *Make it relative to `disp_area` to simplify draw to `disp_buf`*/ - draw_area.x1 -= disp_area->x1; - draw_area.y1 -= disp_area->y1; - draw_area.x2 -= disp_area->x1; - draw_area.y2 -= disp_area->y1; - - int32_t draw_area_w = lv_area_get_width(&draw_area); - - /*Create a mask if there is a radius*/ - lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w); - - /*Create mask for the outer area*/ - int16_t mask_rout_id = LV_MASK_ID_INV; - lv_draw_mask_radius_param_t mask_rout_param; - if(rout > 0) { - lv_draw_mask_radius_init(&mask_rout_param, coords, rout, false); - mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); - } - - /*Create mask for the inner mask*/ - int32_t rin = rout - dsc->border_width; - if(rin < 0) rin = 0; - lv_draw_mask_radius_param_t mask_rin_param; - lv_draw_mask_radius_init(&mask_rin_param, &area_inner, rout - dsc->border_width, true); - int16_t mask_rin_id = lv_draw_mask_add(&mask_rin_param, NULL); - - int32_t corner_size = LV_MAX(rout, dsc->border_width - 1); - - int32_t h; - lv_draw_mask_res_t mask_res; - lv_area_t fill_area; - - lv_color_t color = dsc->border_color; - lv_blend_mode_t blend_mode = dsc->blend_mode; - - fill_area.x1 = coords->x1; - fill_area.x2 = coords->x2; - fill_area.y1 = disp_area->y1 + draw_area.y1; - fill_area.y2 = fill_area.y1; - - if(dsc->border_side == LV_BORDER_SIDE_LEFT) fill_area.x2 = coords->x1 + corner_size; - - volatile bool top_only = false; - volatile bool bottom_only = false; - if(dsc->border_side == LV_BORDER_SIDE_TOP) top_only = true; - if(dsc->border_side == LV_BORDER_SIDE_BOTTOM) bottom_only = true; - if(dsc->border_side == (LV_BORDER_SIDE_TOP | LV_BORDER_SIDE_BOTTOM)) { - top_only = true; - bottom_only = true; - } - - volatile bool normal = !top_only && !bottom_only ? true : false; - - for(h = draw_area.y1; h <= draw_area.y2; h++) { - if(normal || - (top_only && fill_area.y1 <= coords->y1 + corner_size) || - (bottom_only && fill_area.y1 >= coords->y2 - corner_size)) { - lv_memset_ff(mask_buf, draw_area_w); - mask_res = lv_draw_mask_apply(mask_buf, draw_buf->area.x1 + draw_area.x1, draw_buf->area.y1 + h, draw_area_w); - _lv_blend_fill(clip, &fill_area, color, mask_buf, mask_res, opa, blend_mode); - } - fill_area.y1++; - fill_area.y2++; - - } - lv_draw_mask_remove_id(mask_rin_id); - lv_draw_mask_remove_id(mask_rout_id); - lv_mem_buf_release(mask_buf); - } -#else /*LV_DRAW_COMPLEX*/ - draw_simple_border(clip, &area_inner, coords, dsc->border_color, dsc->border_opa, dsc->border_side); -#endif -} - -#if LV_DRAW_COMPLEX -LV_ATTRIBUTE_FAST_MEM static inline lv_color_t grad_get(const lv_draw_rect_dsc_t * dsc, lv_coord_t s, lv_coord_t i) -{ - int32_t min = (dsc->bg_main_color_stop * s) >> 8; - if(i <= min) return dsc->bg_color; - - int32_t max = (dsc->bg_grad_color_stop * s) >> 8; - if(i >= max) return dsc->bg_grad_color; - - int32_t d = dsc->bg_grad_color_stop - dsc->bg_main_color_stop; - d = (s * d) >> 8; - i -= min; - lv_opa_t mix = (i * 255) / d; - return lv_color_mix(dsc->bg_grad_color, dsc->bg_color, mix); -} - -LV_ATTRIBUTE_FAST_MEM static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, - const lv_draw_rect_dsc_t * dsc) -{ - /*Check whether the shadow is visible*/ - if(dsc->shadow_width == 0) return; - if(dsc->shadow_opa <= LV_OPA_MIN) return; - - if(dsc->shadow_width == 1 && dsc->shadow_ofs_x == 0 && - dsc->shadow_ofs_y == 0 && dsc->shadow_spread <= 0) { - return; - } - - int32_t sw = dsc->shadow_width; - - lv_area_t sh_rect_area; - sh_rect_area.x1 = coords->x1 + dsc->shadow_ofs_x - dsc->shadow_spread; - sh_rect_area.x2 = coords->x2 + dsc->shadow_ofs_x + dsc->shadow_spread; - sh_rect_area.y1 = coords->y1 + dsc->shadow_ofs_y - dsc->shadow_spread; - sh_rect_area.y2 = coords->y2 + dsc->shadow_ofs_y + dsc->shadow_spread; - - lv_area_t sh_area; - sh_area.x1 = sh_rect_area.x1 - sw / 2 - 1; - sh_area.x2 = sh_rect_area.x2 + sw / 2 + 1; - sh_area.y1 = sh_rect_area.y1 - sw / 2 - 1; - sh_area.y2 = sh_rect_area.y2 + sw / 2 + 1; - - lv_opa_t opa = dsc->shadow_opa; - - if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; - - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp); - - /*Get clipped fill area which is the real draw area. - *It is always the same or inside `fill_area`*/ - lv_area_t draw_area; - bool is_common; - is_common = _lv_area_intersect(&draw_area, &sh_area, clip); - if(is_common == false) return; - - const lv_area_t * disp_area = &draw_buf->area; - - /*Now `draw_area` has absolute coordinates. - *Make it relative to `disp_area` to simplify draw to `disp_buf`*/ - draw_area.x1 -= disp_area->x1; - draw_area.y1 -= disp_area->y1; - draw_area.x2 -= disp_area->x1; - draw_area.y2 -= disp_area->y1; - - /*Consider 1 px smaller bg to be sure the edge will be covered by the shadow*/ - lv_area_t bg_coords; - lv_area_copy(&bg_coords, coords); - bg_coords.x1 += 1; - bg_coords.y1 += 1; - bg_coords.x2 -= 1; - bg_coords.y2 -= 1; - - /*Get the real radius*/ - int32_t r_bg = dsc->radius; - int32_t short_side = LV_MIN(lv_area_get_width(&bg_coords), lv_area_get_height(&bg_coords)); - if(r_bg > short_side >> 1) r_bg = short_side >> 1; - - int32_t r_sh = dsc->radius; - short_side = LV_MIN(lv_area_get_width(&sh_rect_area), lv_area_get_height(&sh_rect_area)); - if(r_sh > short_side >> 1) r_sh = short_side >> 1; - - int32_t corner_size = sw + r_sh; - - lv_opa_t * sh_buf; - -#if LV_SHADOW_CACHE_SIZE - if(sh_cache_size == corner_size && sh_cache_r == r_sh) { - /*Use the cache if available*/ - sh_buf = lv_mem_buf_get(corner_size * corner_size); - lv_memcpy(sh_buf, sh_cache, corner_size * corner_size); - } - else { - /*A larger buffer is required for calculation*/ - sh_buf = lv_mem_buf_get(corner_size * corner_size * sizeof(uint16_t)); - shadow_draw_corner_buf(&sh_rect_area, (uint16_t *)sh_buf, dsc->shadow_width, r_sh); - - /*Cache the corner if it fits into the cache size*/ - if((uint32_t)corner_size * corner_size < sizeof(sh_cache)) { - lv_memcpy(sh_cache, sh_buf, corner_size * corner_size); - sh_cache_size = corner_size; - sh_cache_r = r_sh; - } - } -#else - sh_buf = lv_mem_buf_get(corner_size * corner_size * sizeof(uint16_t)); - shadow_draw_corner_buf(&sh_rect_area, (uint16_t *)sh_buf, dsc->shadow_width, r_sh); -#endif - - lv_coord_t h_half = sh_area.y1 + lv_area_get_height(&sh_area) / 2; - lv_coord_t w_half = sh_area.x1 + lv_area_get_width(&sh_area) / 2; - - bool simple_mode = true; - if(lv_draw_mask_get_cnt() > 0) simple_mode = false; - else if(dsc->shadow_ofs_x != 0 || dsc->shadow_ofs_y != 0) simple_mode = false; - else if(dsc->shadow_spread != 0) simple_mode = false; - - /*Create a mask*/ - lv_draw_mask_res_t mask_res; - lv_opa_t * mask_buf = lv_mem_buf_get(lv_area_get_width(&sh_area)); - - lv_draw_mask_radius_param_t mask_rout_param; - lv_draw_mask_radius_init(&mask_rout_param, &bg_coords, r_bg, true); - - int16_t mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); - - lv_area_t a; - - /*Draw the top right corner*/ - int32_t y; - lv_opa_t * sh_buf_tmp; - a.x2 = sh_area.x2; - a.x1 = a.x2 - corner_size + 1; - a.y1 = sh_area.y1; - a.y2 = a.y1 + corner_size - 1; - - lv_area_t ca; - bool has_com = _lv_area_intersect(&ca, &a, clip); - if(has_com && _lv_area_is_in(&a, &bg_coords, r_bg) == false) { - /*Avoid overlap in the middle with large radius*/ - if(ca.y2 > h_half) ca.y2 = h_half; - if(ca.x1 <= w_half) ca.x1 = w_half + 1; - - lv_coord_t h = lv_area_get_height(&ca); - lv_coord_t w = lv_area_get_width(&ca); - if(w > 0) { - sh_buf_tmp = sh_buf + (ca.x1 - a.x1); - sh_buf_tmp += corner_size * (ca.y1 - a.y1); - - lv_area_t fa; - lv_area_copy(&fa, &ca); - fa.y2 = fa.y1; - - for(y = 0; y < h; y++) { - lv_memcpy(mask_buf, sh_buf_tmp, w); - mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - - _lv_blend_fill(clip, &fa, dsc->shadow_color, mask_buf, - mask_res, opa, dsc->blend_mode); - fa.y1++; - fa.y2++; - sh_buf_tmp += corner_size; - } - } - } - - /*Draw the bottom right corner*/ - a.x2 = sh_area.x2; - a.x1 = a.x2 - corner_size + 1; - a.y1 = sh_area.y2 - corner_size + 1; - a.y2 = sh_area.y2; - - has_com = _lv_area_intersect(&ca, &a, clip); - if(has_com && _lv_area_is_in(&a, &bg_coords, r_bg) == false) { - /*Avoid overlap in the middle with large radius*/ - if(ca.y1 <= h_half) ca.y1 = h_half; - if(ca.x1 <= w_half) ca.x1 = w_half; - - lv_coord_t h = lv_area_get_height(&ca); - lv_coord_t w = lv_area_get_width(&ca); - - if(w > 0) { - sh_buf_tmp = sh_buf + (ca.x1 - a.x1); - sh_buf_tmp += corner_size * (a.y2 - ca.y2); - - lv_area_t fa; - lv_area_copy(&fa, &ca); - fa.y1 = fa.y2; /*Fill from bottom to top*/ - - for(y = 0; y < h; y++) { - lv_memcpy(mask_buf, sh_buf_tmp, w); - mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - - _lv_blend_fill(clip, &fa, dsc->shadow_color, mask_buf, - mask_res, opa, dsc->blend_mode); - fa.y1--; - fa.y2--; - sh_buf_tmp += corner_size; - } - } - } - - /*Fill the right side*/ - a.x2 = sh_area.x2; - a.x1 = a.x2 - corner_size + 1; - a.y1 = sh_area.y1 + corner_size; - a.y2 = sh_area.y2 - corner_size; - - has_com = _lv_area_intersect(&ca, &a, clip); - if(has_com && _lv_area_is_in(&a, &bg_coords, r_bg) == false) { - /*Avoid overlap in the middle with large radius*/ - if(ca.x1 <= w_half) ca.x1 = w_half + 1; - - if(simple_mode) ca.x1 = LV_MAX(ca.x1, coords->x2); - - /*Draw horizontal lines*/ - lv_coord_t w = lv_area_get_width(&ca); - if(w > 0) { - lv_coord_t h = lv_area_get_height(&ca); - - /*The last line of the shadow is repeated on the side*/ - sh_buf_tmp = sh_buf + corner_size * (corner_size - 1); - sh_buf_tmp += ca.x1 - a.x1; - - lv_area_t fa; - lv_area_copy(&fa, &ca); - fa.y2 = fa.y1; - mask_res = LV_DRAW_MASK_RES_FULL_COVER; - for(y = 0; y < h; y++) { - lv_memcpy(mask_buf, sh_buf_tmp, w); - - if(simple_mode) { - mask_res = LV_DRAW_MASK_RES_CHANGED; - } - else { - mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - } - - _lv_blend_fill(clip, &fa, - dsc->shadow_color, mask_buf, mask_res, dsc->shadow_opa, dsc->blend_mode); - fa.y1++; - fa.y2++; - } - } - } - - /*Invert the shadow corner buffer and draw the corners on the left*/ - sh_buf_tmp = sh_buf ; - for(y = 0; y < corner_size; y++) { - int32_t x; - for(x = 0; x < corner_size / 2; x++) { - lv_opa_t tmp = sh_buf_tmp[x]; - sh_buf_tmp[x] = sh_buf_tmp[corner_size - x - 1]; - sh_buf_tmp[corner_size - x - 1] = tmp; - } - sh_buf_tmp += corner_size; - } - - /*Draw the top left corner*/ - a.x1 = sh_area.x1; - a.x2 = a.x1 + corner_size - 1; - a.y1 = sh_area.y1; - a.y2 = a.y1 + corner_size - 1; - - has_com = _lv_area_intersect(&ca, &a, clip); - if(has_com && _lv_area_is_in(&a, &bg_coords, r_bg) == false) { - /*Avoid overlap in the middle with large radius*/ - if(ca.y2 > h_half) ca.y2 = h_half; - if(ca.x2 > w_half) ca.x2 = w_half; - - lv_coord_t h = lv_area_get_height(&ca); - lv_coord_t w = lv_area_get_width(&ca); - if(w > 0) { - sh_buf_tmp = sh_buf + (ca.x1 - a.x1); - sh_buf_tmp += corner_size * (ca.y1 - a.y1); - - lv_area_t fa; - lv_area_copy(&fa, &ca); - fa.y2 = fa.y1; - - for(y = 0; y < h; y++) { - lv_memcpy(mask_buf, sh_buf_tmp, w); - mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - - _lv_blend_fill(clip, &fa, dsc->shadow_color, mask_buf, - mask_res, opa, dsc->blend_mode); - fa.y1++; - fa.y2++; - sh_buf_tmp += corner_size; - } - } - } - - /*Draw the bottom left corner*/ - a.x1 = sh_area.x1; - a.x2 = a.x1 + corner_size - 1; - a.y1 = sh_area.y2 - corner_size + 1; - a.y2 = sh_area.y2; - - has_com = _lv_area_intersect(&ca, &a, clip); - if(has_com && _lv_area_is_in(&a, &bg_coords, r_bg) == false) { - /*Avoid overlap in the middle with large radius*/ - if(ca.y1 <= h_half) ca.y1 = h_half + 1; - if(ca.x2 > w_half) ca.x2 = w_half; - lv_coord_t h = lv_area_get_height(&ca); - lv_coord_t w = lv_area_get_width(&ca); - - if(w > 0) { - sh_buf_tmp = sh_buf + (ca.x1 - a.x1); - sh_buf_tmp += corner_size * (a.y2 - ca.y2); - - lv_area_t fa; - lv_area_copy(&fa, &ca); - fa.y1 = fa.y2; /*Fill from bottom to top*/ - - for(y = 0; y < h; y++) { - lv_memcpy(mask_buf, sh_buf_tmp, w); - mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - - _lv_blend_fill(clip, &fa, dsc->shadow_color, mask_buf, - mask_res, opa, dsc->blend_mode); - fa.y1--; - fa.y2--; - sh_buf_tmp += corner_size; - } - } - } - - /*Fill the left side*/ - a.x1 = sh_area.x1; - a.x2 = a.x1 + corner_size - 1; - a.y1 = sh_area.y1 + corner_size; - a.y2 = sh_area.y2 - corner_size; - - has_com = _lv_area_intersect(&ca, &a, clip); - if(has_com && _lv_area_is_in(&a, &bg_coords, r_bg) == false) { - /*Avoid overlap in the middle with large radius*/ - if(ca.x2 > w_half) ca.x2 = w_half; - - if(simple_mode) ca.x2 = LV_MIN(coords->x1, ca.x2); - /*Draw vertical lines*/ - lv_coord_t w = lv_area_get_width(&ca); - if(w > 0) { - lv_coord_t h = lv_area_get_height(&ca); - /*The last line of the shadow is repeated on the side*/ - sh_buf_tmp = sh_buf + corner_size * (corner_size - 1); - sh_buf_tmp += ca.x1 - a.x1; - - lv_area_t fa; - lv_area_copy(&fa, &ca); - fa.y2 = fa.y1; - for(y = 0; y < h; y++) { - lv_memcpy(mask_buf, sh_buf_tmp, w); - if(simple_mode) { - mask_res = LV_DRAW_MASK_RES_CHANGED; - } - else { - mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - } - - _lv_blend_fill(clip, &fa, - dsc->shadow_color, mask_buf, mask_res, dsc->shadow_opa, dsc->blend_mode); - fa.y1++; - fa.y2++; - } - } - } - - /*Fill the top side*/ - a.x1 = sh_area.x1 + corner_size; - a.x2 = sh_area.x2 - corner_size; - a.y1 = sh_area.y1; - a.y2 = sh_area.y1 + corner_size - 1; - - has_com = _lv_area_intersect(&ca, &a, clip); - if(has_com && _lv_area_is_in(&a, &bg_coords, r_bg) == false) { - /*Avoid overlap in the middle with large radius*/ - if(ca.y2 > h_half) ca.y2 = h_half; - - if(simple_mode) ca.y2 = LV_MIN(ca.y2, coords->y1); - - /*Draw horizontal lines*/ - lv_coord_t w = lv_area_get_width(&ca); - lv_coord_t h = lv_area_get_height(&ca); - sh_buf_tmp = sh_buf + corner_size - 1; - sh_buf_tmp += corner_size * (ca.y1 - a.y1); - - lv_area_t fa; - lv_area_copy(&fa, &ca); - fa.y2 = fa.y1; - mask_res = LV_DRAW_MASK_RES_FULL_COVER; - for(y = 0; y < h; y++) { - lv_opa_t opa_tmp = sh_buf_tmp[0]; - if(opa_tmp != LV_OPA_COVER || opa != LV_OPA_COVER) opa_tmp = (opa * opa_tmp) >> 8; - - lv_memset(mask_buf, opa_tmp, w); - - if(simple_mode) { - mask_res = LV_DRAW_MASK_RES_CHANGED; - } - else { - mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - } - - _lv_blend_fill(clip, &fa, dsc->shadow_color, mask_buf, - mask_res, LV_OPA_COVER, dsc->blend_mode); - fa.y1++; - fa.y2++; - sh_buf_tmp += corner_size; - } - } - - /*Fill the bottom side*/ - a.x1 = sh_area.x1 + corner_size; - a.x2 = sh_area.x2 - corner_size; - a.y1 = sh_area.y2 - corner_size + 1; - a.y2 = sh_area.y2; - - has_com = _lv_area_intersect(&ca, &a, clip); - if(has_com && _lv_area_is_in(&a, &bg_coords, r_bg) == false) { - /*Avoid overlap in the middle with large radius*/ - if(ca.y1 <= h_half) ca.y1 = h_half + 1; - - if(simple_mode) ca.y1 = LV_MAX(ca.y1, coords->y2); - - /*Draw horizontal lines*/ - lv_coord_t w = lv_area_get_width(&ca); - lv_coord_t h = lv_area_get_height(&ca); - sh_buf_tmp = sh_buf + corner_size - 1; - sh_buf_tmp += corner_size * (a.y2 - ca.y2); - - lv_area_t fa; - lv_area_copy(&fa, &ca); - fa.y1 = fa.y2; - for(y = 0; y < h; y++) { - lv_opa_t opa_tmp = sh_buf_tmp[0]; - if(opa_tmp != LV_OPA_COVER || opa != LV_OPA_COVER) opa_tmp = (opa * opa_tmp) >> 8; - - lv_memset(mask_buf, opa_tmp, w); - if(simple_mode) { - mask_res = LV_DRAW_MASK_RES_CHANGED; - } - else { - mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - } - - _lv_blend_fill(clip, &fa, dsc->shadow_color, mask_buf, - mask_res, LV_OPA_COVER, dsc->blend_mode); - fa.y1--; - fa.y2--; - sh_buf_tmp += corner_size; - } - } - - /*Draw the middle area*/ - a.x1 = sh_area.x1 + corner_size; - a.x2 = sh_area.x2 - corner_size; - a.y1 = sh_area.y1 + corner_size; - a.y2 = sh_area.y2 - corner_size; - - has_com = _lv_area_intersect(&ca, &a, clip); - if(has_com && simple_mode == false && _lv_area_is_in(&a, &bg_coords, r_bg) == false) { - /*Draw horizontal lines*/ - lv_coord_t w = lv_area_get_width(&ca); - lv_coord_t h = lv_area_get_height(&ca); - - lv_area_t fa; - lv_area_copy(&fa, &ca); - fa.y2 = fa.y1; - for(y = 0; y < h; y++) { - lv_memset(mask_buf, dsc->shadow_opa, w); - mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - - _lv_blend_fill(clip, &fa, dsc->shadow_color, mask_buf, - mask_res, LV_OPA_COVER, dsc->blend_mode); - fa.y1++; - fa.y2++; - } - } - - lv_draw_mask_remove_id(mask_rout_id); - lv_mem_buf_release(mask_buf); - lv_mem_buf_release(sh_buf); -} - -/** - * Calculate a blurred corner - * @param coords Coordinates of the shadow - * @param sh_buf a buffer to store the result. It's size should be `(sw + r)^2 * 2` - * @param sw shadow width - * @param r radius - */ -LV_ATTRIBUTE_FAST_MEM static void shadow_draw_corner_buf(const lv_area_t * coords, uint16_t * sh_buf, lv_coord_t sw, - lv_coord_t r) -{ - int32_t sw_ori = sw; - int32_t size = sw_ori + r; - - lv_area_t sh_area; - lv_area_copy(&sh_area, coords); - sh_area.x2 = sw / 2 + r - 1 - ((sw & 1) ? 0 : 1); - sh_area.y1 = sw / 2 + 1; - - sh_area.x1 = sh_area.x2 - lv_area_get_width(coords); - sh_area.y2 = sh_area.y1 + lv_area_get_height(coords); - - lv_draw_mask_radius_param_t mask_param; - lv_draw_mask_radius_init(&mask_param, &sh_area, r, false); - -#if SHADOW_ENHANCE - /*Set half shadow width width because blur will be repeated*/ - if(sw_ori == 1) sw = 1; - else sw = sw_ori >> 1; -#endif - - int32_t y; - lv_opa_t * mask_line = lv_mem_buf_get(size); - uint16_t * sh_ups_tmp_buf = (uint16_t *)sh_buf; - for(y = 0; y < size; y++) { - lv_memset_ff(mask_line, size); - lv_draw_mask_res_t mask_res = mask_param.dsc.cb(mask_line, 0, y, size, &mask_param); - if(mask_res == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(sh_ups_tmp_buf, size * sizeof(sh_ups_tmp_buf[0])); - } - else { - int32_t i; - sh_ups_tmp_buf[0] = (mask_line[0] << SHADOW_UPSCALE_SHIFT) / sw; - for(i = 1; i < size; i++) { - if(mask_line[i] == mask_line[i - 1]) sh_ups_tmp_buf[i] = sh_ups_tmp_buf[i - 1]; - else sh_ups_tmp_buf[i] = (mask_line[i] << SHADOW_UPSCALE_SHIFT) / sw; - } - } - - sh_ups_tmp_buf += size; - } - lv_mem_buf_release(mask_line); - - if(sw == 1) { - int32_t i; - lv_opa_t * res_buf = (lv_opa_t *)sh_buf; - for(i = 0; i < size * size; i++) { - res_buf[i] = (sh_buf[i] >> SHADOW_UPSCALE_SHIFT); - } - return; - } - - shadow_blur_corner(size, sw, sh_buf); - -#if SHADOW_ENHANCE == 0 - /*The result is required in lv_opa_t not uint16_t*/ - uint32_t x; - lv_opa_t * res_buf = (lv_opa_t *)sh_buf; - for(x = 0; x < size * size; x++) { - res_buf[x] = sh_buf[x]; - } -#else - sw += sw_ori & 1; - if(sw > 1) { - uint32_t i; - sh_buf[0] = (sh_buf[0] << SHADOW_UPSCALE_SHIFT) / sw; - for(i = 1; i < (uint32_t) size * size; i++) { - if(sh_buf[i] == sh_buf[i - 1]) sh_buf[i] = sh_buf[i - 1]; - else sh_buf[i] = (sh_buf[i] << SHADOW_UPSCALE_SHIFT) / sw; - } - - shadow_blur_corner(size, sw, sh_buf); - } - int32_t x; - lv_opa_t * res_buf = (lv_opa_t *)sh_buf; - for(x = 0; x < size * size; x++) { - res_buf[x] = sh_buf[x]; - } -#endif - -} - -LV_ATTRIBUTE_FAST_MEM static void shadow_blur_corner(lv_coord_t size, lv_coord_t sw, uint16_t * sh_ups_buf) -{ - int32_t s_left = sw >> 1; - int32_t s_right = (sw >> 1); - if((sw & 1) == 0) s_left--; - - /*Horizontal blur*/ - uint16_t * sh_ups_blur_buf = lv_mem_buf_get(size * sizeof(uint16_t)); - - int32_t x; - int32_t y; - - uint16_t * sh_ups_tmp_buf = sh_ups_buf; - - for(y = 0; y < size; y++) { - int32_t v = sh_ups_tmp_buf[size - 1] * sw; - for(x = size - 1; x >= 0; x--) { - sh_ups_blur_buf[x] = v; - - /*Forget the right pixel*/ - uint32_t right_val = 0; - if(x + s_right < size) right_val = sh_ups_tmp_buf[x + s_right]; - v -= right_val; - - /*Add the left pixel*/ - uint32_t left_val; - if(x - s_left - 1 < 0) left_val = sh_ups_tmp_buf[0]; - else left_val = sh_ups_tmp_buf[x - s_left - 1]; - v += left_val; - } - lv_memcpy(sh_ups_tmp_buf, sh_ups_blur_buf, size * sizeof(uint16_t)); - sh_ups_tmp_buf += size; - } - - /*Vertical blur*/ - uint32_t i; - sh_ups_buf[0] = sh_ups_buf[0] / sw; - for(i = 1; i < (uint32_t)size * size; i++) { - if(sh_ups_buf[i] == sh_ups_buf[i - 1]) sh_ups_buf[i] = sh_ups_buf[i - 1]; - else sh_ups_buf[i] = sh_ups_buf[i] / sw; - } - - for(x = 0; x < size; x++) { - sh_ups_tmp_buf = &sh_ups_buf[x]; - int32_t v = sh_ups_tmp_buf[0] * sw; - for(y = 0; y < size ; y++, sh_ups_tmp_buf += size) { - sh_ups_blur_buf[y] = v < 0 ? 0 : (v >> SHADOW_UPSCALE_SHIFT); - - /*Forget the top pixel*/ - uint32_t top_val; - if(y - s_right <= 0) top_val = sh_ups_tmp_buf[0]; - else top_val = sh_ups_buf[(y - s_right) * size + x]; - v -= top_val; - - /*Add the bottom pixel*/ - uint32_t bottom_val; - if(y + s_left + 1 < size) bottom_val = sh_ups_buf[(y + s_left + 1) * size + x]; - else bottom_val = sh_ups_buf[(size - 1) * size + x]; - v += bottom_val; - } - - /*Write back the result into `sh_ups_buf`*/ - sh_ups_tmp_buf = &sh_ups_buf[x]; - for(y = 0; y < size; y++, sh_ups_tmp_buf += size) { - (*sh_ups_tmp_buf) = sh_ups_blur_buf[y]; - } - } - - lv_mem_buf_release(sh_ups_blur_buf); -} - -#endif - -static void draw_outline(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc) -{ - if(dsc->outline_opa <= LV_OPA_MIN) return; - if(dsc->outline_width == 0) return; - - lv_opa_t opa = dsc->outline_opa; - - if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; - - /*Get the inner radius*/ - lv_area_t area_inner; - lv_area_copy(&area_inner, coords); - - /*Extend the outline into the background area if it's overlapping the edge*/ - lv_coord_t pad = (dsc->outline_pad == 0 ? (dsc->outline_pad - 1) : dsc->outline_pad); - area_inner.x1 -= pad; - area_inner.y1 -= pad; - area_inner.x2 += pad; - area_inner.y2 += pad; - - lv_area_t area_outer; - lv_area_copy(&area_outer, &area_inner); - - area_outer.x1 -= dsc->outline_width; - area_outer.x2 += dsc->outline_width; - area_outer.y1 -= dsc->outline_width; - area_outer.y2 += dsc->outline_width; - -#if LV_DRAW_COMPLEX - draw_full_border(&area_inner, &area_outer, clip, dsc->radius, true, dsc->outline_color, dsc->outline_opa, - dsc->blend_mode); -#else - draw_simple_border(clip, &area_inner, &area_outer, dsc->outline_color, dsc->outline_opa, LV_BORDER_SIDE_FULL); -#endif -} - -#if LV_DRAW_COMPLEX -static void draw_full_border(const lv_area_t * area_inner, const lv_area_t * area_outer, const lv_area_t * clip, - lv_coord_t radius, bool radius_is_in, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode) -{ - - uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); - bool simple_mode = true; - if(other_mask_cnt) simple_mode = false; - - int32_t inner_w = lv_area_get_width(area_inner); - int32_t inner_h = lv_area_get_height(area_inner); - lv_coord_t border_width = area_outer->x2 - area_inner->x2; - - int32_t coords_out_w = lv_area_get_width(area_outer); - int32_t coords_out_h = lv_area_get_height(area_outer); - - int32_t rin; - int32_t rout; - if(radius_is_in) { - rin = radius; - int32_t short_side = LV_MIN(inner_w, inner_h); - if(rin > short_side >> 1) rin = short_side >> 1; - - /*Get the outer area*/ - rout = rin + border_width; - } - else { - rout = radius; - int32_t short_side = LV_MIN(coords_out_w, coords_out_h); - if(rout > short_side >> 1) rout = short_side >> 1; - - /*Get the outer area*/ - rin = rout - border_width; - if(rin < 0) rin = 0; - - } - - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp); - - /*Get clipped fill area which is the real draw area. - *It is always the same or inside `fill_area`*/ - lv_area_t draw_area; - bool is_common; - is_common = _lv_area_intersect(&draw_area, area_outer, clip); - if(is_common == false) return; - - const lv_area_t * disp_area = &draw_buf->area; - - /*Now `draw_area` has absolute coordinates. - *Make it relative to `disp_area` to simplify draw to `disp_buf`*/ - draw_area.x1 -= disp_area->x1; - draw_area.y1 -= disp_area->y1; - draw_area.x2 -= disp_area->x1; - draw_area.y2 -= disp_area->y1; - - int32_t draw_area_w = lv_area_get_width(&draw_area); - - /*Create inner the mask*/ - lv_draw_mask_radius_param_t mask_rin_param; - lv_draw_mask_radius_init(&mask_rin_param, area_inner, rin, true); - int16_t mask_rin_id = lv_draw_mask_add(&mask_rin_param, NULL); - - lv_draw_mask_radius_param_t mask_rout_param; - lv_draw_mask_radius_init(&mask_rout_param, area_outer, rout, false); - int16_t mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); - - lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w); - - int32_t corner_size = LV_MAX(rout, border_width - 1); - - int32_t h; - lv_draw_mask_res_t mask_res; - lv_area_t fill_area; - - /*Apply some optimization if there is no other mask*/ - if(simple_mode) { - /*Draw the upper corner area*/ - int32_t upper_corner_end = area_outer->y1 - disp_area->y1 + corner_size; - - fill_area.x1 = area_outer->x1; - fill_area.x2 = area_outer->x2; - fill_area.y1 = disp_area->y1 + draw_area.y1; - fill_area.y2 = fill_area.y1; - for(h = draw_area.y1; h <= upper_corner_end; h++) { - lv_memset_ff(mask_buf, draw_area_w); - mask_res = lv_draw_mask_apply(mask_buf, draw_buf->area.x1 + draw_area.x1, draw_buf->area.y1 + h, draw_area_w); - - lv_area_t fill_area2; - fill_area2.y1 = fill_area.y1; - fill_area2.y2 = fill_area.y2; - - fill_area2.x1 = area_outer->x1; - fill_area2.x2 = area_outer->x1 + rout - 1; - - _lv_blend_fill(clip, &fill_area2, color, mask_buf, mask_res, opa, blend_mode); - - /*Draw the top horizontal line*/ - if(fill_area2.y2 < area_outer->y1 + border_width) { - fill_area2.x1 = area_outer->x1 + rout; - fill_area2.x2 = area_outer->x2 - rout; - - _lv_blend_fill(clip, &fill_area2, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode); - } - - fill_area2.x1 = area_outer->x2 - rout + 1; - fill_area2.x2 = area_outer->x2; - - int32_t mask_ofs = (area_outer->x2 - rout + 1) - (draw_buf->area.x1 + draw_area.x1); - if(mask_ofs < 0) mask_ofs = 0; - _lv_blend_fill(clip, &fill_area2, color, mask_buf + mask_ofs, mask_res, opa, blend_mode); - - fill_area.y1++; - fill_area.y2++; - } - - /*Draw the lower corner area*/ - int32_t lower_corner_end = area_outer->y2 - disp_area->y1 - corner_size; - if(lower_corner_end <= upper_corner_end) lower_corner_end = upper_corner_end + 1; - fill_area.y1 = disp_area->y1 + lower_corner_end; - fill_area.y2 = fill_area.y1; - for(h = lower_corner_end; h <= draw_area.y2; h++) { - lv_memset_ff(mask_buf, draw_area_w); - mask_res = lv_draw_mask_apply(mask_buf, draw_buf->area.x1 + draw_area.x1, draw_buf->area.y1 + h, draw_area_w); - - lv_area_t fill_area2; - fill_area2.x1 = area_outer->x1; - fill_area2.x2 = area_outer->x1 + rout - 1; - fill_area2.y1 = fill_area.y1; - fill_area2.y2 = fill_area.y2; - - _lv_blend_fill(clip, &fill_area2, color, mask_buf, mask_res, opa, blend_mode); - - /*Draw the bottom horizontal line*/ - if(fill_area2.y2 > area_outer->y2 - border_width) { - fill_area2.x1 = area_outer->x1 + rout; - fill_area2.x2 = area_outer->x2 - rout; - - _lv_blend_fill(clip, &fill_area2, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode); - } - fill_area2.x1 = area_outer->x2 - rout + 1; - fill_area2.x2 = area_outer->x2; - - int32_t mask_ofs = (area_outer->x2 - rout + 1) - (draw_buf->area.x1 + draw_area.x1); - if(mask_ofs < 0) mask_ofs = 0; - _lv_blend_fill(clip, &fill_area2, color, mask_buf + mask_ofs, mask_res, opa, blend_mode); - - fill_area.y1++; - fill_area.y2++; - } - - /*Draw the left vertical part*/ - fill_area.y1 = area_outer->y1 + corner_size + 1; - fill_area.y2 = area_outer->y2 - corner_size - 1; - - fill_area.x1 = area_outer->x1; - fill_area.x2 = area_outer->x1 + border_width - 1; - _lv_blend_fill(clip, &fill_area, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode); - - /*Draw the right vertical border*/ - fill_area.x1 = area_outer->x2 - border_width + 1; - fill_area.x2 = area_outer->x2; - - _lv_blend_fill(clip, &fill_area, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode); - } - /*Process line by line if there is other mask too*/ - else { - fill_area.x1 = area_outer->x1; - fill_area.x2 = area_outer->x2; - fill_area.y1 = disp_area->y1 + draw_area.y1; - fill_area.y2 = fill_area.y1; - - for(h = draw_area.y1; h <= draw_area.y2; h++) { - lv_memset_ff(mask_buf, draw_area_w); - mask_res = lv_draw_mask_apply(mask_buf, draw_buf->area.x1 + draw_area.x1, draw_buf->area.y1 + h, draw_area_w); - - _lv_blend_fill(clip, &fill_area, color, mask_buf, mask_res, opa, blend_mode); - fill_area.y1++; - fill_area.y2++; - - } - } - lv_draw_mask_remove_id(mask_rin_id); - lv_draw_mask_remove_id(mask_rout_id); - lv_mem_buf_release(mask_buf); -} -#else /*LV_DRAW_COMPLEX*/ - -static void draw_simple_border(const lv_area_t * clip, const lv_area_t * area_inner, const lv_area_t * area_outer, - lv_color_t color, lv_opa_t opa, lv_border_side_t side) -{ - lv_area_t a; - /*Top*/ - a.x1 = area_outer->x1; - a.x2 = area_outer->x2; - a.y1 = area_outer->y1; - a.y2 = area_inner->y1; - if(side & LV_BORDER_SIDE_TOP) { - _lv_blend_fill(clip, &a, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, LV_BLEND_MODE_NORMAL); - } - - /*Bottom*/ - a.y1 = area_inner->y2; - a.y2 = area_outer->y2; - if(side & LV_BORDER_SIDE_BOTTOM) { - _lv_blend_fill(clip, &a, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, LV_BLEND_MODE_NORMAL); - } - /*Left*/ - a.x1 = area_outer->x1; - a.x2 = area_inner->x1; - a.y1 = (side & LV_BORDER_SIDE_TOP) ? area_inner->y1 : area_outer->y1; - a.y2 = (side & LV_BORDER_SIDE_BOTTOM) ? area_inner->y2 : area_outer->y2; - if(side & LV_BORDER_SIDE_LEFT) { - _lv_blend_fill(clip, &a, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, LV_BLEND_MODE_NORMAL); - } - - /*Right*/ - a.x1 = area_inner->x2; - a.x2 = area_outer->x2; - if(side & LV_BORDER_SIDE_RIGHT) { - _lv_blend_fill(clip, &a, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, LV_BLEND_MODE_NORMAL); - } - -} - -#endif - diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/msgbox/lv_msgbox.c b/lib/libesp32_lvgl/LVGL8/src/extra/widgets/msgbox/lv_msgbox.c deleted file mode 100644 index 01db38985..000000000 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/msgbox/lv_msgbox.c +++ /dev/null @@ -1,155 +0,0 @@ -/** - * @file lv_msgbox.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_msgbox.h" -#if LV_USE_MSGBOX - - -/********************* - * DEFINES - *********************/ -#define LV_MSGBOX_FLAG_AUTO_PARENT LV_OBJ_FLAG_WIDGET_1 /*Mark that the parent was automatically created*/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void msgbox_close_click_event_cb(lv_event_t * e); - -/********************** - * STATIC VARIABLES - **********************/ -const lv_obj_class_t lv_msgbox_class = {.base_class = &lv_obj_class}; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_obj_t * lv_msgbox_create(lv_obj_t * parent, const char * title, const char * txt, const char * btn_txts[], bool add_close_btn) -{ - LV_LOG_INFO("begin") - bool auto_parent = false; - if(parent == NULL) { - auto_parent = true; - parent = lv_obj_create(lv_layer_top()); - lv_obj_remove_style_all(parent); - lv_obj_clear_flag(parent, LV_OBJ_FLAG_IGNORE_LAYOUT); - lv_obj_set_style_bg_color(parent, lv_palette_main(LV_PALETTE_GREY), 0); - lv_obj_set_style_bg_opa(parent, LV_OPA_50, 0); - lv_obj_set_size(parent, LV_PCT(100), LV_PCT(100)); - } - - lv_obj_t * mbox = lv_obj_class_create_obj(&lv_msgbox_class, parent); - lv_obj_class_init_obj(mbox); - LV_ASSERT_MALLOC(mbox); - if(mbox == NULL) return NULL; - - if(auto_parent) lv_obj_add_flag(mbox, LV_MSGBOX_FLAG_AUTO_PARENT); - - lv_obj_set_size(mbox, LV_DPI_DEF * 2, LV_SIZE_CONTENT); - lv_obj_set_flex_flow(mbox, LV_FLEX_FLOW_ROW_WRAP); - lv_obj_set_flex_align(mbox, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START); - - lv_obj_t * label; - label = lv_label_create(mbox); - lv_label_set_text(label, title); - lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); - if(add_close_btn) lv_obj_set_flex_grow(label, 1); - else lv_obj_set_width(label, LV_PCT(100)); - - if(add_close_btn) { - lv_obj_t * close_btn = lv_btn_create(mbox); - lv_obj_set_ext_click_area(close_btn, LV_DPX(10)); - lv_obj_add_event_cb(close_btn, msgbox_close_click_event_cb, LV_EVENT_CLICKED, NULL); - label = lv_label_create(close_btn); - lv_label_set_text(label, LV_SYMBOL_CLOSE); - const lv_font_t * font = lv_obj_get_style_text_font(close_btn, LV_PART_MAIN); - lv_coord_t close_btn_size = lv_font_get_line_height(font) + LV_DPX(10); - lv_obj_set_size(close_btn, close_btn_size, close_btn_size); - lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); - } - - label = lv_label_create(mbox); - lv_label_set_text(label, txt); - lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP); - lv_obj_set_width(label, LV_PCT(100)); - - if(btn_txts) { - lv_obj_t * btns = lv_btnmatrix_create(mbox); - lv_btnmatrix_set_map(btns, btn_txts); - lv_btnmatrix_set_btn_ctrl_all(btns, LV_BTNMATRIX_CTRL_CLICK_TRIG | LV_BTNMATRIX_CTRL_NO_REPEAT); - - uint32_t btn_cnt = 0; - while(btn_txts[btn_cnt] && btn_txts[btn_cnt][0] != '\0') { - btn_cnt++; - } - - const lv_font_t * font = lv_obj_get_style_text_font(btns, LV_PART_ITEMS); - lv_coord_t btn_h = lv_font_get_line_height(font) + LV_DPI_DEF / 10; - lv_obj_set_size(btns, btn_cnt * (2 * LV_DPI_DEF / 3), btn_h); - lv_obj_add_flag(btns, LV_OBJ_FLAG_EVENT_BUBBLE); /*To see the event directly on the message box*/ - } - - return mbox; -} - - -lv_obj_t * lv_msgbox_get_title(lv_obj_t * mbox) -{ - return lv_obj_get_child(mbox, 0); -} - -lv_obj_t * lv_msgbox_get_close_btn(lv_obj_t * mbox) -{ - lv_obj_t * obj = lv_obj_get_child(mbox, 1); - if(lv_obj_check_type(obj, &lv_btn_class)) return obj; - else return NULL; -} - -lv_obj_t * lv_msgbox_get_text(lv_obj_t * mbox) -{ - return lv_obj_get_child(mbox, lv_obj_get_child_cnt(mbox) - 2); -} - -lv_obj_t * lv_msgbox_get_btns(lv_obj_t * mbox) -{ - return lv_obj_get_child(mbox, lv_obj_get_child_cnt(mbox) - 1); -} - -const char * lv_msgbox_get_active_btn_text(lv_obj_t * mbox) -{ - lv_obj_t * btnm = lv_msgbox_get_btns(mbox); - return lv_btnmatrix_get_btn_text(btnm, lv_btnmatrix_get_selected_btn(btnm)); -} - -void lv_msgbox_close(lv_obj_t * mbox) -{ - if(lv_obj_has_flag(mbox, LV_MSGBOX_FLAG_AUTO_PARENT)) lv_obj_del(lv_obj_get_parent(mbox)); - else lv_obj_del(mbox); -} - - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void msgbox_close_click_event_cb(lv_event_t * e) -{ - lv_obj_t * btn = lv_event_get_target(e); - lv_obj_t * mbox = lv_obj_get_parent(btn); - lv_msgbox_close(mbox); -} - -#endif /*LV_USE_MSGBOX*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/lv_conf_kconfig.h b/lib/libesp32_lvgl/LVGL8/src/lv_conf_kconfig.h deleted file mode 100644 index 1881b0ac4..000000000 --- a/lib/libesp32_lvgl/LVGL8/src/lv_conf_kconfig.h +++ /dev/null @@ -1,147 +0,0 @@ -/** * @file lv_conf_kconfig.h * Configs that needs special handling when LVGL is used with Kconfig */ - -#ifndef LV_CONF_KCONFIG_H -#define LV_CONF_KCONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef LV_CONF_KCONFIG_EXTERNAL_INCLUDE -# include LV_CONF_KCONFIG_EXTERNAL_INCLUDE -#else - -# if defined ESP_PLATFORM -# include "sdkconfig.h" -# include "esp_attr.h" -# endif - -# ifdef __NuttX__ -# include -# endif - -#endif /*LV_CONF_KCONFIG_EXTERNAL_INCLUDE*/ - -/******************* - * LV_MEM_SIZE - *******************/ - -#ifndef LV_MEM_SIZE -#if defined (CONFIG_LV_MEM_SIZE_KILOBYTES) -#define CONFIG_LV_MEM_SIZE (CONFIG_LV_MEM_SIZE_KILOBYTES * 1024U) -#endif -#endif - -/******************* - * LV COLOR CHROMA KEY - *******************/ - -#ifndef LV_COLOR_CHROMA_KEY -#if defined (CONFIG_LV_COLOR_CHROMA_KEY_HEX) -#define CONFIG_LV_COLOR_CHROMA_KEY lv_color_hex(CONFIG_LV_COLOR_CHROMA_KEY_HEX) -#else -#define CONFIG_LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /* pure green */ -#endif -#endif - -/******************** - * FONT SELECTION - *******************/ - -/** - * NOTE: In Kconfig instead of `LV_THEME_DEFAULT_FONT` - * `CONFIG_LV_THEME_DEFAULT_FONT_` is defined - * hence the large selection with if-s - */ - -/*------------------ - * DEFAULT FONT - *-----------------*/ -#ifndef LV_THEME_DEFAULT_FONT -#if defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_8 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_8 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_10 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_10 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_12 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_12 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_14 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_14 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_16 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_16 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_18 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_18 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_20 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_20 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_22 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_22 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_24 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_24 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_26 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_26 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_28 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_28 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_30 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_30 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_32 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_32 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_34 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_34 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_36 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_36 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_38 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_38 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_40 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_40 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_42 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_42 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_44 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_44 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_46 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_46 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT_48 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_48 -#elif defined CONFIG_LV_FONT_DEFAULT_UNSCII_8 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_unscii_8 -#elif defined CONFIG_LV_FONT_DEFAULT_UNSCII_16 -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_unscii_16 -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT12SUBPX -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_12_subpx -#elif defined CONFIG_LV_FONT_DEFAULT_MONTSERRAT28COMPRESSED -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_montserrat_28_compressed -#elif defined CONFIG_LV_FONT_DEFAULT_DEJAVU_16_PERSIAN_HEBREW -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_dejavu_16_persian_hebrew -#elif defined CONFIG_LV_FONT_DEFAULT_SIMSUN_16_CJK -#define CONFIG_LV_THEME_DEFAULT_FONT &lv_font_simsun_16_cjk -#endif -#endif - -/*------------------ - * TEXT ENCODING - *-----------------*/ -#ifndef LV_TEXT_ENC -#ifdef CONFIG_LV_TXT_ENC_UTF8 -#define CONFIG_LV_TXT_ENC LV_TXT_ENC_UTF8 -#elif defined CONFIG_LV_TXT_ENC_ASCII -#define CONFIG_LV_TXT_ENC LV_TXT_ENC_ASCII -#endif -#endif - -/*------------------ - * BIDI DIRECTION - *-----------------*/ - -#ifndef LV_BIDI_BASE_DIR_DEF -#ifdef CONFIG_LV_BASE_DIR_LTR -#define CONFIG_LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_LTR -#elif defined CONFIG_LV_BASE_DIR_RTL -#define CONFIG_LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_RTL -#elif defined CONFIG_LV_BASE_DIR_AUTO -#define CONFIG_LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO -#endif -#endif - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_CONF_KCONFIG_H*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_color.c b/lib/libesp32_lvgl/LVGL8/src/misc/lv_color.c deleted file mode 100644 index 7ec8c7196..000000000 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_color.c +++ /dev/null @@ -1,371 +0,0 @@ -/** - * @file lv_color.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_color.h" -#include "lv_log.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -LV_ATTRIBUTE_FAST_MEM void lv_color_fill(lv_color_t * buf, lv_color_t color, uint32_t px_num) -{ -#if LV_COLOR_DEPTH == 16 - uintptr_t buf_int = (uintptr_t) buf; - if(buf_int & 0x3) { - *buf = color; - buf++; - px_num--; - } - - uint32_t c32 = (uint32_t)color.full + ((uint32_t)color.full << 16); - uint32_t * buf32 = (uint32_t *)buf; - - while(px_num > 16) { - *buf32 = c32; - buf32++; - *buf32 = c32; - buf32++; - *buf32 = c32; - buf32++; - *buf32 = c32; - buf32++; - - *buf32 = c32; - buf32++; - *buf32 = c32; - buf32++; - *buf32 = c32; - buf32++; - *buf32 = c32; - buf32++; - - px_num -= 16; - } - - buf = (lv_color_t *)buf32; - - while(px_num) { - *buf = color; - buf++; - px_num --; - } -#else - while(px_num > 16) { - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; - - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; - - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; - - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; - - px_num -= 16; - } - while(px_num) { - *buf = color; - buf++; - px_num --; - } -#endif -} - -lv_color_t lv_color_lighten(lv_color_t c, lv_opa_t lvl) -{ - return lv_color_mix(lv_color_white(), c, lvl); -} - -lv_color_t lv_color_darken(lv_color_t c, lv_opa_t lvl) -{ - return lv_color_mix(lv_color_black(), c, lvl); -} - -lv_color_t lv_color_change_lightness(lv_color_t c, lv_opa_t lvl) -{ - /*It'd be better to convert the color to HSL, change L and convert back to RGB.*/ - if(lvl == LV_OPA_50) return c; - else if(lvl < LV_OPA_50) return lv_color_darken(c, (LV_OPA_50 - lvl) * 2); - else return lv_color_lighten(c, (lvl - LV_OPA_50) * 2); -} - -/** - * Convert a HSV color to RGB - * @param h hue [0..359] - * @param s saturation [0..100] - * @param v value [0..100] - * @return the given RGB color in RGB (with LV_COLOR_DEPTH depth) - */ -lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v) -{ - h = (uint32_t)((uint32_t)h * 255) / 360; - s = (uint16_t)((uint16_t)s * 255) / 100; - v = (uint16_t)((uint16_t)v * 255) / 100; - - uint8_t r, g, b; - - uint8_t region, remainder, p, q, t; - - if(s == 0) { - return lv_color_make(v, v, v); - } - - region = h / 43; - remainder = (h - (region * 43)) * 6; - - p = (v * (255 - s)) >> 8; - q = (v * (255 - ((s * remainder) >> 8))) >> 8; - t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8; - - switch(region) { - case 0: - r = v; - g = t; - b = p; - break; - case 1: - r = q; - g = v; - b = p; - break; - case 2: - r = p; - g = v; - b = t; - break; - case 3: - r = p; - g = q; - b = v; - break; - case 4: - r = t; - g = p; - b = v; - break; - default: - r = v; - g = p; - b = q; - break; - } - - lv_color_t result = lv_color_make(r, g, b); - return result; -} - -/** - * Convert a 32-bit RGB color to HSV - * @param r8 8-bit red - * @param g8 8-bit green - * @param b8 8-bit blue - * @return the given RGB color in HSV - */ -lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8) -{ - uint16_t r = ((uint32_t)r8 << 10) / 255; - uint16_t g = ((uint32_t)g8 << 10) / 255; - uint16_t b = ((uint32_t)b8 << 10) / 255; - - uint16_t rgbMin = r < g ? (r < b ? r : b) : (g < b ? g : b); - uint16_t rgbMax = r > g ? (r > b ? r : b) : (g > b ? g : b); - - lv_color_hsv_t hsv; - - // https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness - hsv.v = (100 * rgbMax) >> 10; - - int32_t delta = rgbMax - rgbMin; - if(delta < 3) { - hsv.h = 0; - hsv.s = 0; - return hsv; - } - - // https://en.wikipedia.org/wiki/HSL_and_HSV#Saturation - hsv.s = 100 * delta / rgbMax; - if(hsv.s < 3) { - hsv.h = 0; - return hsv; - } - - // https://en.wikipedia.org/wiki/HSL_and_HSV#Hue_and_chroma - int32_t h; - if(rgbMax == r) - h = (((g - b) << 10) / delta) + (g < b ? (6 << 10) : 0); // between yellow & magenta - else if(rgbMax == g) - h = (((b - r) << 10) / delta) + (2 << 10); // between cyan & yellow - else if(rgbMax == b) - h = (((r - g) << 10) / delta) + (4 << 10); // between magenta & cyan - else - h = 0; - h *= 60; - h >>= 10; - if(h < 0) h += 360; - - hsv.h = h; - return hsv; -} - -/** - * Convert a color to HSV - * @param color color - * @return the given color in HSV - */ -lv_color_hsv_t lv_color_to_hsv(lv_color_t color) -{ - lv_color32_t color32; - color32.full = lv_color_to32(color); - return lv_color_rgb_to_hsv(color32.ch.red, color32.ch.green, color32.ch.blue); -} - -lv_color_t lv_palette_main(lv_palette_t p) -{ - static const lv_color_t colors[] = { - LV_COLOR_MAKE(0xF4, 0x43, 0x36), LV_COLOR_MAKE(0xE9, 0x1E, 0x63), LV_COLOR_MAKE(0x9C, 0x27, 0xB0), LV_COLOR_MAKE(0x67, 0x3A, 0xB7), - LV_COLOR_MAKE(0x3F, 0x51, 0xB5), LV_COLOR_MAKE(0x21, 0x96, 0xF3), LV_COLOR_MAKE(0x03, 0xA9, 0xF4), LV_COLOR_MAKE(0x00, 0xBC, 0xD4), - LV_COLOR_MAKE(0x00, 0x96, 0x88), LV_COLOR_MAKE(0x4C, 0xAF, 0x50), LV_COLOR_MAKE(0x8B, 0xC3, 0x4A), LV_COLOR_MAKE(0xCD, 0xDC, 0x39), - LV_COLOR_MAKE(0xFF, 0xEB, 0x3B), LV_COLOR_MAKE(0xFF, 0xC1, 0x07), LV_COLOR_MAKE(0xFF, 0x98, 0x00), LV_COLOR_MAKE(0xFF, 0x57, 0x22), - LV_COLOR_MAKE(0x79, 0x55, 0x48), LV_COLOR_MAKE(0x60, 0x7D, 0x8B), LV_COLOR_MAKE(0x9E, 0x9E, 0x9E) - }; - - if(p >= _LV_PALETTE_LAST) { - LV_LOG_WARN("Invalid palette: %d", p); - return lv_color_black(); - } - - return colors[p]; - -} - -lv_color_t lv_palette_lighten(lv_palette_t p, uint8_t lvl) -{ - static const lv_color_t colors[][5] = { - {LV_COLOR_MAKE(0xEF, 0x53, 0x50), LV_COLOR_MAKE(0xE5, 0x73, 0x73), LV_COLOR_MAKE(0xEF, 0x9A, 0x9A), LV_COLOR_MAKE(0xFF, 0xCD, 0xD2), LV_COLOR_MAKE(0xFF, 0xEB, 0xEE)}, - {LV_COLOR_MAKE(0xEC, 0x40, 0x7A), LV_COLOR_MAKE(0xF0, 0x62, 0x92), LV_COLOR_MAKE(0xF4, 0x8F, 0xB1), LV_COLOR_MAKE(0xF8, 0xBB, 0xD0), LV_COLOR_MAKE(0xFC, 0xE4, 0xEC)}, - {LV_COLOR_MAKE(0xAB, 0x47, 0xBC), LV_COLOR_MAKE(0xBA, 0x68, 0xC8), LV_COLOR_MAKE(0xCE, 0x93, 0xD8), LV_COLOR_MAKE(0xE1, 0xBE, 0xE7), LV_COLOR_MAKE(0xF3, 0xE5, 0xF5)}, - {LV_COLOR_MAKE(0x7E, 0x57, 0xC2), LV_COLOR_MAKE(0x95, 0x75, 0xCD), LV_COLOR_MAKE(0xB3, 0x9D, 0xDB), LV_COLOR_MAKE(0xD1, 0xC4, 0xE9), LV_COLOR_MAKE(0xED, 0xE7, 0xF6)}, - {LV_COLOR_MAKE(0x5C, 0x6B, 0xC0), LV_COLOR_MAKE(0x79, 0x86, 0xCB), LV_COLOR_MAKE(0x9F, 0xA8, 0xDA), LV_COLOR_MAKE(0xC5, 0xCA, 0xE9), LV_COLOR_MAKE(0xE8, 0xEA, 0xF6)}, - {LV_COLOR_MAKE(0x42, 0xA5, 0xF5), LV_COLOR_MAKE(0x64, 0xB5, 0xF6), LV_COLOR_MAKE(0x90, 0xCA, 0xF9), LV_COLOR_MAKE(0xBB, 0xDE, 0xFB), LV_COLOR_MAKE(0xE3, 0xF2, 0xFD)}, - {LV_COLOR_MAKE(0x29, 0xB6, 0xF6), LV_COLOR_MAKE(0x4F, 0xC3, 0xF7), LV_COLOR_MAKE(0x81, 0xD4, 0xFA), LV_COLOR_MAKE(0xB3, 0xE5, 0xFC), LV_COLOR_MAKE(0xE1, 0xF5, 0xFE)}, - {LV_COLOR_MAKE(0x26, 0xC6, 0xDA), LV_COLOR_MAKE(0x4D, 0xD0, 0xE1), LV_COLOR_MAKE(0x80, 0xDE, 0xEA), LV_COLOR_MAKE(0xB2, 0xEB, 0xF2), LV_COLOR_MAKE(0xE0, 0xF7, 0xFA)}, - {LV_COLOR_MAKE(0x26, 0xA6, 0x9A), LV_COLOR_MAKE(0x4D, 0xB6, 0xAC), LV_COLOR_MAKE(0x80, 0xCB, 0xC4), LV_COLOR_MAKE(0xB2, 0xDF, 0xDB), LV_COLOR_MAKE(0xE0, 0xF2, 0xF1)}, - {LV_COLOR_MAKE(0x66, 0xBB, 0x6A), LV_COLOR_MAKE(0x81, 0xC7, 0x84), LV_COLOR_MAKE(0xA5, 0xD6, 0xA7), LV_COLOR_MAKE(0xC8, 0xE6, 0xC9), LV_COLOR_MAKE(0xE8, 0xF5, 0xE9)}, - {LV_COLOR_MAKE(0x9C, 0xCC, 0x65), LV_COLOR_MAKE(0xAE, 0xD5, 0x81), LV_COLOR_MAKE(0xC5, 0xE1, 0xA5), LV_COLOR_MAKE(0xDC, 0xED, 0xC8), LV_COLOR_MAKE(0xF1, 0xF8, 0xE9)}, - {LV_COLOR_MAKE(0xD4, 0xE1, 0x57), LV_COLOR_MAKE(0xDC, 0xE7, 0x75), LV_COLOR_MAKE(0xE6, 0xEE, 0x9C), LV_COLOR_MAKE(0xF0, 0xF4, 0xC3), LV_COLOR_MAKE(0xF9, 0xFB, 0xE7)}, - {LV_COLOR_MAKE(0xFF, 0xEE, 0x58), LV_COLOR_MAKE(0xFF, 0xF1, 0x76), LV_COLOR_MAKE(0xFF, 0xF5, 0x9D), LV_COLOR_MAKE(0xFF, 0xF9, 0xC4), LV_COLOR_MAKE(0xFF, 0xFD, 0xE7)}, - {LV_COLOR_MAKE(0xFF, 0xCA, 0x28), LV_COLOR_MAKE(0xFF, 0xD5, 0x4F), LV_COLOR_MAKE(0xFF, 0xE0, 0x82), LV_COLOR_MAKE(0xFF, 0xEC, 0xB3), LV_COLOR_MAKE(0xFF, 0xF8, 0xE1)}, - {LV_COLOR_MAKE(0xFF, 0xA7, 0x26), LV_COLOR_MAKE(0xFF, 0xB7, 0x4D), LV_COLOR_MAKE(0xFF, 0xCC, 0x80), LV_COLOR_MAKE(0xFF, 0xE0, 0xB2), LV_COLOR_MAKE(0xFF, 0xF3, 0xE0)}, - {LV_COLOR_MAKE(0xFF, 0x70, 0x43), LV_COLOR_MAKE(0xFF, 0x8A, 0x65), LV_COLOR_MAKE(0xFF, 0xAB, 0x91), LV_COLOR_MAKE(0xFF, 0xCC, 0xBC), LV_COLOR_MAKE(0xFB, 0xE9, 0xE7)}, - {LV_COLOR_MAKE(0x8D, 0x6E, 0x63), LV_COLOR_MAKE(0xA1, 0x88, 0x7F), LV_COLOR_MAKE(0xBC, 0xAA, 0xA4), LV_COLOR_MAKE(0xD7, 0xCC, 0xC8), LV_COLOR_MAKE(0xEF, 0xEB, 0xE9)}, - {LV_COLOR_MAKE(0x78, 0x90, 0x9C), LV_COLOR_MAKE(0x90, 0xA4, 0xAE), LV_COLOR_MAKE(0xB0, 0xBE, 0xC5), LV_COLOR_MAKE(0xCF, 0xD8, 0xDC), LV_COLOR_MAKE(0xEC, 0xEF, 0xF1)}, - {LV_COLOR_MAKE(0xBD, 0xBD, 0xBD), LV_COLOR_MAKE(0xE0, 0xE0, 0xE0), LV_COLOR_MAKE(0xEE, 0xEE, 0xEE), LV_COLOR_MAKE(0xF5, 0xF5, 0xF5), LV_COLOR_MAKE(0xFA, 0xFA, 0xFA)}, - }; - - if(p >= _LV_PALETTE_LAST) { - LV_LOG_WARN("Invalid palette: %d", p); - return lv_color_black(); - } - - if(lvl == 0 || lvl > 5) { - LV_LOG_WARN("Invalid level: %d. Must be 1..5", lvl); - return lv_color_black(); - } - - lvl--; - - return colors[p][lvl]; -} - -lv_color_t lv_palette_darken(lv_palette_t p, uint8_t lvl) -{ - static const lv_color_t colors[][4] = { - {LV_COLOR_MAKE(0xE5, 0x39, 0x35), LV_COLOR_MAKE(0xD3, 0x2F, 0x2F), LV_COLOR_MAKE(0xC6, 0x28, 0x28), LV_COLOR_MAKE(0xB7, 0x1C, 0x1C)}, - {LV_COLOR_MAKE(0xD8, 0x1B, 0x60), LV_COLOR_MAKE(0xC2, 0x18, 0x5B), LV_COLOR_MAKE(0xAD, 0x14, 0x57), LV_COLOR_MAKE(0x88, 0x0E, 0x4F)}, - {LV_COLOR_MAKE(0x8E, 0x24, 0xAA), LV_COLOR_MAKE(0x7B, 0x1F, 0xA2), LV_COLOR_MAKE(0x6A, 0x1B, 0x9A), LV_COLOR_MAKE(0x4A, 0x14, 0x8C)}, - {LV_COLOR_MAKE(0x5E, 0x35, 0xB1), LV_COLOR_MAKE(0x51, 0x2D, 0xA8), LV_COLOR_MAKE(0x45, 0x27, 0xA0), LV_COLOR_MAKE(0x31, 0x1B, 0x92)}, - {LV_COLOR_MAKE(0x39, 0x49, 0xAB), LV_COLOR_MAKE(0x30, 0x3F, 0x9F), LV_COLOR_MAKE(0x28, 0x35, 0x93), LV_COLOR_MAKE(0x1A, 0x23, 0x7E)}, - {LV_COLOR_MAKE(0x1E, 0x88, 0xE5), LV_COLOR_MAKE(0x19, 0x76, 0xD2), LV_COLOR_MAKE(0x15, 0x65, 0xC0), LV_COLOR_MAKE(0x0D, 0x47, 0xA1)}, - {LV_COLOR_MAKE(0x03, 0x9B, 0xE5), LV_COLOR_MAKE(0x02, 0x88, 0xD1), LV_COLOR_MAKE(0x02, 0x77, 0xBD), LV_COLOR_MAKE(0x01, 0x57, 0x9B)}, - {LV_COLOR_MAKE(0x00, 0xAC, 0xC1), LV_COLOR_MAKE(0x00, 0x97, 0xA7), LV_COLOR_MAKE(0x00, 0x83, 0x8F), LV_COLOR_MAKE(0x00, 0x60, 0x64)}, - {LV_COLOR_MAKE(0x00, 0x89, 0x7B), LV_COLOR_MAKE(0x00, 0x79, 0x6B), LV_COLOR_MAKE(0x00, 0x69, 0x5C), LV_COLOR_MAKE(0x00, 0x4D, 0x40)}, - {LV_COLOR_MAKE(0x43, 0xA0, 0x47), LV_COLOR_MAKE(0x38, 0x8E, 0x3C), LV_COLOR_MAKE(0x2E, 0x7D, 0x32), LV_COLOR_MAKE(0x1B, 0x5E, 0x20)}, - {LV_COLOR_MAKE(0x7C, 0xB3, 0x42), LV_COLOR_MAKE(0x68, 0x9F, 0x38), LV_COLOR_MAKE(0x55, 0x8B, 0x2F), LV_COLOR_MAKE(0x33, 0x69, 0x1E)}, - {LV_COLOR_MAKE(0xC0, 0xCA, 0x33), LV_COLOR_MAKE(0xAF, 0xB4, 0x2B), LV_COLOR_MAKE(0x9E, 0x9D, 0x24), LV_COLOR_MAKE(0x82, 0x77, 0x17)}, - {LV_COLOR_MAKE(0xFD, 0xD8, 0x35), LV_COLOR_MAKE(0xFB, 0xC0, 0x2D), LV_COLOR_MAKE(0xF9, 0xA8, 0x25), LV_COLOR_MAKE(0xF5, 0x7F, 0x17)}, - {LV_COLOR_MAKE(0xFF, 0xB3, 0x00), LV_COLOR_MAKE(0xFF, 0xA0, 0x00), LV_COLOR_MAKE(0xFF, 0x8F, 0x00), LV_COLOR_MAKE(0xFF, 0x6F, 0x00)}, - {LV_COLOR_MAKE(0xFB, 0x8C, 0x00), LV_COLOR_MAKE(0xF5, 0x7C, 0x00), LV_COLOR_MAKE(0xEF, 0x6C, 0x00), LV_COLOR_MAKE(0xE6, 0x51, 0x00)}, - {LV_COLOR_MAKE(0xF4, 0x51, 0x1E), LV_COLOR_MAKE(0xE6, 0x4A, 0x19), LV_COLOR_MAKE(0xD8, 0x43, 0x15), LV_COLOR_MAKE(0xBF, 0x36, 0x0C)}, - {LV_COLOR_MAKE(0x6D, 0x4C, 0x41), LV_COLOR_MAKE(0x5D, 0x40, 0x37), LV_COLOR_MAKE(0x4E, 0x34, 0x2E), LV_COLOR_MAKE(0x3E, 0x27, 0x23)}, - {LV_COLOR_MAKE(0x54, 0x6E, 0x7A), LV_COLOR_MAKE(0x45, 0x5A, 0x64), LV_COLOR_MAKE(0x37, 0x47, 0x4F), LV_COLOR_MAKE(0x26, 0x32, 0x38)}, - {LV_COLOR_MAKE(0x75, 0x75, 0x75), LV_COLOR_MAKE(0x61, 0x61, 0x61), LV_COLOR_MAKE(0x42, 0x42, 0x42), LV_COLOR_MAKE(0x21, 0x21, 0x21)}, - }; - - if(p >= _LV_PALETTE_LAST) { - LV_LOG_WARN("Invalid palette: %d", p); - return lv_color_black(); - } - - if(lvl == 0 || lvl > 4) { - LV_LOG_WARN("Invalid level: %d. Must be 1..4", lvl); - return lv_color_black(); - } - - lvl--; - - return colors[p][lvl]; -} - - diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_tlsf.c b/lib/libesp32_lvgl/LVGL8/src/misc/lv_tlsf.c deleted file mode 100644 index 998f0f055..000000000 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_tlsf.c +++ /dev/null @@ -1,1288 +0,0 @@ -#include "../lv_conf_internal.h" -#if LV_MEM_CUSTOM == 0 - -#include -#include -#include "lv_tlsf.h" -#include "lv_mem.h" -#include "lv_log.h" -#include "lv_assert.h" -#define printf LV_LOG_ERROR - -#define TLSF_MAX_POOL_SIZE LV_MEM_SIZE - -#if !defined(_DEBUG) -#define _DEBUG 0 -#endif - -#if defined(__cplusplus) -#define tlsf_decl inline -#else -#define tlsf_decl static -#endif - -/* -** Architecture-specific bit manipulation routines. -** -** TLSF achieves O(1) cost for malloc and free operations by limiting -** the search for a free block to a free list of guaranteed size -** adequate to fulfill the request, combined with efficient free list -** queries using bitmasks and architecture-specific bit-manipulation -** routines. -** -** Most modern processors provide instructions to count leading zeroes -** in a word, find the lowest and highest set bit, etc. These -** specific implementations will be used when available, falling back -** to a reasonably efficient generic implementation. -** -** NOTE: TLSF spec relies on ffs/fls returning value 0..31. -** ffs/fls return 1-32 by default, returning 0 for error. -*/ - -/* -** Detect whether or not we are building for a 32- or 64-bit (LP/LLP) -** architecture. There is no reliable portable method at compile-time. -*/ -#if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) \ - || defined (_WIN64) || defined (__LP64__) || defined (__LLP64__) -#define TLSF_64BIT -#endif - -/* -** Returns one plus the index of the most significant 1-bit of n, -** or if n is zero, returns zero. -*/ -#ifdef TLSF_64BIT -#define TLSF_FLS(n) ((n) & 0xffffffff00000000ull ? 32 + TLSF_FLS32((size_t)(n) >> 32) : TLSF_FLS32(n)) -#else -#define TLSF_FLS(n) TLSF_FLS32(n) -#endif - -#define TLSF_FLS32(n) ((n) & 0xffff0000 ? 16 + TLSF_FLS16((n) >> 16) : TLSF_FLS16(n)) -#define TLSF_FLS16(n) ((n) & 0xff00 ? 8 + TLSF_FLS8 ((n) >> 8) : TLSF_FLS8 (n)) -#define TLSF_FLS8(n) ((n) & 0xf0 ? 4 + TLSF_FLS4 ((n) >> 4) : TLSF_FLS4 (n)) -#define TLSF_FLS4(n) ((n) & 0xc ? 2 + TLSF_FLS2 ((n) >> 2) : TLSF_FLS2 (n)) -#define TLSF_FLS2(n) ((n) & 0x2 ? 1 + TLSF_FLS1 ((n) >> 1) : TLSF_FLS1 (n)) -#define TLSF_FLS1(n) ((n) & 0x1 ? 1 : 0) - -/* -** Returns round up value of log2(n). -** Note: it is used at compile time. -*/ -#define TLSF_LOG2_CEIL(n) ((n) & (n - 1) ? TLSF_FLS(n) : TLSF_FLS(n) - 1) - -/* -** gcc 3.4 and above have builtin support, specialized for architecture. -** Some compilers masquerade as gcc; patchlevel test filters them out. -*/ -#if defined (__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \ - && defined (__GNUC_PATCHLEVEL__) - -#if defined (__SNC__) -/* SNC for Playstation 3. */ - -tlsf_decl int tlsf_ffs(unsigned int word) -{ - const unsigned int reverse = word & (~word + 1); - const int bit = 32 - __builtin_clz(reverse); - return bit - 1; -} - -#else - -tlsf_decl int tlsf_ffs(unsigned int word) -{ - return __builtin_ffs(word) - 1; -} - -#endif - -tlsf_decl int tlsf_fls(unsigned int word) -{ - const int bit = word ? 32 - __builtin_clz(word) : 0; - return bit - 1; -} - -#elif defined (_MSC_VER) && (_MSC_VER >= 1400) && (defined (_M_IX86) || defined (_M_X64)) -/* Microsoft Visual C++ support on x86/X64 architectures. */ - -#include - -#pragma intrinsic(_BitScanReverse) -#pragma intrinsic(_BitScanForward) - -tlsf_decl int tlsf_fls(unsigned int word) -{ - unsigned long index; - return _BitScanReverse(&index, word) ? index : -1; -} - -tlsf_decl int tlsf_ffs(unsigned int word) -{ - unsigned long index; - return _BitScanForward(&index, word) ? index : -1; -} - -#elif defined (_MSC_VER) && defined (_M_PPC) -/* Microsoft Visual C++ support on PowerPC architectures. */ - -#include - -tlsf_decl int tlsf_fls(unsigned int word) -{ - const int bit = 32 - _CountLeadingZeros(word); - return bit - 1; -} - -tlsf_decl int tlsf_ffs(unsigned int word) -{ - const unsigned int reverse = word & (~word + 1); - const int bit = 32 - _CountLeadingZeros(reverse); - return bit - 1; -} - -#elif defined (__ARMCC_VERSION) -/* RealView Compilation Tools for ARM */ - -tlsf_decl int tlsf_ffs(unsigned int word) -{ - const unsigned int reverse = word & (~word + 1); - const int bit = 32 - __clz(reverse); - return bit - 1; -} - -tlsf_decl int tlsf_fls(unsigned int word) -{ - const int bit = word ? 32 - __clz(word) : 0; - return bit - 1; -} - -#elif defined (__ghs__) -/* Green Hills support for PowerPC */ - -#include - -tlsf_decl int tlsf_ffs(unsigned int word) -{ - const unsigned int reverse = word & (~word + 1); - const int bit = 32 - __CLZ32(reverse); - return bit - 1; -} - -tlsf_decl int tlsf_fls(unsigned int word) -{ - const int bit = word ? 32 - __CLZ32(word) : 0; - return bit - 1; -} - -#else -/* Fall back to generic implementation. */ - -/* Implement ffs in terms of fls. */ -tlsf_decl int tlsf_ffs(unsigned int word) -{ - const unsigned int reverse = word & (~word + 1); - return TLSF_FLS32(reverse) - 1; -} - -tlsf_decl int tlsf_fls(unsigned int word) -{ - return TLSF_FLS32(word) - 1; -} - -#endif - -/* Possibly 64-bit version of tlsf_fls. */ -#if defined (TLSF_64BIT) -tlsf_decl int tlsf_fls_sizet(size_t size) -{ - int high = (int)(size >> 32); - int bits = 0; - if (high) - { - bits = 32 + tlsf_fls(high); - } - else - { - bits = tlsf_fls((int)size & 0xffffffff); - - } - return bits; -} -#else -#define tlsf_fls_sizet tlsf_fls -#endif - -#undef tlsf_decl - -/* -** Constants. -*/ - -/* Public constants: may be modified. */ -enum tlsf_public -{ - /* log2 of number of linear subdivisions of block sizes. Larger - ** values require more memory in the control structure. Values of - ** 4 or 5 are typical. - */ - SL_INDEX_COUNT_LOG2 = 5, -}; - -/* Private constants: do not modify. */ -enum tlsf_private -{ -#if defined (TLSF_64BIT) - /* All allocation sizes and addresses are aligned to 8 bytes. */ - ALIGN_SIZE_LOG2 = 3, -#else - /* All allocation sizes and addresses are aligned to 4 bytes. */ - ALIGN_SIZE_LOG2 = 2, -#endif - ALIGN_SIZE = (1 << ALIGN_SIZE_LOG2), - - /* - ** We support allocations of sizes up to (1 << FL_INDEX_MAX) bits. - ** However, because we linearly subdivide the second-level lists, and - ** our minimum size granularity is 4 bytes, it doesn't make sense to - ** create first-level lists for sizes smaller than SL_INDEX_COUNT * 4, - ** or (1 << (SL_INDEX_COUNT_LOG2 + 2)) bytes, as there we will be - ** trying to split size ranges into more slots than we have available. - ** Instead, we calculate the minimum threshold size, and place all - ** blocks below that size into the 0th first-level list. - */ - -#if defined (TLSF_MAX_POOL_SIZE) - FL_INDEX_MAX = TLSF_LOG2_CEIL(TLSF_MAX_POOL_SIZE), -#elif defined (TLSF_64BIT) - /* - ** TODO: We can increase this to support larger sizes, at the expense - ** of more overhead in the TLSF structure. - */ - FL_INDEX_MAX = 32, -#else - FL_INDEX_MAX = 30, -#endif - SL_INDEX_COUNT = (1 << SL_INDEX_COUNT_LOG2), - FL_INDEX_SHIFT = (SL_INDEX_COUNT_LOG2 + ALIGN_SIZE_LOG2), - FL_INDEX_COUNT = (FL_INDEX_MAX - FL_INDEX_SHIFT + 1), - - SMALL_BLOCK_SIZE = (1 << FL_INDEX_SHIFT), -}; - -/* -** Cast and min/max macros. -*/ - -#define tlsf_cast(t, exp) ((t) (exp)) -#define tlsf_min(a, b) ((a) < (b) ? (a) : (b)) -#define tlsf_max(a, b) ((a) > (b) ? (a) : (b)) - -/* -** Set assert macro, if it has not been provided by the user. -*/ -#define tlsf_assert LV_ASSERT - -#if !defined (tlsf_assert) -#define tlsf_assert assert -#endif - -/* -** Static assertion mechanism. -*/ - -#define _tlsf_glue2(x, y) x ## y -#define _tlsf_glue(x, y) _tlsf_glue2(x, y) -#define tlsf_static_assert(exp) \ - typedef char _tlsf_glue(static_assert, __LINE__) [(exp) ? 1 : -1] - -/* This code has been tested on 32- and 64-bit (LP/LLP) architectures. */ -tlsf_static_assert(sizeof(int) * CHAR_BIT == 32); -tlsf_static_assert(sizeof(size_t) * CHAR_BIT >= 32); -tlsf_static_assert(sizeof(size_t) * CHAR_BIT <= 64); - -/* SL_INDEX_COUNT must be <= number of bits in sl_bitmap's storage type. */ -tlsf_static_assert(sizeof(unsigned int) * CHAR_BIT >= SL_INDEX_COUNT); - -/* Ensure we've properly tuned our sizes. */ -tlsf_static_assert(ALIGN_SIZE == SMALL_BLOCK_SIZE / SL_INDEX_COUNT); - -/* -** Data structures and associated constants. -*/ - -/* -** Block header structure. -** -** There are several implementation subtleties involved: -** - The prev_phys_block field is only valid if the previous block is free. -** - The prev_phys_block field is actually stored at the end of the -** previous block. It appears at the beginning of this structure only to -** simplify the implementation. -** - The next_free / prev_free fields are only valid if the block is free. -*/ -typedef struct block_header_t -{ - /* Points to the previous physical block. */ - struct block_header_t* prev_phys_block; - - /* The size of this block, excluding the block header. */ - size_t size; - - /* Next and previous free blocks. */ - struct block_header_t* next_free; - struct block_header_t* prev_free; -} block_header_t; - -/* -** Since block sizes are always at least a multiple of 4, the two least -** significant bits of the size field are used to store the block status: -** - bit 0: whether block is busy or free -** - bit 1: whether previous block is busy or free -*/ -static const size_t block_header_free_bit = 1 << 0; -static const size_t block_header_prev_free_bit = 1 << 1; - -/* -** The size of the block header exposed to used blocks is the size field. -** The prev_phys_block field is stored *inside* the previous free block. -*/ -static const size_t block_header_overhead = sizeof(size_t); - -/* User data starts directly after the size field in a used block. */ -static const size_t block_start_offset = - offsetof(block_header_t, size) + sizeof(size_t); - -/* -** A free block must be large enough to store its header minus the size of -** the prev_phys_block field, and no larger than the number of addressable -** bits for FL_INDEX. -*/ -static const size_t block_size_min = - sizeof(block_header_t) - sizeof(block_header_t*); -static const size_t block_size_max = tlsf_cast(size_t, 1) << FL_INDEX_MAX; - - -/* The TLSF control structure. */ -typedef struct control_t -{ - /* Empty lists point at this block to indicate they are free. */ - block_header_t block_null; - - /* Bitmaps for free lists. */ - unsigned int fl_bitmap; - unsigned int sl_bitmap[FL_INDEX_COUNT]; - - /* Head of free lists. */ - block_header_t* blocks[FL_INDEX_COUNT][SL_INDEX_COUNT]; -} control_t; - -/* A type used for casting when doing pointer arithmetic. */ -typedef ptrdiff_t tlsfptr_t; - -/* -** block_header_t member functions. -*/ - -static size_t block_size(const block_header_t* block) -{ - return block->size & ~(block_header_free_bit | block_header_prev_free_bit); -} - -static void block_set_size(block_header_t* block, size_t size) -{ - const size_t oldsize = block->size; - block->size = size | (oldsize & (block_header_free_bit | block_header_prev_free_bit)); -} - -static int block_is_last(const block_header_t* block) -{ - return block_size(block) == 0; -} - -static int block_is_free(const block_header_t* block) -{ - return tlsf_cast(int, block->size & block_header_free_bit); -} - -static void block_set_free(block_header_t* block) -{ - block->size |= block_header_free_bit; -} - -static void block_set_used(block_header_t* block) -{ - block->size &= ~block_header_free_bit; -} - -static int block_is_prev_free(const block_header_t* block) -{ - return tlsf_cast(int, block->size & block_header_prev_free_bit); -} - -static void block_set_prev_free(block_header_t* block) -{ - block->size |= block_header_prev_free_bit; -} - -static void block_set_prev_used(block_header_t* block) -{ - block->size &= ~block_header_prev_free_bit; -} - -static block_header_t* block_from_ptr(const void* ptr) -{ - return tlsf_cast(block_header_t*, - tlsf_cast(unsigned char*, ptr) - block_start_offset); -} - -static void* block_to_ptr(const block_header_t* block) -{ - return tlsf_cast(void*, - tlsf_cast(unsigned char*, block) + block_start_offset); -} - -/* Return location of next block after block of given size. */ -static block_header_t* offset_to_block(const void* ptr, size_t size) -{ - return tlsf_cast(block_header_t*, tlsf_cast(tlsfptr_t, ptr) + size); -} - -/* Return location of previous block. */ -static block_header_t* block_prev(const block_header_t* block) -{ - tlsf_assert(block_is_prev_free(block) && "previous block must be free"); - return block->prev_phys_block; -} - -/* Return location of next existing block. */ -static block_header_t* block_next(const block_header_t* block) -{ - block_header_t* next = offset_to_block(block_to_ptr(block), - block_size(block) - block_header_overhead); - tlsf_assert(!block_is_last(block)); - return next; -} - -/* Link a new block with its physical neighbor, return the neighbor. */ -static block_header_t* block_link_next(block_header_t* block) -{ - block_header_t* next = block_next(block); - next->prev_phys_block = block; - return next; -} - -static void block_mark_as_free(block_header_t* block) -{ - /* Link the block to the next block, first. */ - block_header_t* next = block_link_next(block); - block_set_prev_free(next); - block_set_free(block); -} - -static void block_mark_as_used(block_header_t* block) -{ - block_header_t* next = block_next(block); - block_set_prev_used(next); - block_set_used(block); -} - -static size_t align_up(size_t x, size_t align) -{ - tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two"); - return (x + (align - 1)) & ~(align - 1); -} - -static size_t align_down(size_t x, size_t align) -{ - tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two"); - return x - (x & (align - 1)); -} - -static void* align_ptr(const void* ptr, size_t align) -{ - const tlsfptr_t aligned = - (tlsf_cast(tlsfptr_t, ptr) + (align - 1)) & ~(align - 1); - tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two"); - return tlsf_cast(void*, aligned); -} - -/* -** Adjust an allocation size to be aligned to word size, and no smaller -** than internal minimum. -*/ -static size_t adjust_request_size(size_t size, size_t align) -{ - size_t adjust = 0; - if (size) - { - const size_t aligned = align_up(size, align); - - /* aligned sized must not exceed block_size_max or we'll go out of bounds on sl_bitmap */ - if (aligned < block_size_max) - { - adjust = tlsf_max(aligned, block_size_min); - } - } - return adjust; -} - -/* -** TLSF utility functions. In most cases, these are direct translations of -** the documentation found in the white paper. -*/ - -static void mapping_insert(size_t size, int* fli, int* sli) -{ - int fl, sl; - if (size < SMALL_BLOCK_SIZE) - { - /* Store small blocks in first list. */ - fl = 0; - sl = tlsf_cast(int, size) / (SMALL_BLOCK_SIZE / SL_INDEX_COUNT); - } - else - { - fl = tlsf_fls_sizet(size); - sl = tlsf_cast(int, size >> (fl - SL_INDEX_COUNT_LOG2)) ^ (1 << SL_INDEX_COUNT_LOG2); - fl -= (FL_INDEX_SHIFT - 1); - } - *fli = fl; - *sli = sl; -} - -/* This version rounds up to the next block size (for allocations) */ -static void mapping_search(size_t size, int* fli, int* sli) -{ - if (size >= SMALL_BLOCK_SIZE) - { - const size_t round = (1 << (tlsf_fls_sizet(size) - SL_INDEX_COUNT_LOG2)) - 1; - size += round; - } - mapping_insert(size, fli, sli); -} - -static block_header_t* search_suitable_block(control_t* control, int* fli, int* sli) -{ - int fl = *fli; - int sl = *sli; - - /* - ** First, search for a block in the list associated with the given - ** fl/sl index. - */ - unsigned int sl_map = control->sl_bitmap[fl] & (~0U << sl); - if (!sl_map) - { - /* No block exists. Search in the next largest first-level list. */ - const unsigned int fl_map = control->fl_bitmap & (~0U << (fl + 1)); - if (!fl_map) - { - /* No free blocks available, memory has been exhausted. */ - return 0; - } - - fl = tlsf_ffs(fl_map); - *fli = fl; - sl_map = control->sl_bitmap[fl]; - } - tlsf_assert(sl_map && "internal error - second level bitmap is null"); - sl = tlsf_ffs(sl_map); - *sli = sl; - - /* Return the first block in the free list. */ - return control->blocks[fl][sl]; -} - -/* Remove a free block from the free list.*/ -static void remove_free_block(control_t* control, block_header_t* block, int fl, int sl) -{ - block_header_t* prev = block->prev_free; - block_header_t* next = block->next_free; - tlsf_assert(prev && "prev_free field can not be null"); - tlsf_assert(next && "next_free field can not be null"); - next->prev_free = prev; - prev->next_free = next; - - /* If this block is the head of the free list, set new head. */ - if (control->blocks[fl][sl] == block) - { - control->blocks[fl][sl] = next; - - /* If the new head is null, clear the bitmap. */ - if (next == &control->block_null) - { - control->sl_bitmap[fl] &= ~(1U << sl); - - /* If the second bitmap is now empty, clear the fl bitmap. */ - if (!control->sl_bitmap[fl]) - { - control->fl_bitmap &= ~(1U << fl); - } - } - } -} - -/* Insert a free block into the free block list. */ -static void insert_free_block(control_t* control, block_header_t* block, int fl, int sl) -{ - block_header_t* current = control->blocks[fl][sl]; - tlsf_assert(current && "free list cannot have a null entry"); - tlsf_assert(block && "cannot insert a null entry into the free list"); - block->next_free = current; - block->prev_free = &control->block_null; - current->prev_free = block; - - tlsf_assert(block_to_ptr(block) == align_ptr(block_to_ptr(block), ALIGN_SIZE) - && "block not aligned properly"); - /* - ** Insert the new block at the head of the list, and mark the first- - ** and second-level bitmaps appropriately. - */ - control->blocks[fl][sl] = block; - control->fl_bitmap |= (1U << fl); - control->sl_bitmap[fl] |= (1U << sl); -} - -/* Remove a given block from the free list. */ -static void block_remove(control_t* control, block_header_t* block) -{ - int fl, sl; - mapping_insert(block_size(block), &fl, &sl); - remove_free_block(control, block, fl, sl); -} - -/* Insert a given block into the free list. */ -static void block_insert(control_t* control, block_header_t* block) -{ - int fl, sl; - mapping_insert(block_size(block), &fl, &sl); - insert_free_block(control, block, fl, sl); -} - -static int block_can_split(block_header_t* block, size_t size) -{ - return block_size(block) >= sizeof(block_header_t) + size; -} - -/* Split a block into two, the second of which is free. */ -static block_header_t* block_split(block_header_t* block, size_t size) -{ - /* Calculate the amount of space left in the remaining block. */ - block_header_t* remaining = - offset_to_block(block_to_ptr(block), size - block_header_overhead); - - const size_t remain_size = block_size(block) - (size + block_header_overhead); - - tlsf_assert(block_to_ptr(remaining) == align_ptr(block_to_ptr(remaining), ALIGN_SIZE) - && "remaining block not aligned properly"); - - tlsf_assert(block_size(block) == remain_size + size + block_header_overhead); - block_set_size(remaining, remain_size); - tlsf_assert(block_size(remaining) >= block_size_min && "block split with invalid size"); - - block_set_size(block, size); - block_mark_as_free(remaining); - - return remaining; -} - -/* Absorb a free block's storage into an adjacent previous free block. */ -static block_header_t* block_absorb(block_header_t* prev, block_header_t* block) -{ - tlsf_assert(!block_is_last(prev) && "previous block can't be last"); - /* Note: Leaves flags untouched. */ - prev->size += block_size(block) + block_header_overhead; - block_link_next(prev); - return prev; -} - -/* Merge a just-freed block with an adjacent previous free block. */ -static block_header_t* block_merge_prev(control_t* control, block_header_t* block) -{ - if (block_is_prev_free(block)) - { - block_header_t* prev = block_prev(block); - tlsf_assert(prev && "prev physical block can't be null"); - tlsf_assert(block_is_free(prev) && "prev block is not free though marked as such"); - block_remove(control, prev); - block = block_absorb(prev, block); - } - - return block; -} - -/* Merge a just-freed block with an adjacent free block. */ -static block_header_t* block_merge_next(control_t* control, block_header_t* block) -{ - block_header_t* next = block_next(block); - tlsf_assert(next && "next physical block can't be null"); - - if (block_is_free(next)) - { - tlsf_assert(!block_is_last(block) && "previous block can't be last"); - block_remove(control, next); - block = block_absorb(block, next); - } - - return block; -} - -/* Trim any trailing block space off the end of a block, return to pool. */ -static void block_trim_free(control_t* control, block_header_t* block, size_t size) -{ - tlsf_assert(block_is_free(block) && "block must be free"); - if (block_can_split(block, size)) - { - block_header_t* remaining_block = block_split(block, size); - block_link_next(block); - block_set_prev_free(remaining_block); - block_insert(control, remaining_block); - } -} - -/* Trim any trailing block space off the end of a used block, return to pool. */ -static void block_trim_used(control_t* control, block_header_t* block, size_t size) -{ - tlsf_assert(!block_is_free(block) && "block must be used"); - if (block_can_split(block, size)) - { - /* If the next block is free, we must coalesce. */ - block_header_t* remaining_block = block_split(block, size); - block_set_prev_used(remaining_block); - - remaining_block = block_merge_next(control, remaining_block); - block_insert(control, remaining_block); - } -} - -static block_header_t* block_trim_free_leading(control_t* control, block_header_t* block, size_t size) -{ - block_header_t* remaining_block = block; - if (block_can_split(block, size)) - { - /* We want the 2nd block. */ - remaining_block = block_split(block, size - block_header_overhead); - block_set_prev_free(remaining_block); - - block_link_next(block); - block_insert(control, block); - } - - return remaining_block; -} - -static block_header_t* block_locate_free(control_t* control, size_t size) -{ - int fl = 0, sl = 0; - block_header_t* block = 0; - - if (size) - { - mapping_search(size, &fl, &sl); - - /* - ** mapping_search can futz with the size, so for excessively large sizes it can sometimes wind up - ** with indices that are off the end of the block array. - ** So, we protect against that here, since this is the only callsite of mapping_search. - ** Note that we don't need to check sl, since it comes from a modulo operation that guarantees it's always in range. - */ - if (fl < FL_INDEX_COUNT) - { - block = search_suitable_block(control, &fl, &sl); - } - } - - if (block) - { - tlsf_assert(block_size(block) >= size); - remove_free_block(control, block, fl, sl); - } - - return block; -} - -static void* block_prepare_used(control_t* control, block_header_t* block, size_t size) -{ - void* p = 0; - if (block) - { - tlsf_assert(size && "size must be non-zero"); - block_trim_free(control, block, size); - block_mark_as_used(block); - p = block_to_ptr(block); - } - return p; -} - -/* Clear structure and point all empty lists at the null block. */ -static void control_constructor(control_t* control) -{ - int i, j; - - control->block_null.next_free = &control->block_null; - control->block_null.prev_free = &control->block_null; - - control->fl_bitmap = 0; - for (i = 0; i < FL_INDEX_COUNT; ++i) - { - control->sl_bitmap[i] = 0; - for (j = 0; j < SL_INDEX_COUNT; ++j) - { - control->blocks[i][j] = &control->block_null; - } - } -} - -/* -** Debugging utilities. -*/ - -typedef struct integrity_t -{ - int prev_status; - int status; -} integrity_t; - -#define tlsf_insist(x) { tlsf_assert(x); if (!(x)) { status--; } } - -static void integrity_walker(void* ptr, size_t size, int used, void* user) -{ - block_header_t* block = block_from_ptr(ptr); - integrity_t* integ = tlsf_cast(integrity_t*, user); - const int this_prev_status = block_is_prev_free(block) ? 1 : 0; - const int this_status = block_is_free(block) ? 1 : 0; - const size_t this_block_size = block_size(block); - - int status = 0; - (void)used; - tlsf_insist(integ->prev_status == this_prev_status && "prev status incorrect"); - tlsf_insist(size == this_block_size && "block size incorrect"); - - integ->prev_status = this_status; - integ->status += status; -} - -int lv_tlsf_check(lv_tlsf_t tlsf) -{ - int i, j; - - control_t* control = tlsf_cast(control_t*, tlsf); - int status = 0; - - /* Check that the free lists and bitmaps are accurate. */ - for (i = 0; i < FL_INDEX_COUNT; ++i) - { - for (j = 0; j < SL_INDEX_COUNT; ++j) - { - const int fl_map = control->fl_bitmap & (1U << i); - const int sl_list = control->sl_bitmap[i]; - const int sl_map = sl_list & (1U << j); - const block_header_t* block = control->blocks[i][j]; - - /* Check that first- and second-level lists agree. */ - if (!fl_map) - { - tlsf_insist(!sl_map && "second-level map must be null"); - } - - if (!sl_map) - { - tlsf_insist(block == &control->block_null && "block list must be null"); - continue; - } - - /* Check that there is at least one free block. */ - tlsf_insist(sl_list && "no free blocks in second-level map"); - tlsf_insist(block != &control->block_null && "block should not be null"); - - while (block != &control->block_null) - { - int fli, sli; - tlsf_insist(block_is_free(block) && "block should be free"); - tlsf_insist(!block_is_prev_free(block) && "blocks should have coalesced"); - tlsf_insist(!block_is_free(block_next(block)) && "blocks should have coalesced"); - tlsf_insist(block_is_prev_free(block_next(block)) && "block should be free"); - tlsf_insist(block_size(block) >= block_size_min && "block not minimum size"); - - mapping_insert(block_size(block), &fli, &sli); - tlsf_insist(fli == i && sli == j && "block size indexed in wrong list"); - block = block->next_free; - } - } - } - - return status; -} - -#undef tlsf_insist - -static void default_walker(void* ptr, size_t size, int used, void* user) -{ - (void)user; - printf("\t%p %s size: %x (%p)\n", ptr, used ? "used" : "free", (unsigned int)size, (void*)block_from_ptr(ptr)); -} - -void lv_tlsf_walk_pool(lv_pool_t pool, lv_tlsf_walker walker, void* user) -{ - lv_tlsf_walker pool_walker = walker ? walker : default_walker; - block_header_t* block = - offset_to_block(pool, -(int)block_header_overhead); - - while (block && !block_is_last(block)) - { - pool_walker( - block_to_ptr(block), - block_size(block), - !block_is_free(block), - user); - block = block_next(block); - } -} - -size_t lv_tlsf_block_size(void* ptr) -{ - size_t size = 0; - if (ptr) - { - const block_header_t* block = block_from_ptr(ptr); - size = block_size(block); - } - return size; -} - -int lv_tlsf_check_pool(lv_pool_t pool) -{ - /* Check that the blocks are physically correct. */ - integrity_t integ = { 0, 0 }; - lv_tlsf_walk_pool(pool, integrity_walker, &integ); - - return integ.status; -} - -/* -** Size of the TLSF structures in a given memory block passed to -** lv_tlsf_create, equal to the size of a control_t -*/ -size_t lv_tlsf_size(void) -{ - return sizeof(control_t); -} - -size_t lv_tlsf_align_size(void) -{ - return ALIGN_SIZE; -} - -size_t lv_tlsf_block_size_min(void) -{ - return block_size_min; -} - -size_t lv_tlsf_block_size_max(void) -{ - return block_size_max; -} - -/* -** Overhead of the TLSF structures in a given memory block passed to -** lv_tlsf_add_pool, equal to the overhead of a free block and the -** sentinel block. -*/ -size_t lv_tlsf_pool_overhead(void) -{ - return 2 * block_header_overhead; -} - -size_t lv_tlsf_alloc_overhead(void) -{ - return block_header_overhead; -} - -lv_pool_t lv_tlsf_add_pool(lv_tlsf_t tlsf, void* mem, size_t bytes) -{ - block_header_t* block; - block_header_t* next; - - const size_t pool_overhead = lv_tlsf_pool_overhead(); - const size_t pool_bytes = align_down(bytes - pool_overhead, ALIGN_SIZE); - - if (((ptrdiff_t)mem % ALIGN_SIZE) != 0) - { - printf("lv_tlsf_add_pool: Memory must be aligned by %u bytes.\n", - (unsigned int)ALIGN_SIZE); - return 0; - } - - if (pool_bytes < block_size_min || pool_bytes > block_size_max) - { -#if defined (TLSF_64BIT) - printf("lv_tlsf_add_pool: Memory size must be between 0x%x and 0x%x00 bytes.\n", - (unsigned int)(pool_overhead + block_size_min), - (unsigned int)((pool_overhead + block_size_max) / 256)); -#else - printf("lv_tlsf_add_pool: Memory size must be between %u and %u bytes.\n", - (unsigned int)(pool_overhead + block_size_min), - (unsigned int)(pool_overhead + block_size_max)); -#endif - return 0; - } - - /* - ** Create the main free block. Offset the start of the block slightly - ** so that the prev_phys_block field falls outside of the pool - - ** it will never be used. - */ - block = offset_to_block(mem, -(tlsfptr_t)block_header_overhead); - block_set_size(block, pool_bytes); - block_set_free(block); - block_set_prev_used(block); - block_insert(tlsf_cast(control_t*, tlsf), block); - - /* Split the block to create a zero-size sentinel block. */ - next = block_link_next(block); - block_set_size(next, 0); - block_set_used(next); - block_set_prev_free(next); - - return mem; -} - -void lv_tlsf_remove_pool(lv_tlsf_t tlsf, lv_pool_t pool) -{ - control_t* control = tlsf_cast(control_t*, tlsf); - block_header_t* block = offset_to_block(pool, -(int)block_header_overhead); - - int fl = 0, sl = 0; - - tlsf_assert(block_is_free(block) && "block should be free"); - tlsf_assert(!block_is_free(block_next(block)) && "next block should not be free"); - tlsf_assert(block_size(block_next(block)) == 0 && "next block size should be zero"); - - mapping_insert(block_size(block), &fl, &sl); - remove_free_block(control, block, fl, sl); -} - -/* -** TLSF main interface. -*/ - -#if _DEBUG -int test_ffs_fls() -{ - /* Verify ffs/fls work properly. */ - int rv = 0; - rv += (tlsf_ffs(0) == -1) ? 0 : 0x1; - rv += (tlsf_fls(0) == -1) ? 0 : 0x2; - rv += (tlsf_ffs(1) == 0) ? 0 : 0x4; - rv += (tlsf_fls(1) == 0) ? 0 : 0x8; - rv += (tlsf_ffs(0x80000000) == 31) ? 0 : 0x10; - rv += (tlsf_ffs(0x80008000) == 15) ? 0 : 0x20; - rv += (tlsf_fls(0x80000008) == 31) ? 0 : 0x40; - rv += (tlsf_fls(0x7FFFFFFF) == 30) ? 0 : 0x80; - -#if defined (TLSF_64BIT) - rv += (tlsf_fls_sizet(0x80000000) == 31) ? 0 : 0x100; - rv += (tlsf_fls_sizet(0x100000000) == 32) ? 0 : 0x200; - rv += (tlsf_fls_sizet(0xffffffffffffffff) == 63) ? 0 : 0x400; -#endif - - if (rv) - { - printf("test_ffs_fls: %x ffs/fls tests failed.\n", rv); - } - return rv; -} -#endif - -lv_tlsf_t lv_tlsf_create(void* mem) -{ -#if _DEBUG - if (test_ffs_fls()) - { - return 0; - } -#endif - - if (((tlsfptr_t)mem % ALIGN_SIZE) != 0) - { - printf("lv_tlsf_create: Memory must be aligned to %u bytes.\n", - (unsigned int)ALIGN_SIZE); - return 0; - } - - control_constructor(tlsf_cast(control_t*, mem)); - - return tlsf_cast(lv_tlsf_t, mem); -} - -lv_tlsf_t lv_tlsf_create_with_pool(void* mem, size_t bytes) -{ - lv_tlsf_t tlsf = lv_tlsf_create(mem); - lv_tlsf_add_pool(tlsf, (char*)mem + lv_tlsf_size(), bytes - lv_tlsf_size()); - return tlsf; -} - -void lv_tlsf_destroy(lv_tlsf_t tlsf) -{ - /* Nothing to do. */ - (void)tlsf; -} - -lv_pool_t lv_tlsf_get_pool(lv_tlsf_t tlsf) -{ - return tlsf_cast(lv_pool_t, (char*)tlsf + lv_tlsf_size()); -} - -void* lv_tlsf_malloc(lv_tlsf_t tlsf, size_t size) -{ - control_t* control = tlsf_cast(control_t*, tlsf); - const size_t adjust = adjust_request_size(size, ALIGN_SIZE); - block_header_t* block = block_locate_free(control, adjust); - return block_prepare_used(control, block, adjust); -} - -void* lv_tlsf_memalign(lv_tlsf_t tlsf, size_t align, size_t size) -{ - control_t* control = tlsf_cast(control_t*, tlsf); - const size_t adjust = adjust_request_size(size, ALIGN_SIZE); - - /* - ** We must allocate an additional minimum block size bytes so that if - ** our free block will leave an alignment gap which is smaller, we can - ** trim a leading free block and release it back to the pool. We must - ** do this because the previous physical block is in use, therefore - ** the prev_phys_block field is not valid, and we can't simply adjust - ** the size of that block. - */ - const size_t gap_minimum = sizeof(block_header_t); - const size_t size_with_gap = adjust_request_size(adjust + align + gap_minimum, align); - - /* - ** If alignment is less than or equals base alignment, we're done. - ** If we requested 0 bytes, return null, as lv_tlsf_malloc(0) does. - */ - const size_t aligned_size = (adjust && align > ALIGN_SIZE) ? size_with_gap : adjust; - - block_header_t* block = block_locate_free(control, aligned_size); - - /* This can't be a static assert. */ - tlsf_assert(sizeof(block_header_t) == block_size_min + block_header_overhead); - - if (block) - { - void* ptr = block_to_ptr(block); - void* aligned = align_ptr(ptr, align); - size_t gap = tlsf_cast(size_t, - tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr)); - - /* If gap size is too small, offset to next aligned boundary. */ - if (gap && gap < gap_minimum) - { - const size_t gap_remain = gap_minimum - gap; - const size_t offset = tlsf_max(gap_remain, align); - const void* next_aligned = tlsf_cast(void*, - tlsf_cast(tlsfptr_t, aligned) + offset); - - aligned = align_ptr(next_aligned, align); - gap = tlsf_cast(size_t, - tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr)); - } - - if (gap) - { - tlsf_assert(gap >= gap_minimum && "gap size too small"); - block = block_trim_free_leading(control, block, gap); - } - } - - return block_prepare_used(control, block, adjust); -} - -void lv_tlsf_free(lv_tlsf_t tlsf, void* ptr) -{ - /* Don't attempt to free a NULL pointer. */ - if (ptr) - { - control_t* control = tlsf_cast(control_t*, tlsf); - block_header_t* block = block_from_ptr(ptr); - tlsf_assert(!block_is_free(block) && "block already marked as free"); - block_mark_as_free(block); - block = block_merge_prev(control, block); - block = block_merge_next(control, block); - block_insert(control, block); - } -} - -/* -** The TLSF block information provides us with enough information to -** provide a reasonably intelligent implementation of realloc, growing or -** shrinking the currently allocated block as required. -** -** This routine handles the somewhat esoteric edge cases of realloc: -** - a non-zero size with a null pointer will behave like malloc -** - a zero size with a non-null pointer will behave like free -** - a request that cannot be satisfied will leave the original buffer -** untouched -** - an extended buffer size will leave the newly-allocated area with -** contents undefined -*/ -void* lv_tlsf_realloc(lv_tlsf_t tlsf, void* ptr, size_t size) -{ - control_t* control = tlsf_cast(control_t*, tlsf); - void* p = 0; - - /* Zero-size requests are treated as free. */ - if (ptr && size == 0) - { - lv_tlsf_free(tlsf, ptr); - } - /* Requests with NULL pointers are treated as malloc. */ - else if (!ptr) - { - p = lv_tlsf_malloc(tlsf, size); - } - else - { - block_header_t* block = block_from_ptr(ptr); - block_header_t* next = block_next(block); - - const size_t cursize = block_size(block); - const size_t combined = cursize + block_size(next) + block_header_overhead; - const size_t adjust = adjust_request_size(size, ALIGN_SIZE); - - tlsf_assert(!block_is_free(block) && "block already marked as free"); - - /* - ** If the next block is used, or when combined with the current - ** block, does not offer enough space, we must reallocate and copy. - */ - if (adjust > cursize && (!block_is_free(next) || adjust > combined)) - { - p = lv_tlsf_malloc(tlsf, size); - if (p) - { - const size_t minsize = tlsf_min(cursize, size); - lv_memcpy(p, ptr, minsize); - lv_tlsf_free(tlsf, ptr); - } - } - else - { - /* Do we need to expand to the next block? */ - if (adjust > cursize) - { - block_merge_next(control, block); - block_mark_as_used(block); - } - - /* Trim the resulting block and return the original pointer. */ - block_trim_used(control, block, adjust); - p = ptr; - } - } - - return p; -} - -#endif /* LV_MEM_CUSTOM == 0 */ diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_arc.c b/lib/libesp32_lvgl/LVGL8/src/widgets/lv_arc.c deleted file mode 100644 index 2b7bc8a35..000000000 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_arc.c +++ /dev/null @@ -1,974 +0,0 @@ -/** - * @file lv_arc.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_arc.h" -#if LV_USE_ARC != 0 - -#include "../core/lv_group.h" -#include "../core/lv_indev.h" -#include "../misc/lv_assert.h" -#include "../misc/lv_math.h" -#include "../draw/lv_draw_arc.h" - -/********************* - * DEFINES - *********************/ -#define MY_CLASS &lv_arc_class - -#define VALUE_UNSET INT16_MIN - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -static void lv_arc_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void lv_arc_draw(lv_event_t * e); -static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e); -static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angle, lv_part_t part); -static void get_center(lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r); -static void get_knob_area(lv_obj_t * arc, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area); -static void value_update(lv_obj_t * arc); - -/********************** - * STATIC VARIABLES - **********************/ -const lv_obj_class_t lv_arc_class = { - .constructor_cb = lv_arc_constructor, - .event_cb = lv_arc_event, - .instance_size = sizeof(lv_arc_t), - .editable = LV_OBJ_CLASS_EDITABLE_TRUE, - .base_class = &lv_obj_class -}; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a arc object - * @param par pointer to an object, it will be the parent of the new arc - * @return pointer to the created arc - */ -lv_obj_t * lv_arc_create(lv_obj_t * parent) -{ - LV_LOG_INFO("begin") - lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); - lv_obj_class_init_obj(obj); - return obj; -} - -/*====================== - * Add/remove functions - *=====================*/ - -/* - * New object specific "add" or "remove" functions come here - */ - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the start angle of an arc. 0 deg: right, 90 bottom, etc. - * @param arc pointer to an arc object - * @param start the start angle [0..360] - */ -void lv_arc_set_start_angle(lv_obj_t * obj, uint16_t start) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - if(start > 360) start -= 360; - - /*Too large move, the whole arc need to be invalidated anyway*/ - if(LV_ABS(start -arc->indic_angle_start) >= 180) { - lv_obj_invalidate(obj); - } - /*Only a smaller incremental move*/ - else if(arc->indic_angle_start >arc->indic_angle_end && start >arc->indic_angle_end) { - inv_arc_area(obj, LV_MIN(arc->indic_angle_start, start), LV_MAX(arc->indic_angle_start, start), - LV_PART_INDICATOR); - } - /*Only a smaller incremental move*/ - else if(arc->indic_angle_start indic_angle_end && start indic_angle_end) { - inv_arc_area(obj, LV_MIN(arc->indic_angle_start, start), LV_MAX(arc->indic_angle_start, start), - LV_PART_INDICATOR); - } - /*Crossing the start angle makes the whole arc change*/ - else { - lv_obj_invalidate(obj); - } - - arc->indic_angle_start = start; -} - -/** - * Set the start angle of an arc. 0 deg: right, 90 bottom, etc. - * @param arc pointer to an arc object - * @param start the start angle [0..360] - */ -void lv_arc_set_end_angle(lv_obj_t * obj, uint16_t end) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - if(end > (arc->indic_angle_start + 360)) end =arc->indic_angle_start + 360; - - /*Too large move, the whole arc need to be invalidated anyway*/ - if(LV_ABS(end -arc->indic_angle_end) >= 180) { - lv_obj_invalidate(obj); - } - /*Only a smaller incremental move*/ - else if(arc->indic_angle_end >arc->indic_angle_start && end >arc->indic_angle_start) { - inv_arc_area(obj, LV_MIN(arc->indic_angle_end, end), LV_MAX(arc->indic_angle_end, end), LV_PART_INDICATOR); - } - /*Only a smaller incremental move*/ - else if(arc->indic_angle_end indic_angle_start && end indic_angle_start) { - inv_arc_area(obj, LV_MIN(arc->indic_angle_end, end), LV_MAX(arc->indic_angle_end, end), LV_PART_INDICATOR); - } - /*Crossing the end angle makes the whole arc change*/ - else { - lv_obj_invalidate(obj); - } - - arc->indic_angle_end = end; -} - -/** - * Set the start and end angles - * @param arc pointer to an arc object - * @param start the start angle - * @param end the end angle - */ -void lv_arc_set_angles(lv_obj_t * obj, uint16_t start, uint16_t end) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - if(start > 360) start -= 360; - if(end > (start + 360)) end = start + 360; - - inv_arc_area(obj,arc->indic_angle_start,arc->indic_angle_end, LV_PART_INDICATOR); - - arc->indic_angle_start = start; - arc->indic_angle_end = end; - - inv_arc_area(obj,arc->indic_angle_start,arc->indic_angle_end, LV_PART_INDICATOR); -} - -/** - * Set the start angle of an arc background. 0 deg: right, 90 bottom, etc. - * @param arc pointer to an arc object - * @param start the start angle - */ -void lv_arc_set_bg_start_angle(lv_obj_t * obj, uint16_t start) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - if(start > 360) start -= 360; - - /*Too large move, the whole arc need to be invalidated anyway*/ - if(LV_ABS(start -arc->bg_angle_start) >= 180) { - lv_obj_invalidate(obj); - } - /*Only a smaller incremental move*/ - else if(arc->bg_angle_start >arc->bg_angle_end && start >arc->bg_angle_end) { - inv_arc_area(obj, LV_MIN(arc->bg_angle_start, start), LV_MAX(arc->bg_angle_start, start), LV_PART_MAIN); - } - /*Only a smaller incremental move*/ - else if(arc->bg_angle_start bg_angle_end && start bg_angle_end) { - inv_arc_area(obj, LV_MIN(arc->bg_angle_start, start), LV_MAX(arc->bg_angle_start, start), LV_PART_MAIN); - } - /*Crossing the start angle makes the whole arc change*/ - else { - lv_obj_invalidate(obj); - } - - arc->bg_angle_start = start; - - value_update(obj); -} - -/** - * Set the start angle of an arc background. 0 deg: right, 90 bottom etc. - * @param arc pointer to an arc object - * @param end the end angle - */ -void lv_arc_set_bg_end_angle(lv_obj_t * obj, uint16_t end) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - - if(end > (arc->bg_angle_start + 360)) end =arc->bg_angle_start + 360; - - /*Too large move, the whole arc need to be invalidated anyway*/ - if(LV_ABS(end -arc->bg_angle_end) >= 180) { - lv_obj_invalidate(obj); - } - /*Only a smaller incremental move*/ - else if(arc->bg_angle_end >arc->bg_angle_start && end >arc->bg_angle_start) { - inv_arc_area(obj, LV_MIN(arc->bg_angle_end, end), LV_MAX(arc->bg_angle_end, end), LV_PART_MAIN); - } - /*Only a smaller incremental move*/ - else if(arc->bg_angle_end bg_angle_start && end bg_angle_start) { - inv_arc_area(obj, LV_MIN(arc->bg_angle_end, end), LV_MAX(arc->bg_angle_end, end), LV_PART_MAIN); - } - /*Crossing the end angle makes the whole arc change*/ - else { - lv_obj_invalidate(obj); - } - - value_update(obj); - - arc->bg_angle_end = end; -} - -/** - * Set the start and end angles of the arc background - * @param arc pointer to an arc object - * @param start the start angle - * @param end the end angle - */ -void lv_arc_set_bg_angles(lv_obj_t * obj, uint16_t start, uint16_t end) -{ - - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - if(start > 360) start -= 360; - if(end > (start + 360)) end = start + 360; - - inv_arc_area(obj,arc->bg_angle_start,arc->bg_angle_end, LV_PART_MAIN); - - arc->bg_angle_start = start; - arc->bg_angle_end = end; - - inv_arc_area(obj,arc->bg_angle_start,arc->bg_angle_end, LV_PART_MAIN); - - value_update(obj); -} - -/** - * Set the rotation for the whole arc - * @param arc pointer to an arc object - * @param rotation rotation angle - */ -void lv_arc_set_rotation(lv_obj_t * obj, uint16_t rotation) -{ - - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - arc->rotation = rotation; - - lv_obj_invalidate(obj); -} - -/** - * Set the type of arc. - * @param arc pointer to arc object - * @param type arc type - */ -void lv_arc_set_mode(lv_obj_t * obj, lv_arc_mode_t type) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - int16_t val =arc->value; - - arc->type = type; - arc->value = -1; /** Force set_value handling*/ - - int16_t bg_midpoint, bg_end =arc->bg_angle_end; - if(arc->bg_angle_end bg_angle_start) bg_end =arc->bg_angle_end + 360; - - switch(arc->type) { - case LV_ARC_MODE_SYMMETRICAL: - bg_midpoint = (arc->bg_angle_start + bg_end) / 2; - lv_arc_set_start_angle(obj, bg_midpoint); - lv_arc_set_end_angle(obj, bg_midpoint); - break; - case LV_ARC_MODE_REVERSE: - lv_arc_set_end_angle(obj,arc->bg_angle_end); - break; - default: /** LV_ARC_TYPE_NORMAL*/ - lv_arc_set_start_angle(obj,arc->bg_angle_start); - } - - lv_arc_set_value(obj, val); -} - -/** - * Set a new value on the arc - * @param arc pointer to a arc object - * @param value new value - */ -void lv_arc_set_value(lv_obj_t * obj, int16_t value) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - if(arc->value == value) return; - - int16_t new_value; - new_value = value >arc->max_value ?arc->max_value : value; - new_value = new_value min_value ?arc->min_value : new_value; - - if(arc->value == new_value) return; - arc->value = new_value; - - value_update(obj); -} - -/** - * Set minimum and the maximum values of a arc - * @param arc pointer to the arc object - * @param min minimum value - * @param max maximum value - */ -void lv_arc_set_range(lv_obj_t * obj, int16_t min, int16_t max) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - if(arc->min_value == min &&arc->max_value == max) return; - - arc->min_value = min; - arc->max_value = max; - - if(arc->value < min) { - arc->value = min; - } - if(arc->value > max) { - arc->value = max; - } - - value_update(obj); /*value has changed relative to the new range*/ -} - -/** - * Set the threshold of arc knob increments - * position. - * @param arc pointer to a arc object - * @param threshold increment threshold - */ -void lv_arc_set_change_rate(lv_obj_t * obj, uint16_t rate) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - arc->chg_rate = rate; -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the start angle of an arc. - * @param arc pointer to an arc object - * @return the start angle [0..360] - */ -uint16_t lv_arc_get_angle_start(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - return ((lv_arc_t*) obj)->indic_angle_start; -} - -/** - * Get the end angle of an arc. - * @param arc pointer to an arc object - * @return the end angle [0..360] - */ - uint16_t lv_arc_get_angle_end(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - return ((lv_arc_t*) obj)->indic_angle_end; -} - -/** - * Get the start angle of an arc background. - * @param arc pointer to an arc object - * @return the start angle [0..360] - */ -uint16_t lv_arc_get_bg_angle_start(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - return ((lv_arc_t*) obj)->bg_angle_start; -} - -/** - * Get the end angle of an arc background. - * @param arc pointer to an arc object - * @return the end angle [0..360] - */ -uint16_t lv_arc_get_bg_angle_end(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - return ((lv_arc_t*) obj)->bg_angle_end; -} - - -/** - * Get the value of a arc - * @param arc pointer to a arc object - * @return the value of the arc - */ -int16_t lv_arc_get_value(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - return ((lv_arc_t*) obj)->value; -} - -/** - * Get the minimum value of a arc - * @param arc pointer to a arc object - * @return the minimum value of the arc - */ -int16_t lv_arc_get_min_value(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - return ((lv_arc_t*) obj)->min_value; -} - -/** - * Get the maximum value of a arc - * @param arc pointer to a arc object - * @return the maximum value of the arc - */ -int16_t lv_arc_get_max_value(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - return ((lv_arc_t*) obj)->max_value; -} - -/** - * Get whether the arc is type or not. - * @param arc pointer to a arc object - * @return arc type - */ -lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - return ((lv_arc_t*) obj)->type; -} - -/*===================== - * Other functions - *====================*/ - -/* - * New object specific "other" functions come here - */ - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void lv_arc_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) -{ - LV_UNUSED(class_p); - LV_TRACE_OBJ_CREATE("begin"); - - lv_arc_t * arc = (lv_arc_t *)obj; - - /*Initialize the allocated 'ext'*/ - arc->rotation = 0; - arc->bg_angle_start = 135; - arc->bg_angle_end = 45; - arc->indic_angle_start = 135; - arc->indic_angle_end = 270; - arc->type = LV_ARC_MODE_NORMAL; - arc->value = VALUE_UNSET; - arc->min_close = 1; - arc->min_value = 0; - arc->max_value = 100; - arc->dragging = false; - arc->chg_rate = 720; - arc->last_tick = lv_tick_get(); - arc->last_angle =arc->indic_angle_end; - - lv_obj_add_flag(obj, LV_OBJ_FLAG_CLICKABLE); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN); - lv_obj_set_ext_click_area(obj, LV_DPI_DEF / 10); - - - LV_TRACE_OBJ_CREATE("finished"); -} - -static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) -{ - LV_UNUSED(class_p); - - lv_res_t res; - - /*Call the ancestor's event handler*/ - res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; - - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); - lv_arc_t * arc = (lv_arc_t *)lv_event_get_target(e); - if(code == LV_EVENT_PRESSING) { - lv_indev_t * indev = lv_indev_get_act(); - if(indev == NULL) return; - - /*Handle only pointers here*/ - lv_indev_type_t indev_type = lv_indev_get_type(indev); - if(indev_type != LV_INDEV_TYPE_POINTER) return; - - lv_point_t p; - lv_indev_get_point(indev, &p); - - /*Make point relative to the arc's center*/ - lv_point_t center; - lv_coord_t r; - get_center(obj, ¢er, &r); - - p.x -= center.x; - p.y -= center.y; - - /*Enter dragging mode if pressed out of the knob*/ - if(arc->dragging == false) { - lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); - r -= indic_width; - r -= r / 2; /*Add some more sensitive area*/ - if(p.x * p.x + p.y * p.y > r * r) { - arc->dragging = true; - arc->last_tick = lv_tick_get(); /*Capture timestamp at dragging start*/ - } - } - - /*It must be in "dragging" mode to turn the arc*/ - if(arc->dragging == false) return; - - /*No angle can be determined if exactly the middle of the arc is being pressed*/ - if(p.x == 0 && p.y == 0) return; - - /*Calculate the angle of the pressed point*/ - int16_t angle; - int16_t bg_end =arc->bg_angle_end; - if(arc->bg_angle_end bg_angle_start) { - bg_end =arc->bg_angle_end + 360; - } - - angle = lv_atan2(p.y, p.x); - angle -=arc->rotation; - angle -=arc->bg_angle_start; /*Make the angle relative to the start angle*/ - - if(angle < 0) angle += 360; - - int16_t deg_range = bg_end -arc->bg_angle_start; - - int16_t last_angle_rel =arc->last_angle -arc->bg_angle_start; - int16_t delta_angle = angle - last_angle_rel; - - /*Do not allow big jumps. - *It's mainly to avoid jumping to the opposite end if the "dead" range between min. an max. is crossed. - *Check which was closer on the last valid press (arc->min_close) and prefer that end*/ - if(LV_ABS(delta_angle) > 280) { - if(arc->min_close) angle = 0; - else angle = deg_range; - } - else { - if(angle < deg_range / 2)arc->min_close = 1; - else arc->min_close = 0; - } - - /*Calculate the slew rate limited angle based on change rate (degrees/sec)*/ - delta_angle = angle - last_angle_rel; - uint32_t delta_tick = lv_tick_elaps(arc->last_tick); - int16_t delta_angle_max = (arc->chg_rate * delta_tick) / 1000; - - if(delta_angle > delta_angle_max) { - delta_angle = delta_angle_max; - } - else if(delta_angle < -delta_angle_max) { - delta_angle = -delta_angle_max; - } - - angle = last_angle_rel + delta_angle; /*Apply the limited angle change*/ - - /*Rounding for symmetry*/ - int32_t round = ((bg_end -arc->bg_angle_start) * 8) / (arc->max_value -arc->min_value); - round = (round + 4) >> 4; - angle += round; - - angle +=arc->bg_angle_start; /*Make the angle absolute again*/ - - /*Set the new value*/ - int16_t old_value =arc->value; - int16_t new_value = lv_map(angle,arc->bg_angle_start, bg_end,arc->min_value,arc->max_value); - if(new_value != lv_arc_get_value(obj)) { - arc->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/ - lv_arc_set_value(obj, new_value); /*set_value caches the last_angle for the next iteration*/ - if(new_value != old_value) { - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; - } - } - - /*Don1't let the elapsed time to big while sitting on an end point*/ - if(new_value ==arc->min_value || new_value ==arc->max_value) { - arc->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/ - } - } - else if(code == LV_EVENT_RELEASED || code == LV_EVENT_PRESS_LOST) { - arc->dragging = false; - - /*Leave edit mode if released. (No need to wait for LONG_PRESS)*/ - lv_group_t * g = lv_obj_get_group(obj); - bool editing = lv_group_get_editing(g); - lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); - if(indev_type == LV_INDEV_TYPE_ENCODER) { - if(editing) lv_group_set_editing(g, false); - } - - } - else if(code == LV_EVENT_KEY) { - char c = *((char *)lv_event_get_param(e)); - - int16_t old_value =arc->value; - if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { - lv_arc_set_value(obj, lv_arc_get_value(obj) + 1); - } - else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { - lv_arc_set_value(obj, lv_arc_get_value(obj) - 1); - } - - if(old_value !=arc->value) { - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; - } - } - else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); - lv_coord_t bg_pad = LV_MAX4(bg_left, bg_right, bg_top, bg_bottom); - - lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); - lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); - lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); - lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); - lv_coord_t knob_pad = LV_MAX4(knob_left, knob_right, knob_top, knob_bottom) + 2; - - lv_coord_t * s = lv_event_get_param(e); - *s = LV_MAX(*s, knob_pad - bg_pad); - } else if(code == LV_EVENT_DRAW_MAIN) { - lv_arc_draw(e); - } -} - -static void lv_arc_draw(lv_event_t * e) -{ - lv_obj_t * obj = lv_event_get_target(e); - lv_arc_t * arc = (lv_arc_t *)obj; - - const lv_area_t * clip_area = lv_event_get_param(e); - - lv_point_t center; - lv_coord_t arc_r; - get_center(obj, ¢er, &arc_r); - - lv_obj_draw_part_dsc_t obj_draw_dsc; - lv_obj_draw_dsc_init(&obj_draw_dsc, clip_area); - - /*Draw the background arc*/ - lv_draw_arc_dsc_t arc_dsc; - if(arc_r > 0) { - lv_draw_arc_dsc_init(&arc_dsc); - lv_obj_init_draw_arc_dsc(obj, LV_PART_MAIN, &arc_dsc); - - obj_draw_dsc.part = LV_PART_MAIN; - obj_draw_dsc.p1 = ¢er; - obj_draw_dsc.radius = arc_r; - obj_draw_dsc.arc_dsc = &arc_dsc; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &obj_draw_dsc); - - lv_draw_arc(center.x, center.y, arc_r, arc->bg_angle_start + arc->rotation, - arc->bg_angle_end + arc->rotation, clip_area, - &arc_dsc); - - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &obj_draw_dsc); - } - - /*make the indicator arc smaller or larger according to its greatest padding value*/ - lv_coord_t left_indic = lv_obj_get_style_pad_left(obj, LV_PART_INDICATOR); - lv_coord_t right_indic = lv_obj_get_style_pad_right(obj, LV_PART_INDICATOR); - lv_coord_t top_indic = lv_obj_get_style_pad_top(obj, LV_PART_INDICATOR); - lv_coord_t bottom_indic = lv_obj_get_style_pad_bottom(obj, LV_PART_INDICATOR); - lv_coord_t indic_r = arc_r - LV_MAX4(left_indic, right_indic, top_indic, bottom_indic); - - if(indic_r > 0) { - lv_draw_arc_dsc_init(&arc_dsc); - lv_obj_init_draw_arc_dsc(obj, LV_PART_INDICATOR, &arc_dsc); - - obj_draw_dsc.part = LV_PART_INDICATOR; - obj_draw_dsc.p1 = ¢er; - obj_draw_dsc.radius = indic_r; - obj_draw_dsc.arc_dsc = &arc_dsc; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &obj_draw_dsc); - - lv_draw_arc(center.x, center.y, indic_r, arc->indic_angle_start +arc->rotation, - arc->indic_angle_end + arc->rotation, clip_area, - &arc_dsc); - - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &obj_draw_dsc); - } - - lv_area_t knob_area; - get_knob_area(obj, ¢er, arc_r, &knob_area); - - lv_draw_rect_dsc_t knob_rect_dsc; - lv_draw_rect_dsc_init(&knob_rect_dsc); - lv_obj_init_draw_rect_dsc(obj, LV_PART_KNOB, &knob_rect_dsc); - - obj_draw_dsc.part = LV_PART_KNOB; - obj_draw_dsc.draw_area = &knob_area; - obj_draw_dsc.rect_dsc = &knob_rect_dsc; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &obj_draw_dsc); - - lv_draw_rect(&knob_area, clip_area, &knob_rect_dsc); - - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &obj_draw_dsc); -} - -static void inv_arc_area(lv_obj_t * obj, uint16_t start_angle, uint16_t end_angle, lv_part_t part) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - /*Skip this complicated invalidation if the arc is not visible*/ - if(lv_obj_is_visible(obj) == false) return; - - start_angle +=arc->rotation; - end_angle +=arc->rotation; - - if(start_angle >= 360) start_angle -= 360; - if(end_angle >= 360) end_angle -= 360; - - uint8_t start_quarter = start_angle / 90; - uint8_t end_quarter = end_angle / 90; - - lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); - lv_coord_t rout = (LV_MIN(lv_obj_get_width(obj) - left - right, lv_obj_get_height(obj) - top - bottom)) / 2; - lv_coord_t x = obj->coords.x1 + rout + left; - lv_coord_t y = obj->coords.y1 + rout + top; - lv_coord_t w = lv_obj_get_style_arc_width(obj, part); - lv_coord_t rounded = lv_obj_get_style_arc_rounded(obj, part); - lv_coord_t rin = rout - w; - lv_coord_t extra_area = 0; - - extra_area = rounded ? w / 2 + 2 : 0; - - if(part == LV_PART_INDICATOR) { - lv_coord_t knob_extra_size = lv_obj_calculate_ext_draw_size(obj, LV_PART_KNOB); - - lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); - lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); - lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); - lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); - - knob_extra_size += LV_MAX4(knob_left, knob_right, knob_top, knob_bottom); - - extra_area = LV_MAX(extra_area, w / 2 + 2 + knob_extra_size); - } - - lv_area_t inv_area; - - if(start_quarter == end_quarter && start_angle <= end_angle) { - if(start_quarter == 0) { - inv_area.y1 = y + ((lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) - extra_area; - inv_area.x2 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area; - - inv_area.y2 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area; - inv_area.x1 = x + ((lv_trigo_sin(end_angle + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area; - - lv_obj_invalidate_area(obj, &inv_area); - } - else if(start_quarter == 1) { - inv_area.y2 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area; - inv_area.x2 = x + ((lv_trigo_sin(start_angle + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area; - - inv_area.y1 = y + ((lv_trigo_sin(end_angle) * rin) >> LV_TRIGO_SHIFT) - extra_area; - inv_area.x1 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area; - - lv_obj_invalidate_area(obj, &inv_area); - } - else if(start_quarter == 2) { - inv_area.x1 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area; - inv_area.y2 = y + ((lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area; - - inv_area.y1 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area; - inv_area.x2 = x + ((lv_trigo_sin(end_angle + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area; - - lv_obj_invalidate_area(obj, &inv_area); - } - else if(start_quarter == 3) { - /*Small arc here*/ - inv_area.x1 = x + ((lv_trigo_sin(start_angle + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area; - inv_area.y1 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area; - - inv_area.x2 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area; - inv_area.y2 = y + ((lv_trigo_sin(end_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area; - - lv_obj_invalidate_area(obj, &inv_area); - } - } - else if(start_quarter == 0 && end_quarter == 1) { - inv_area.x1 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area; - inv_area.y1 = y + ((LV_MIN(lv_trigo_sin(end_angle), - lv_trigo_sin(start_angle)) * rin) >> LV_TRIGO_SHIFT) - extra_area; - inv_area.x2 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area; - inv_area.y2 = y + rout + extra_area; - lv_obj_invalidate_area(obj, &inv_area); - } - else if(start_quarter == 1 && end_quarter == 2) { - inv_area.x1 = x - rout - extra_area; - inv_area.y1 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area; - inv_area.x2 = x + ((LV_MAX(lv_trigo_sin(start_angle + 90), - lv_trigo_sin(end_angle + 90)) * rin) >> LV_TRIGO_SHIFT) + extra_area; - inv_area.y2 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area; - lv_obj_invalidate_area(obj, &inv_area); - } - else if(start_quarter == 2 && end_quarter == 3) { - inv_area.x1 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area; - inv_area.y1 = y - rout - extra_area; - inv_area.x2 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area; - inv_area.y2 = y + (LV_MAX(lv_trigo_sin(end_angle) * rin, - lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area; - lv_obj_invalidate_area(obj, &inv_area); - } - else if(start_quarter == 3 && end_quarter == 0) { - inv_area.x1 = x + ((LV_MIN(lv_trigo_sin(end_angle + 90), - lv_trigo_sin(start_angle + 90)) * rin) >> LV_TRIGO_SHIFT) - extra_area; - inv_area.y1 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area; - inv_area.x2 = x + rout + extra_area; - inv_area.y2 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area; - - lv_obj_invalidate_area(obj, &inv_area); - } - else { - lv_obj_invalidate(obj); - } -} - -static void get_center(lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r) -{ - lv_coord_t left_bg = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t right_bg = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t top_bg = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t bottom_bg = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); - - lv_coord_t r = (LV_MIN(lv_obj_get_width(obj) - left_bg - right_bg, - lv_obj_get_height(obj) - top_bg - bottom_bg)) / 2; - - *arc_r = r; - center->x = obj->coords.x1 + r + left_bg; - center->y = obj->coords.y1 + r + top_bg; - - lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); - r -= indic_width; -} - -static void get_knob_area(lv_obj_t * obj, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); - lv_coord_t indic_width_half = indic_width / 2; - r -= indic_width_half; - - uint16_t angle =arc->rotation; - if(arc->type == LV_ARC_MODE_NORMAL) { - angle +=arc->indic_angle_end; - } - else if(arc->type == LV_ARC_MODE_REVERSE) { - angle +=arc->indic_angle_start; - } - else if(arc->type == LV_ARC_MODE_SYMMETRICAL) { - int32_t range_midpoint = (int32_t)(arc->min_value +arc->max_value) / 2; - if(arc->value < range_midpoint) angle +=arc->indic_angle_start; - else angle +=arc->indic_angle_end; - } - lv_coord_t knob_x = (r * lv_trigo_sin(angle + 90)) >> LV_TRIGO_SHIFT; - lv_coord_t knob_y = (r * lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT; - - lv_coord_t left_knob = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); - lv_coord_t right_knob = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); - lv_coord_t top_knob = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); - lv_coord_t bottom_knob = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); - - knob_area->x1 = center->x + knob_x - left_knob - indic_width_half; - knob_area->x2 = center->x + knob_x + right_knob + indic_width_half; - knob_area->y1 = center->y + knob_y - top_knob - indic_width_half; - knob_area->y2 = center->y + knob_y + bottom_knob + indic_width_half; -} - -/** - * Used internally to update arc angles after a value change - * @param arc pointer to a arc object - */ -static void value_update(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - /*If the value is still not set to any value do not update*/ - if(arc->value == VALUE_UNSET) return; - - int16_t bg_midpoint, range_midpoint, bg_end =arc->bg_angle_end; - if(arc->bg_angle_end bg_angle_start) bg_end =arc->bg_angle_end + 360; - - int16_t angle; - switch(arc->type) { - case LV_ARC_MODE_SYMMETRICAL: - bg_midpoint = (arc->bg_angle_start + bg_end) / 2; - range_midpoint = (int32_t)(arc->min_value +arc->max_value) / 2; - - if(arc->value < range_midpoint) { - angle = lv_map(arc->value,arc->min_value, range_midpoint,arc->bg_angle_start, bg_midpoint); - lv_arc_set_start_angle(obj, angle); - lv_arc_set_end_angle(obj, bg_midpoint); - } - else { - angle = lv_map(arc->value, range_midpoint,arc->max_value, bg_midpoint, bg_end); - lv_arc_set_start_angle(obj, bg_midpoint); - lv_arc_set_end_angle(obj, angle); - } - break; - case LV_ARC_MODE_REVERSE: - angle = lv_map(arc->value,arc->min_value,arc->max_value,arc->bg_angle_start, bg_end); - lv_arc_set_start_angle(obj, angle); - break; - default: /** LV_ARC_TYPE_NORMAL*/ - angle = lv_map(arc->value,arc->min_value,arc->max_value,arc->bg_angle_start, bg_end); - lv_arc_set_end_angle(obj, angle); - lv_arc_set_start_angle(obj,arc->bg_angle_start); - } - arc->last_angle = angle; /*Cache angle for slew rate limiting*/ -} - -#endif diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_switch.c b/lib/libesp32_lvgl/LVGL8/src/widgets/lv_switch.c deleted file mode 100644 index 0a4b55bcf..000000000 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_switch.c +++ /dev/null @@ -1,188 +0,0 @@ -/** - * @file lv_sw.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_switch.h" - -#if LV_USE_SWITCH != 0 - -/*Testing of dependencies*/ -#if LV_USE_SLIDER == 0 - #error "lv_sw: lv_slider is required. Enable it in lv_conf.h (LV_USE_SLIDER 1)" -#endif - -#include "../misc/lv_assert.h" -#include "../misc/lv_math.h" -#include "../core/lv_indev.h" -#include "../core/lv_disp.h" -#include "lv_img.h" - -/********************* - * DEFINES - *********************/ -#define MY_CLASS &lv_switch_class - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void lv_switch_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void lv_switch_event(const lv_obj_class_t * class_p, lv_event_t * e); -static void draw_main(lv_event_t * e); - -/********************** - * STATIC VARIABLES - **********************/ -const lv_obj_class_t lv_switch_class = { - .constructor_cb = lv_switch_constructor, - .event_cb = lv_switch_event, - .width_def = (4 * LV_DPI_DEF) / 10, - .height_def = (4 * LV_DPI_DEF) / 17, - .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, - .instance_size = sizeof(lv_switch_t), - .base_class = &lv_obj_class -}; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_obj_t * lv_switch_create(lv_obj_t * parent) -{ - LV_LOG_INFO("begin") - lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); - lv_obj_class_init_obj(obj); - return obj; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void lv_switch_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) -{ - LV_UNUSED(class_p); - LV_TRACE_OBJ_CREATE("begin"); - - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); - lv_obj_add_flag(obj, LV_OBJ_FLAG_CHECKABLE); - lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS); - - LV_TRACE_OBJ_CREATE("finished"); -} - - -static void lv_switch_event(const lv_obj_class_t * class_p, lv_event_t * e) -{ - LV_UNUSED(class_p); - - lv_res_t res; - - /*Call the ancestor's event handler*/ - res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; - - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); - - if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); - lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); - lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); - lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); - - /*The smaller size is the knob diameter*/ - lv_coord_t knob_size = LV_MAX4(knob_left, knob_right, knob_bottom, knob_top); - knob_size += 2; /*For rounding error*/ - knob_size += lv_obj_calculate_ext_draw_size(obj, LV_PART_KNOB); - - lv_coord_t * s = lv_event_get_param(e); - *s = LV_MAX(*s, knob_size); - *s = LV_MAX(*s, lv_obj_calculate_ext_draw_size(obj, LV_PART_INDICATOR)); - } - else if(code == LV_EVENT_CLICKED) { - lv_obj_invalidate(obj); - } - else if(code == LV_EVENT_DRAW_MAIN) { - draw_main(e); - } -} - -static void draw_main(lv_event_t * e) -{ - lv_obj_t * obj = lv_event_get_target(e); - const lv_area_t * clip_area = lv_event_get_param(e); - lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN); - - /*Calculate the indicator area*/ - lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); - - bool chk = lv_obj_get_state(obj) & LV_STATE_CHECKED; - /*Draw the indicator in checked state*/ - if(chk) { - /*Respect the background's padding*/ - lv_area_t indic_area; - lv_area_copy(&indic_area, &obj->coords); - indic_area.x1 += bg_left; - indic_area.x2 -= bg_right; - indic_area.y1 += bg_top; - indic_area.y2 -= bg_bottom; - - lv_draw_rect_dsc_t draw_indic_dsc; - lv_draw_rect_dsc_init(&draw_indic_dsc); - lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &draw_indic_dsc); - lv_draw_rect(&indic_area, clip_area, &draw_indic_dsc); - } - - /*Draw the knob*/ - lv_coord_t objh = lv_obj_get_height(obj); - lv_coord_t knob_size = objh; - lv_area_t knob_area; - - /*Left*/ - if((base_dir != LV_BASE_DIR_RTL && !chk) || (base_dir == LV_BASE_DIR_RTL && chk)) { - knob_area.x1 = obj->coords.x1 + bg_left; - knob_area.x2 = knob_area.x1 + knob_size; - } - else { - knob_area.x2 = obj->coords.x2 - bg_right; - knob_area.x1 = knob_area.x2 - knob_size; - } - - knob_area.y1 = obj->coords.y1 + bg_top; - knob_area.y2 = obj->coords.y2 - bg_bottom; - - lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); - lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); - lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); - lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); - - /*Apply the paddings on the knob area*/ - knob_area.x1 -= knob_left; - knob_area.x2 += knob_right; - knob_area.y1 -= knob_top; - knob_area.y2 += knob_bottom; - - lv_draw_rect_dsc_t knob_rect_dsc; - lv_draw_rect_dsc_init(&knob_rect_dsc); - lv_obj_init_draw_rect_dsc(obj, LV_PART_KNOB, &knob_rect_dsc); - - lv_draw_rect(&knob_area, clip_area, &knob_rect_dsc); - -} - -#endif diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/autoexec.be b/lib/libesp32_lvgl/LVGL_assets/roboto/autoexec.be new file mode 100644 index 000000000..b45037ee0 --- /dev/null +++ b/lib/libesp32_lvgl/LVGL_assets/roboto/autoexec.be @@ -0,0 +1,3 @@ +# `autoexec.be` for module `lv` with `font_robotocondensed_latin1(size)` + +import robotocondensed_latin1 diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1.be b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1.be new file mode 100644 index 000000000..713340c60 --- /dev/null +++ b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1.be @@ -0,0 +1,22 @@ +# Extend module `lv` with `font_robotocondensed_latin1(size)` + +var font_robotocondensed_latin1 = module("font_robotocondensed_latin1") + +font_robotocondensed_latin1.init = def (m) + import lv + var wd = tasmota.wd # save current working dir + + lv.font_robotocondensed_latin1 = def (size) + return lv.load_font("A:" + wd + "robotocondensed_latin1_" + str(size) + ".bin") + end +end + +return font_robotocondensed_latin1 + +#- + +font_robotocondensed_latin1.init(font_robotocondensed_latin1) +print(lv.font_robotocondensed_latin1) +print(lv.font_robotocondensed_latin1(32)) + +-# diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1.tapp b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1.tapp new file mode 100644 index 000000000..bf714bc6e Binary files /dev/null and b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1.tapp differ diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_12.bin b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_12.bin new file mode 100644 index 000000000..253bdc824 Binary files /dev/null and b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_12.bin differ diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_14.bin b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_14.bin new file mode 100644 index 000000000..07fc9ca32 Binary files /dev/null and b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_14.bin differ diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_16.bin b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_16.bin new file mode 100644 index 000000000..5275a5242 Binary files /dev/null and b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_16.bin differ diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_20.bin b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_20.bin new file mode 100644 index 000000000..b8fedd494 Binary files /dev/null and b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_20.bin differ diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_22.bin b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_22.bin new file mode 100644 index 000000000..77dc1ba36 Binary files /dev/null and b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_22.bin differ diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_24.bin b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_24.bin new file mode 100644 index 000000000..d14650d19 Binary files /dev/null and b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_24.bin differ diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_26.bin b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_26.bin new file mode 100644 index 000000000..cd8434031 Binary files /dev/null and b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_26.bin differ diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_28.bin b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_28.bin new file mode 100644 index 000000000..8ab0bf3f6 Binary files /dev/null and b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_28.bin differ diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_32.bin b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_32.bin new file mode 100644 index 000000000..94902d09c Binary files /dev/null and b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_32.bin differ diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_36.bin b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_36.bin new file mode 100644 index 000000000..47f1258a1 Binary files /dev/null and b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_36.bin differ diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_40.bin b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_40.bin new file mode 100644 index 000000000..2ddf52959 Binary files /dev/null and b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_40.bin differ diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_44.bin b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_44.bin new file mode 100644 index 000000000..04dda2e87 Binary files /dev/null and b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_44.bin differ diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_48.bin b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_48.bin new file mode 100644 index 000000000..f02a5ee91 Binary files /dev/null and b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_48.bin differ diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_gen.sh b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_gen.sh new file mode 100755 index 000000000..a49c019e3 --- /dev/null +++ b/lib/libesp32_lvgl/LVGL_assets/roboto/robotocondensed_latin1_gen.sh @@ -0,0 +1,4 @@ + +rm robotocondensed_latin1.tapp +zip -j -0 robotocondensed_latin1.tapp autoexec.be robotocondensed_latin1.be robotocondensed_latin1_12.bin robotocondensed_latin1_16.bin robotocondensed_latin1_24.bin robotocondensed_latin1_32.bin + diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/LICENSE b/lib/libesp32_lvgl/LVGL_assets/roboto/ttf/LICENSE similarity index 100% rename from lib/libesp32_lvgl/LVGL_assets/roboto/LICENSE rename to lib/libesp32_lvgl/LVGL_assets/roboto/ttf/LICENSE diff --git a/lib/libesp32_lvgl/LVGL_assets/roboto/RobotoCondensed-Regular.ttf b/lib/libesp32_lvgl/LVGL_assets/roboto/ttf/RobotoCondensed-Regular.ttf similarity index 100% rename from lib/libesp32_lvgl/LVGL_assets/roboto/RobotoCondensed-Regular.ttf rename to lib/libesp32_lvgl/LVGL_assets/roboto/ttf/RobotoCondensed-Regular.ttf diff --git a/lib/libesp32_lvgl/freetype/library.json b/lib/libesp32_lvgl/freetype/library.json index 1349b099a..f8864de49 100644 --- a/lib/libesp32_lvgl/freetype/library.json +++ b/lib/libesp32_lvgl/freetype/library.json @@ -8,8 +8,8 @@ "type": "git", "url": "https://gitlab.freedesktop.org/freetype" }, - "frameworks": "*", - "platforms": "*", + "frameworks": "arduino", + "platforms": "espressif32", "build": { "srcFilter": [ "+", diff --git a/lib/libesp32_lvgl/lv_berry/.gitignore b/lib/libesp32_lvgl/lv_berry/.gitignore new file mode 100644 index 000000000..7bd8f1151 --- /dev/null +++ b/lib/libesp32_lvgl/lv_berry/.gitignore @@ -0,0 +1,25 @@ +## OS specific ######## +.DS_Store +.fuse_hidden* + +## Compilation artefacts ######## +*.pyc +*.d +*.o +*.gcno +*.gcda + +## Project files ###### +.platformio +.pio +.clang_complete +.gcc-flags.json +.cache + +## Visual Studio Code specific ###### +.vscode +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +*.bak +*.code-workspace diff --git a/lib/libesp32_lvgl/lv_lib_freetype/LICENSE b/lib/libesp32_lvgl/lv_berry/LICENSE similarity index 94% rename from lib/libesp32_lvgl/lv_lib_freetype/LICENSE rename to lib/libesp32_lvgl/lv_berry/LICENSE index cc227abed..ad32e03bf 100644 --- a/lib/libesp32_lvgl/lv_lib_freetype/LICENSE +++ b/lib/libesp32_lvgl/lv_berry/LICENSE @@ -1,6 +1,4 @@ -MIT License - -Copyright (c) 2019 LittlevGL +Copyright (c) 2021 Stephan Hadinger, LVGL Kft Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +16,4 @@ 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. +SOFTWARE. \ No newline at end of file diff --git a/lib/libesp32_lvgl/lv_berry/generate/be_lv_c_mapping.h b/lib/libesp32_lvgl/lv_berry/generate/be_lv_c_mapping.h new file mode 100644 index 000000000..3dd268c7d --- /dev/null +++ b/lib/libesp32_lvgl/lv_berry/generate/be_lv_c_mapping.h @@ -0,0 +1,1176 @@ + +/******************************************************************** + * Generated code, don't edit + *******************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "be_ctypes.h" +#include "be_mapping.h" + +/* `lv_style` methods */ +const be_ntv_func_def_t lv_style_func[] = { + { "set_align", { (const void*) &lv_style_set_align, "", "(lv.lv_style)i" } }, + { "set_anim_speed", { (const void*) &lv_style_set_anim_speed, "", "(lv.lv_style)i" } }, + { "set_anim_time", { (const void*) &lv_style_set_anim_time, "", "(lv.lv_style)i" } }, + { "set_arc_color", { (const void*) &lv_style_set_arc_color, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_arc_color_filtered", { (const void*) &lv_style_set_arc_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_arc_img_src", { (const void*) &lv_style_set_arc_img_src, "", "(lv.lv_style)." } }, + { "set_arc_opa", { (const void*) &lv_style_set_arc_opa, "", "(lv.lv_style)i" } }, + { "set_arc_rounded", { (const void*) &lv_style_set_arc_rounded, "", "(lv.lv_style)b" } }, + { "set_arc_width", { (const void*) &lv_style_set_arc_width, "", "(lv.lv_style)i" } }, + { "set_base_dir", { (const void*) &lv_style_set_base_dir, "", "(lv.lv_style)i" } }, + { "set_bg_color", { (const void*) &lv_style_set_bg_color, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_bg_color_filtered", { (const void*) &lv_style_set_bg_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_bg_grad_color", { (const void*) &lv_style_set_bg_grad_color, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_bg_grad_color_filtered", { (const void*) &lv_style_set_bg_grad_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_bg_grad_dir", { (const void*) &lv_style_set_bg_grad_dir, "", "(lv.lv_style)i" } }, + { "set_bg_grad_stop", { (const void*) &lv_style_set_bg_grad_stop, "", "(lv.lv_style)i" } }, + { "set_bg_img_opa", { (const void*) &lv_style_set_bg_img_opa, "", "(lv.lv_style)i" } }, + { "set_bg_img_recolor", { (const void*) &lv_style_set_bg_img_recolor, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_bg_img_recolor_filtered", { (const void*) &lv_style_set_bg_img_recolor_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_bg_img_recolor_opa", { (const void*) &lv_style_set_bg_img_recolor_opa, "", "(lv.lv_style)i" } }, + { "set_bg_img_src", { (const void*) &lv_style_set_bg_img_src, "", "(lv.lv_style)." } }, + { "set_bg_img_tiled", { (const void*) &lv_style_set_bg_img_tiled, "", "(lv.lv_style)b" } }, + { "set_bg_main_stop", { (const void*) &lv_style_set_bg_main_stop, "", "(lv.lv_style)i" } }, + { "set_bg_opa", { (const void*) &lv_style_set_bg_opa, "", "(lv.lv_style)i" } }, + { "set_blend_mode", { (const void*) &lv_style_set_blend_mode, "", "(lv.lv_style)i" } }, + { "set_border_color", { (const void*) &lv_style_set_border_color, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_border_color_filtered", { (const void*) &lv_style_set_border_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_border_opa", { (const void*) &lv_style_set_border_opa, "", "(lv.lv_style)i" } }, + { "set_border_post", { (const void*) &lv_style_set_border_post, "", "(lv.lv_style)b" } }, + { "set_border_side", { (const void*) &lv_style_set_border_side, "", "(lv.lv_style)i" } }, + { "set_border_width", { (const void*) &lv_style_set_border_width, "", "(lv.lv_style)i" } }, + { "set_clip_corner", { (const void*) &lv_style_set_clip_corner, "", "(lv.lv_style)b" } }, + { "set_color_filter_dsc", { (const void*) &lv_style_set_color_filter_dsc, "", "(lv.lv_style)(lv.lv_color_filter_dsc)" } }, + { "set_color_filter_opa", { (const void*) &lv_style_set_color_filter_opa, "", "(lv.lv_style)i" } }, + { "set_flex_cross_place", { (const void*) &lv_style_set_flex_cross_place, "", "(lv.lv_style)i" } }, + { "set_flex_flow", { (const void*) &lv_style_set_flex_flow, "", "(lv.lv_style)i" } }, + { "set_flex_grow", { (const void*) &lv_style_set_flex_grow, "", "(lv.lv_style)i" } }, + { "set_flex_main_place", { (const void*) &lv_style_set_flex_main_place, "", "(lv.lv_style)i" } }, + { "set_flex_track_place", { (const void*) &lv_style_set_flex_track_place, "", "(lv.lv_style)i" } }, + { "set_grid_cell_column_pos", { (const void*) &lv_style_set_grid_cell_column_pos, "", "(lv.lv_style)i" } }, + { "set_grid_cell_column_span", { (const void*) &lv_style_set_grid_cell_column_span, "", "(lv.lv_style)i" } }, + { "set_grid_cell_row_pos", { (const void*) &lv_style_set_grid_cell_row_pos, "", "(lv.lv_style)i" } }, + { "set_grid_cell_row_span", { (const void*) &lv_style_set_grid_cell_row_span, "", "(lv.lv_style)i" } }, + { "set_grid_cell_x_align", { (const void*) &lv_style_set_grid_cell_x_align, "", "(lv.lv_style)i" } }, + { "set_grid_cell_y_align", { (const void*) &lv_style_set_grid_cell_y_align, "", "(lv.lv_style)i" } }, + { "set_grid_column_align", { (const void*) &lv_style_set_grid_column_align, "", "(lv.lv_style)i" } }, + { "set_grid_column_dsc_array", { (const void*) &lv_style_set_grid_column_dsc_array, "", "(lv.lv_style)(lv.lv_coord_arr)" } }, + { "set_grid_row_align", { (const void*) &lv_style_set_grid_row_align, "", "(lv.lv_style)i" } }, + { "set_grid_row_dsc_array", { (const void*) &lv_style_set_grid_row_dsc_array, "", "(lv.lv_style)(lv.lv_coord_arr)" } }, + { "set_height", { (const void*) &lv_style_set_height, "", "(lv.lv_style)i" } }, + { "set_img_opa", { (const void*) &lv_style_set_img_opa, "", "(lv.lv_style)i" } }, + { "set_img_recolor", { (const void*) &lv_style_set_img_recolor, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_img_recolor_filtered", { (const void*) &lv_style_set_img_recolor_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_img_recolor_opa", { (const void*) &lv_style_set_img_recolor_opa, "", "(lv.lv_style)i" } }, + { "set_layout", { (const void*) &lv_style_set_layout, "", "(lv.lv_style)i" } }, + { "set_line_color", { (const void*) &lv_style_set_line_color, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_line_color_filtered", { (const void*) &lv_style_set_line_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_line_dash_gap", { (const void*) &lv_style_set_line_dash_gap, "", "(lv.lv_style)i" } }, + { "set_line_dash_width", { (const void*) &lv_style_set_line_dash_width, "", "(lv.lv_style)i" } }, + { "set_line_opa", { (const void*) &lv_style_set_line_opa, "", "(lv.lv_style)i" } }, + { "set_line_rounded", { (const void*) &lv_style_set_line_rounded, "", "(lv.lv_style)b" } }, + { "set_line_width", { (const void*) &lv_style_set_line_width, "", "(lv.lv_style)i" } }, + { "set_max_height", { (const void*) &lv_style_set_max_height, "", "(lv.lv_style)i" } }, + { "set_max_width", { (const void*) &lv_style_set_max_width, "", "(lv.lv_style)i" } }, + { "set_min_height", { (const void*) &lv_style_set_min_height, "", "(lv.lv_style)i" } }, + { "set_min_width", { (const void*) &lv_style_set_min_width, "", "(lv.lv_style)i" } }, + { "set_opa", { (const void*) &lv_style_set_opa, "", "(lv.lv_style)i" } }, + { "set_outline_color", { (const void*) &lv_style_set_outline_color, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_outline_color_filtered", { (const void*) &lv_style_set_outline_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_outline_opa", { (const void*) &lv_style_set_outline_opa, "", "(lv.lv_style)i" } }, + { "set_outline_pad", { (const void*) &lv_style_set_outline_pad, "", "(lv.lv_style)i" } }, + { "set_outline_width", { (const void*) &lv_style_set_outline_width, "", "(lv.lv_style)i" } }, + { "set_pad_bottom", { (const void*) &lv_style_set_pad_bottom, "", "(lv.lv_style)i" } }, + { "set_pad_column", { (const void*) &lv_style_set_pad_column, "", "(lv.lv_style)i" } }, + { "set_pad_left", { (const void*) &lv_style_set_pad_left, "", "(lv.lv_style)i" } }, + { "set_pad_right", { (const void*) &lv_style_set_pad_right, "", "(lv.lv_style)i" } }, + { "set_pad_row", { (const void*) &lv_style_set_pad_row, "", "(lv.lv_style)i" } }, + { "set_pad_top", { (const void*) &lv_style_set_pad_top, "", "(lv.lv_style)i" } }, + { "set_radius", { (const void*) &lv_style_set_radius, "", "(lv.lv_style)i" } }, + { "set_shadow_color", { (const void*) &lv_style_set_shadow_color, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_shadow_color_filtered", { (const void*) &lv_style_set_shadow_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_shadow_ofs_x", { (const void*) &lv_style_set_shadow_ofs_x, "", "(lv.lv_style)i" } }, + { "set_shadow_ofs_y", { (const void*) &lv_style_set_shadow_ofs_y, "", "(lv.lv_style)i" } }, + { "set_shadow_opa", { (const void*) &lv_style_set_shadow_opa, "", "(lv.lv_style)i" } }, + { "set_shadow_spread", { (const void*) &lv_style_set_shadow_spread, "", "(lv.lv_style)i" } }, + { "set_shadow_width", { (const void*) &lv_style_set_shadow_width, "", "(lv.lv_style)i" } }, + { "set_text_align", { (const void*) &lv_style_set_text_align, "", "(lv.lv_style)i" } }, + { "set_text_color", { (const void*) &lv_style_set_text_color, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_text_color_filtered", { (const void*) &lv_style_set_text_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, + { "set_text_decor", { (const void*) &lv_style_set_text_decor, "", "(lv.lv_style)i" } }, + { "set_text_font", { (const void*) &lv_style_set_text_font, "", "(lv.lv_style)(lv.lv_font)" } }, + { "set_text_letter_space", { (const void*) &lv_style_set_text_letter_space, "", "(lv.lv_style)i" } }, + { "set_text_line_space", { (const void*) &lv_style_set_text_line_space, "", "(lv.lv_style)i" } }, + { "set_text_opa", { (const void*) &lv_style_set_text_opa, "", "(lv.lv_style)i" } }, + { "set_transform_angle", { (const void*) &lv_style_set_transform_angle, "", "(lv.lv_style)i" } }, + { "set_transform_height", { (const void*) &lv_style_set_transform_height, "", "(lv.lv_style)i" } }, + { "set_transform_width", { (const void*) &lv_style_set_transform_width, "", "(lv.lv_style)i" } }, + { "set_transform_zoom", { (const void*) &lv_style_set_transform_zoom, "", "(lv.lv_style)i" } }, + { "set_transition", { (const void*) &lv_style_set_transition, "", "(lv.lv_style)(lv.lv_style_transition_dsc)" } }, + { "set_translate_x", { (const void*) &lv_style_set_translate_x, "", "(lv.lv_style)i" } }, + { "set_translate_y", { (const void*) &lv_style_set_translate_y, "", "(lv.lv_style)i" } }, + { "set_width", { (const void*) &lv_style_set_width, "", "(lv.lv_style)i" } }, + { "set_x", { (const void*) &lv_style_set_x, "", "(lv.lv_style)i" } }, + { "set_y", { (const void*) &lv_style_set_y, "", "(lv.lv_style)i" } }, +}; + +/* `lv_font` methods */ +const be_ntv_func_def_t lv_font_func[] = { +}; + +/* `lv_color` methods */ +const be_ntv_func_def_t lv_color_func[] = { +}; + +/* `lv_theme` methods */ +const be_ntv_func_def_t lv_theme_func[] = { +}; + +/* `lv_img` methods */ +#ifdef BE_LV_WIDGET_IMG +const be_ntv_func_def_t lv_img_func[] = { + { "get_angle", { (const void*) &lv_img_get_angle, "i", "(lv.lv_obj)" } }, + { "get_antialias", { (const void*) &lv_img_get_antialias, "b", "(lv.lv_obj)" } }, + { "get_offset_x", { (const void*) &lv_img_get_offset_x, "i", "(lv.lv_obj)" } }, + { "get_offset_y", { (const void*) &lv_img_get_offset_y, "i", "(lv.lv_obj)" } }, + { "get_pivot", { (const void*) &lv_img_get_pivot, "", "(lv.lv_obj)(lv.lv_point)" } }, + { "get_size_mode", { (const void*) &lv_img_get_size_mode, "i", "(lv.lv_obj)" } }, + { "get_src", { (const void*) &lv_img_get_src, ".", "(lv.lv_obj)" } }, + { "get_zoom", { (const void*) &lv_img_get_zoom, "i", "(lv.lv_obj)" } }, + { "set_angle", { (const void*) &lv_img_set_angle, "", "(lv.lv_obj)i" } }, + { "set_antialias", { (const void*) &lv_img_set_antialias, "", "(lv.lv_obj)b" } }, + { "set_offset_x", { (const void*) &lv_img_set_offset_x, "", "(lv.lv_obj)i" } }, + { "set_offset_y", { (const void*) &lv_img_set_offset_y, "", "(lv.lv_obj)i" } }, + { "set_pivot", { (const void*) &lv_img_set_pivot, "", "(lv.lv_obj)ii" } }, + { "set_size_mode", { (const void*) &lv_img_set_size_mode, "", "(lv.lv_obj)i" } }, + { "set_src", { (const void*) &lv_img_set_src, "", "(lv.lv_obj)." } }, + { "set_tasmota_logo", { (const void*) &lv_img_set_tasmota_logo, "", "(lv.lv_obj)" } }, + { "set_zoom", { (const void*) &lv_img_set_zoom, "", "(lv.lv_obj)i" } }, +}; +#endif // BE_LV_WIDGET_IMG + +/* `lv_disp` methods */ +const be_ntv_func_def_t lv_disp_func[] = { + { "clean_dcache", { (const void*) &lv_disp_clean_dcache, "", "(lv.lv_disp)" } }, + { "dpx", { (const void*) &lv_disp_dpx, "i", "(lv.lv_disp)i" } }, + { "get_inactive_time", { (const void*) &lv_disp_get_inactive_time, "i", "(lv.lv_disp)" } }, + { "get_layer_sys", { (const void*) &lv_disp_get_layer_sys, "lv.lv_obj", "(lv.lv_disp)" } }, + { "get_layer_top", { (const void*) &lv_disp_get_layer_top, "lv.lv_obj", "(lv.lv_disp)" } }, + { "get_scr_act", { (const void*) &lv_disp_get_scr_act, "lv.lv_obj", "(lv.lv_disp)" } }, + { "get_scr_prev", { (const void*) &lv_disp_get_scr_prev, "lv.lv_obj", "(lv.lv_disp)" } }, + { "get_theme", { (const void*) &lv_disp_get_theme, "lv.lv_theme", "(lv.lv_disp)" } }, + { "load_scr", { (const void*) &lv_disp_load_scr, "", "(lv.lv_obj)" } }, + { "set_bg_color", { (const void*) &lv_disp_set_bg_color, "", "(lv.lv_disp)(lv.lv_color)" } }, + { "set_bg_image", { (const void*) &lv_disp_set_bg_image, "", "(lv.lv_disp)." } }, + { "set_bg_opa", { (const void*) &lv_disp_set_bg_opa, "", "(lv.lv_disp)i" } }, + { "set_theme", { (const void*) &lv_disp_set_theme, "", "(lv.lv_disp)(lv.lv_theme)" } }, + { "trig_activity", { (const void*) &lv_disp_trig_activity, "", "(lv.lv_disp)" } }, +}; + +/* `lv_obj` methods */ +const be_ntv_func_def_t lv_obj_func[] = { + { "add_event_cb", { (const void*) &lv_obj_add_event_cb, "i", "(lv.lv_obj)^lv_event_cb^i." } }, + { "add_flag", { (const void*) &lv_obj_add_flag, "", "(lv.lv_obj)i" } }, + { "add_state", { (const void*) &lv_obj_add_state, "", "(lv.lv_obj)i" } }, + { "add_style", { (const void*) &lv_obj_add_style, "", "(lv.lv_obj)(lv.lv_style)i" } }, + { "align", { (const void*) &lv_obj_align, "", "(lv.lv_obj)iii" } }, + { "align_to", { (const void*) &lv_obj_align_to, "", "(lv.lv_obj)(lv.lv_obj)iii" } }, + { "allocate_spec_attr", { (const void*) &lv_obj_allocate_spec_attr, "", "(lv.lv_obj)" } }, + { "area_is_visible", { (const void*) &lv_obj_area_is_visible, "b", "(lv.lv_obj)(lv.lv_area)" } }, + { "calculate_ext_draw_size", { (const void*) &lv_obj_calculate_ext_draw_size, "i", "(lv.lv_obj)i" } }, + { "calculate_style_text_align", { (const void*) &lv_obj_calculate_style_text_align, "i", "(lv.lv_obj)is" } }, + { "center", { (const void*) &lv_obj_center, "", "(lv.lv_obj)" } }, + { "check_type", { (const void*) &lv_obj_check_type, "b", "(lv.lv_obj)(lv.lv_obj_class)" } }, + { "class_init_obj", { (const void*) &lv_obj_class_init_obj, "", "(lv.lv_obj)" } }, + { "clean", { (const void*) &lv_obj_clean, "", "(lv.lv_obj)" } }, + { "clear_flag", { (const void*) &lv_obj_clear_flag, "", "(lv.lv_obj)i" } }, + { "clear_state", { (const void*) &lv_obj_clear_state, "", "(lv.lv_obj)i" } }, + { "del", { (const void*) &lv_obj_del, "", "(lv.lv_obj)" } }, + { "del_async", { (const void*) &lv_obj_del_async, "", "(lv.lv_obj)" } }, + { "del_delayed", { (const void*) &lv_obj_del_delayed, "", "(lv.lv_obj)i" } }, + { "dpx", { (const void*) &lv_obj_dpx, "i", "(lv.lv_obj)i" } }, + { "fade_in", { (const void*) &lv_obj_fade_in, "", "(lv.lv_obj)ii" } }, + { "fade_out", { (const void*) &lv_obj_fade_out, "", "(lv.lv_obj)ii" } }, + { "get_child", { (const void*) &lv_obj_get_child, "lv.lv_obj", "(lv.lv_obj)i" } }, + { "get_child_cnt", { (const void*) &lv_obj_get_child_cnt, "i", "(lv.lv_obj)" } }, + { "get_child_id", { (const void*) &lv_obj_get_child_id, "i", "(lv.lv_obj)" } }, + { "get_class", { (const void*) &lv_obj_get_class, "lv.lv_obj_class", "(lv.lv_obj)" } }, + { "get_click_area", { (const void*) &lv_obj_get_click_area, "", "(lv.lv_obj)(lv.lv_area)" } }, + { "get_content_coords", { (const void*) &lv_obj_get_content_coords, "", "(lv.lv_obj)(lv.lv_area)" } }, + { "get_content_height", { (const void*) &lv_obj_get_content_height, "i", "(lv.lv_obj)" } }, + { "get_content_width", { (const void*) &lv_obj_get_content_width, "i", "(lv.lv_obj)" } }, + { "get_coords", { (const void*) &lv_obj_get_coords, "", "(lv.lv_obj)(lv.lv_area)" } }, + { "get_disp", { (const void*) &lv_obj_get_disp, "lv.lv_disp", "(lv.lv_obj)" } }, + { "get_group", { (const void*) &lv_obj_get_group, ".", "(lv.lv_obj)" } }, + { "get_height", { (const void*) &lv_obj_get_height, "i", "(lv.lv_obj)" } }, + { "get_index", { (const void*) &lv_obj_get_index, "i", "(lv.lv_obj)" } }, + { "get_local_style_prop", { (const void*) &lv_obj_get_local_style_prop, "i", "(lv.lv_obj)(lv.lv_style_prop)(lv.lv_style_value)i" } }, + { "get_parent", { (const void*) &lv_obj_get_parent, "lv.lv_obj", "(lv.lv_obj)" } }, + { "get_screen", { (const void*) &lv_obj_get_screen, "lv.lv_obj", "(lv.lv_obj)" } }, + { "get_scroll_bottom", { (const void*) &lv_obj_get_scroll_bottom, "i", "(lv.lv_obj)" } }, + { "get_scroll_dir", { (const void*) &lv_obj_get_scroll_dir, "i", "(lv.lv_obj)" } }, + { "get_scroll_end", { (const void*) &lv_obj_get_scroll_end, "", "(lv.lv_obj)(lv.lv_point)" } }, + { "get_scroll_left", { (const void*) &lv_obj_get_scroll_left, "i", "(lv.lv_obj)" } }, + { "get_scroll_right", { (const void*) &lv_obj_get_scroll_right, "i", "(lv.lv_obj)" } }, + { "get_scroll_snap_x", { (const void*) &lv_obj_get_scroll_snap_x, "i", "(lv.lv_obj)" } }, + { "get_scroll_snap_y", { (const void*) &lv_obj_get_scroll_snap_y, "i", "(lv.lv_obj)" } }, + { "get_scroll_top", { (const void*) &lv_obj_get_scroll_top, "i", "(lv.lv_obj)" } }, + { "get_scroll_x", { (const void*) &lv_obj_get_scroll_x, "i", "(lv.lv_obj)" } }, + { "get_scroll_y", { (const void*) &lv_obj_get_scroll_y, "i", "(lv.lv_obj)" } }, + { "get_scrollbar_area", { (const void*) &lv_obj_get_scrollbar_area, "", "(lv.lv_obj)(lv.lv_area)(lv.lv_area)" } }, + { "get_scrollbar_mode", { (const void*) &lv_obj_get_scrollbar_mode, "i", "(lv.lv_obj)" } }, + { "get_self_height", { (const void*) &lv_obj_get_self_height, "i", "(lv.lv_obj)" } }, + { "get_self_width", { (const void*) &lv_obj_get_self_width, "i", "(lv.lv_obj)" } }, + { "get_state", { (const void*) &lv_obj_get_state, "i", "(lv.lv_obj)" } }, + { "get_style_align", { (const void*) &lv_obj_get_style_align, "i", "(lv.lv_obj)i" } }, + { "get_style_anim_speed", { (const void*) &lv_obj_get_style_anim_speed, "i", "(lv.lv_obj)i" } }, + { "get_style_anim_time", { (const void*) &lv_obj_get_style_anim_time, "i", "(lv.lv_obj)i" } }, + { "get_style_arc_color", { (const void*) &lv_obj_get_style_arc_color, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_arc_color_filtered", { (const void*) &lv_obj_get_style_arc_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_arc_img_src", { (const void*) &lv_obj_get_style_arc_img_src, ".", "(lv.lv_obj)i" } }, + { "get_style_arc_opa", { (const void*) &lv_obj_get_style_arc_opa, "i", "(lv.lv_obj)i" } }, + { "get_style_arc_rounded", { (const void*) &lv_obj_get_style_arc_rounded, "b", "(lv.lv_obj)i" } }, + { "get_style_arc_width", { (const void*) &lv_obj_get_style_arc_width, "i", "(lv.lv_obj)i" } }, + { "get_style_base_dir", { (const void*) &lv_obj_get_style_base_dir, "i", "(lv.lv_obj)i" } }, + { "get_style_bg_color", { (const void*) &lv_obj_get_style_bg_color, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_bg_color_filtered", { (const void*) &lv_obj_get_style_bg_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_bg_grad_color", { (const void*) &lv_obj_get_style_bg_grad_color, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_bg_grad_color_filtered", { (const void*) &lv_obj_get_style_bg_grad_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_bg_grad_dir", { (const void*) &lv_obj_get_style_bg_grad_dir, "i", "(lv.lv_obj)i" } }, + { "get_style_bg_grad_stop", { (const void*) &lv_obj_get_style_bg_grad_stop, "i", "(lv.lv_obj)i" } }, + { "get_style_bg_img_opa", { (const void*) &lv_obj_get_style_bg_img_opa, "i", "(lv.lv_obj)i" } }, + { "get_style_bg_img_recolor", { (const void*) &lv_obj_get_style_bg_img_recolor, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_bg_img_recolor_filtered", { (const void*) &lv_obj_get_style_bg_img_recolor_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_bg_img_recolor_opa", { (const void*) &lv_obj_get_style_bg_img_recolor_opa, "i", "(lv.lv_obj)i" } }, + { "get_style_bg_img_src", { (const void*) &lv_obj_get_style_bg_img_src, ".", "(lv.lv_obj)i" } }, + { "get_style_bg_img_tiled", { (const void*) &lv_obj_get_style_bg_img_tiled, "b", "(lv.lv_obj)i" } }, + { "get_style_bg_main_stop", { (const void*) &lv_obj_get_style_bg_main_stop, "i", "(lv.lv_obj)i" } }, + { "get_style_bg_opa", { (const void*) &lv_obj_get_style_bg_opa, "i", "(lv.lv_obj)i" } }, + { "get_style_blend_mode", { (const void*) &lv_obj_get_style_blend_mode, "i", "(lv.lv_obj)i" } }, + { "get_style_border_color", { (const void*) &lv_obj_get_style_border_color, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_border_color_filtered", { (const void*) &lv_obj_get_style_border_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_border_opa", { (const void*) &lv_obj_get_style_border_opa, "i", "(lv.lv_obj)i" } }, + { "get_style_border_post", { (const void*) &lv_obj_get_style_border_post, "b", "(lv.lv_obj)i" } }, + { "get_style_border_side", { (const void*) &lv_obj_get_style_border_side, "i", "(lv.lv_obj)i" } }, + { "get_style_border_width", { (const void*) &lv_obj_get_style_border_width, "i", "(lv.lv_obj)i" } }, + { "get_style_clip_corner", { (const void*) &lv_obj_get_style_clip_corner, "b", "(lv.lv_obj)i" } }, + { "get_style_color_filter_dsc", { (const void*) &lv_obj_get_style_color_filter_dsc, "lv.lv_color_filter_dsc", "(lv.lv_obj)i" } }, + { "get_style_color_filter_opa", { (const void*) &lv_obj_get_style_color_filter_opa, "i", "(lv.lv_obj)i" } }, + { "get_style_flex_cross_place", { (const void*) &lv_obj_get_style_flex_cross_place, "i", "(lv.lv_obj)i" } }, + { "get_style_flex_flow", { (const void*) &lv_obj_get_style_flex_flow, "i", "(lv.lv_obj)i" } }, + { "get_style_flex_grow", { (const void*) &lv_obj_get_style_flex_grow, "i", "(lv.lv_obj)i" } }, + { "get_style_flex_main_place", { (const void*) &lv_obj_get_style_flex_main_place, "i", "(lv.lv_obj)i" } }, + { "get_style_flex_track_place", { (const void*) &lv_obj_get_style_flex_track_place, "i", "(lv.lv_obj)i" } }, + { "get_style_grid_cell_column_pos", { (const void*) &lv_obj_get_style_grid_cell_column_pos, "i", "(lv.lv_obj)i" } }, + { "get_style_grid_cell_column_span", { (const void*) &lv_obj_get_style_grid_cell_column_span, "i", "(lv.lv_obj)i" } }, + { "get_style_grid_cell_row_pos", { (const void*) &lv_obj_get_style_grid_cell_row_pos, "i", "(lv.lv_obj)i" } }, + { "get_style_grid_cell_row_span", { (const void*) &lv_obj_get_style_grid_cell_row_span, "i", "(lv.lv_obj)i" } }, + { "get_style_grid_cell_x_align", { (const void*) &lv_obj_get_style_grid_cell_x_align, "i", "(lv.lv_obj)i" } }, + { "get_style_grid_cell_y_align", { (const void*) &lv_obj_get_style_grid_cell_y_align, "i", "(lv.lv_obj)i" } }, + { "get_style_grid_column_align", { (const void*) &lv_obj_get_style_grid_column_align, "i", "(lv.lv_obj)i" } }, + { "get_style_grid_column_dsc_array", { (const void*) &lv_obj_get_style_grid_column_dsc_array, "c", "(lv.lv_obj)i" } }, + { "get_style_grid_row_align", { (const void*) &lv_obj_get_style_grid_row_align, "i", "(lv.lv_obj)i" } }, + { "get_style_grid_row_dsc_array", { (const void*) &lv_obj_get_style_grid_row_dsc_array, "c", "(lv.lv_obj)i" } }, + { "get_style_height", { (const void*) &lv_obj_get_style_height, "i", "(lv.lv_obj)i" } }, + { "get_style_img_opa", { (const void*) &lv_obj_get_style_img_opa, "i", "(lv.lv_obj)i" } }, + { "get_style_img_recolor", { (const void*) &lv_obj_get_style_img_recolor, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_img_recolor_filtered", { (const void*) &lv_obj_get_style_img_recolor_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_img_recolor_opa", { (const void*) &lv_obj_get_style_img_recolor_opa, "i", "(lv.lv_obj)i" } }, + { "get_style_layout", { (const void*) &lv_obj_get_style_layout, "i", "(lv.lv_obj)i" } }, + { "get_style_line_color", { (const void*) &lv_obj_get_style_line_color, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_line_color_filtered", { (const void*) &lv_obj_get_style_line_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_line_dash_gap", { (const void*) &lv_obj_get_style_line_dash_gap, "i", "(lv.lv_obj)i" } }, + { "get_style_line_dash_width", { (const void*) &lv_obj_get_style_line_dash_width, "i", "(lv.lv_obj)i" } }, + { "get_style_line_opa", { (const void*) &lv_obj_get_style_line_opa, "i", "(lv.lv_obj)i" } }, + { "get_style_line_rounded", { (const void*) &lv_obj_get_style_line_rounded, "b", "(lv.lv_obj)i" } }, + { "get_style_line_width", { (const void*) &lv_obj_get_style_line_width, "i", "(lv.lv_obj)i" } }, + { "get_style_max_height", { (const void*) &lv_obj_get_style_max_height, "i", "(lv.lv_obj)i" } }, + { "get_style_max_width", { (const void*) &lv_obj_get_style_max_width, "i", "(lv.lv_obj)i" } }, + { "get_style_min_height", { (const void*) &lv_obj_get_style_min_height, "i", "(lv.lv_obj)i" } }, + { "get_style_min_width", { (const void*) &lv_obj_get_style_min_width, "i", "(lv.lv_obj)i" } }, + { "get_style_opa", { (const void*) &lv_obj_get_style_opa, "i", "(lv.lv_obj)i" } }, + { "get_style_outline_color", { (const void*) &lv_obj_get_style_outline_color, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_outline_color_filtered", { (const void*) &lv_obj_get_style_outline_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_outline_opa", { (const void*) &lv_obj_get_style_outline_opa, "i", "(lv.lv_obj)i" } }, + { "get_style_outline_pad", { (const void*) &lv_obj_get_style_outline_pad, "i", "(lv.lv_obj)i" } }, + { "get_style_outline_width", { (const void*) &lv_obj_get_style_outline_width, "i", "(lv.lv_obj)i" } }, + { "get_style_pad_bottom", { (const void*) &lv_obj_get_style_pad_bottom, "i", "(lv.lv_obj)i" } }, + { "get_style_pad_column", { (const void*) &lv_obj_get_style_pad_column, "i", "(lv.lv_obj)i" } }, + { "get_style_pad_left", { (const void*) &lv_obj_get_style_pad_left, "i", "(lv.lv_obj)i" } }, + { "get_style_pad_right", { (const void*) &lv_obj_get_style_pad_right, "i", "(lv.lv_obj)i" } }, + { "get_style_pad_row", { (const void*) &lv_obj_get_style_pad_row, "i", "(lv.lv_obj)i" } }, + { "get_style_pad_top", { (const void*) &lv_obj_get_style_pad_top, "i", "(lv.lv_obj)i" } }, + { "get_style_prop", { (const void*) &lv_obj_get_style_prop, "i", "(lv.lv_obj)i(lv.lv_style_prop)" } }, + { "get_style_radius", { (const void*) &lv_obj_get_style_radius, "i", "(lv.lv_obj)i" } }, + { "get_style_shadow_color", { (const void*) &lv_obj_get_style_shadow_color, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_shadow_color_filtered", { (const void*) &lv_obj_get_style_shadow_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_shadow_ofs_x", { (const void*) &lv_obj_get_style_shadow_ofs_x, "i", "(lv.lv_obj)i" } }, + { "get_style_shadow_ofs_y", { (const void*) &lv_obj_get_style_shadow_ofs_y, "i", "(lv.lv_obj)i" } }, + { "get_style_shadow_opa", { (const void*) &lv_obj_get_style_shadow_opa, "i", "(lv.lv_obj)i" } }, + { "get_style_shadow_spread", { (const void*) &lv_obj_get_style_shadow_spread, "i", "(lv.lv_obj)i" } }, + { "get_style_shadow_width", { (const void*) &lv_obj_get_style_shadow_width, "i", "(lv.lv_obj)i" } }, + { "get_style_text_align", { (const void*) &lv_obj_get_style_text_align, "i", "(lv.lv_obj)i" } }, + { "get_style_text_color", { (const void*) &lv_obj_get_style_text_color, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_text_color_filtered", { (const void*) &lv_obj_get_style_text_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, + { "get_style_text_decor", { (const void*) &lv_obj_get_style_text_decor, "i", "(lv.lv_obj)i" } }, + { "get_style_text_font", { (const void*) &lv_obj_get_style_text_font, "lv.lv_font", "(lv.lv_obj)i" } }, + { "get_style_text_letter_space", { (const void*) &lv_obj_get_style_text_letter_space, "i", "(lv.lv_obj)i" } }, + { "get_style_text_line_space", { (const void*) &lv_obj_get_style_text_line_space, "i", "(lv.lv_obj)i" } }, + { "get_style_text_opa", { (const void*) &lv_obj_get_style_text_opa, "i", "(lv.lv_obj)i" } }, + { "get_style_transform_angle", { (const void*) &lv_obj_get_style_transform_angle, "i", "(lv.lv_obj)i" } }, + { "get_style_transform_height", { (const void*) &lv_obj_get_style_transform_height, "i", "(lv.lv_obj)i" } }, + { "get_style_transform_width", { (const void*) &lv_obj_get_style_transform_width, "i", "(lv.lv_obj)i" } }, + { "get_style_transform_zoom", { (const void*) &lv_obj_get_style_transform_zoom, "i", "(lv.lv_obj)i" } }, + { "get_style_transition", { (const void*) &lv_obj_get_style_transition, "lv.lv_style_transition_dsc", "(lv.lv_obj)i" } }, + { "get_style_translate_x", { (const void*) &lv_obj_get_style_translate_x, "i", "(lv.lv_obj)i" } }, + { "get_style_translate_y", { (const void*) &lv_obj_get_style_translate_y, "i", "(lv.lv_obj)i" } }, + { "get_style_width", { (const void*) &lv_obj_get_style_width, "i", "(lv.lv_obj)i" } }, + { "get_style_x", { (const void*) &lv_obj_get_style_x, "i", "(lv.lv_obj)i" } }, + { "get_style_y", { (const void*) &lv_obj_get_style_y, "i", "(lv.lv_obj)i" } }, + { "get_user_data", { (const void*) &lv_obj_get_user_data, ".", "(lv.lv_obj)" } }, + { "get_width", { (const void*) &lv_obj_get_width, "i", "(lv.lv_obj)" } }, + { "get_x", { (const void*) &lv_obj_get_x, "i", "(lv.lv_obj)" } }, + { "get_x2", { (const void*) &lv_obj_get_x2, "i", "(lv.lv_obj)" } }, + { "get_x_aligned", { (const void*) &lv_obj_get_x_aligned, "i", "(lv.lv_obj)" } }, + { "get_y", { (const void*) &lv_obj_get_y, "i", "(lv.lv_obj)" } }, + { "get_y2", { (const void*) &lv_obj_get_y2, "i", "(lv.lv_obj)" } }, + { "get_y_aligned", { (const void*) &lv_obj_get_y_aligned, "i", "(lv.lv_obj)" } }, + { "has_class", { (const void*) &lv_obj_has_class, "b", "(lv.lv_obj)(lv.lv_obj_class)" } }, + { "has_flag", { (const void*) &lv_obj_has_flag, "b", "(lv.lv_obj)i" } }, + { "has_flag_any", { (const void*) &lv_obj_has_flag_any, "b", "(lv.lv_obj)i" } }, + { "has_state", { (const void*) &lv_obj_has_state, "b", "(lv.lv_obj)i" } }, + { "hit_test", { (const void*) &lv_obj_hit_test, "b", "(lv.lv_obj)(lv.lv_point)" } }, + { "init_draw_arc_dsc", { (const void*) &lv_obj_init_draw_arc_dsc, "", "(lv.lv_obj)i(lv.lv_draw_arc_dsc)" } }, + { "init_draw_img_dsc", { (const void*) &lv_obj_init_draw_img_dsc, "", "(lv.lv_obj)i(lv.lv_draw_img_dsc)" } }, + { "init_draw_label_dsc", { (const void*) &lv_obj_init_draw_label_dsc, "", "(lv.lv_obj)i(lv.lv_draw_label_dsc)" } }, + { "init_draw_line_dsc", { (const void*) &lv_obj_init_draw_line_dsc, "", "(lv.lv_obj)i(lv.lv_draw_line_dsc)" } }, + { "init_draw_rect_dsc", { (const void*) &lv_obj_init_draw_rect_dsc, "", "(lv.lv_obj)i(lv.lv_draw_rect_dsc)" } }, + { "invalidate", { (const void*) &lv_obj_invalidate, "", "(lv.lv_obj)" } }, + { "invalidate_area", { (const void*) &lv_obj_invalidate_area, "", "(lv.lv_obj)(lv.lv_area)" } }, + { "is_editable", { (const void*) &lv_obj_is_editable, "b", "(lv.lv_obj)" } }, + { "is_group_def", { (const void*) &lv_obj_is_group_def, "b", "(lv.lv_obj)" } }, + { "is_layout_positioned", { (const void*) &lv_obj_is_layout_positioned, "b", "(lv.lv_obj)" } }, + { "is_scrolling", { (const void*) &lv_obj_is_scrolling, "b", "(lv.lv_obj)" } }, + { "is_valid", { (const void*) &lv_obj_is_valid, "b", "(lv.lv_obj)" } }, + { "is_visible", { (const void*) &lv_obj_is_visible, "b", "(lv.lv_obj)" } }, + { "mark_layout_as_dirty", { (const void*) &lv_obj_mark_layout_as_dirty, "", "(lv.lv_obj)" } }, + { "move_background", { (const void*) &lv_obj_move_background, "", "(lv.lv_obj)" } }, + { "move_children_by", { (const void*) &lv_obj_move_children_by, "", "(lv.lv_obj)iib" } }, + { "move_foreground", { (const void*) &lv_obj_move_foreground, "", "(lv.lv_obj)" } }, + { "move_to", { (const void*) &lv_obj_move_to, "", "(lv.lv_obj)ii" } }, + { "move_to_index", { (const void*) &lv_obj_move_to_index, "", "(lv.lv_obj)i" } }, + { "readjust_scroll", { (const void*) &lv_obj_readjust_scroll, "", "(lv.lv_obj)(lv.lv_anim_enable)" } }, + { "refr_pos", { (const void*) &lv_obj_refr_pos, "", "(lv.lv_obj)" } }, + { "refr_size", { (const void*) &lv_obj_refr_size, "b", "(lv.lv_obj)" } }, + { "refresh_ext_draw_size", { (const void*) &lv_obj_refresh_ext_draw_size, "", "(lv.lv_obj)" } }, + { "refresh_self_size", { (const void*) &lv_obj_refresh_self_size, "b", "(lv.lv_obj)" } }, + { "refresh_style", { (const void*) &lv_obj_refresh_style, "", "(lv.lv_obj)i(lv.lv_style_prop)" } }, + { "remove_event_cb", { (const void*) &lv_obj_remove_event_cb, "b", "(lv.lv_obj)." } }, + { "remove_event_cb_with_user_data", { (const void*) &lv_obj_remove_event_cb_with_user_data, "b", "(lv.lv_obj).." } }, + { "remove_event_dsc", { (const void*) &lv_obj_remove_event_dsc, "b", "(lv.lv_obj)i" } }, + { "remove_local_style_prop", { (const void*) &lv_obj_remove_local_style_prop, "b", "(lv.lv_obj)(lv.lv_style_prop)i" } }, + { "remove_style", { (const void*) &lv_obj_remove_style, "", "(lv.lv_obj)(lv.lv_style)i" } }, + { "remove_style_all", { (const void*) &lv_obj_remove_style_all, "", "(lv.lv_obj)" } }, + { "scroll_by", { (const void*) &lv_obj_scroll_by, "", "(lv.lv_obj)ii(lv.lv_anim_enable)" } }, + { "scroll_to", { (const void*) &lv_obj_scroll_to, "", "(lv.lv_obj)ii(lv.lv_anim_enable)" } }, + { "scroll_to_view", { (const void*) &lv_obj_scroll_to_view, "", "(lv.lv_obj)(lv.lv_anim_enable)" } }, + { "scroll_to_view_recursive", { (const void*) &lv_obj_scroll_to_view_recursive, "", "(lv.lv_obj)(lv.lv_anim_enable)" } }, + { "scroll_to_x", { (const void*) &lv_obj_scroll_to_x, "", "(lv.lv_obj)i(lv.lv_anim_enable)" } }, + { "scroll_to_y", { (const void*) &lv_obj_scroll_to_y, "", "(lv.lv_obj)i(lv.lv_anim_enable)" } }, + { "scrollbar_invalidate", { (const void*) &lv_obj_scrollbar_invalidate, "", "(lv.lv_obj)" } }, + { "set_align", { (const void*) &lv_obj_set_align, "", "(lv.lv_obj)i" } }, + { "set_content_height", { (const void*) &lv_obj_set_content_height, "", "(lv.lv_obj)i" } }, + { "set_content_width", { (const void*) &lv_obj_set_content_width, "", "(lv.lv_obj)i" } }, + { "set_ext_click_area", { (const void*) &lv_obj_set_ext_click_area, "", "(lv.lv_obj)i" } }, + { "set_flex_align", { (const void*) &lv_obj_set_flex_align, "", "(lv.lv_obj)iii" } }, + { "set_flex_flow", { (const void*) &lv_obj_set_flex_flow, "", "(lv.lv_obj)i" } }, + { "set_flex_grow", { (const void*) &lv_obj_set_flex_grow, "", "(lv.lv_obj)i" } }, + { "set_grid_align", { (const void*) &lv_obj_set_grid_align, "", "(lv.lv_obj)ii" } }, + { "set_grid_cell", { (const void*) &lv_obj_set_grid_cell, "", "(lv.lv_obj)iiiiii" } }, + { "set_grid_dsc_array", { (const void*) &lv_obj_set_grid_dsc_array, "", "(lv.lv_obj)(lv.lv_coord_arr)(lv.lv_coord_arr)" } }, + { "set_height", { (const void*) &lv_obj_set_height, "", "(lv.lv_obj)i" } }, + { "set_layout", { (const void*) &lv_obj_set_layout, "", "(lv.lv_obj)i" } }, + { "set_local_style_prop", { (const void*) &lv_obj_set_local_style_prop, "", "(lv.lv_obj)(lv.lv_style_prop)ii" } }, + { "set_parent", { (const void*) &lv_obj_set_parent, "", "(lv.lv_obj)(lv.lv_obj)" } }, + { "set_pos", { (const void*) &lv_obj_set_pos, "", "(lv.lv_obj)ii" } }, + { "set_scroll_dir", { (const void*) &lv_obj_set_scroll_dir, "", "(lv.lv_obj)i" } }, + { "set_scroll_snap_x", { (const void*) &lv_obj_set_scroll_snap_x, "", "(lv.lv_obj)i" } }, + { "set_scroll_snap_y", { (const void*) &lv_obj_set_scroll_snap_y, "", "(lv.lv_obj)i" } }, + { "set_scrollbar_mode", { (const void*) &lv_obj_set_scrollbar_mode, "", "(lv.lv_obj)i" } }, + { "set_size", { (const void*) &lv_obj_set_size, "", "(lv.lv_obj)ii" } }, + { "set_style_align", { (const void*) &lv_obj_set_style_align, "", "(lv.lv_obj)ii" } }, + { "set_style_anim_speed", { (const void*) &lv_obj_set_style_anim_speed, "", "(lv.lv_obj)ii" } }, + { "set_style_anim_time", { (const void*) &lv_obj_set_style_anim_time, "", "(lv.lv_obj)ii" } }, + { "set_style_arc_color", { (const void*) &lv_obj_set_style_arc_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_arc_color_filtered", { (const void*) &lv_obj_set_style_arc_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_arc_img_src", { (const void*) &lv_obj_set_style_arc_img_src, "", "(lv.lv_obj).i" } }, + { "set_style_arc_opa", { (const void*) &lv_obj_set_style_arc_opa, "", "(lv.lv_obj)ii" } }, + { "set_style_arc_rounded", { (const void*) &lv_obj_set_style_arc_rounded, "", "(lv.lv_obj)bi" } }, + { "set_style_arc_width", { (const void*) &lv_obj_set_style_arc_width, "", "(lv.lv_obj)ii" } }, + { "set_style_base_dir", { (const void*) &lv_obj_set_style_base_dir, "", "(lv.lv_obj)ii" } }, + { "set_style_bg_color", { (const void*) &lv_obj_set_style_bg_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_bg_color_filtered", { (const void*) &lv_obj_set_style_bg_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_bg_grad_color", { (const void*) &lv_obj_set_style_bg_grad_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_bg_grad_color_filtered", { (const void*) &lv_obj_set_style_bg_grad_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_bg_grad_dir", { (const void*) &lv_obj_set_style_bg_grad_dir, "", "(lv.lv_obj)ii" } }, + { "set_style_bg_grad_stop", { (const void*) &lv_obj_set_style_bg_grad_stop, "", "(lv.lv_obj)ii" } }, + { "set_style_bg_img_opa", { (const void*) &lv_obj_set_style_bg_img_opa, "", "(lv.lv_obj)ii" } }, + { "set_style_bg_img_recolor", { (const void*) &lv_obj_set_style_bg_img_recolor, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_bg_img_recolor_filtered", { (const void*) &lv_obj_set_style_bg_img_recolor_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_bg_img_recolor_opa", { (const void*) &lv_obj_set_style_bg_img_recolor_opa, "", "(lv.lv_obj)ii" } }, + { "set_style_bg_img_src", { (const void*) &lv_obj_set_style_bg_img_src, "", "(lv.lv_obj).i" } }, + { "set_style_bg_img_tiled", { (const void*) &lv_obj_set_style_bg_img_tiled, "", "(lv.lv_obj)bi" } }, + { "set_style_bg_main_stop", { (const void*) &lv_obj_set_style_bg_main_stop, "", "(lv.lv_obj)ii" } }, + { "set_style_bg_opa", { (const void*) &lv_obj_set_style_bg_opa, "", "(lv.lv_obj)ii" } }, + { "set_style_blend_mode", { (const void*) &lv_obj_set_style_blend_mode, "", "(lv.lv_obj)ii" } }, + { "set_style_border_color", { (const void*) &lv_obj_set_style_border_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_border_color_filtered", { (const void*) &lv_obj_set_style_border_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_border_opa", { (const void*) &lv_obj_set_style_border_opa, "", "(lv.lv_obj)ii" } }, + { "set_style_border_post", { (const void*) &lv_obj_set_style_border_post, "", "(lv.lv_obj)bi" } }, + { "set_style_border_side", { (const void*) &lv_obj_set_style_border_side, "", "(lv.lv_obj)ii" } }, + { "set_style_border_width", { (const void*) &lv_obj_set_style_border_width, "", "(lv.lv_obj)ii" } }, + { "set_style_clip_corner", { (const void*) &lv_obj_set_style_clip_corner, "", "(lv.lv_obj)bi" } }, + { "set_style_color_filter_dsc", { (const void*) &lv_obj_set_style_color_filter_dsc, "", "(lv.lv_obj)(lv.lv_color_filter_dsc)i" } }, + { "set_style_color_filter_opa", { (const void*) &lv_obj_set_style_color_filter_opa, "", "(lv.lv_obj)ii" } }, + { "set_style_flex_cross_place", { (const void*) &lv_obj_set_style_flex_cross_place, "", "(lv.lv_obj)ii" } }, + { "set_style_flex_flow", { (const void*) &lv_obj_set_style_flex_flow, "", "(lv.lv_obj)ii" } }, + { "set_style_flex_grow", { (const void*) &lv_obj_set_style_flex_grow, "", "(lv.lv_obj)ii" } }, + { "set_style_flex_main_place", { (const void*) &lv_obj_set_style_flex_main_place, "", "(lv.lv_obj)ii" } }, + { "set_style_flex_track_place", { (const void*) &lv_obj_set_style_flex_track_place, "", "(lv.lv_obj)ii" } }, + { "set_style_grid_cell_column_pos", { (const void*) &lv_obj_set_style_grid_cell_column_pos, "", "(lv.lv_obj)ii" } }, + { "set_style_grid_cell_column_span", { (const void*) &lv_obj_set_style_grid_cell_column_span, "", "(lv.lv_obj)ii" } }, + { "set_style_grid_cell_row_pos", { (const void*) &lv_obj_set_style_grid_cell_row_pos, "", "(lv.lv_obj)ii" } }, + { "set_style_grid_cell_row_span", { (const void*) &lv_obj_set_style_grid_cell_row_span, "", "(lv.lv_obj)ii" } }, + { "set_style_grid_cell_x_align", { (const void*) &lv_obj_set_style_grid_cell_x_align, "", "(lv.lv_obj)ii" } }, + { "set_style_grid_cell_y_align", { (const void*) &lv_obj_set_style_grid_cell_y_align, "", "(lv.lv_obj)ii" } }, + { "set_style_grid_column_align", { (const void*) &lv_obj_set_style_grid_column_align, "", "(lv.lv_obj)ii" } }, + { "set_style_grid_column_dsc_array", { (const void*) &lv_obj_set_style_grid_column_dsc_array, "", "(lv.lv_obj)(lv.lv_coord_arr)i" } }, + { "set_style_grid_row_align", { (const void*) &lv_obj_set_style_grid_row_align, "", "(lv.lv_obj)ii" } }, + { "set_style_grid_row_dsc_array", { (const void*) &lv_obj_set_style_grid_row_dsc_array, "", "(lv.lv_obj)(lv.lv_coord_arr)i" } }, + { "set_style_height", { (const void*) &lv_obj_set_style_height, "", "(lv.lv_obj)ii" } }, + { "set_style_img_opa", { (const void*) &lv_obj_set_style_img_opa, "", "(lv.lv_obj)ii" } }, + { "set_style_img_recolor", { (const void*) &lv_obj_set_style_img_recolor, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_img_recolor_filtered", { (const void*) &lv_obj_set_style_img_recolor_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_img_recolor_opa", { (const void*) &lv_obj_set_style_img_recolor_opa, "", "(lv.lv_obj)ii" } }, + { "set_style_layout", { (const void*) &lv_obj_set_style_layout, "", "(lv.lv_obj)ii" } }, + { "set_style_line_color", { (const void*) &lv_obj_set_style_line_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_line_color_filtered", { (const void*) &lv_obj_set_style_line_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_line_dash_gap", { (const void*) &lv_obj_set_style_line_dash_gap, "", "(lv.lv_obj)ii" } }, + { "set_style_line_dash_width", { (const void*) &lv_obj_set_style_line_dash_width, "", "(lv.lv_obj)ii" } }, + { "set_style_line_opa", { (const void*) &lv_obj_set_style_line_opa, "", "(lv.lv_obj)ii" } }, + { "set_style_line_rounded", { (const void*) &lv_obj_set_style_line_rounded, "", "(lv.lv_obj)bi" } }, + { "set_style_line_width", { (const void*) &lv_obj_set_style_line_width, "", "(lv.lv_obj)ii" } }, + { "set_style_max_height", { (const void*) &lv_obj_set_style_max_height, "", "(lv.lv_obj)ii" } }, + { "set_style_max_width", { (const void*) &lv_obj_set_style_max_width, "", "(lv.lv_obj)ii" } }, + { "set_style_min_height", { (const void*) &lv_obj_set_style_min_height, "", "(lv.lv_obj)ii" } }, + { "set_style_min_width", { (const void*) &lv_obj_set_style_min_width, "", "(lv.lv_obj)ii" } }, + { "set_style_opa", { (const void*) &lv_obj_set_style_opa, "", "(lv.lv_obj)ii" } }, + { "set_style_outline_color", { (const void*) &lv_obj_set_style_outline_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_outline_color_filtered", { (const void*) &lv_obj_set_style_outline_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_outline_opa", { (const void*) &lv_obj_set_style_outline_opa, "", "(lv.lv_obj)ii" } }, + { "set_style_outline_pad", { (const void*) &lv_obj_set_style_outline_pad, "", "(lv.lv_obj)ii" } }, + { "set_style_outline_width", { (const void*) &lv_obj_set_style_outline_width, "", "(lv.lv_obj)ii" } }, + { "set_style_pad_all", { (const void*) &lv_obj_set_style_pad_all, "", "(lv.lv_obj)ii" } }, + { "set_style_pad_bottom", { (const void*) &lv_obj_set_style_pad_bottom, "", "(lv.lv_obj)ii" } }, + { "set_style_pad_column", { (const void*) &lv_obj_set_style_pad_column, "", "(lv.lv_obj)ii" } }, + { "set_style_pad_gap", { (const void*) &lv_obj_set_style_pad_gap, "", "(lv.lv_obj)ii" } }, + { "set_style_pad_hor", { (const void*) &lv_obj_set_style_pad_hor, "", "(lv.lv_obj)ii" } }, + { "set_style_pad_left", { (const void*) &lv_obj_set_style_pad_left, "", "(lv.lv_obj)ii" } }, + { "set_style_pad_right", { (const void*) &lv_obj_set_style_pad_right, "", "(lv.lv_obj)ii" } }, + { "set_style_pad_row", { (const void*) &lv_obj_set_style_pad_row, "", "(lv.lv_obj)ii" } }, + { "set_style_pad_top", { (const void*) &lv_obj_set_style_pad_top, "", "(lv.lv_obj)ii" } }, + { "set_style_pad_ver", { (const void*) &lv_obj_set_style_pad_ver, "", "(lv.lv_obj)ii" } }, + { "set_style_radius", { (const void*) &lv_obj_set_style_radius, "", "(lv.lv_obj)ii" } }, + { "set_style_shadow_color", { (const void*) &lv_obj_set_style_shadow_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_shadow_color_filtered", { (const void*) &lv_obj_set_style_shadow_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_shadow_ofs_x", { (const void*) &lv_obj_set_style_shadow_ofs_x, "", "(lv.lv_obj)ii" } }, + { "set_style_shadow_ofs_y", { (const void*) &lv_obj_set_style_shadow_ofs_y, "", "(lv.lv_obj)ii" } }, + { "set_style_shadow_opa", { (const void*) &lv_obj_set_style_shadow_opa, "", "(lv.lv_obj)ii" } }, + { "set_style_shadow_spread", { (const void*) &lv_obj_set_style_shadow_spread, "", "(lv.lv_obj)ii" } }, + { "set_style_shadow_width", { (const void*) &lv_obj_set_style_shadow_width, "", "(lv.lv_obj)ii" } }, + { "set_style_size", { (const void*) &lv_obj_set_style_size, "", "(lv.lv_obj)ii" } }, + { "set_style_text_align", { (const void*) &lv_obj_set_style_text_align, "", "(lv.lv_obj)ii" } }, + { "set_style_text_color", { (const void*) &lv_obj_set_style_text_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_text_color_filtered", { (const void*) &lv_obj_set_style_text_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "set_style_text_decor", { (const void*) &lv_obj_set_style_text_decor, "", "(lv.lv_obj)ii" } }, + { "set_style_text_font", { (const void*) &lv_obj_set_style_text_font, "", "(lv.lv_obj)(lv.lv_font)i" } }, + { "set_style_text_letter_space", { (const void*) &lv_obj_set_style_text_letter_space, "", "(lv.lv_obj)ii" } }, + { "set_style_text_line_space", { (const void*) &lv_obj_set_style_text_line_space, "", "(lv.lv_obj)ii" } }, + { "set_style_text_opa", { (const void*) &lv_obj_set_style_text_opa, "", "(lv.lv_obj)ii" } }, + { "set_style_transform_angle", { (const void*) &lv_obj_set_style_transform_angle, "", "(lv.lv_obj)ii" } }, + { "set_style_transform_height", { (const void*) &lv_obj_set_style_transform_height, "", "(lv.lv_obj)ii" } }, + { "set_style_transform_width", { (const void*) &lv_obj_set_style_transform_width, "", "(lv.lv_obj)ii" } }, + { "set_style_transform_zoom", { (const void*) &lv_obj_set_style_transform_zoom, "", "(lv.lv_obj)ii" } }, + { "set_style_transition", { (const void*) &lv_obj_set_style_transition, "", "(lv.lv_obj)(lv.lv_style_transition_dsc)i" } }, + { "set_style_translate_x", { (const void*) &lv_obj_set_style_translate_x, "", "(lv.lv_obj)ii" } }, + { "set_style_translate_y", { (const void*) &lv_obj_set_style_translate_y, "", "(lv.lv_obj)ii" } }, + { "set_style_width", { (const void*) &lv_obj_set_style_width, "", "(lv.lv_obj)ii" } }, + { "set_style_x", { (const void*) &lv_obj_set_style_x, "", "(lv.lv_obj)ii" } }, + { "set_style_y", { (const void*) &lv_obj_set_style_y, "", "(lv.lv_obj)ii" } }, + { "set_user_data", { (const void*) &lv_obj_set_user_data, "", "(lv.lv_obj)." } }, + { "set_width", { (const void*) &lv_obj_set_width, "", "(lv.lv_obj)i" } }, + { "set_x", { (const void*) &lv_obj_set_x, "", "(lv.lv_obj)i" } }, + { "set_y", { (const void*) &lv_obj_set_y, "", "(lv.lv_obj)i" } }, + { "swap", { (const void*) &lv_obj_swap, "", "(lv.lv_obj)(lv.lv_obj)" } }, + { "tree_walk", { (const void*) &lv_obj_tree_walk, "", "(lv.lv_obj)^lv_obj_tree_walk_cb^." } }, + { "update_layout", { (const void*) &lv_obj_update_layout, "", "(lv.lv_obj)" } }, + { "update_snap", { (const void*) &lv_obj_update_snap, "", "(lv.lv_obj)(lv.lv_anim_enable)" } }, +}; + +/* `lv_group` methods */ +const be_ntv_func_def_t lv_group_func[] = { + { "add_obj", { (const void*) &lv_group_add_obj, "", "(lv.lv_group)(lv.lv_obj)" } }, + { "del", { (const void*) &lv_group_del, "", "(lv.lv_group)" } }, + { "focus_freeze", { (const void*) &lv_group_focus_freeze, "", "(lv.lv_group)b" } }, + { "focus_next", { (const void*) &lv_group_focus_next, "", "(lv.lv_group)" } }, + { "focus_obj", { (const void*) &lv_group_focus_obj, "", "(lv.lv_obj)" } }, + { "focus_prev", { (const void*) &lv_group_focus_prev, "", "(lv.lv_group)" } }, + { "get_editing", { (const void*) &lv_group_get_editing, "b", "(lv.lv_group)" } }, + { "get_focus_cb", { (const void*) &lv_group_get_focus_cb, "lv.lv_group_focus_cb", "(lv.lv_group)" } }, + { "get_focused", { (const void*) &lv_group_get_focused, "lv.lv_obj", "(lv.lv_group)" } }, + { "get_obj_count", { (const void*) &lv_group_get_obj_count, "i", "(lv.lv_group)" } }, + { "get_wrap", { (const void*) &lv_group_get_wrap, "b", "(lv.lv_group)" } }, + { "remove_all_objs", { (const void*) &lv_group_remove_all_objs, "", "(lv.lv_group)" } }, + { "remove_obj", { (const void*) &lv_group_remove_obj, "", "(lv.lv_obj)" } }, + { "send_data", { (const void*) &lv_group_send_data, "i", "(lv.lv_group)i" } }, + { "set_default", { (const void*) &lv_group_set_default, "", "(lv.lv_group)" } }, + { "set_editing", { (const void*) &lv_group_set_editing, "", "(lv.lv_group)b" } }, + { "set_focus_cb", { (const void*) &lv_group_set_focus_cb, "", "(lv.lv_group)^lv_group_focus_cb^" } }, + { "set_refocus_policy", { (const void*) &lv_group_set_refocus_policy, "", "(lv.lv_group)(lv.lv_group_refocus_policy)" } }, + { "set_wrap", { (const void*) &lv_group_set_wrap, "", "(lv.lv_group)b" } }, + { "swap_obj", { (const void*) &lv_group_swap_obj, "", "(lv.lv_obj)(lv.lv_obj)" } }, +}; + +/* `lv_indev` methods */ +const be_ntv_func_def_t lv_indev_func[] = { + { "enable", { (const void*) &lv_indev_enable, "", "(lv.lv_indev)b" } }, + { "get_gesture_dir", { (const void*) &lv_indev_get_gesture_dir, "i", "(lv.lv_indev)" } }, + { "get_key", { (const void*) &lv_indev_get_key, "i", "(lv.lv_indev)" } }, + { "get_point", { (const void*) &lv_indev_get_point, "", "(lv.lv_indev)(lv.lv_point)" } }, + { "get_scroll_dir", { (const void*) &lv_indev_get_scroll_dir, "i", "(lv.lv_indev)" } }, + { "get_scroll_obj", { (const void*) &lv_indev_get_scroll_obj, "lv.lv_obj", "(lv.lv_indev)" } }, + { "get_type", { (const void*) &lv_indev_get_type, "i", "(lv.lv_indev)" } }, + { "get_vect", { (const void*) &lv_indev_get_vect, "", "(lv.lv_indev)(lv.lv_point)" } }, + { "reset", { (const void*) &lv_indev_reset, "", "(lv.lv_indev)(lv.lv_obj)" } }, + { "reset_long_press", { (const void*) &lv_indev_reset_long_press, "", "(lv.lv_indev)" } }, + { "search_obj", { (const void*) &lv_indev_search_obj, "lv.lv_obj", "(lv.lv_obj)(lv.lv_point)" } }, + { "set_button_points", { (const void*) &lv_indev_set_button_points, "", "(lv.lv_indev)(lv.lv_point_arr)" } }, + { "set_cursor", { (const void*) &lv_indev_set_cursor, "", "(lv.lv_indev)(lv.lv_obj)" } }, + { "set_group", { (const void*) &lv_indev_set_group, "", "(lv.lv_indev)(lv.lv_group)" } }, + { "wait_release", { (const void*) &lv_indev_wait_release, "", "(lv.lv_indev)" } }, +}; + +/* `lv_chart` methods */ +#ifdef BE_LV_WIDGET_CHART +const be_ntv_func_def_t lv_chart_func[] = { + { "add_cursor", { (const void*) &lv_chart_add_cursor, "lv.lv_chart_cursor", "(lv.lv_obj)(lv.lv_color)i" } }, + { "add_series", { (const void*) &lv_chart_add_series, "lv.lv_chart_series", "(lv.lv_obj)(lv.lv_color)i" } }, + { "get_cursor_point", { (const void*) &lv_chart_get_cursor_point, "i", "(lv.lv_obj)(lv.lv_chart_cursor)" } }, + { "get_point_count", { (const void*) &lv_chart_get_point_count, "i", "(lv.lv_obj)" } }, + { "get_point_pos_by_id", { (const void*) &lv_chart_get_point_pos_by_id, "", "(lv.lv_obj)(lv.lv_chart_series)i(lv.lv_point)" } }, + { "get_pressed_point", { (const void*) &lv_chart_get_pressed_point, "i", "(lv.lv_obj)" } }, + { "get_series_next", { (const void*) &lv_chart_get_series_next, "lv.lv_chart_series", "(lv.lv_obj)(lv.lv_chart_series)" } }, + { "get_type", { (const void*) &lv_chart_get_type, "i", "(lv.lv_obj)" } }, + { "get_x_array", { (const void*) &lv_chart_get_x_array, "c", "(lv.lv_obj)(lv.lv_chart_series)" } }, + { "get_x_start_point", { (const void*) &lv_chart_get_x_start_point, "i", "(lv.lv_obj)(lv.lv_chart_series)" } }, + { "get_y_array", { (const void*) &lv_chart_get_y_array, "c", "(lv.lv_obj)(lv.lv_chart_series)" } }, + { "get_zoom_x", { (const void*) &lv_chart_get_zoom_x, "i", "(lv.lv_obj)" } }, + { "get_zoom_y", { (const void*) &lv_chart_get_zoom_y, "i", "(lv.lv_obj)" } }, + { "hide_series", { (const void*) &lv_chart_hide_series, "", "(lv.lv_obj)(lv.lv_chart_series)b" } }, + { "refresh", { (const void*) &lv_chart_refresh, "", "(lv.lv_obj)" } }, + { "remove_series", { (const void*) &lv_chart_remove_series, "", "(lv.lv_obj)(lv.lv_chart_series)" } }, + { "set_all_value", { (const void*) &lv_chart_set_all_value, "", "(lv.lv_obj)(lv.lv_chart_series)i" } }, + { "set_axis_tick", { (const void*) &lv_chart_set_axis_tick, "", "(lv.lv_obj)iiiiibi" } }, + { "set_cursor_point", { (const void*) &lv_chart_set_cursor_point, "", "(lv.lv_obj)(lv.lv_chart_cursor)(lv.lv_chart_series)i" } }, + { "set_cursor_pos", { (const void*) &lv_chart_set_cursor_pos, "", "(lv.lv_obj)(lv.lv_chart_cursor)(lv.lv_point)" } }, + { "set_div_line_count", { (const void*) &lv_chart_set_div_line_count, "", "(lv.lv_obj)ii" } }, + { "set_ext_x_array", { (const void*) &lv_chart_set_ext_x_array, "", "(lv.lv_obj)(lv.lv_chart_series)(lv.lv_coord_arr)" } }, + { "set_ext_y_array", { (const void*) &lv_chart_set_ext_y_array, "", "(lv.lv_obj)(lv.lv_chart_series)(lv.lv_coord_arr)" } }, + { "set_next_value", { (const void*) &lv_chart_set_next_value, "", "(lv.lv_obj)(lv.lv_chart_series)i" } }, + { "set_next_value2", { (const void*) &lv_chart_set_next_value2, "", "(lv.lv_obj)(lv.lv_chart_series)ii" } }, + { "set_point_count", { (const void*) &lv_chart_set_point_count, "", "(lv.lv_obj)i" } }, + { "set_range", { (const void*) &lv_chart_set_range, "", "(lv.lv_obj)iii" } }, + { "set_series_color", { (const void*) &lv_chart_set_series_color, "", "(lv.lv_obj)(lv.lv_chart_series)(lv.lv_color)" } }, + { "set_type", { (const void*) &lv_chart_set_type, "", "(lv.lv_obj)i" } }, + { "set_update_mode", { (const void*) &lv_chart_set_update_mode, "", "(lv.lv_obj)(lv.lv_chart_update_mode)" } }, + { "set_value_by_id", { (const void*) &lv_chart_set_value_by_id, "", "(lv.lv_obj)(lv.lv_chart_series)ii" } }, + { "set_value_by_id2", { (const void*) &lv_chart_set_value_by_id2, "", "(lv.lv_obj)(lv.lv_chart_series)iii" } }, + { "set_x_start_point", { (const void*) &lv_chart_set_x_start_point, "", "(lv.lv_obj)(lv.lv_chart_series)i" } }, + { "set_zoom_x", { (const void*) &lv_chart_set_zoom_x, "", "(lv.lv_obj)i" } }, + { "set_zoom_y", { (const void*) &lv_chart_set_zoom_y, "", "(lv.lv_obj)i" } }, +}; +#endif // BE_LV_WIDGET_CHART + +/* `lv_colorwheel` methods */ +#ifdef BE_LV_WIDGET_COLORWHEEL +const be_ntv_func_def_t lv_colorwheel_func[] = { + { "get_color_mode", { (const void*) &lv_colorwheel_get_color_mode, "i", "(lv.lv_obj)" } }, + { "get_color_mode_fixed", { (const void*) &lv_colorwheel_get_color_mode_fixed, "b", "(lv.lv_obj)" } }, + { "get_hsv", { (const void*) &lv_colorwheel_get_hsv, "i", "(lv.lv_obj)" } }, + { "get_rgb", { (const void*) &lv_colorwheel_get_rgb, "lv.lv_color", "(lv.lv_obj)" } }, + { "set_hsv", { (const void*) &lv_colorwheel_set_hsv, "b", "(lv.lv_obj)i" } }, + { "set_mode", { (const void*) &lv_colorwheel_set_mode, "", "(lv.lv_obj)i" } }, + { "set_mode_fixed", { (const void*) &lv_colorwheel_set_mode_fixed, "", "(lv.lv_obj)b" } }, + { "set_rgb", { (const void*) &lv_colorwheel_set_rgb, "b", "(lv.lv_obj)(lv.lv_color)" } }, +}; +#endif // BE_LV_WIDGET_COLORWHEEL + +/* `lv_imgbtn` methods */ +#ifdef BE_LV_WIDGET_IMGBTN +const be_ntv_func_def_t lv_imgbtn_func[] = { + { "set_src", { (const void*) &lv_imgbtn_set_src, "", "(lv.lv_obj)(lv.lv_imgbtn_state)..." } }, + { "set_state", { (const void*) &lv_imgbtn_set_state, "", "(lv.lv_obj)(lv.lv_imgbtn_state)" } }, +}; +#endif // BE_LV_WIDGET_IMGBTN + +/* `lv_led` methods */ +#ifdef BE_LV_WIDGET_LED +const be_ntv_func_def_t lv_led_func[] = { + { "get_brightness", { (const void*) &lv_led_get_brightness, "i", "(lv.lv_obj)" } }, + { "off", { (const void*) &lv_led_off, "", "(lv.lv_obj)" } }, + { "on", { (const void*) &lv_led_on, "", "(lv.lv_obj)" } }, + { "set_brightness", { (const void*) &lv_led_set_brightness, "", "(lv.lv_obj)i" } }, + { "set_color", { (const void*) &lv_led_set_color, "", "(lv.lv_obj)(lv.lv_color)" } }, + { "toggle", { (const void*) &lv_led_toggle, "", "(lv.lv_obj)" } }, +}; +#endif // BE_LV_WIDGET_LED + +/* `lv_meter` methods */ +#ifdef BE_LV_WIDGET_METER +const be_ntv_func_def_t lv_meter_func[] = { + { "add_arc", { (const void*) &lv_meter_add_arc, "lv.lv_meter_indicator", "(lv.lv_obj)(lv.lv_meter_scale)i(lv.lv_color)i" } }, + { "add_needle_img", { (const void*) &lv_meter_add_needle_img, "lv.lv_meter_indicator", "(lv.lv_obj)(lv.lv_meter_scale).ii" } }, + { "add_needle_line", { (const void*) &lv_meter_add_needle_line, "lv.lv_meter_indicator", "(lv.lv_obj)(lv.lv_meter_scale)i(lv.lv_color)i" } }, + { "add_scale", { (const void*) &lv_meter_add_scale, "lv.lv_meter_scale", "(lv.lv_obj)" } }, + { "add_scale_lines", { (const void*) &lv_meter_add_scale_lines, "lv.lv_meter_indicator", "(lv.lv_obj)(lv.lv_meter_scale)(lv.lv_color)(lv.lv_color)bi" } }, + { "set_indicator_end_value", { (const void*) &lv_meter_set_indicator_end_value, "", "(lv.lv_obj)(lv.lv_meter_indicator)i" } }, + { "set_indicator_start_value", { (const void*) &lv_meter_set_indicator_start_value, "", "(lv.lv_obj)(lv.lv_meter_indicator)i" } }, + { "set_indicator_value", { (const void*) &lv_meter_set_indicator_value, "", "(lv.lv_obj)(lv.lv_meter_indicator)i" } }, + { "set_scale_major_ticks", { (const void*) &lv_meter_set_scale_major_ticks, "", "(lv.lv_obj)(lv.lv_meter_scale)iii(lv.lv_color)i" } }, + { "set_scale_range", { (const void*) &lv_meter_set_scale_range, "", "(lv.lv_obj)(lv.lv_meter_scale)iiii" } }, + { "set_scale_ticks", { (const void*) &lv_meter_set_scale_ticks, "", "(lv.lv_obj)(lv.lv_meter_scale)iii(lv.lv_color)" } }, +}; +#endif // BE_LV_WIDGET_METER + +/* `lv_msgbox` methods */ +#ifdef BE_LV_WIDGET_MSGBOX +const be_ntv_func_def_t lv_msgbox_func[] = { + { "close", { (const void*) &lv_msgbox_close, "", "(lv.lv_obj)" } }, + { "close_async", { (const void*) &lv_msgbox_close_async, "", "(lv.lv_obj)" } }, + { "get_active_btn", { (const void*) &lv_msgbox_get_active_btn, "i", "(lv.lv_obj)" } }, + { "get_active_btn_text", { (const void*) &lv_msgbox_get_active_btn_text, "s", "(lv.lv_obj)" } }, + { "get_btns", { (const void*) &lv_msgbox_get_btns, "lv.lv_obj", "(lv.lv_obj)" } }, + { "get_close_btn", { (const void*) &lv_msgbox_get_close_btn, "lv.lv_obj", "(lv.lv_obj)" } }, + { "get_content", { (const void*) &lv_msgbox_get_content, "lv.lv_obj", "(lv.lv_obj)" } }, + { "get_text", { (const void*) &lv_msgbox_get_text, "lv.lv_obj", "(lv.lv_obj)" } }, + { "get_title", { (const void*) &lv_msgbox_get_title, "lv.lv_obj", "(lv.lv_obj)" } }, +}; +#endif // BE_LV_WIDGET_MSGBOX + +/* `lv_spinbox` methods */ +#ifdef BE_LV_WIDGET_SPINBOX +const be_ntv_func_def_t lv_spinbox_func[] = { + { "decrement", { (const void*) &lv_spinbox_decrement, "", "(lv.lv_obj)" } }, + { "get_rollover", { (const void*) &lv_spinbox_get_rollover, "b", "(lv.lv_obj)" } }, + { "get_step", { (const void*) &lv_spinbox_get_step, "i", "(lv.lv_obj)" } }, + { "get_value", { (const void*) &lv_spinbox_get_value, "i", "(lv.lv_obj)" } }, + { "increment", { (const void*) &lv_spinbox_increment, "", "(lv.lv_obj)" } }, + { "set_digit_format", { (const void*) &lv_spinbox_set_digit_format, "", "(lv.lv_obj)ii" } }, + { "set_digit_step_direction", { (const void*) &lv_spinbox_set_digit_step_direction, "", "(lv.lv_obj)i" } }, + { "set_pos", { (const void*) &lv_spinbox_set_pos, "", "(lv.lv_obj)i" } }, + { "set_range", { (const void*) &lv_spinbox_set_range, "", "(lv.lv_obj)ii" } }, + { "set_rollover", { (const void*) &lv_spinbox_set_rollover, "", "(lv.lv_obj)b" } }, + { "set_step", { (const void*) &lv_spinbox_set_step, "", "(lv.lv_obj)i" } }, + { "set_value", { (const void*) &lv_spinbox_set_value, "", "(lv.lv_obj)i" } }, + { "step_next", { (const void*) &lv_spinbox_step_next, "", "(lv.lv_obj)" } }, + { "step_prev", { (const void*) &lv_spinbox_step_prev, "", "(lv.lv_obj)" } }, +}; +#endif // BE_LV_WIDGET_SPINBOX + +/* `lv_spinner` methods */ +#ifdef BE_LV_WIDGET_SPINNER +const be_ntv_func_def_t lv_spinner_func[] = { +}; +#endif // BE_LV_WIDGET_SPINNER + +/* `lv_arc` methods */ +#ifdef BE_LV_WIDGET_ARC +const be_ntv_func_def_t lv_arc_func[] = { + { "get_angle_end", { (const void*) &lv_arc_get_angle_end, "i", "(lv.lv_obj)" } }, + { "get_angle_start", { (const void*) &lv_arc_get_angle_start, "i", "(lv.lv_obj)" } }, + { "get_bg_angle_end", { (const void*) &lv_arc_get_bg_angle_end, "i", "(lv.lv_obj)" } }, + { "get_bg_angle_start", { (const void*) &lv_arc_get_bg_angle_start, "i", "(lv.lv_obj)" } }, + { "get_max_value", { (const void*) &lv_arc_get_max_value, "i", "(lv.lv_obj)" } }, + { "get_min_value", { (const void*) &lv_arc_get_min_value, "i", "(lv.lv_obj)" } }, + { "get_mode", { (const void*) &lv_arc_get_mode, "i", "(lv.lv_obj)" } }, + { "get_value", { (const void*) &lv_arc_get_value, "i", "(lv.lv_obj)" } }, + { "set_angles", { (const void*) &lv_arc_set_angles, "", "(lv.lv_obj)ii" } }, + { "set_bg_angles", { (const void*) &lv_arc_set_bg_angles, "", "(lv.lv_obj)ii" } }, + { "set_bg_end_angle", { (const void*) &lv_arc_set_bg_end_angle, "", "(lv.lv_obj)i" } }, + { "set_bg_start_angle", { (const void*) &lv_arc_set_bg_start_angle, "", "(lv.lv_obj)i" } }, + { "set_change_rate", { (const void*) &lv_arc_set_change_rate, "", "(lv.lv_obj)i" } }, + { "set_end_angle", { (const void*) &lv_arc_set_end_angle, "", "(lv.lv_obj)i" } }, + { "set_mode", { (const void*) &lv_arc_set_mode, "", "(lv.lv_obj)i" } }, + { "set_range", { (const void*) &lv_arc_set_range, "", "(lv.lv_obj)ii" } }, + { "set_rotation", { (const void*) &lv_arc_set_rotation, "", "(lv.lv_obj)i" } }, + { "set_start_angle", { (const void*) &lv_arc_set_start_angle, "", "(lv.lv_obj)i" } }, + { "set_value", { (const void*) &lv_arc_set_value, "", "(lv.lv_obj)i" } }, +}; +#endif // BE_LV_WIDGET_ARC + +/* `lv_bar` methods */ +#ifdef BE_LV_WIDGET_BAR +const be_ntv_func_def_t lv_bar_func[] = { + { "get_max_value", { (const void*) &lv_bar_get_max_value, "i", "(lv.lv_obj)" } }, + { "get_min_value", { (const void*) &lv_bar_get_min_value, "i", "(lv.lv_obj)" } }, + { "get_mode", { (const void*) &lv_bar_get_mode, "i", "(lv.lv_obj)" } }, + { "get_start_value", { (const void*) &lv_bar_get_start_value, "i", "(lv.lv_obj)" } }, + { "get_value", { (const void*) &lv_bar_get_value, "i", "(lv.lv_obj)" } }, + { "set_mode", { (const void*) &lv_bar_set_mode, "", "(lv.lv_obj)i" } }, + { "set_range", { (const void*) &lv_bar_set_range, "", "(lv.lv_obj)ii" } }, + { "set_start_value", { (const void*) &lv_bar_set_start_value, "", "(lv.lv_obj)i(lv.lv_anim_enable)" } }, + { "set_value", { (const void*) &lv_bar_set_value, "", "(lv.lv_obj)i(lv.lv_anim_enable)" } }, +}; +#endif // BE_LV_WIDGET_BAR + +/* `lv_btn` methods */ +#ifdef BE_LV_WIDGET_BTN +const be_ntv_func_def_t lv_btn_func[] = { +}; +#endif // BE_LV_WIDGET_BTN + +/* `lv_btnmatrix` methods */ +#ifdef BE_LV_WIDGET_BTNMATRIX +const be_ntv_func_def_t lv_btnmatrix_func[] = { + { "clear_btn_ctrl", { (const void*) &lv_btnmatrix_clear_btn_ctrl, "", "(lv.lv_obj)i(lv.lv_btnmatrix_ctrl)" } }, + { "clear_btn_ctrl_all", { (const void*) &lv_btnmatrix_clear_btn_ctrl_all, "", "(lv.lv_obj)(lv.lv_btnmatrix_ctrl)" } }, + { "get_btn_text", { (const void*) &lv_btnmatrix_get_btn_text, "s", "(lv.lv_obj)i" } }, + { "get_map", { (const void*) &lv_btnmatrix_get_map, "c", "(lv.lv_obj)" } }, + { "get_one_checked", { (const void*) &lv_btnmatrix_get_one_checked, "b", "(lv.lv_obj)" } }, + { "get_selected_btn", { (const void*) &lv_btnmatrix_get_selected_btn, "i", "(lv.lv_obj)" } }, + { "has_btn_ctrl", { (const void*) &lv_btnmatrix_has_btn_ctrl, "b", "(lv.lv_obj)i(lv.lv_btnmatrix_ctrl)" } }, + { "set_btn_ctrl", { (const void*) &lv_btnmatrix_set_btn_ctrl, "", "(lv.lv_obj)i(lv.lv_btnmatrix_ctrl)" } }, + { "set_btn_ctrl_all", { (const void*) &lv_btnmatrix_set_btn_ctrl_all, "", "(lv.lv_obj)(lv.lv_btnmatrix_ctrl)" } }, + { "set_btn_width", { (const void*) &lv_btnmatrix_set_btn_width, "", "(lv.lv_obj)ii" } }, + { "set_ctrl_map", { (const void*) &lv_btnmatrix_set_ctrl_map, "", "(lv.lv_obj)(lv.lv_btnmatrix_ctrl)" } }, + { "set_map", { (const void*) &lv_btnmatrix_set_map, "", "(lv.lv_obj)(lv.str_arr)" } }, + { "set_one_checked", { (const void*) &lv_btnmatrix_set_one_checked, "", "(lv.lv_obj)b" } }, + { "set_selected_btn", { (const void*) &lv_btnmatrix_set_selected_btn, "", "(lv.lv_obj)i" } }, +}; +#endif // BE_LV_WIDGET_BTNMATRIX + +/* `lv_canvas` methods */ +#ifdef BE_LV_WIDGET_CANVAS +const be_ntv_func_def_t lv_canvas_func[] = { + { "blur_hor", { (const void*) &lv_canvas_blur_hor, "", "(lv.lv_obj)(lv.lv_area)i" } }, + { "blur_ver", { (const void*) &lv_canvas_blur_ver, "", "(lv.lv_obj)(lv.lv_area)i" } }, + { "copy_buf", { (const void*) &lv_canvas_copy_buf, "", "(lv.lv_obj).iiii" } }, + { "draw_arc", { (const void*) &lv_canvas_draw_arc, "", "(lv.lv_obj)iiiii(lv.lv_draw_arc_dsc)" } }, + { "draw_img", { (const void*) &lv_canvas_draw_img, "", "(lv.lv_obj)ii.(lv.lv_draw_img_dsc)" } }, + { "draw_line", { (const void*) &lv_canvas_draw_line, "", "(lv.lv_obj)(lv.lv_point_arr)i(lv.lv_draw_line_dsc)" } }, + { "draw_polygon", { (const void*) &lv_canvas_draw_polygon, "", "(lv.lv_obj)(lv.lv_point_arr)i(lv.lv_draw_rect_dsc)" } }, + { "draw_rect", { (const void*) &lv_canvas_draw_rect, "", "(lv.lv_obj)iiii(lv.lv_draw_rect_dsc)" } }, + { "draw_text", { (const void*) &lv_canvas_draw_text, "", "(lv.lv_obj)iii(lv.lv_draw_label_dsc)s" } }, + { "fill_bg", { (const void*) &lv_canvas_fill_bg, "", "(lv.lv_obj)(lv.lv_color)i" } }, + { "get_img", { (const void*) &lv_canvas_get_img, "lv.lv_img_dsc", "(lv.lv_obj)" } }, + { "get_px", { (const void*) &lv_canvas_get_px, "lv.lv_color", "(lv.lv_obj)ii" } }, + { "set_buffer", { (const void*) &lv_canvas_set_buffer, "", "(lv.lv_obj).iii" } }, + { "set_palette", { (const void*) &lv_canvas_set_palette, "", "(lv.lv_obj)i(lv.lv_color)" } }, + { "set_px", { (const void*) &lv_canvas_set_px, "", "(lv.lv_obj)ii(lv.lv_color)" } }, + { "set_px_color", { (const void*) &lv_canvas_set_px_color, "", "(lv.lv_obj)ii(lv.lv_color)" } }, + { "set_px_opa", { (const void*) &lv_canvas_set_px_opa, "", "(lv.lv_obj)iii" } }, + { "transform", { (const void*) &lv_canvas_transform, "", "(lv.lv_obj)(lv.lv_img_dsc)iiiiiib" } }, +}; +#endif // BE_LV_WIDGET_CANVAS + +/* `lv_checkbox` methods */ +#ifdef BE_LV_WIDGET_CHECKBOX +const be_ntv_func_def_t lv_checkbox_func[] = { + { "get_text", { (const void*) &lv_checkbox_get_text, "s", "(lv.lv_obj)" } }, + { "set_text", { (const void*) &lv_checkbox_set_text, "", "(lv.lv_obj)s" } }, + { "set_text_static", { (const void*) &lv_checkbox_set_text_static, "", "(lv.lv_obj)s" } }, +}; +#endif // BE_LV_WIDGET_CHECKBOX + +/* `lv_dropdown` methods */ +#ifdef BE_LV_WIDGET_DROPDOWN +const be_ntv_func_def_t lv_dropdown_func[] = { + { "add_option", { (const void*) &lv_dropdown_add_option, "", "(lv.lv_obj)si" } }, + { "clear_options", { (const void*) &lv_dropdown_clear_options, "", "(lv.lv_obj)" } }, + { "close", { (const void*) &lv_dropdown_close, "", "(lv.lv_obj)" } }, + { "get_dir", { (const void*) &lv_dropdown_get_dir, "i", "(lv.lv_obj)" } }, + { "get_list", { (const void*) &lv_dropdown_get_list, "lv.lv_obj", "(lv.lv_obj)" } }, + { "get_option_cnt", { (const void*) &lv_dropdown_get_option_cnt, "i", "(lv.lv_obj)" } }, + { "get_options", { (const void*) &lv_dropdown_get_options, "s", "(lv.lv_obj)" } }, + { "get_selected", { (const void*) &lv_dropdown_get_selected, "i", "(lv.lv_obj)" } }, + { "get_selected_highlight", { (const void*) &lv_dropdown_get_selected_highlight, "b", "(lv.lv_obj)" } }, + { "get_selected_str", { (const void*) &lv_dropdown_get_selected_str, "", "(lv.lv_obj)si" } }, + { "get_symbol", { (const void*) &lv_dropdown_get_symbol, "s", "(lv.lv_obj)" } }, + { "get_text", { (const void*) &lv_dropdown_get_text, "s", "(lv.lv_obj)" } }, + { "open", { (const void*) &lv_dropdown_open, "", "(lv.lv_obj)" } }, + { "set_dir", { (const void*) &lv_dropdown_set_dir, "", "(lv.lv_obj)i" } }, + { "set_options", { (const void*) &lv_dropdown_set_options, "", "(lv.lv_obj)s" } }, + { "set_options_static", { (const void*) &lv_dropdown_set_options_static, "", "(lv.lv_obj)s" } }, + { "set_selected", { (const void*) &lv_dropdown_set_selected, "", "(lv.lv_obj)i" } }, + { "set_selected_highlight", { (const void*) &lv_dropdown_set_selected_highlight, "", "(lv.lv_obj)b" } }, + { "set_symbol", { (const void*) &lv_dropdown_set_symbol, "", "(lv.lv_obj)." } }, + { "set_text", { (const void*) &lv_dropdown_set_text, "", "(lv.lv_obj)s" } }, +}; +#endif // BE_LV_WIDGET_DROPDOWN + +/* `lv_label` methods */ +#ifdef BE_LV_WIDGET_LABEL +const be_ntv_func_def_t lv_label_func[] = { + { "cut_text", { (const void*) &lv_label_cut_text, "", "(lv.lv_obj)ii" } }, + { "get_letter_on", { (const void*) &lv_label_get_letter_on, "i", "(lv.lv_obj)(lv.lv_point)" } }, + { "get_letter_pos", { (const void*) &lv_label_get_letter_pos, "", "(lv.lv_obj)i(lv.lv_point)" } }, + { "get_long_mode", { (const void*) &lv_label_get_long_mode, "i", "(lv.lv_obj)" } }, + { "get_recolor", { (const void*) &lv_label_get_recolor, "b", "(lv.lv_obj)" } }, + { "get_text", { (const void*) &lv_label_get_text, "s", "(lv.lv_obj)" } }, + { "get_text_selection_end", { (const void*) &lv_label_get_text_selection_end, "i", "(lv.lv_obj)" } }, + { "get_text_selection_start", { (const void*) &lv_label_get_text_selection_start, "i", "(lv.lv_obj)" } }, + { "ins_text", { (const void*) &lv_label_ins_text, "", "(lv.lv_obj)is" } }, + { "is_char_under_pos", { (const void*) &lv_label_is_char_under_pos, "b", "(lv.lv_obj)(lv.lv_point)" } }, + { "set_long_mode", { (const void*) &lv_label_set_long_mode, "", "(lv.lv_obj)i" } }, + { "set_recolor", { (const void*) &lv_label_set_recolor, "", "(lv.lv_obj)b" } }, + { "set_text", { (const void*) &lv_label_set_text, "", "(lv.lv_obj)s" } }, + { "set_text_fmt", { (const void*) &lv_label_set_text_fmt, "", "(lv.lv_obj)s[......]" } }, + { "set_text_sel_end", { (const void*) &lv_label_set_text_sel_end, "", "(lv.lv_obj)i" } }, + { "set_text_sel_start", { (const void*) &lv_label_set_text_sel_start, "", "(lv.lv_obj)i" } }, + { "set_text_static", { (const void*) &lv_label_set_text_static, "", "(lv.lv_obj)s" } }, +}; +#endif // BE_LV_WIDGET_LABEL + +/* `lv_line` methods */ +#ifdef BE_LV_WIDGET_LINE +const be_ntv_func_def_t lv_line_func[] = { + { "get_y_invert", { (const void*) &lv_line_get_y_invert, "b", "(lv.lv_obj)" } }, + { "set_points", { (const void*) &lv_line_set_points, "", "(lv.lv_obj)(lv.lv_point_arr)i" } }, + { "set_y_invert", { (const void*) &lv_line_set_y_invert, "", "(lv.lv_obj)b" } }, +}; +#endif // BE_LV_WIDGET_LINE + +/* `lv_roller` methods */ +#ifdef BE_LV_WIDGET_ROLLER +const be_ntv_func_def_t lv_roller_func[] = { + { "get_option_cnt", { (const void*) &lv_roller_get_option_cnt, "i", "(lv.lv_obj)" } }, + { "get_options", { (const void*) &lv_roller_get_options, "s", "(lv.lv_obj)" } }, + { "get_selected", { (const void*) &lv_roller_get_selected, "i", "(lv.lv_obj)" } }, + { "get_selected_str", { (const void*) &lv_roller_get_selected_str, "", "(lv.lv_obj)si" } }, + { "set_options", { (const void*) &lv_roller_set_options, "", "(lv.lv_obj)s(lv.lv_roller_mode)" } }, + { "set_selected", { (const void*) &lv_roller_set_selected, "", "(lv.lv_obj)i(lv.lv_anim_enable)" } }, + { "set_visible_row_count", { (const void*) &lv_roller_set_visible_row_count, "", "(lv.lv_obj)i" } }, +}; +#endif // BE_LV_WIDGET_ROLLER + +/* `lv_slider` methods */ +#ifdef BE_LV_WIDGET_SLIDER +const be_ntv_func_def_t lv_slider_func[] = { + { "get_left_value", { (const void*) &lv_slider_get_left_value, "i", "(lv.lv_obj)" } }, + { "get_max_value", { (const void*) &lv_slider_get_max_value, "i", "(lv.lv_obj)" } }, + { "get_min_value", { (const void*) &lv_slider_get_min_value, "i", "(lv.lv_obj)" } }, + { "get_mode", { (const void*) &lv_slider_get_mode, "i", "(lv.lv_obj)" } }, + { "get_value", { (const void*) &lv_slider_get_value, "i", "(lv.lv_obj)" } }, + { "is_dragged", { (const void*) &lv_slider_is_dragged, "b", "(lv.lv_obj)" } }, + { "set_left_value", { (const void*) &lv_slider_set_left_value, "", "(lv.lv_obj)i(lv.lv_anim_enable)" } }, + { "set_mode", { (const void*) &lv_slider_set_mode, "", "(lv.lv_obj)i" } }, + { "set_range", { (const void*) &lv_slider_set_range, "", "(lv.lv_obj)ii" } }, + { "set_value", { (const void*) &lv_slider_set_value, "", "(lv.lv_obj)i(lv.lv_anim_enable)" } }, +}; +#endif // BE_LV_WIDGET_SLIDER + +/* `lv_switch` methods */ +#ifdef BE_LV_WIDGET_SWITCH +const be_ntv_func_def_t lv_switch_func[] = { +}; +#endif // BE_LV_WIDGET_SWITCH + +/* `lv_table` methods */ +#ifdef BE_LV_WIDGET_TABLE +const be_ntv_func_def_t lv_table_func[] = { + { "add_cell_ctrl", { (const void*) &lv_table_add_cell_ctrl, "", "(lv.lv_obj)ii(lv.lv_table_cell_ctrl)" } }, + { "clear_cell_ctrl", { (const void*) &lv_table_clear_cell_ctrl, "", "(lv.lv_obj)ii(lv.lv_table_cell_ctrl)" } }, + { "get_cell_value", { (const void*) &lv_table_get_cell_value, "s", "(lv.lv_obj)ii" } }, + { "get_col_cnt", { (const void*) &lv_table_get_col_cnt, "i", "(lv.lv_obj)" } }, + { "get_col_width", { (const void*) &lv_table_get_col_width, "i", "(lv.lv_obj)i" } }, + { "get_row_cnt", { (const void*) &lv_table_get_row_cnt, "i", "(lv.lv_obj)" } }, + { "get_selected_cell", { (const void*) &lv_table_get_selected_cell, "", "(lv.lv_obj)(lv.uint16)(lv.uint16)" } }, + { "has_cell_ctrl", { (const void*) &lv_table_has_cell_ctrl, "b", "(lv.lv_obj)ii(lv.lv_table_cell_ctrl)" } }, + { "set_cell_value", { (const void*) &lv_table_set_cell_value, "", "(lv.lv_obj)iis" } }, + { "set_cell_value_fmt", { (const void*) &lv_table_set_cell_value_fmt, "", "(lv.lv_obj)iis[......]" } }, + { "set_col_cnt", { (const void*) &lv_table_set_col_cnt, "", "(lv.lv_obj)i" } }, + { "set_col_width", { (const void*) &lv_table_set_col_width, "", "(lv.lv_obj)ii" } }, + { "set_row_cnt", { (const void*) &lv_table_set_row_cnt, "", "(lv.lv_obj)i" } }, +}; +#endif // BE_LV_WIDGET_TABLE + +/* `lv_textarea` methods */ +#ifdef BE_LV_WIDGET_TEXTAREA +const be_ntv_func_def_t lv_textarea_func[] = { + { "add_char", { (const void*) &lv_textarea_add_char, "", "(lv.lv_obj)i" } }, + { "add_text", { (const void*) &lv_textarea_add_text, "", "(lv.lv_obj)s" } }, + { "clear_selection", { (const void*) &lv_textarea_clear_selection, "", "(lv.lv_obj)" } }, + { "cursor_down", { (const void*) &lv_textarea_cursor_down, "", "(lv.lv_obj)" } }, + { "cursor_left", { (const void*) &lv_textarea_cursor_left, "", "(lv.lv_obj)" } }, + { "cursor_right", { (const void*) &lv_textarea_cursor_right, "", "(lv.lv_obj)" } }, + { "cursor_up", { (const void*) &lv_textarea_cursor_up, "", "(lv.lv_obj)" } }, + { "del_char", { (const void*) &lv_textarea_del_char, "", "(lv.lv_obj)" } }, + { "del_char_forward", { (const void*) &lv_textarea_del_char_forward, "", "(lv.lv_obj)" } }, + { "get_accepted_chars", { (const void*) &lv_textarea_get_accepted_chars, "s", "(lv.lv_obj)" } }, + { "get_cursor_click_pos", { (const void*) &lv_textarea_get_cursor_click_pos, "b", "(lv.lv_obj)" } }, + { "get_cursor_pos", { (const void*) &lv_textarea_get_cursor_pos, "i", "(lv.lv_obj)" } }, + { "get_label", { (const void*) &lv_textarea_get_label, "lv.lv_obj", "(lv.lv_obj)" } }, + { "get_max_length", { (const void*) &lv_textarea_get_max_length, "i", "(lv.lv_obj)" } }, + { "get_one_line", { (const void*) &lv_textarea_get_one_line, "b", "(lv.lv_obj)" } }, + { "get_password_mode", { (const void*) &lv_textarea_get_password_mode, "b", "(lv.lv_obj)" } }, + { "get_password_show_time", { (const void*) &lv_textarea_get_password_show_time, "i", "(lv.lv_obj)" } }, + { "get_placeholder_text", { (const void*) &lv_textarea_get_placeholder_text, "s", "(lv.lv_obj)" } }, + { "get_text", { (const void*) &lv_textarea_get_text, "s", "(lv.lv_obj)" } }, + { "get_text_selection", { (const void*) &lv_textarea_get_text_selection, "b", "(lv.lv_obj)" } }, + { "set_accepted_chars", { (const void*) &lv_textarea_set_accepted_chars, "", "(lv.lv_obj)s" } }, + { "set_align", { (const void*) &lv_textarea_set_align, "", "(lv.lv_obj)i" } }, + { "set_cursor_click_pos", { (const void*) &lv_textarea_set_cursor_click_pos, "", "(lv.lv_obj)b" } }, + { "set_cursor_pos", { (const void*) &lv_textarea_set_cursor_pos, "", "(lv.lv_obj)i" } }, + { "set_insert_replace", { (const void*) &lv_textarea_set_insert_replace, "", "(lv.lv_obj)s" } }, + { "set_max_length", { (const void*) &lv_textarea_set_max_length, "", "(lv.lv_obj)i" } }, + { "set_one_line", { (const void*) &lv_textarea_set_one_line, "", "(lv.lv_obj)b" } }, + { "set_password_mode", { (const void*) &lv_textarea_set_password_mode, "", "(lv.lv_obj)b" } }, + { "set_password_show_time", { (const void*) &lv_textarea_set_password_show_time, "", "(lv.lv_obj)i" } }, + { "set_placeholder_text", { (const void*) &lv_textarea_set_placeholder_text, "", "(lv.lv_obj)s" } }, + { "set_text", { (const void*) &lv_textarea_set_text, "", "(lv.lv_obj)s" } }, + { "set_text_selection", { (const void*) &lv_textarea_set_text_selection, "", "(lv.lv_obj)b" } }, + { "text_is_selected", { (const void*) &lv_textarea_text_is_selected, "b", "(lv.lv_obj)" } }, +}; +#endif // BE_LV_WIDGET_TEXTAREA + +extern const bclass be_class_lv_arc; +extern const bclass be_class_lv_bar; +extern const bclass be_class_lv_btn; +extern const bclass be_class_lv_btnmatrix; +extern const bclass be_class_lv_canvas; +extern const bclass be_class_lv_chart; +extern const bclass be_class_lv_checkbox; +extern const bclass be_class_lv_color; +extern const bclass be_class_lv_colorwheel; +extern const bclass be_class_lv_disp; +extern const bclass be_class_lv_dropdown; +extern const bclass be_class_lv_font; +extern const bclass be_class_lv_group; +extern const bclass be_class_lv_img; +extern const bclass be_class_lv_imgbtn; +extern const bclass be_class_lv_indev; +extern const bclass be_class_lv_label; +extern const bclass be_class_lv_led; +extern const bclass be_class_lv_line; +extern const bclass be_class_lv_meter; +extern const bclass be_class_lv_msgbox; +extern const bclass be_class_lv_obj; +extern const bclass be_class_lv_roller; +extern const bclass be_class_lv_slider; +extern const bclass be_class_lv_spinbox; +extern const bclass be_class_lv_spinner; +extern const bclass be_class_lv_style; +extern const bclass be_class_lv_switch; +extern const bclass be_class_lv_table; +extern const bclass be_class_lv_textarea; +extern const bclass be_class_lv_theme; + + +// map of clases +const be_ntv_class_def_t lv_classes[] = { +#ifdef BE_LV_WIDGET_ARC + { "lv_arc", &be_class_lv_arc, lv_arc_func, sizeof(lv_arc_func) / sizeof(lv_arc_func[0]) }, +#endif // BE_LV_WIDGET_ARC +#ifdef BE_LV_WIDGET_BAR + { "lv_bar", &be_class_lv_bar, lv_bar_func, sizeof(lv_bar_func) / sizeof(lv_bar_func[0]) }, +#endif // BE_LV_WIDGET_BAR +#ifdef BE_LV_WIDGET_BTN + { "lv_btn", &be_class_lv_btn, lv_btn_func, sizeof(lv_btn_func) / sizeof(lv_btn_func[0]) }, +#endif // BE_LV_WIDGET_BTN +#ifdef BE_LV_WIDGET_BTNMATRIX + { "lv_btnmatrix", &be_class_lv_btnmatrix, lv_btnmatrix_func, sizeof(lv_btnmatrix_func) / sizeof(lv_btnmatrix_func[0]) }, +#endif // BE_LV_WIDGET_BTNMATRIX +#ifdef BE_LV_WIDGET_CANVAS + { "lv_canvas", &be_class_lv_canvas, lv_canvas_func, sizeof(lv_canvas_func) / sizeof(lv_canvas_func[0]) }, +#endif // BE_LV_WIDGET_CANVAS +#ifdef BE_LV_WIDGET_CHART + { "lv_chart", &be_class_lv_chart, lv_chart_func, sizeof(lv_chart_func) / sizeof(lv_chart_func[0]) }, +#endif // BE_LV_WIDGET_CHART +#ifdef BE_LV_WIDGET_CHECKBOX + { "lv_checkbox", &be_class_lv_checkbox, lv_checkbox_func, sizeof(lv_checkbox_func) / sizeof(lv_checkbox_func[0]) }, +#endif // BE_LV_WIDGET_CHECKBOX + { "lv_color", &be_class_lv_color, lv_color_func, sizeof(lv_color_func) / sizeof(lv_color_func[0]) }, +#ifdef BE_LV_WIDGET_COLORWHEEL + { "lv_colorwheel", &be_class_lv_colorwheel, lv_colorwheel_func, sizeof(lv_colorwheel_func) / sizeof(lv_colorwheel_func[0]) }, +#endif // BE_LV_WIDGET_COLORWHEEL + { "lv_disp", &be_class_lv_disp, lv_disp_func, sizeof(lv_disp_func) / sizeof(lv_disp_func[0]) }, +#ifdef BE_LV_WIDGET_DROPDOWN + { "lv_dropdown", &be_class_lv_dropdown, lv_dropdown_func, sizeof(lv_dropdown_func) / sizeof(lv_dropdown_func[0]) }, +#endif // BE_LV_WIDGET_DROPDOWN + { "lv_font", &be_class_lv_font, lv_font_func, sizeof(lv_font_func) / sizeof(lv_font_func[0]) }, + { "lv_group", &be_class_lv_group, lv_group_func, sizeof(lv_group_func) / sizeof(lv_group_func[0]) }, +#ifdef BE_LV_WIDGET_IMG + { "lv_img", &be_class_lv_img, lv_img_func, sizeof(lv_img_func) / sizeof(lv_img_func[0]) }, +#endif // BE_LV_WIDGET_IMG +#ifdef BE_LV_WIDGET_IMGBTN + { "lv_imgbtn", &be_class_lv_imgbtn, lv_imgbtn_func, sizeof(lv_imgbtn_func) / sizeof(lv_imgbtn_func[0]) }, +#endif // BE_LV_WIDGET_IMGBTN + { "lv_indev", &be_class_lv_indev, lv_indev_func, sizeof(lv_indev_func) / sizeof(lv_indev_func[0]) }, +#ifdef BE_LV_WIDGET_LABEL + { "lv_label", &be_class_lv_label, lv_label_func, sizeof(lv_label_func) / sizeof(lv_label_func[0]) }, +#endif // BE_LV_WIDGET_LABEL +#ifdef BE_LV_WIDGET_LED + { "lv_led", &be_class_lv_led, lv_led_func, sizeof(lv_led_func) / sizeof(lv_led_func[0]) }, +#endif // BE_LV_WIDGET_LED +#ifdef BE_LV_WIDGET_LINE + { "lv_line", &be_class_lv_line, lv_line_func, sizeof(lv_line_func) / sizeof(lv_line_func[0]) }, +#endif // BE_LV_WIDGET_LINE +#ifdef BE_LV_WIDGET_METER + { "lv_meter", &be_class_lv_meter, lv_meter_func, sizeof(lv_meter_func) / sizeof(lv_meter_func[0]) }, +#endif // BE_LV_WIDGET_METER +#ifdef BE_LV_WIDGET_MSGBOX + { "lv_msgbox", &be_class_lv_msgbox, lv_msgbox_func, sizeof(lv_msgbox_func) / sizeof(lv_msgbox_func[0]) }, +#endif // BE_LV_WIDGET_MSGBOX + { "lv_obj", &be_class_lv_obj, lv_obj_func, sizeof(lv_obj_func) / sizeof(lv_obj_func[0]) }, +#ifdef BE_LV_WIDGET_ROLLER + { "lv_roller", &be_class_lv_roller, lv_roller_func, sizeof(lv_roller_func) / sizeof(lv_roller_func[0]) }, +#endif // BE_LV_WIDGET_ROLLER +#ifdef BE_LV_WIDGET_SLIDER + { "lv_slider", &be_class_lv_slider, lv_slider_func, sizeof(lv_slider_func) / sizeof(lv_slider_func[0]) }, +#endif // BE_LV_WIDGET_SLIDER +#ifdef BE_LV_WIDGET_SPINBOX + { "lv_spinbox", &be_class_lv_spinbox, lv_spinbox_func, sizeof(lv_spinbox_func) / sizeof(lv_spinbox_func[0]) }, +#endif // BE_LV_WIDGET_SPINBOX +#ifdef BE_LV_WIDGET_SPINNER + { "lv_spinner", &be_class_lv_spinner, lv_spinner_func, sizeof(lv_spinner_func) / sizeof(lv_spinner_func[0]) }, +#endif // BE_LV_WIDGET_SPINNER + { "lv_style", &be_class_lv_style, lv_style_func, sizeof(lv_style_func) / sizeof(lv_style_func[0]) }, +#ifdef BE_LV_WIDGET_SWITCH + { "lv_switch", &be_class_lv_switch, lv_switch_func, sizeof(lv_switch_func) / sizeof(lv_switch_func[0]) }, +#endif // BE_LV_WIDGET_SWITCH +#ifdef BE_LV_WIDGET_TABLE + { "lv_table", &be_class_lv_table, lv_table_func, sizeof(lv_table_func) / sizeof(lv_table_func[0]) }, +#endif // BE_LV_WIDGET_TABLE +#ifdef BE_LV_WIDGET_TEXTAREA + { "lv_textarea", &be_class_lv_textarea, lv_textarea_func, sizeof(lv_textarea_func) / sizeof(lv_textarea_func[0]) }, +#endif // BE_LV_WIDGET_TEXTAREA + { "lv_theme", &be_class_lv_theme, lv_theme_func, sizeof(lv_theme_func) / sizeof(lv_theme_func[0]) }, +}; +const size_t lv_classes_size = sizeof(lv_classes) / sizeof(lv_classes[0]); + + /* `lv_style` methods */ + /* `lv_font` methods */ + /* `lv_color` methods */ + /* `lv_theme` methods */ + /* `lv_img` methods */ +#ifdef BE_LV_WIDGET_IMG + int be_ntv_lv_img_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_img_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_IMG + /* `lv_disp` methods */ + /* `lv_obj` methods */ + int be_ntv_lv_obj_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_obj_create, "+_p", "(lv.lv_obj)"); } + /* `lv_group` methods */ + int be_ntv_lv_group_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_group_create, "+_p", ""); } + /* `lv_indev` methods */ + /* `lv_chart` methods */ +#ifdef BE_LV_WIDGET_CHART + int be_ntv_lv_chart_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_chart_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_CHART + /* `lv_colorwheel` methods */ +#ifdef BE_LV_WIDGET_COLORWHEEL + int be_ntv_lv_colorwheel_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_colorwheel_create, "+_p", "(lv.lv_obj)b"); } +#endif // BE_LV_WIDGET_COLORWHEEL + /* `lv_imgbtn` methods */ +#ifdef BE_LV_WIDGET_IMGBTN + int be_ntv_lv_imgbtn_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_imgbtn_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_IMGBTN + /* `lv_led` methods */ +#ifdef BE_LV_WIDGET_LED + int be_ntv_lv_led_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_led_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_LED + /* `lv_meter` methods */ +#ifdef BE_LV_WIDGET_METER + int be_ntv_lv_meter_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_meter_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_METER + /* `lv_msgbox` methods */ +#ifdef BE_LV_WIDGET_MSGBOX + int be_ntv_lv_msgbox_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_msgbox_create, "+_p", "(lv.lv_obj)ss(lv.str_arr)b"); } +#endif // BE_LV_WIDGET_MSGBOX + /* `lv_spinbox` methods */ +#ifdef BE_LV_WIDGET_SPINBOX + int be_ntv_lv_spinbox_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_spinbox_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_SPINBOX + /* `lv_spinner` methods */ +#ifdef BE_LV_WIDGET_SPINNER + int be_ntv_lv_spinner_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_spinner_create, "+_p", "(lv.lv_obj)ii"); } +#endif // BE_LV_WIDGET_SPINNER + /* `lv_arc` methods */ +#ifdef BE_LV_WIDGET_ARC + int be_ntv_lv_arc_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_arc_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_ARC + /* `lv_bar` methods */ +#ifdef BE_LV_WIDGET_BAR + int be_ntv_lv_bar_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_bar_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_BAR + /* `lv_btn` methods */ +#ifdef BE_LV_WIDGET_BTN + int be_ntv_lv_btn_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_btn_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_BTN + /* `lv_btnmatrix` methods */ +#ifdef BE_LV_WIDGET_BTNMATRIX + int be_ntv_lv_btnmatrix_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_btnmatrix_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_BTNMATRIX + /* `lv_canvas` methods */ +#ifdef BE_LV_WIDGET_CANVAS + int be_ntv_lv_canvas_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_canvas_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_CANVAS + /* `lv_checkbox` methods */ +#ifdef BE_LV_WIDGET_CHECKBOX + int be_ntv_lv_checkbox_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_checkbox_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_CHECKBOX + /* `lv_dropdown` methods */ +#ifdef BE_LV_WIDGET_DROPDOWN + int be_ntv_lv_dropdown_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_dropdown_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_DROPDOWN + /* `lv_label` methods */ +#ifdef BE_LV_WIDGET_LABEL + int be_ntv_lv_label_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_label_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_LABEL + /* `lv_line` methods */ +#ifdef BE_LV_WIDGET_LINE + int be_ntv_lv_line_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_line_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_LINE + /* `lv_roller` methods */ +#ifdef BE_LV_WIDGET_ROLLER + int be_ntv_lv_roller_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_roller_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_ROLLER + /* `lv_slider` methods */ +#ifdef BE_LV_WIDGET_SLIDER + int be_ntv_lv_slider_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_slider_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_SLIDER + /* `lv_switch` methods */ +#ifdef BE_LV_WIDGET_SWITCH + int be_ntv_lv_switch_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_switch_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_SWITCH + /* `lv_table` methods */ +#ifdef BE_LV_WIDGET_TABLE + int be_ntv_lv_table_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_table_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_TABLE + /* `lv_textarea` methods */ +#ifdef BE_LV_WIDGET_TEXTAREA + int be_ntv_lv_textarea_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_textarea_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_TEXTAREA + +// create font either empty or from parameter on stack +int lvbe_font_create(bvm *vm) { return be_call_c_func(vm, NULL, "+_p", ""); } +int lvbe_theme_create(bvm *vm) { return be_call_c_func(vm, NULL, "+_p", ""); } + + +#ifdef __cplusplus +} /* extern "C" */ +#endif +/********************************************************************/ diff --git a/lib/libesp32_lvgl/lv_berry/generate/be_lvgl_module.c b/lib/libesp32_lvgl/lv_berry/generate/be_lvgl_module.c new file mode 100644 index 000000000..18677a91e --- /dev/null +++ b/lib/libesp32_lvgl/lv_berry/generate/be_lvgl_module.c @@ -0,0 +1,784 @@ +/******************************************************************** + * Generated code, don't edit + *******************************************************************/ +/******************************************************************** + * LVGL Module + *******************************************************************/ +#include "be_constobj.h" + +#include "lvgl.h" +#include "be_mapping.h" +#include "lv_berry.h" +#include "lv_theme_openhasp.h" + +extern int lv0_member(bvm *vm); // resolve virtual members +extern int lv0_load_font(bvm *vm); + +extern lv_ts_calibration_t * lv_get_ts_calibration(void); + + +static int lv_get_hor_res(void) { + return lv_disp_get_hor_res(lv_disp_get_default()); +} +static int lv_get_ver_res(void) { + return lv_disp_get_ver_res(lv_disp_get_default()); +} + +/* `lv` methods */ +const be_ntv_func_def_t lv_func[] = { + + { "clamp_height", { (const void*) &lv_clamp_height, "i", "iiii" } }, + { "clamp_width", { (const void*) &lv_clamp_width, "i", "iiii" } }, + { "color_black", { (const void*) &lv_color_black, "lv.lv_color", "" } }, + { "color_brightness", { (const void*) &lv_color_brightness, "i", "(lv.lv_color)" } }, + { "color_change_lightness", { (const void*) &lv_color_change_lightness, "lv.lv_color", "(lv.lv_color)i" } }, + { "color_chroma_key", { (const void*) &lv_color_chroma_key, "lv.lv_color", "" } }, + { "color_darken", { (const void*) &lv_color_darken, "lv.lv_color", "(lv.lv_color)i" } }, + { "color_fill", { (const void*) &lv_color_fill, "", "(lv.lv_color)(lv.lv_color)i" } }, + { "color_filter_dsc_init", { (const void*) &lv_color_filter_dsc_init, "", "(lv.lv_color_filter_dsc)^lv_color_filter_cb^" } }, + { "color_hex", { (const void*) &lv_color_hex, "lv.lv_color", "i" } }, + { "color_hex3", { (const void*) &lv_color_hex3, "lv.lv_color", "i" } }, + { "color_hsv_to_rgb", { (const void*) &lv_color_hsv_to_rgb, "lv.lv_color", "iii" } }, + { "color_lighten", { (const void*) &lv_color_lighten, "lv.lv_color", "(lv.lv_color)i" } }, + { "color_make", { (const void*) &lv_color_make, "lv.lv_color", "iii" } }, + { "color_mix", { (const void*) &lv_color_mix, "lv.lv_color", "(lv.lv_color)(lv.lv_color)i" } }, + { "color_mix_premult", { (const void*) &lv_color_mix_premult, "lv.lv_color", "(lv.uint16)(lv.lv_color)i" } }, + { "color_mix_with_alpha", { (const void*) &lv_color_mix_with_alpha, "", "(lv.lv_color)i(lv.lv_color)i(lv.lv_color)(lv.lv_opa)" } }, + { "color_premult", { (const void*) &lv_color_premult, "", "(lv.lv_color)i(lv.uint16)" } }, + { "color_rgb_to_hsv", { (const void*) &lv_color_rgb_to_hsv, "i", "iii" } }, + { "color_to1", { (const void*) &lv_color_to1, "i", "(lv.lv_color)" } }, + { "color_to16", { (const void*) &lv_color_to16, "i", "(lv.lv_color)" } }, + { "color_to32", { (const void*) &lv_color_to32, "i", "(lv.lv_color)" } }, + { "color_to8", { (const void*) &lv_color_to8, "i", "(lv.lv_color)" } }, + { "color_to_hsv", { (const void*) &lv_color_to_hsv, "i", "(lv.lv_color)" } }, + { "color_white", { (const void*) &lv_color_white, "lv.lv_color", "" } }, + { "dpx", { (const void*) &lv_dpx, "i", "i" } }, + { "draw_arc", { (const void*) &lv_draw_arc, "", "iiiii(lv.lv_area)(lv.lv_draw_arc_dsc)" } }, + { "draw_arc_dsc_init", { (const void*) &lv_draw_arc_dsc_init, "", "(lv.lv_draw_arc_dsc)" } }, + { "draw_arc_get_area", { (const void*) &lv_draw_arc_get_area, "", "iiiiiib(lv.lv_area)" } }, + { "draw_img", { (const void*) &lv_draw_img, "", "(lv.lv_area)(lv.lv_area).(lv.lv_draw_img_dsc)" } }, + { "draw_img_dsc_init", { (const void*) &lv_draw_img_dsc_init, "", "(lv.lv_draw_img_dsc)" } }, + { "draw_label", { (const void*) &lv_draw_label, "", "(lv.lv_area)(lv.lv_area)(lv.lv_draw_label_dsc)s(lv.lv_draw_label_hint)" } }, + { "draw_label_dsc_init", { (const void*) &lv_draw_label_dsc_init, "", "(lv.lv_draw_label_dsc)" } }, + { "draw_letter", { (const void*) &lv_draw_letter, "", "(lv.lv_point)(lv.lv_area)(lv.lv_font)i(lv.lv_color)ii" } }, + { "draw_line", { (const void*) &lv_draw_line, "", "(lv.lv_point)(lv.lv_point)(lv.lv_area)(lv.lv_draw_line_dsc)" } }, + { "draw_line_dsc_init", { (const void*) &lv_draw_line_dsc_init, "", "(lv.lv_draw_line_dsc)" } }, + { "draw_mask_add", { (const void*) &lv_draw_mask_add, "i", ".." } }, + { "draw_mask_angle_init", { (const void*) &lv_draw_mask_angle_init, "", "(lv.lv_draw_mask_angle_param)iiii" } }, + { "draw_mask_apply", { (const void*) &lv_draw_mask_apply, "i", "(lv.lv_opa)iii" } }, + { "draw_mask_apply_ids", { (const void*) &lv_draw_mask_apply_ids, "i", "(lv.lv_opa)iii(lv.int16)i" } }, + { "draw_mask_fade_init", { (const void*) &lv_draw_mask_fade_init, "", "(lv.lv_draw_mask_fade_param)(lv.lv_area)iiii" } }, + { "draw_mask_free_param", { (const void*) &lv_draw_mask_free_param, "", "." } }, + { "draw_mask_get_cnt", { (const void*) &lv_draw_mask_get_cnt, "i", "" } }, + { "draw_mask_is_any", { (const void*) &lv_draw_mask_is_any, "b", "(lv.lv_area)" } }, + { "draw_mask_line_angle_init", { (const void*) &lv_draw_mask_line_angle_init, "", "(lv.lv_draw_mask_line_param)iiii" } }, + { "draw_mask_line_points_init", { (const void*) &lv_draw_mask_line_points_init, "", "(lv.lv_draw_mask_line_param)iiiii" } }, + { "draw_mask_map_init", { (const void*) &lv_draw_mask_map_init, "", "(lv.lv_draw_mask_map_param)(lv.lv_area)(lv.lv_opa)" } }, + { "draw_mask_radius_init", { (const void*) &lv_draw_mask_radius_init, "", "(lv.lv_draw_mask_radius_param)(lv.lv_area)ib" } }, + { "draw_mask_remove_custom", { (const void*) &lv_draw_mask_remove_custom, ".", "." } }, + { "draw_mask_remove_id", { (const void*) &lv_draw_mask_remove_id, ".", "i" } }, + { "draw_polygon", { (const void*) &lv_draw_polygon, "", "(lv.lv_point_arr)i(lv.lv_area)(lv.lv_draw_rect_dsc)" } }, + { "draw_rect", { (const void*) &lv_draw_rect, "", "(lv.lv_area)(lv.lv_area)(lv.lv_draw_rect_dsc)" } }, + { "draw_rect_dsc_init", { (const void*) &lv_draw_rect_dsc_init, "", "(lv.lv_draw_rect_dsc)" } }, + { "draw_triangle", { (const void*) &lv_draw_triangle, "", "(lv.lv_point_arr)(lv.lv_area)(lv.lv_draw_rect_dsc)" } }, + { "event_register_id", { (const void*) &lv_event_register_id, "i", "" } }, + { "event_send", { (const void*) &lv_event_send, "i", "(lv.lv_obj)i." } }, + { "event_set_cover_res", { (const void*) &lv_event_set_cover_res, "", "(lv.lv_event)(lv.lv_cover_res)" } }, + { "event_set_ext_draw_size", { (const void*) &lv_event_set_ext_draw_size, "", "(lv.lv_event)i" } }, + { "flex_init", { (const void*) &lv_flex_init, "", "" } }, + { "get_hor_res", { (const void*) &lv_get_hor_res, "i", "" } }, + { "get_ts_calibration", { (const void*) &lv_get_ts_calibration, "lv.lv_ts_calibration", "" } }, + { "get_ver_res", { (const void*) &lv_get_ver_res, "i", "" } }, + { "grid_fr", { (const void*) &lv_grid_fr, "i", "i" } }, + { "grid_init", { (const void*) &lv_grid_init, "", "" } }, + { "group_get_default", { (const void*) &lv_group_get_default, "lv.lv_group", "" } }, + { "img_src_get_type", { (const void*) &lv_img_src_get_type, "i", "." } }, + { "indev_get_act", { (const void*) &lv_indev_get_act, "lv.lv_indev", "" } }, + { "indev_get_obj_act", { (const void*) &lv_indev_get_obj_act, "lv.lv_obj", "" } }, + { "indev_get_read_timer", { (const void*) &lv_indev_get_read_timer, "lv.lv_timer", "(lv.lv_disp)" } }, + { "indev_read_timer_cb", { (const void*) &lv_indev_read_timer_cb, "", "(lv.lv_timer)" } }, + { "is_initialized", { (const void*) &lv_is_initialized, "b", "" } }, + { "layer_sys", { (const void*) &lv_layer_sys, "lv.lv_obj", "" } }, + { "layer_top", { (const void*) &lv_layer_top, "lv.lv_obj", "" } }, + { "layout_register", { (const void*) &lv_layout_register, "i", "^lv_layout_update_cb^." } }, + { "obj_class_create_obj", { (const void*) &lv_obj_class_create_obj, "lv.lv_obj", "(lv._lv_obj_class)(lv.lv_obj)" } }, + { "obj_del_anim_ready_cb", { (const void*) &lv_obj_del_anim_ready_cb, "", "(lv.lv_anim)" } }, + { "obj_draw_dsc_init", { (const void*) &lv_obj_draw_dsc_init, "", "(lv.lv_obj_draw_part_dsc)(lv.lv_area)" } }, + { "obj_draw_part_check_type", { (const void*) &lv_obj_draw_part_check_type, "b", "(lv.lv_obj_draw_part_dsc)(lv._lv_obj_class)i" } }, + { "obj_enable_style_refresh", { (const void*) &lv_obj_enable_style_refresh, "", "b" } }, + { "obj_event_base", { (const void*) &lv_obj_event_base, "i", "(lv.lv_obj_class)(lv.lv_event)" } }, + { "obj_report_style_change", { (const void*) &lv_obj_report_style_change, "", "(lv.lv_style)" } }, + { "obj_style_get_selector_part", { (const void*) &lv_obj_style_get_selector_part, "i", "i" } }, + { "obj_style_get_selector_state", { (const void*) &lv_obj_style_get_selector_state, "i", "i" } }, + { "palette_darken", { (const void*) &lv_palette_darken, "lv.lv_color", "ii" } }, + { "palette_lighten", { (const void*) &lv_palette_lighten, "lv.lv_color", "ii" } }, + { "palette_main", { (const void*) &lv_palette_main, "lv.lv_color", "i" } }, + { "refr_now", { (const void*) &lv_refr_now, "", "(lv.lv_disp)" } }, + { "scr_act", { (const void*) &lv_scr_act, "lv.lv_obj", "" } }, + { "scr_load", { (const void*) &lv_scr_load, "", "(lv.lv_obj)" } }, + { "scr_load_anim", { (const void*) &lv_scr_load_anim, "", "(lv.lv_obj)iiib" } }, + { "task_handler", { (const void*) &lv_task_handler, "i", "" } }, + { "theme_apply", { (const void*) &lv_theme_apply, "", "(lv.lv_obj)" } }, + { "theme_default_get", { (const void*) &lv_theme_default_get, "lv.lv_theme", "" } }, + { "theme_default_init", { (const void*) &lv_theme_default_init, "lv.lv_theme", "(lv.lv_disp)(lv.lv_color)(lv.lv_color)b(lv.lv_font)" } }, + { "theme_default_is_inited", { (const void*) &lv_theme_default_is_inited, "b", "" } }, + { "theme_get_color_primary", { (const void*) &lv_theme_get_color_primary, "lv.lv_color", "(lv.lv_obj)" } }, + { "theme_get_color_secondary", { (const void*) &lv_theme_get_color_secondary, "lv.lv_color", "(lv.lv_obj)" } }, + { "theme_get_font_large", { (const void*) &lv_theme_get_font_large, "lv.lv_font", "(lv.lv_obj)" } }, + { "theme_get_font_normal", { (const void*) &lv_theme_get_font_normal, "lv.lv_font", "(lv.lv_obj)" } }, + { "theme_get_font_small", { (const void*) &lv_theme_get_font_small, "lv.lv_font", "(lv.lv_obj)" } }, + { "theme_get_from_obj", { (const void*) &lv_theme_get_from_obj, "lv.lv_theme", "(lv.lv_obj)" } }, + { "theme_mono_init", { (const void*) &lv_theme_mono_init, "lv.lv_theme", "(lv.lv_disp)b(lv.lv_font)" } }, + { "theme_openhasp_init", { (const void*) &lv_theme_openhasp_init, "lv.lv_theme", "(lv.lv_disp)(lv.lv_color)(lv.lv_color)b(lv.lv_font)" } }, + { "theme_openhasp_is_inited", { (const void*) &lv_theme_openhasp_is_inited, "b", "" } }, + { "theme_set_apply_cb", { (const void*) &lv_theme_set_apply_cb, "", "(lv.lv_theme)^lv_theme_apply_cb^" } }, + { "theme_set_parent", { (const void*) &lv_theme_set_parent, "", "(lv.lv_theme)(lv.lv_theme)" } }, + +}; +const size_t lv_func_size = sizeof(lv_func) / sizeof(lv_func[0]); + + + + +const be_const_member_t lv0_constants[] = { + + { "ALIGN_BOTTOM_LEFT", be_cconst_int(LV_ALIGN_BOTTOM_LEFT) }, + { "ALIGN_BOTTOM_MID", be_cconst_int(LV_ALIGN_BOTTOM_MID) }, + { "ALIGN_BOTTOM_RIGHT", be_cconst_int(LV_ALIGN_BOTTOM_RIGHT) }, + { "ALIGN_CENTER", be_cconst_int(LV_ALIGN_CENTER) }, + { "ALIGN_DEFAULT", be_cconst_int(LV_ALIGN_DEFAULT) }, + { "ALIGN_LEFT_MID", be_cconst_int(LV_ALIGN_LEFT_MID) }, + { "ALIGN_OUT_BOTTOM_LEFT", be_cconst_int(LV_ALIGN_OUT_BOTTOM_LEFT) }, + { "ALIGN_OUT_BOTTOM_MID", be_cconst_int(LV_ALIGN_OUT_BOTTOM_MID) }, + { "ALIGN_OUT_BOTTOM_RIGHT", be_cconst_int(LV_ALIGN_OUT_BOTTOM_RIGHT) }, + { "ALIGN_OUT_LEFT_BOTTOM", be_cconst_int(LV_ALIGN_OUT_LEFT_BOTTOM) }, + { "ALIGN_OUT_LEFT_MID", be_cconst_int(LV_ALIGN_OUT_LEFT_MID) }, + { "ALIGN_OUT_LEFT_TOP", be_cconst_int(LV_ALIGN_OUT_LEFT_TOP) }, + { "ALIGN_OUT_RIGHT_BOTTOM", be_cconst_int(LV_ALIGN_OUT_RIGHT_BOTTOM) }, + { "ALIGN_OUT_RIGHT_MID", be_cconst_int(LV_ALIGN_OUT_RIGHT_MID) }, + { "ALIGN_OUT_RIGHT_TOP", be_cconst_int(LV_ALIGN_OUT_RIGHT_TOP) }, + { "ALIGN_OUT_TOP_LEFT", be_cconst_int(LV_ALIGN_OUT_TOP_LEFT) }, + { "ALIGN_OUT_TOP_MID", be_cconst_int(LV_ALIGN_OUT_TOP_MID) }, + { "ALIGN_OUT_TOP_RIGHT", be_cconst_int(LV_ALIGN_OUT_TOP_RIGHT) }, + { "ALIGN_RIGHT_MID", be_cconst_int(LV_ALIGN_RIGHT_MID) }, + { "ALIGN_TOP_LEFT", be_cconst_int(LV_ALIGN_TOP_LEFT) }, + { "ALIGN_TOP_MID", be_cconst_int(LV_ALIGN_TOP_MID) }, + { "ALIGN_TOP_RIGHT", be_cconst_int(LV_ALIGN_TOP_RIGHT) }, + { "ANIM_IMG_PART_MAIN", be_cconst_int(LV_ANIM_IMG_PART_MAIN) }, + { "ANIM_OFF", be_cconst_int(LV_ANIM_OFF) }, + { "ANIM_ON", be_cconst_int(LV_ANIM_ON) }, + { "ARC_DRAW_PART_BACKGROUND", be_cconst_int(LV_ARC_DRAW_PART_BACKGROUND) }, + { "ARC_DRAW_PART_FOREGROUND", be_cconst_int(LV_ARC_DRAW_PART_FOREGROUND) }, + { "ARC_DRAW_PART_KNOB", be_cconst_int(LV_ARC_DRAW_PART_KNOB) }, + { "ARC_MODE_NORMAL", be_cconst_int(LV_ARC_MODE_NORMAL) }, + { "ARC_MODE_REVERSE", be_cconst_int(LV_ARC_MODE_REVERSE) }, + { "ARC_MODE_SYMMETRICAL", be_cconst_int(LV_ARC_MODE_SYMMETRICAL) }, + { "BAR_DRAW_PART_INDICATOR", be_cconst_int(LV_BAR_DRAW_PART_INDICATOR) }, + { "BAR_MODE_NORMAL", be_cconst_int(LV_BAR_MODE_NORMAL) }, + { "BAR_MODE_RANGE", be_cconst_int(LV_BAR_MODE_RANGE) }, + { "BAR_MODE_SYMMETRICAL", be_cconst_int(LV_BAR_MODE_SYMMETRICAL) }, + { "BASE_DIR_AUTO", be_cconst_int(LV_BASE_DIR_AUTO) }, + { "BASE_DIR_LTR", be_cconst_int(LV_BASE_DIR_LTR) }, + { "BASE_DIR_NEUTRAL", be_cconst_int(LV_BASE_DIR_NEUTRAL) }, + { "BASE_DIR_RTL", be_cconst_int(LV_BASE_DIR_RTL) }, + { "BASE_DIR_WEAK", be_cconst_int(LV_BASE_DIR_WEAK) }, + { "BLEND_MODE_ADDITIVE", be_cconst_int(LV_BLEND_MODE_ADDITIVE) }, + { "BLEND_MODE_MULTIPLY", be_cconst_int(LV_BLEND_MODE_MULTIPLY) }, + { "BLEND_MODE_NORMAL", be_cconst_int(LV_BLEND_MODE_NORMAL) }, + { "BLEND_MODE_SUBTRACTIVE", be_cconst_int(LV_BLEND_MODE_SUBTRACTIVE) }, + { "BORDER_SIDE_BOTTOM", be_cconst_int(LV_BORDER_SIDE_BOTTOM) }, + { "BORDER_SIDE_FULL", be_cconst_int(LV_BORDER_SIDE_FULL) }, + { "BORDER_SIDE_INTERNAL", be_cconst_int(LV_BORDER_SIDE_INTERNAL) }, + { "BORDER_SIDE_LEFT", be_cconst_int(LV_BORDER_SIDE_LEFT) }, + { "BORDER_SIDE_NONE", be_cconst_int(LV_BORDER_SIDE_NONE) }, + { "BORDER_SIDE_RIGHT", be_cconst_int(LV_BORDER_SIDE_RIGHT) }, + { "BORDER_SIDE_TOP", be_cconst_int(LV_BORDER_SIDE_TOP) }, + { "BTNMATRIX_CTRL_CHECKABLE", be_cconst_int(LV_BTNMATRIX_CTRL_CHECKABLE) }, + { "BTNMATRIX_CTRL_CHECKED", be_cconst_int(LV_BTNMATRIX_CTRL_CHECKED) }, + { "BTNMATRIX_CTRL_CLICK_TRIG", be_cconst_int(LV_BTNMATRIX_CTRL_CLICK_TRIG) }, + { "BTNMATRIX_CTRL_CUSTOM_1", be_cconst_int(LV_BTNMATRIX_CTRL_CUSTOM_1) }, + { "BTNMATRIX_CTRL_CUSTOM_2", be_cconst_int(LV_BTNMATRIX_CTRL_CUSTOM_2) }, + { "BTNMATRIX_CTRL_DISABLED", be_cconst_int(LV_BTNMATRIX_CTRL_DISABLED) }, + { "BTNMATRIX_CTRL_HIDDEN", be_cconst_int(LV_BTNMATRIX_CTRL_HIDDEN) }, + { "BTNMATRIX_CTRL_NO_REPEAT", be_cconst_int(LV_BTNMATRIX_CTRL_NO_REPEAT) }, + { "BTNMATRIX_CTRL_POPOVER", be_cconst_int(LV_BTNMATRIX_CTRL_POPOVER) }, + { "BTNMATRIX_CTRL_RECOLOR", be_cconst_int(LV_BTNMATRIX_CTRL_RECOLOR) }, + { "BTNMATRIX_DRAW_PART_BTN", be_cconst_int(LV_BTNMATRIX_DRAW_PART_BTN) }, + { "CHART_AXIS_PRIMARY_X", be_cconst_int(LV_CHART_AXIS_PRIMARY_X) }, + { "CHART_AXIS_PRIMARY_Y", be_cconst_int(LV_CHART_AXIS_PRIMARY_Y) }, + { "CHART_AXIS_SECONDARY_X", be_cconst_int(LV_CHART_AXIS_SECONDARY_X) }, + { "CHART_AXIS_SECONDARY_Y", be_cconst_int(LV_CHART_AXIS_SECONDARY_Y) }, + { "CHART_DRAW_PART_BAR", be_cconst_int(LV_CHART_DRAW_PART_BAR) }, + { "CHART_DRAW_PART_CURSOR", be_cconst_int(LV_CHART_DRAW_PART_CURSOR) }, + { "CHART_DRAW_PART_DIV_LINE_HOR", be_cconst_int(LV_CHART_DRAW_PART_DIV_LINE_HOR) }, + { "CHART_DRAW_PART_DIV_LINE_INIT", be_cconst_int(LV_CHART_DRAW_PART_DIV_LINE_INIT) }, + { "CHART_DRAW_PART_DIV_LINE_VER", be_cconst_int(LV_CHART_DRAW_PART_DIV_LINE_VER) }, + { "CHART_DRAW_PART_LINE_AND_POINT", be_cconst_int(LV_CHART_DRAW_PART_LINE_AND_POINT) }, + { "CHART_DRAW_PART_TICK_LABEL", be_cconst_int(LV_CHART_DRAW_PART_TICK_LABEL) }, + { "CHART_TYPE_BAR", be_cconst_int(LV_CHART_TYPE_BAR) }, + { "CHART_TYPE_LINE", be_cconst_int(LV_CHART_TYPE_LINE) }, + { "CHART_TYPE_NONE", be_cconst_int(LV_CHART_TYPE_NONE) }, + { "CHART_TYPE_SCATTER", be_cconst_int(LV_CHART_TYPE_SCATTER) }, + { "CHART_UPDATE_MODE_CIRCULAR", be_cconst_int(LV_CHART_UPDATE_MODE_CIRCULAR) }, + { "CHART_UPDATE_MODE_SHIFT", be_cconst_int(LV_CHART_UPDATE_MODE_SHIFT) }, + { "CHECKBOX_DRAW_PART_BOX", be_cconst_int(LV_CHECKBOX_DRAW_PART_BOX) }, + { "COLORWHEEL_MODE_HUE", be_cconst_int(LV_COLORWHEEL_MODE_HUE) }, + { "COLORWHEEL_MODE_SATURATION", be_cconst_int(LV_COLORWHEEL_MODE_SATURATION) }, + { "COLORWHEEL_MODE_VALUE", be_cconst_int(LV_COLORWHEEL_MODE_VALUE) }, + { "COLOR_AQUA", be_cconst_int(0x00FFFF) }, + { "COLOR_BLACK", be_cconst_int(0x000000) }, + { "COLOR_BLUE", be_cconst_int(0x0000FF) }, + { "COLOR_CYAN", be_cconst_int(0x00FFFF) }, + { "COLOR_GRAY", be_cconst_int(0x808080) }, + { "COLOR_GREEN", be_cconst_int(0x008000) }, + { "COLOR_LIME", be_cconst_int(0x00FF00) }, + { "COLOR_MAGENTA", be_cconst_int(0xFF00FF) }, + { "COLOR_MAROON", be_cconst_int(0x800000) }, + { "COLOR_NAVY", be_cconst_int(0x000080) }, + { "COLOR_OLIVE", be_cconst_int(0x808000) }, + { "COLOR_PURPLE", be_cconst_int(0x800080) }, + { "COLOR_RED", be_cconst_int(0xFF0000) }, + { "COLOR_SILVER", be_cconst_int(0xC0C0C0) }, + { "COLOR_TEAL", be_cconst_int(0x008080) }, + { "COLOR_WHITE", be_cconst_int(0xFFFFFF) }, + { "COLOR_YELLOW", be_cconst_int(0xFFFF00) }, + { "COVER_RES_COVER", be_cconst_int(LV_COVER_RES_COVER) }, + { "COVER_RES_MASKED", be_cconst_int(LV_COVER_RES_MASKED) }, + { "COVER_RES_NOT_COVER", be_cconst_int(LV_COVER_RES_NOT_COVER) }, + { "DIR_ALL", be_cconst_int(LV_DIR_ALL) }, + { "DIR_BOTTOM", be_cconst_int(LV_DIR_BOTTOM) }, + { "DIR_HOR", be_cconst_int(LV_DIR_HOR) }, + { "DIR_LEFT", be_cconst_int(LV_DIR_LEFT) }, + { "DIR_NONE", be_cconst_int(LV_DIR_NONE) }, + { "DIR_RIGHT", be_cconst_int(LV_DIR_RIGHT) }, + { "DIR_TOP", be_cconst_int(LV_DIR_TOP) }, + { "DIR_VER", be_cconst_int(LV_DIR_VER) }, + { "DISP_ROT_180", be_cconst_int(LV_DISP_ROT_180) }, + { "DISP_ROT_270", be_cconst_int(LV_DISP_ROT_270) }, + { "DISP_ROT_90", be_cconst_int(LV_DISP_ROT_90) }, + { "DISP_ROT_NONE", be_cconst_int(LV_DISP_ROT_NONE) }, + { "DRAW_MASK_LINE_SIDE_BOTTOM", be_cconst_int(LV_DRAW_MASK_LINE_SIDE_BOTTOM) }, + { "DRAW_MASK_LINE_SIDE_LEFT", be_cconst_int(LV_DRAW_MASK_LINE_SIDE_LEFT) }, + { "DRAW_MASK_LINE_SIDE_RIGHT", be_cconst_int(LV_DRAW_MASK_LINE_SIDE_RIGHT) }, + { "DRAW_MASK_LINE_SIDE_TOP", be_cconst_int(LV_DRAW_MASK_LINE_SIDE_TOP) }, + { "DRAW_MASK_RES_CHANGED", be_cconst_int(LV_DRAW_MASK_RES_CHANGED) }, + { "DRAW_MASK_RES_FULL_COVER", be_cconst_int(LV_DRAW_MASK_RES_FULL_COVER) }, + { "DRAW_MASK_RES_TRANSP", be_cconst_int(LV_DRAW_MASK_RES_TRANSP) }, + { "DRAW_MASK_RES_UNKNOWN", be_cconst_int(LV_DRAW_MASK_RES_UNKNOWN) }, + { "DRAW_MASK_TYPE_ANGLE", be_cconst_int(LV_DRAW_MASK_TYPE_ANGLE) }, + { "DRAW_MASK_TYPE_FADE", be_cconst_int(LV_DRAW_MASK_TYPE_FADE) }, + { "DRAW_MASK_TYPE_LINE", be_cconst_int(LV_DRAW_MASK_TYPE_LINE) }, + { "DRAW_MASK_TYPE_MAP", be_cconst_int(LV_DRAW_MASK_TYPE_MAP) }, + { "DRAW_MASK_TYPE_RADIUS", be_cconst_int(LV_DRAW_MASK_TYPE_RADIUS) }, + { "EVENT_ALL", be_cconst_int(LV_EVENT_ALL) }, + { "EVENT_CANCEL", be_cconst_int(LV_EVENT_CANCEL) }, + { "EVENT_CHILD_CHANGED", be_cconst_int(LV_EVENT_CHILD_CHANGED) }, + { "EVENT_CHILD_CREATED", be_cconst_int(LV_EVENT_CHILD_CREATED) }, + { "EVENT_CHILD_DELETED", be_cconst_int(LV_EVENT_CHILD_DELETED) }, + { "EVENT_CLICKED", be_cconst_int(LV_EVENT_CLICKED) }, + { "EVENT_COVER_CHECK", be_cconst_int(LV_EVENT_COVER_CHECK) }, + { "EVENT_DEFOCUSED", be_cconst_int(LV_EVENT_DEFOCUSED) }, + { "EVENT_DELETE", be_cconst_int(LV_EVENT_DELETE) }, + { "EVENT_DRAW_MAIN", be_cconst_int(LV_EVENT_DRAW_MAIN) }, + { "EVENT_DRAW_MAIN_BEGIN", be_cconst_int(LV_EVENT_DRAW_MAIN_BEGIN) }, + { "EVENT_DRAW_MAIN_END", be_cconst_int(LV_EVENT_DRAW_MAIN_END) }, + { "EVENT_DRAW_PART_BEGIN", be_cconst_int(LV_EVENT_DRAW_PART_BEGIN) }, + { "EVENT_DRAW_PART_END", be_cconst_int(LV_EVENT_DRAW_PART_END) }, + { "EVENT_DRAW_POST", be_cconst_int(LV_EVENT_DRAW_POST) }, + { "EVENT_DRAW_POST_BEGIN", be_cconst_int(LV_EVENT_DRAW_POST_BEGIN) }, + { "EVENT_DRAW_POST_END", be_cconst_int(LV_EVENT_DRAW_POST_END) }, + { "EVENT_FOCUSED", be_cconst_int(LV_EVENT_FOCUSED) }, + { "EVENT_GESTURE", be_cconst_int(LV_EVENT_GESTURE) }, + { "EVENT_GET_SELF_SIZE", be_cconst_int(LV_EVENT_GET_SELF_SIZE) }, + { "EVENT_HIT_TEST", be_cconst_int(LV_EVENT_HIT_TEST) }, + { "EVENT_INSERT", be_cconst_int(LV_EVENT_INSERT) }, + { "EVENT_KEY", be_cconst_int(LV_EVENT_KEY) }, + { "EVENT_LAYOUT_CHANGED", be_cconst_int(LV_EVENT_LAYOUT_CHANGED) }, + { "EVENT_LEAVE", be_cconst_int(LV_EVENT_LEAVE) }, + { "EVENT_LONG_PRESSED", be_cconst_int(LV_EVENT_LONG_PRESSED) }, + { "EVENT_LONG_PRESSED_REPEAT", be_cconst_int(LV_EVENT_LONG_PRESSED_REPEAT) }, + { "EVENT_PRESSED", be_cconst_int(LV_EVENT_PRESSED) }, + { "EVENT_PRESSING", be_cconst_int(LV_EVENT_PRESSING) }, + { "EVENT_PRESS_LOST", be_cconst_int(LV_EVENT_PRESS_LOST) }, + { "EVENT_READY", be_cconst_int(LV_EVENT_READY) }, + { "EVENT_REFRESH", be_cconst_int(LV_EVENT_REFRESH) }, + { "EVENT_REFR_EXT_DRAW_SIZE", be_cconst_int(LV_EVENT_REFR_EXT_DRAW_SIZE) }, + { "EVENT_RELEASED", be_cconst_int(LV_EVENT_RELEASED) }, + { "EVENT_SCREEN_LOADED", be_cconst_int(LV_EVENT_SCREEN_LOADED) }, + { "EVENT_SCREEN_LOAD_START", be_cconst_int(LV_EVENT_SCREEN_LOAD_START) }, + { "EVENT_SCREEN_UNLOADED", be_cconst_int(LV_EVENT_SCREEN_UNLOADED) }, + { "EVENT_SCREEN_UNLOAD_START", be_cconst_int(LV_EVENT_SCREEN_UNLOAD_START) }, + { "EVENT_SCROLL", be_cconst_int(LV_EVENT_SCROLL) }, + { "EVENT_SCROLL_BEGIN", be_cconst_int(LV_EVENT_SCROLL_BEGIN) }, + { "EVENT_SCROLL_END", be_cconst_int(LV_EVENT_SCROLL_END) }, + { "EVENT_SHORT_CLICKED", be_cconst_int(LV_EVENT_SHORT_CLICKED) }, + { "EVENT_SIZE_CHANGED", be_cconst_int(LV_EVENT_SIZE_CHANGED) }, + { "EVENT_STYLE_CHANGED", be_cconst_int(LV_EVENT_STYLE_CHANGED) }, + { "EVENT_VALUE_CHANGED", be_cconst_int(LV_EVENT_VALUE_CHANGED) }, + { "FLEX_ALIGN_CENTER", be_cconst_int(LV_FLEX_ALIGN_CENTER) }, + { "FLEX_ALIGN_END", be_cconst_int(LV_FLEX_ALIGN_END) }, + { "FLEX_ALIGN_SPACE_AROUND", be_cconst_int(LV_FLEX_ALIGN_SPACE_AROUND) }, + { "FLEX_ALIGN_SPACE_BETWEEN", be_cconst_int(LV_FLEX_ALIGN_SPACE_BETWEEN) }, + { "FLEX_ALIGN_SPACE_EVENLY", be_cconst_int(LV_FLEX_ALIGN_SPACE_EVENLY) }, + { "FLEX_ALIGN_START", be_cconst_int(LV_FLEX_ALIGN_START) }, + { "FLEX_FLOW_COLUMN", be_cconst_int(LV_FLEX_FLOW_COLUMN) }, + { "FLEX_FLOW_COLUMN_REVERSE", be_cconst_int(LV_FLEX_FLOW_COLUMN_REVERSE) }, + { "FLEX_FLOW_COLUMN_WRAP", be_cconst_int(LV_FLEX_FLOW_COLUMN_WRAP) }, + { "FLEX_FLOW_COLUMN_WRAP_REVERSE", be_cconst_int(LV_FLEX_FLOW_COLUMN_WRAP_REVERSE) }, + { "FLEX_FLOW_ROW", be_cconst_int(LV_FLEX_FLOW_ROW) }, + { "FLEX_FLOW_ROW_REVERSE", be_cconst_int(LV_FLEX_FLOW_ROW_REVERSE) }, + { "FLEX_FLOW_ROW_WRAP", be_cconst_int(LV_FLEX_FLOW_ROW_WRAP) }, + { "FLEX_FLOW_ROW_WRAP_REVERSE", be_cconst_int(LV_FLEX_FLOW_ROW_WRAP_REVERSE) }, + { "FS_MODE_RD", be_cconst_int(LV_FS_MODE_RD) }, + { "FS_MODE_WR", be_cconst_int(LV_FS_MODE_WR) }, + { "FS_RES_BUSY", be_cconst_int(LV_FS_RES_BUSY) }, + { "FS_RES_DENIED", be_cconst_int(LV_FS_RES_DENIED) }, + { "FS_RES_FS_ERR", be_cconst_int(LV_FS_RES_FS_ERR) }, + { "FS_RES_FULL", be_cconst_int(LV_FS_RES_FULL) }, + { "FS_RES_HW_ERR", be_cconst_int(LV_FS_RES_HW_ERR) }, + { "FS_RES_INV_PARAM", be_cconst_int(LV_FS_RES_INV_PARAM) }, + { "FS_RES_LOCKED", be_cconst_int(LV_FS_RES_LOCKED) }, + { "FS_RES_NOT_EX", be_cconst_int(LV_FS_RES_NOT_EX) }, + { "FS_RES_NOT_IMP", be_cconst_int(LV_FS_RES_NOT_IMP) }, + { "FS_RES_OK", be_cconst_int(LV_FS_RES_OK) }, + { "FS_RES_OUT_OF_MEM", be_cconst_int(LV_FS_RES_OUT_OF_MEM) }, + { "FS_RES_TOUT", be_cconst_int(LV_FS_RES_TOUT) }, + { "FS_RES_UNKNOWN", be_cconst_int(LV_FS_RES_UNKNOWN) }, + { "FS_SEEK_CUR", be_cconst_int(LV_FS_SEEK_CUR) }, + { "FS_SEEK_END", be_cconst_int(LV_FS_SEEK_END) }, + { "FS_SEEK_SET", be_cconst_int(LV_FS_SEEK_SET) }, + { "FT_FONT_STYLE_BOLD", be_cconst_int(FT_FONT_STYLE_BOLD) }, + { "FT_FONT_STYLE_ITALIC", be_cconst_int(FT_FONT_STYLE_ITALIC) }, + { "FT_FONT_STYLE_NORMAL", be_cconst_int(FT_FONT_STYLE_NORMAL) }, + { "GRAD_DIR_HOR", be_cconst_int(LV_GRAD_DIR_HOR) }, + { "GRAD_DIR_NONE", be_cconst_int(LV_GRAD_DIR_NONE) }, + { "GRAD_DIR_VER", be_cconst_int(LV_GRAD_DIR_VER) }, + { "GRID_ALIGN_CENTER", be_cconst_int(LV_GRID_ALIGN_CENTER) }, + { "GRID_ALIGN_END", be_cconst_int(LV_GRID_ALIGN_END) }, + { "GRID_ALIGN_SPACE_AROUND", be_cconst_int(LV_GRID_ALIGN_SPACE_AROUND) }, + { "GRID_ALIGN_SPACE_BETWEEN", be_cconst_int(LV_GRID_ALIGN_SPACE_BETWEEN) }, + { "GRID_ALIGN_SPACE_EVENLY", be_cconst_int(LV_GRID_ALIGN_SPACE_EVENLY) }, + { "GRID_ALIGN_START", be_cconst_int(LV_GRID_ALIGN_START) }, + { "GRID_ALIGN_STRETCH", be_cconst_int(LV_GRID_ALIGN_STRETCH) }, + { "GRID_CONTENT", be_cconst_int(LV_GRID_CONTENT) }, + { "GRID_FR", be_cconst_int(LV_GRID_FR(0)) }, + { "GRID_TEMPLATE_LAST", be_cconst_int(LV_GRID_TEMPLATE_LAST) }, + { "GROUP_REFOCUS_POLICY_NEXT", be_cconst_int(LV_GROUP_REFOCUS_POLICY_NEXT) }, + { "GROUP_REFOCUS_POLICY_PREV", be_cconst_int(LV_GROUP_REFOCUS_POLICY_PREV) }, + { "IMGBTN_STATE_CHECKED_DISABLED", be_cconst_int(LV_IMGBTN_STATE_CHECKED_DISABLED) }, + { "IMGBTN_STATE_CHECKED_PRESSED", be_cconst_int(LV_IMGBTN_STATE_CHECKED_PRESSED) }, + { "IMGBTN_STATE_CHECKED_RELEASED", be_cconst_int(LV_IMGBTN_STATE_CHECKED_RELEASED) }, + { "IMGBTN_STATE_DISABLED", be_cconst_int(LV_IMGBTN_STATE_DISABLED) }, + { "IMGBTN_STATE_PRESSED", be_cconst_int(LV_IMGBTN_STATE_PRESSED) }, + { "IMGBTN_STATE_RELEASED", be_cconst_int(LV_IMGBTN_STATE_RELEASED) }, + { "IMG_CF_ALPHA_1BIT", be_cconst_int(LV_IMG_CF_ALPHA_1BIT) }, + { "IMG_CF_ALPHA_2BIT", be_cconst_int(LV_IMG_CF_ALPHA_2BIT) }, + { "IMG_CF_ALPHA_4BIT", be_cconst_int(LV_IMG_CF_ALPHA_4BIT) }, + { "IMG_CF_ALPHA_8BIT", be_cconst_int(LV_IMG_CF_ALPHA_8BIT) }, + { "IMG_CF_INDEXED_1BIT", be_cconst_int(LV_IMG_CF_INDEXED_1BIT) }, + { "IMG_CF_INDEXED_2BIT", be_cconst_int(LV_IMG_CF_INDEXED_2BIT) }, + { "IMG_CF_INDEXED_4BIT", be_cconst_int(LV_IMG_CF_INDEXED_4BIT) }, + { "IMG_CF_INDEXED_8BIT", be_cconst_int(LV_IMG_CF_INDEXED_8BIT) }, + { "IMG_CF_RAW", be_cconst_int(LV_IMG_CF_RAW) }, + { "IMG_CF_RAW_ALPHA", be_cconst_int(LV_IMG_CF_RAW_ALPHA) }, + { "IMG_CF_RAW_CHROMA_KEYED", be_cconst_int(LV_IMG_CF_RAW_CHROMA_KEYED) }, + { "IMG_CF_TRUE_COLOR", be_cconst_int(LV_IMG_CF_TRUE_COLOR) }, + { "IMG_CF_TRUE_COLOR_ALPHA", be_cconst_int(LV_IMG_CF_TRUE_COLOR_ALPHA) }, + { "IMG_CF_TRUE_COLOR_CHROMA_KEYED", be_cconst_int(LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) }, + { "IMG_CF_UNKNOWN", be_cconst_int(LV_IMG_CF_UNKNOWN) }, + { "IMG_SIZE_MODE_REAL", be_cconst_int(LV_IMG_SIZE_MODE_REAL) }, + { "IMG_SIZE_MODE_VIRTUAL", be_cconst_int(LV_IMG_SIZE_MODE_VIRTUAL) }, + { "IMG_SRC_FILE", be_cconst_int(LV_IMG_SRC_FILE) }, + { "IMG_SRC_SYMBOL", be_cconst_int(LV_IMG_SRC_SYMBOL) }, + { "IMG_SRC_UNKNOWN", be_cconst_int(LV_IMG_SRC_UNKNOWN) }, + { "IMG_SRC_VARIABLE", be_cconst_int(LV_IMG_SRC_VARIABLE) }, + { "INDEV_STATE_PRESSED", be_cconst_int(LV_INDEV_STATE_PRESSED) }, + { "INDEV_STATE_RELEASED", be_cconst_int(LV_INDEV_STATE_RELEASED) }, + { "INDEV_TYPE_BUTTON", be_cconst_int(LV_INDEV_TYPE_BUTTON) }, + { "INDEV_TYPE_ENCODER", be_cconst_int(LV_INDEV_TYPE_ENCODER) }, + { "INDEV_TYPE_KEYPAD", be_cconst_int(LV_INDEV_TYPE_KEYPAD) }, + { "INDEV_TYPE_NONE", be_cconst_int(LV_INDEV_TYPE_NONE) }, + { "INDEV_TYPE_POINTER", be_cconst_int(LV_INDEV_TYPE_POINTER) }, + { "KEY_BACKSPACE", be_cconst_int(LV_KEY_BACKSPACE) }, + { "KEY_DEL", be_cconst_int(LV_KEY_DEL) }, + { "KEY_DOWN", be_cconst_int(LV_KEY_DOWN) }, + { "KEY_END", be_cconst_int(LV_KEY_END) }, + { "KEY_ENTER", be_cconst_int(LV_KEY_ENTER) }, + { "KEY_ESC", be_cconst_int(LV_KEY_ESC) }, + { "KEY_HOME", be_cconst_int(LV_KEY_HOME) }, + { "KEY_LEFT", be_cconst_int(LV_KEY_LEFT) }, + { "KEY_NEXT", be_cconst_int(LV_KEY_NEXT) }, + { "KEY_PREV", be_cconst_int(LV_KEY_PREV) }, + { "KEY_RIGHT", be_cconst_int(LV_KEY_RIGHT) }, + { "KEY_UP", be_cconst_int(LV_KEY_UP) }, + { "LABEL_LONG_CLIP", be_cconst_int(LV_LABEL_LONG_CLIP) }, + { "LABEL_LONG_DOT", be_cconst_int(LV_LABEL_LONG_DOT) }, + { "LABEL_LONG_SCROLL", be_cconst_int(LV_LABEL_LONG_SCROLL) }, + { "LABEL_LONG_SCROLL_CIRCULAR", be_cconst_int(LV_LABEL_LONG_SCROLL_CIRCULAR) }, + { "LABEL_LONG_WRAP", be_cconst_int(LV_LABEL_LONG_WRAP) }, + { "LED_DRAW_PART_RECTANGLE", be_cconst_int(LV_LED_DRAW_PART_RECTANGLE) }, + { "METER_DRAW_PART_ARC", be_cconst_int(LV_METER_DRAW_PART_ARC) }, + { "METER_DRAW_PART_NEEDLE_IMG", be_cconst_int(LV_METER_DRAW_PART_NEEDLE_IMG) }, + { "METER_DRAW_PART_NEEDLE_LINE", be_cconst_int(LV_METER_DRAW_PART_NEEDLE_LINE) }, + { "METER_DRAW_PART_TICK", be_cconst_int(LV_METER_DRAW_PART_TICK) }, + { "METER_INDICATOR_TYPE_ARC", be_cconst_int(LV_METER_INDICATOR_TYPE_ARC) }, + { "METER_INDICATOR_TYPE_NEEDLE_IMG", be_cconst_int(LV_METER_INDICATOR_TYPE_NEEDLE_IMG) }, + { "METER_INDICATOR_TYPE_NEEDLE_LINE", be_cconst_int(LV_METER_INDICATOR_TYPE_NEEDLE_LINE) }, + { "METER_INDICATOR_TYPE_SCALE_LINES", be_cconst_int(LV_METER_INDICATOR_TYPE_SCALE_LINES) }, + { "OBJ_CLASS_EDITABLE_FALSE", be_cconst_int(LV_OBJ_CLASS_EDITABLE_FALSE) }, + { "OBJ_CLASS_EDITABLE_INHERIT", be_cconst_int(LV_OBJ_CLASS_EDITABLE_INHERIT) }, + { "OBJ_CLASS_EDITABLE_TRUE", be_cconst_int(LV_OBJ_CLASS_EDITABLE_TRUE) }, + { "OBJ_CLASS_GROUP_DEF_FALSE", be_cconst_int(LV_OBJ_CLASS_GROUP_DEF_FALSE) }, + { "OBJ_CLASS_GROUP_DEF_INHERIT", be_cconst_int(LV_OBJ_CLASS_GROUP_DEF_INHERIT) }, + { "OBJ_CLASS_GROUP_DEF_TRUE", be_cconst_int(LV_OBJ_CLASS_GROUP_DEF_TRUE) }, + { "OBJ_DRAW_PART_BORDER_POST", be_cconst_int(LV_OBJ_DRAW_PART_BORDER_POST) }, + { "OBJ_DRAW_PART_RECTANGLE", be_cconst_int(LV_OBJ_DRAW_PART_RECTANGLE) }, + { "OBJ_DRAW_PART_SCROLLBAR", be_cconst_int(LV_OBJ_DRAW_PART_SCROLLBAR) }, + { "OBJ_FLAG_ADV_HITTEST", be_cconst_int(LV_OBJ_FLAG_ADV_HITTEST) }, + { "OBJ_FLAG_CHECKABLE", be_cconst_int(LV_OBJ_FLAG_CHECKABLE) }, + { "OBJ_FLAG_CLICKABLE", be_cconst_int(LV_OBJ_FLAG_CLICKABLE) }, + { "OBJ_FLAG_CLICK_FOCUSABLE", be_cconst_int(LV_OBJ_FLAG_CLICK_FOCUSABLE) }, + { "OBJ_FLAG_EVENT_BUBBLE", be_cconst_int(LV_OBJ_FLAG_EVENT_BUBBLE) }, + { "OBJ_FLAG_FLEX_IN_NEW_TRACK", be_cconst_int(LV_OBJ_FLAG_FLEX_IN_NEW_TRACK) }, + { "OBJ_FLAG_FLOATING", be_cconst_int(LV_OBJ_FLAG_FLOATING) }, + { "OBJ_FLAG_GESTURE_BUBBLE", be_cconst_int(LV_OBJ_FLAG_GESTURE_BUBBLE) }, + { "OBJ_FLAG_HIDDEN", be_cconst_int(LV_OBJ_FLAG_HIDDEN) }, + { "OBJ_FLAG_IGNORE_LAYOUT", be_cconst_int(LV_OBJ_FLAG_IGNORE_LAYOUT) }, + { "OBJ_FLAG_LAYOUT_1", be_cconst_int(LV_OBJ_FLAG_LAYOUT_1) }, + { "OBJ_FLAG_LAYOUT_2", be_cconst_int(LV_OBJ_FLAG_LAYOUT_2) }, + { "OBJ_FLAG_PRESS_LOCK", be_cconst_int(LV_OBJ_FLAG_PRESS_LOCK) }, + { "OBJ_FLAG_SCROLLABLE", be_cconst_int(LV_OBJ_FLAG_SCROLLABLE) }, + { "OBJ_FLAG_SCROLL_CHAIN", be_cconst_int(LV_OBJ_FLAG_SCROLL_CHAIN) }, + { "OBJ_FLAG_SCROLL_ELASTIC", be_cconst_int(LV_OBJ_FLAG_SCROLL_ELASTIC) }, + { "OBJ_FLAG_SCROLL_MOMENTUM", be_cconst_int(LV_OBJ_FLAG_SCROLL_MOMENTUM) }, + { "OBJ_FLAG_SCROLL_ONE", be_cconst_int(LV_OBJ_FLAG_SCROLL_ONE) }, + { "OBJ_FLAG_SCROLL_ON_FOCUS", be_cconst_int(LV_OBJ_FLAG_SCROLL_ON_FOCUS) }, + { "OBJ_FLAG_SNAPPABLE", be_cconst_int(LV_OBJ_FLAG_SNAPPABLE) }, + { "OBJ_FLAG_USER_1", be_cconst_int(LV_OBJ_FLAG_USER_1) }, + { "OBJ_FLAG_USER_2", be_cconst_int(LV_OBJ_FLAG_USER_2) }, + { "OBJ_FLAG_USER_3", be_cconst_int(LV_OBJ_FLAG_USER_3) }, + { "OBJ_FLAG_USER_4", be_cconst_int(LV_OBJ_FLAG_USER_4) }, + { "OBJ_FLAG_WIDGET_1", be_cconst_int(LV_OBJ_FLAG_WIDGET_1) }, + { "OBJ_FLAG_WIDGET_2", be_cconst_int(LV_OBJ_FLAG_WIDGET_2) }, + { "OBJ_TREE_WALK_END", be_cconst_int(LV_OBJ_TREE_WALK_END) }, + { "OBJ_TREE_WALK_NEXT", be_cconst_int(LV_OBJ_TREE_WALK_NEXT) }, + { "OBJ_TREE_WALK_SKIP_CHILDREN", be_cconst_int(LV_OBJ_TREE_WALK_SKIP_CHILDREN) }, + { "OPA_0", be_cconst_int(LV_OPA_0) }, + { "OPA_10", be_cconst_int(LV_OPA_10) }, + { "OPA_100", be_cconst_int(LV_OPA_100) }, + { "OPA_20", be_cconst_int(LV_OPA_20) }, + { "OPA_30", be_cconst_int(LV_OPA_30) }, + { "OPA_40", be_cconst_int(LV_OPA_40) }, + { "OPA_50", be_cconst_int(LV_OPA_50) }, + { "OPA_60", be_cconst_int(LV_OPA_60) }, + { "OPA_70", be_cconst_int(LV_OPA_70) }, + { "OPA_80", be_cconst_int(LV_OPA_80) }, + { "OPA_90", be_cconst_int(LV_OPA_90) }, + { "OPA_COVER", be_cconst_int(LV_OPA_COVER) }, + { "OPA_TRANSP", be_cconst_int(LV_OPA_TRANSP) }, + { "PALETTE_AMBER", be_cconst_int(LV_PALETTE_AMBER) }, + { "PALETTE_BLUE", be_cconst_int(LV_PALETTE_BLUE) }, + { "PALETTE_BLUE_GREY", be_cconst_int(LV_PALETTE_BLUE_GREY) }, + { "PALETTE_BROWN", be_cconst_int(LV_PALETTE_BROWN) }, + { "PALETTE_CYAN", be_cconst_int(LV_PALETTE_CYAN) }, + { "PALETTE_DEEP_ORANGE", be_cconst_int(LV_PALETTE_DEEP_ORANGE) }, + { "PALETTE_DEEP_PURPLE", be_cconst_int(LV_PALETTE_DEEP_PURPLE) }, + { "PALETTE_GREEN", be_cconst_int(LV_PALETTE_GREEN) }, + { "PALETTE_GREY", be_cconst_int(LV_PALETTE_GREY) }, + { "PALETTE_INDIGO", be_cconst_int(LV_PALETTE_INDIGO) }, + { "PALETTE_LIGHT_BLUE", be_cconst_int(LV_PALETTE_LIGHT_BLUE) }, + { "PALETTE_LIGHT_GREEN", be_cconst_int(LV_PALETTE_LIGHT_GREEN) }, + { "PALETTE_LIME", be_cconst_int(LV_PALETTE_LIME) }, + { "PALETTE_NONE", be_cconst_int(LV_PALETTE_NONE) }, + { "PALETTE_ORANGE", be_cconst_int(LV_PALETTE_ORANGE) }, + { "PALETTE_PINK", be_cconst_int(LV_PALETTE_PINK) }, + { "PALETTE_PURPLE", be_cconst_int(LV_PALETTE_PURPLE) }, + { "PALETTE_RED", be_cconst_int(LV_PALETTE_RED) }, + { "PALETTE_TEAL", be_cconst_int(LV_PALETTE_TEAL) }, + { "PALETTE_YELLOW", be_cconst_int(LV_PALETTE_YELLOW) }, + { "PART_ANY", be_cconst_int(LV_PART_ANY) }, + { "PART_CURSOR", be_cconst_int(LV_PART_CURSOR) }, + { "PART_CUSTOM_FIRST", be_cconst_int(LV_PART_CUSTOM_FIRST) }, + { "PART_INDICATOR", be_cconst_int(LV_PART_INDICATOR) }, + { "PART_ITEMS", be_cconst_int(LV_PART_ITEMS) }, + { "PART_KNOB", be_cconst_int(LV_PART_KNOB) }, + { "PART_MAIN", be_cconst_int(LV_PART_MAIN) }, + { "PART_SCROLLBAR", be_cconst_int(LV_PART_SCROLLBAR) }, + { "PART_SELECTED", be_cconst_int(LV_PART_SELECTED) }, + { "PART_TEXTAREA_PLACEHOLDER", be_cconst_int(LV_PART_TEXTAREA_PLACEHOLDER) }, + { "PART_TICKS", be_cconst_int(LV_PART_TICKS) }, + { "RADIUS_CIRCLE", be_cconst_int(LV_RADIUS_CIRCLE) }, + { "RES_INV", be_cconst_int(LV_RES_INV) }, + { "RES_OK", be_cconst_int(LV_RES_OK) }, + { "ROLLER_MODE_INFINITE", be_cconst_int(LV_ROLLER_MODE_INFINITE) }, + { "ROLLER_MODE_NORMAL", be_cconst_int(LV_ROLLER_MODE_NORMAL) }, + { "SCROLLBAR_MODE_ACTIVE", be_cconst_int(LV_SCROLLBAR_MODE_ACTIVE) }, + { "SCROLLBAR_MODE_AUTO", be_cconst_int(LV_SCROLLBAR_MODE_AUTO) }, + { "SCROLLBAR_MODE_OFF", be_cconst_int(LV_SCROLLBAR_MODE_OFF) }, + { "SCROLLBAR_MODE_ON", be_cconst_int(LV_SCROLLBAR_MODE_ON) }, + { "SCROLL_SNAP_CENTER", be_cconst_int(LV_SCROLL_SNAP_CENTER) }, + { "SCROLL_SNAP_END", be_cconst_int(LV_SCROLL_SNAP_END) }, + { "SCROLL_SNAP_NONE", be_cconst_int(LV_SCROLL_SNAP_NONE) }, + { "SCROLL_SNAP_START", be_cconst_int(LV_SCROLL_SNAP_START) }, + { "SCR_LOAD_ANIM_FADE_ON", be_cconst_int(LV_SCR_LOAD_ANIM_FADE_ON) }, + { "SCR_LOAD_ANIM_MOVE_BOTTOM", be_cconst_int(LV_SCR_LOAD_ANIM_MOVE_BOTTOM) }, + { "SCR_LOAD_ANIM_MOVE_LEFT", be_cconst_int(LV_SCR_LOAD_ANIM_MOVE_LEFT) }, + { "SCR_LOAD_ANIM_MOVE_RIGHT", be_cconst_int(LV_SCR_LOAD_ANIM_MOVE_RIGHT) }, + { "SCR_LOAD_ANIM_MOVE_TOP", be_cconst_int(LV_SCR_LOAD_ANIM_MOVE_TOP) }, + { "SCR_LOAD_ANIM_NONE", be_cconst_int(LV_SCR_LOAD_ANIM_NONE) }, + { "SCR_LOAD_ANIM_OVER_BOTTOM", be_cconst_int(LV_SCR_LOAD_ANIM_OVER_BOTTOM) }, + { "SCR_LOAD_ANIM_OVER_LEFT", be_cconst_int(LV_SCR_LOAD_ANIM_OVER_LEFT) }, + { "SCR_LOAD_ANIM_OVER_RIGHT", be_cconst_int(LV_SCR_LOAD_ANIM_OVER_RIGHT) }, + { "SCR_LOAD_ANIM_OVER_TOP", be_cconst_int(LV_SCR_LOAD_ANIM_OVER_TOP) }, + { "SIZE_CONTENT", be_cconst_int(LV_SIZE_CONTENT) }, + { "SLIDER_DRAW_PART_KNOB", be_cconst_int(LV_SLIDER_DRAW_PART_KNOB) }, + { "SLIDER_DRAW_PART_KNOB_LEFT", be_cconst_int(LV_SLIDER_DRAW_PART_KNOB_LEFT) }, + { "SLIDER_MODE_NORMAL", be_cconst_int(LV_SLIDER_MODE_NORMAL) }, + { "SLIDER_MODE_RANGE", be_cconst_int(LV_SLIDER_MODE_RANGE) }, + { "SLIDER_MODE_SYMMETRICAL", be_cconst_int(LV_SLIDER_MODE_SYMMETRICAL) }, + { "SPAN_MODE_BREAK", be_cconst_int(LV_SPAN_MODE_BREAK) }, + { "SPAN_MODE_EXPAND", be_cconst_int(LV_SPAN_MODE_EXPAND) }, + { "SPAN_MODE_FIXED", be_cconst_int(LV_SPAN_MODE_FIXED) }, + { "SPAN_OVERFLOW_CLIP", be_cconst_int(LV_SPAN_OVERFLOW_CLIP) }, + { "SPAN_OVERFLOW_ELLIPSIS", be_cconst_int(LV_SPAN_OVERFLOW_ELLIPSIS) }, + { "STATE_ANY", be_cconst_int(LV_STATE_ANY) }, + { "STATE_CHECKED", be_cconst_int(LV_STATE_CHECKED) }, + { "STATE_DEFAULT", be_cconst_int(LV_STATE_DEFAULT) }, + { "STATE_DISABLED", be_cconst_int(LV_STATE_DISABLED) }, + { "STATE_EDITED", be_cconst_int(LV_STATE_EDITED) }, + { "STATE_FOCUSED", be_cconst_int(LV_STATE_FOCUSED) }, + { "STATE_FOCUS_KEY", be_cconst_int(LV_STATE_FOCUS_KEY) }, + { "STATE_HOVERED", be_cconst_int(LV_STATE_HOVERED) }, + { "STATE_PRESSED", be_cconst_int(LV_STATE_PRESSED) }, + { "STATE_SCROLLED", be_cconst_int(LV_STATE_SCROLLED) }, + { "STATE_USER_1", be_cconst_int(LV_STATE_USER_1) }, + { "STATE_USER_2", be_cconst_int(LV_STATE_USER_2) }, + { "STATE_USER_3", be_cconst_int(LV_STATE_USER_3) }, + { "STATE_USER_4", be_cconst_int(LV_STATE_USER_4) }, + { "STYLE_ALIGN", be_cconst_int(LV_STYLE_ALIGN) }, + { "STYLE_ANIM_SPEED", be_cconst_int(LV_STYLE_ANIM_SPEED) }, + { "STYLE_ANIM_TIME", be_cconst_int(LV_STYLE_ANIM_TIME) }, + { "STYLE_ARC_COLOR", be_cconst_int(LV_STYLE_ARC_COLOR) }, + { "STYLE_ARC_COLOR_FILTERED", be_cconst_int(LV_STYLE_ARC_COLOR_FILTERED) }, + { "STYLE_ARC_IMG_SRC", be_cconst_int(LV_STYLE_ARC_IMG_SRC) }, + { "STYLE_ARC_OPA", be_cconst_int(LV_STYLE_ARC_OPA) }, + { "STYLE_ARC_ROUNDED", be_cconst_int(LV_STYLE_ARC_ROUNDED) }, + { "STYLE_ARC_WIDTH", be_cconst_int(LV_STYLE_ARC_WIDTH) }, + { "STYLE_BASE_DIR", be_cconst_int(LV_STYLE_BASE_DIR) }, + { "STYLE_BG_COLOR", be_cconst_int(LV_STYLE_BG_COLOR) }, + { "STYLE_BG_COLOR_FILTERED", be_cconst_int(LV_STYLE_BG_COLOR_FILTERED) }, + { "STYLE_BG_GRAD_COLOR", be_cconst_int(LV_STYLE_BG_GRAD_COLOR) }, + { "STYLE_BG_GRAD_COLOR_FILTERED", be_cconst_int(LV_STYLE_BG_GRAD_COLOR_FILTERED) }, + { "STYLE_BG_GRAD_DIR", be_cconst_int(LV_STYLE_BG_GRAD_DIR) }, + { "STYLE_BG_GRAD_STOP", be_cconst_int(LV_STYLE_BG_GRAD_STOP) }, + { "STYLE_BG_IMG_OPA", be_cconst_int(LV_STYLE_BG_IMG_OPA) }, + { "STYLE_BG_IMG_RECOLOR", be_cconst_int(LV_STYLE_BG_IMG_RECOLOR) }, + { "STYLE_BG_IMG_RECOLOR_FILTERED", be_cconst_int(LV_STYLE_BG_IMG_RECOLOR_FILTERED) }, + { "STYLE_BG_IMG_RECOLOR_OPA", be_cconst_int(LV_STYLE_BG_IMG_RECOLOR_OPA) }, + { "STYLE_BG_IMG_SRC", be_cconst_int(LV_STYLE_BG_IMG_SRC) }, + { "STYLE_BG_IMG_TILED", be_cconst_int(LV_STYLE_BG_IMG_TILED) }, + { "STYLE_BG_MAIN_STOP", be_cconst_int(LV_STYLE_BG_MAIN_STOP) }, + { "STYLE_BG_OPA", be_cconst_int(LV_STYLE_BG_OPA) }, + { "STYLE_BLEND_MODE", be_cconst_int(LV_STYLE_BLEND_MODE) }, + { "STYLE_BORDER_COLOR", be_cconst_int(LV_STYLE_BORDER_COLOR) }, + { "STYLE_BORDER_COLOR_FILTERED", be_cconst_int(LV_STYLE_BORDER_COLOR_FILTERED) }, + { "STYLE_BORDER_OPA", be_cconst_int(LV_STYLE_BORDER_OPA) }, + { "STYLE_BORDER_POST", be_cconst_int(LV_STYLE_BORDER_POST) }, + { "STYLE_BORDER_SIDE", be_cconst_int(LV_STYLE_BORDER_SIDE) }, + { "STYLE_BORDER_WIDTH", be_cconst_int(LV_STYLE_BORDER_WIDTH) }, + { "STYLE_CLIP_CORNER", be_cconst_int(LV_STYLE_CLIP_CORNER) }, + { "STYLE_COLOR_FILTER_DSC", be_cconst_int(LV_STYLE_COLOR_FILTER_DSC) }, + { "STYLE_COLOR_FILTER_OPA", be_cconst_int(LV_STYLE_COLOR_FILTER_OPA) }, + { "STYLE_HEIGHT", be_cconst_int(LV_STYLE_HEIGHT) }, + { "STYLE_IMG_OPA", be_cconst_int(LV_STYLE_IMG_OPA) }, + { "STYLE_IMG_RECOLOR", be_cconst_int(LV_STYLE_IMG_RECOLOR) }, + { "STYLE_IMG_RECOLOR_FILTERED", be_cconst_int(LV_STYLE_IMG_RECOLOR_FILTERED) }, + { "STYLE_IMG_RECOLOR_OPA", be_cconst_int(LV_STYLE_IMG_RECOLOR_OPA) }, + { "STYLE_LAYOUT", be_cconst_int(LV_STYLE_LAYOUT) }, + { "STYLE_LINE_COLOR", be_cconst_int(LV_STYLE_LINE_COLOR) }, + { "STYLE_LINE_COLOR_FILTERED", be_cconst_int(LV_STYLE_LINE_COLOR_FILTERED) }, + { "STYLE_LINE_DASH_GAP", be_cconst_int(LV_STYLE_LINE_DASH_GAP) }, + { "STYLE_LINE_DASH_WIDTH", be_cconst_int(LV_STYLE_LINE_DASH_WIDTH) }, + { "STYLE_LINE_OPA", be_cconst_int(LV_STYLE_LINE_OPA) }, + { "STYLE_LINE_ROUNDED", be_cconst_int(LV_STYLE_LINE_ROUNDED) }, + { "STYLE_LINE_WIDTH", be_cconst_int(LV_STYLE_LINE_WIDTH) }, + { "STYLE_MAX_HEIGHT", be_cconst_int(LV_STYLE_MAX_HEIGHT) }, + { "STYLE_MAX_WIDTH", be_cconst_int(LV_STYLE_MAX_WIDTH) }, + { "STYLE_MIN_HEIGHT", be_cconst_int(LV_STYLE_MIN_HEIGHT) }, + { "STYLE_MIN_WIDTH", be_cconst_int(LV_STYLE_MIN_WIDTH) }, + { "STYLE_OPA", be_cconst_int(LV_STYLE_OPA) }, + { "STYLE_OUTLINE_COLOR", be_cconst_int(LV_STYLE_OUTLINE_COLOR) }, + { "STYLE_OUTLINE_COLOR_FILTERED", be_cconst_int(LV_STYLE_OUTLINE_COLOR_FILTERED) }, + { "STYLE_OUTLINE_OPA", be_cconst_int(LV_STYLE_OUTLINE_OPA) }, + { "STYLE_OUTLINE_PAD", be_cconst_int(LV_STYLE_OUTLINE_PAD) }, + { "STYLE_OUTLINE_WIDTH", be_cconst_int(LV_STYLE_OUTLINE_WIDTH) }, + { "STYLE_PAD_BOTTOM", be_cconst_int(LV_STYLE_PAD_BOTTOM) }, + { "STYLE_PAD_COLUMN", be_cconst_int(LV_STYLE_PAD_COLUMN) }, + { "STYLE_PAD_LEFT", be_cconst_int(LV_STYLE_PAD_LEFT) }, + { "STYLE_PAD_RIGHT", be_cconst_int(LV_STYLE_PAD_RIGHT) }, + { "STYLE_PAD_ROW", be_cconst_int(LV_STYLE_PAD_ROW) }, + { "STYLE_PAD_TOP", be_cconst_int(LV_STYLE_PAD_TOP) }, + { "STYLE_PROP_ANY", be_cconst_int(LV_STYLE_PROP_ANY) }, + { "STYLE_PROP_INV", be_cconst_int(LV_STYLE_PROP_INV) }, + { "STYLE_RADIUS", be_cconst_int(LV_STYLE_RADIUS) }, + { "STYLE_SHADOW_COLOR", be_cconst_int(LV_STYLE_SHADOW_COLOR) }, + { "STYLE_SHADOW_COLOR_FILTERED", be_cconst_int(LV_STYLE_SHADOW_COLOR_FILTERED) }, + { "STYLE_SHADOW_OFS_X", be_cconst_int(LV_STYLE_SHADOW_OFS_X) }, + { "STYLE_SHADOW_OFS_Y", be_cconst_int(LV_STYLE_SHADOW_OFS_Y) }, + { "STYLE_SHADOW_OPA", be_cconst_int(LV_STYLE_SHADOW_OPA) }, + { "STYLE_SHADOW_SPREAD", be_cconst_int(LV_STYLE_SHADOW_SPREAD) }, + { "STYLE_SHADOW_WIDTH", be_cconst_int(LV_STYLE_SHADOW_WIDTH) }, + { "STYLE_TEXT_ALIGN", be_cconst_int(LV_STYLE_TEXT_ALIGN) }, + { "STYLE_TEXT_COLOR", be_cconst_int(LV_STYLE_TEXT_COLOR) }, + { "STYLE_TEXT_COLOR_FILTERED", be_cconst_int(LV_STYLE_TEXT_COLOR_FILTERED) }, + { "STYLE_TEXT_DECOR", be_cconst_int(LV_STYLE_TEXT_DECOR) }, + { "STYLE_TEXT_FONT", be_cconst_int(LV_STYLE_TEXT_FONT) }, + { "STYLE_TEXT_LETTER_SPACE", be_cconst_int(LV_STYLE_TEXT_LETTER_SPACE) }, + { "STYLE_TEXT_LINE_SPACE", be_cconst_int(LV_STYLE_TEXT_LINE_SPACE) }, + { "STYLE_TEXT_OPA", be_cconst_int(LV_STYLE_TEXT_OPA) }, + { "STYLE_TRANSFORM_ANGLE", be_cconst_int(LV_STYLE_TRANSFORM_ANGLE) }, + { "STYLE_TRANSFORM_HEIGHT", be_cconst_int(LV_STYLE_TRANSFORM_HEIGHT) }, + { "STYLE_TRANSFORM_WIDTH", be_cconst_int(LV_STYLE_TRANSFORM_WIDTH) }, + { "STYLE_TRANSFORM_ZOOM", be_cconst_int(LV_STYLE_TRANSFORM_ZOOM) }, + { "STYLE_TRANSITION", be_cconst_int(LV_STYLE_TRANSITION) }, + { "STYLE_TRANSLATE_X", be_cconst_int(LV_STYLE_TRANSLATE_X) }, + { "STYLE_TRANSLATE_Y", be_cconst_int(LV_STYLE_TRANSLATE_Y) }, + { "STYLE_WIDTH", be_cconst_int(LV_STYLE_WIDTH) }, + { "STYLE_X", be_cconst_int(LV_STYLE_X) }, + { "STYLE_Y", be_cconst_int(LV_STYLE_Y) }, + { "$SYMBOL_AUDIO", be_cconst_string("\xef\x80\x81") }, + { "$SYMBOL_BACKSPACE", be_cconst_string("\xef\x95\x9A") }, + { "$SYMBOL_BATTERY_1", be_cconst_string("\xef\x89\x83") }, + { "$SYMBOL_BATTERY_2", be_cconst_string("\xef\x89\x82") }, + { "$SYMBOL_BATTERY_3", be_cconst_string("\xef\x89\x81") }, + { "$SYMBOL_BATTERY_EMPTY", be_cconst_string("\xef\x89\x84") }, + { "$SYMBOL_BATTERY_FULL", be_cconst_string("\xef\x89\x80") }, + { "$SYMBOL_BELL", be_cconst_string("\xef\x83\xb3") }, + { "$SYMBOL_BLUETOOTH", be_cconst_string("\xef\x8a\x93") }, + { "$SYMBOL_BULLET", be_cconst_string("\xE2\x80\xA2") }, + { "$SYMBOL_CALL", be_cconst_string("\xef\x82\x95") }, + { "$SYMBOL_CHARGE", be_cconst_string("\xef\x83\xa7") }, + { "$SYMBOL_CLOSE", be_cconst_string("\xef\x80\x8d") }, + { "$SYMBOL_COPY", be_cconst_string("\xef\x83\x85") }, + { "$SYMBOL_CUT", be_cconst_string("\xef\x83\x84") }, + { "$SYMBOL_DIRECTORY", be_cconst_string("\xef\x81\xbb") }, + { "$SYMBOL_DOWN", be_cconst_string("\xef\x81\xb8") }, + { "$SYMBOL_DOWNLOAD", be_cconst_string("\xef\x80\x99") }, + { "$SYMBOL_DRIVE", be_cconst_string("\xef\x80\x9c") }, + { "$SYMBOL_DUMMY", be_cconst_string("\xEF\xA3\xBF") }, + { "$SYMBOL_EDIT", be_cconst_string("\xef\x8C\x84") }, + { "$SYMBOL_EJECT", be_cconst_string("\xef\x81\x92") }, + { "$SYMBOL_EYE_CLOSE", be_cconst_string("\xef\x81\xb0") }, + { "$SYMBOL_EYE_OPEN", be_cconst_string("\xef\x81\xae") }, + { "$SYMBOL_FILE", be_cconst_string("\xef\x85\x9b") }, + { "$SYMBOL_GPS", be_cconst_string("\xef\x84\xa4") }, + { "$SYMBOL_HOME", be_cconst_string("\xef\x80\x95") }, + { "$SYMBOL_IMAGE", be_cconst_string("\xef\x80\xbe") }, + { "$SYMBOL_KEYBOARD", be_cconst_string("\xef\x84\x9c") }, + { "$SYMBOL_LEFT", be_cconst_string("\xef\x81\x93") }, + { "$SYMBOL_LIST", be_cconst_string("\xef\x80\x8b") }, + { "$SYMBOL_LOOP", be_cconst_string("\xef\x81\xb9") }, + { "$SYMBOL_MINUS", be_cconst_string("\xef\x81\xa8") }, + { "$SYMBOL_MUTE", be_cconst_string("\xef\x80\xa6") }, + { "$SYMBOL_NEW_LINE", be_cconst_string("\xef\xA2\xA2") }, + { "$SYMBOL_NEXT", be_cconst_string("\xef\x81\x91") }, + { "$SYMBOL_OK", be_cconst_string("\xef\x80\x8c") }, + { "$SYMBOL_PASTE", be_cconst_string("\xef\x83\xAA") }, + { "$SYMBOL_PAUSE", be_cconst_string("\xef\x81\x8c") }, + { "$SYMBOL_PLAY", be_cconst_string("\xef\x81\x8b") }, + { "$SYMBOL_PLUS", be_cconst_string("\xef\x81\xa7") }, + { "$SYMBOL_POWER", be_cconst_string("\xef\x80\x91") }, + { "$SYMBOL_PREV", be_cconst_string("\xef\x81\x88") }, + { "$SYMBOL_REFRESH", be_cconst_string("\xef\x80\xa1") }, + { "$SYMBOL_RIGHT", be_cconst_string("\xef\x81\x94") }, + { "$SYMBOL_SAVE", be_cconst_string("\xef\x83\x87") }, + { "$SYMBOL_SD_CARD", be_cconst_string("\xef\x9F\x82") }, + { "$SYMBOL_SETTINGS", be_cconst_string("\xef\x80\x93") }, + { "$SYMBOL_SHUFFLE", be_cconst_string("\xef\x81\xb4") }, + { "$SYMBOL_STOP", be_cconst_string("\xef\x81\x8d") }, + { "$SYMBOL_TRASH", be_cconst_string("\xef\x8B\xAD") }, + { "$SYMBOL_UP", be_cconst_string("\xef\x81\xb7") }, + { "$SYMBOL_UPLOAD", be_cconst_string("\xef\x82\x93") }, + { "$SYMBOL_USB", be_cconst_string("\xef\x8a\x87") }, + { "$SYMBOL_VIDEO", be_cconst_string("\xef\x80\x88") }, + { "$SYMBOL_VOLUME_MAX", be_cconst_string("\xef\x80\xa8") }, + { "$SYMBOL_VOLUME_MID", be_cconst_string("\xef\x80\xa7") }, + { "$SYMBOL_WARNING", be_cconst_string("\xef\x81\xb1") }, + { "$SYMBOL_WIFI", be_cconst_string("\xef\x87\xab") }, + { "TABLE_CELL_CTRL_CUSTOM_1", be_cconst_int(LV_TABLE_CELL_CTRL_CUSTOM_1) }, + { "TABLE_CELL_CTRL_CUSTOM_2", be_cconst_int(LV_TABLE_CELL_CTRL_CUSTOM_2) }, + { "TABLE_CELL_CTRL_CUSTOM_3", be_cconst_int(LV_TABLE_CELL_CTRL_CUSTOM_3) }, + { "TABLE_CELL_CTRL_CUSTOM_4", be_cconst_int(LV_TABLE_CELL_CTRL_CUSTOM_4) }, + { "TABLE_CELL_CTRL_MERGE_RIGHT", be_cconst_int(LV_TABLE_CELL_CTRL_MERGE_RIGHT) }, + { "TABLE_CELL_CTRL_TEXT_CROP", be_cconst_int(LV_TABLE_CELL_CTRL_TEXT_CROP) }, + { "TABLE_DRAW_PART_CELL", be_cconst_int(LV_TABLE_DRAW_PART_CELL) }, + { "TEXTAREA_CURSOR_LAST", be_cconst_int(LV_TEXTAREA_CURSOR_LAST) }, + { "TEXT_ALIGN_AUTO", be_cconst_int(LV_TEXT_ALIGN_AUTO) }, + { "TEXT_ALIGN_CENTER", be_cconst_int(LV_TEXT_ALIGN_CENTER) }, + { "TEXT_ALIGN_LEFT", be_cconst_int(LV_TEXT_ALIGN_LEFT) }, + { "TEXT_ALIGN_RIGHT", be_cconst_int(LV_TEXT_ALIGN_RIGHT) }, + { "TEXT_CMD_STATE_IN", be_cconst_int(LV_TEXT_CMD_STATE_IN) }, + { "TEXT_CMD_STATE_PAR", be_cconst_int(LV_TEXT_CMD_STATE_PAR) }, + { "TEXT_CMD_STATE_WAIT", be_cconst_int(LV_TEXT_CMD_STATE_WAIT) }, + { "TEXT_DECOR_NONE", be_cconst_int(LV_TEXT_DECOR_NONE) }, + { "TEXT_DECOR_STRIKETHROUGH", be_cconst_int(LV_TEXT_DECOR_STRIKETHROUGH) }, + { "TEXT_DECOR_UNDERLINE", be_cconst_int(LV_TEXT_DECOR_UNDERLINE) }, + { "TEXT_FLAG_EXPAND", be_cconst_int(LV_TEXT_FLAG_EXPAND) }, + { "TEXT_FLAG_FIT", be_cconst_int(LV_TEXT_FLAG_FIT) }, + { "TEXT_FLAG_NONE", be_cconst_int(LV_TEXT_FLAG_NONE) }, + { "TEXT_FLAG_RECOLOR", be_cconst_int(LV_TEXT_FLAG_RECOLOR) }, + { "&load_font", be_cconst_ptr(&lv0_load_font) }, + +}; + +const size_t lv0_constants_size = sizeof(lv0_constants)/sizeof(lv0_constants[0]); + +/******************************************************************** +** Solidified function: lv_module_init +********************************************************************/ +be_local_closure(lv_lv_module_init, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str(lv), + /* K1 */ be_nested_str(member), + /* K2 */ be_nested_str(lv_solidified), + }), + &be_const_str_lv_module_init, + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x6004000B, // 0000 GETGBL R1 G11 + 0x58080000, // 0001 LDCONST R2 K0 + 0x7C040200, // 0002 CALL R1 1 + 0x88080101, // 0003 GETMBR R2 R0 K1 + 0x90060202, // 0004 SETMBR R1 K1 R2 + 0x90060400, // 0005 SETMBR R1 K2 R0 + 0x80040200, // 0006 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified module: lv +********************************************************************/ +be_local_module(lv, + "lv", + be_nested_map(2, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key(init, -1), be_const_closure(lv_lv_module_init_closure) }, + { be_const_key(member, 0), be_const_func(lv0_member) }, + })) +); +BE_EXPORT_VARIABLE be_define_const_native_module(lv); +/********************************************************************/ + +/********************************************************************/ diff --git a/lib/libesp32/Berry/default/be_lvgl_widgets_lib.c b/lib/libesp32_lvgl/lv_berry/generate/be_lvgl_widgets_lib.c similarity index 93% rename from lib/libesp32/Berry/default/be_lvgl_widgets_lib.c rename to lib/libesp32_lvgl/lv_berry/generate/be_lvgl_widgets_lib.c index 68950d144..22e823250 100644 --- a/lib/libesp32/Berry/default/be_lvgl_widgets_lib.c +++ b/lib/libesp32_lvgl/lv_berry/generate/be_lvgl_widgets_lib.c @@ -8,8 +8,6 @@ *******************************************************************/ #include "be_constobj.h" -#ifdef USE_LVGL - #include "lvgl.h" extern int lv0_init(bvm *vm); @@ -18,11 +16,11 @@ extern int lco_init(bvm *vm); // generic function extern int lco_tostring(bvm *vm); // generic function extern int lco_toint(bvm *vm); // generic function -extern int lvx_member(bvm *vm); -extern int lvx_tostring(bvm *vm); // generic function +extern int lv_x_member(bvm *vm); +extern int lv_x_tostring(bvm *vm); // generic function -extern int lvs_init(bvm *vm); -extern int lvs_tostring(bvm *vm); +extern int lv_be_style_init(bvm *vm); +extern int lv_x_tostring(bvm *vm); BE_EXPORT_VARIABLE extern const bclass be_class_lv_obj; @@ -31,6 +29,21 @@ extern int lvbe_theme_create(bvm *vm); /* `lv_style` external functions definitions */ +extern int lvbe_style_set_flex_flow(bvm *vm); +extern int lvbe_style_set_flex_main_place(bvm *vm); +extern int lvbe_style_set_flex_cross_place(bvm *vm); +extern int lvbe_style_set_flex_track_place(bvm *vm); +extern int lvbe_style_set_flex_grow(bvm *vm); +extern int lvbe_style_set_grid_row_dsc_array(bvm *vm); +extern int lvbe_style_set_grid_column_dsc_array(bvm *vm); +extern int lvbe_style_set_grid_row_align(bvm *vm); +extern int lvbe_style_set_grid_column_align(bvm *vm); +extern int lvbe_style_set_grid_cell_column_pos(bvm *vm); +extern int lvbe_style_set_grid_cell_column_span(bvm *vm); +extern int lvbe_style_set_grid_cell_row_pos(bvm *vm); +extern int lvbe_style_set_grid_cell_row_span(bvm *vm); +extern int lvbe_style_set_grid_cell_x_align(bvm *vm); +extern int lvbe_style_set_grid_cell_y_align(bvm *vm); extern int lvbe_style_set_width(bvm *vm); extern int lvbe_style_set_min_width(bvm *vm); extern int lvbe_style_set_max_width(bvm *vm); @@ -137,6 +150,7 @@ extern int lvbe_img_set_angle(bvm *vm); extern int lvbe_img_set_pivot(bvm *vm); extern int lvbe_img_set_zoom(bvm *vm); extern int lvbe_img_set_antialias(bvm *vm); +extern int lvbe_img_set_size_mode(bvm *vm); extern int lvbe_img_get_src(bvm *vm); extern int lvbe_img_get_offset_x(bvm *vm); extern int lvbe_img_get_offset_y(bvm *vm); @@ -144,6 +158,7 @@ extern int lvbe_img_get_angle(bvm *vm); extern int lvbe_img_get_pivot(bvm *vm); extern int lvbe_img_get_zoom(bvm *vm); extern int lvbe_img_get_antialias(bvm *vm); +extern int lvbe_img_get_size_mode(bvm *vm); /* `lv_disp` external functions definitions */ extern int lvbe_disp_get_scr_act(bvm *vm); @@ -164,6 +179,7 @@ extern int lvbe_disp_dpx(bvm *vm); /* `lv_obj` external functions definitions */ extern int lvbe_obj_add_event_cb(bvm *vm); extern int lvbe_obj_remove_event_cb(bvm *vm); +extern int lvbe_obj_remove_event_cb_with_user_data(bvm *vm); extern int lvbe_obj_remove_event_dsc(bvm *vm); extern int lvbe_obj_create(bvm *vm); extern int lvbe_obj_add_flag(bvm *vm); @@ -274,6 +290,9 @@ extern int lvbe_obj_set_style_pad_hor(bvm *vm); extern int lvbe_obj_set_style_pad_ver(bvm *vm); extern int lvbe_obj_set_style_pad_gap(bvm *vm); extern int lvbe_obj_set_style_size(bvm *vm); +extern int lvbe_obj_calculate_style_text_align(bvm *vm); +extern int lvbe_obj_get_x_aligned(bvm *vm); +extern int lvbe_obj_get_y_aligned(bvm *vm); extern int lvbe_obj_get_style_width(bvm *vm); extern int lvbe_obj_get_style_min_width(bvm *vm); extern int lvbe_obj_get_style_max_width(bvm *vm); @@ -298,9 +317,11 @@ extern int lvbe_obj_get_style_pad_column(bvm *vm); extern int lvbe_obj_get_style_radius(bvm *vm); extern int lvbe_obj_get_style_clip_corner(bvm *vm); extern int lvbe_obj_get_style_opa(bvm *vm); +extern int lvbe_obj_get_style_color_filter_dsc(bvm *vm); extern int lvbe_obj_get_style_color_filter_opa(bvm *vm); extern int lvbe_obj_get_style_anim_time(bvm *vm); extern int lvbe_obj_get_style_anim_speed(bvm *vm); +extern int lvbe_obj_get_style_transition(bvm *vm); extern int lvbe_obj_get_style_blend_mode(bvm *vm); extern int lvbe_obj_get_style_layout(bvm *vm); extern int lvbe_obj_get_style_base_dir(bvm *vm); @@ -452,23 +473,64 @@ extern int lvbe_obj_set_style_arc_opa(bvm *vm); extern int lvbe_obj_set_style_arc_img_src(bvm *vm); extern int lvbe_obj_del(bvm *vm); extern int lvbe_obj_clean(bvm *vm); +extern int lvbe_obj_del_delayed(bvm *vm); extern int lvbe_obj_del_async(bvm *vm); extern int lvbe_obj_set_parent(bvm *vm); -extern int lvbe_obj_move_foreground(bvm *vm); -extern int lvbe_obj_move_background(bvm *vm); +extern int lvbe_obj_swap(bvm *vm); +extern int lvbe_obj_move_to_index(bvm *vm); extern int lvbe_obj_get_screen(bvm *vm); extern int lvbe_obj_get_disp(bvm *vm); extern int lvbe_obj_get_parent(bvm *vm); extern int lvbe_obj_get_child(bvm *vm); extern int lvbe_obj_get_child_cnt(bvm *vm); -extern int lvbe_obj_get_child_id(bvm *vm); +extern int lvbe_obj_get_index(bvm *vm); extern int lvbe_obj_tree_walk(bvm *vm); +extern int lvbe_obj_set_flex_flow(bvm *vm); +extern int lvbe_obj_set_flex_align(bvm *vm); +extern int lvbe_obj_set_flex_grow(bvm *vm); +extern int lvbe_obj_set_style_flex_flow(bvm *vm); +extern int lvbe_obj_set_style_flex_main_place(bvm *vm); +extern int lvbe_obj_set_style_flex_cross_place(bvm *vm); +extern int lvbe_obj_set_style_flex_track_place(bvm *vm); +extern int lvbe_obj_set_style_flex_grow(bvm *vm); +extern int lvbe_obj_get_style_flex_flow(bvm *vm); +extern int lvbe_obj_get_style_flex_main_place(bvm *vm); +extern int lvbe_obj_get_style_flex_cross_place(bvm *vm); +extern int lvbe_obj_get_style_flex_track_place(bvm *vm); +extern int lvbe_obj_get_style_flex_grow(bvm *vm); +extern int lvbe_obj_set_grid_dsc_array(bvm *vm); +extern int lvbe_obj_set_grid_align(bvm *vm); +extern int lvbe_obj_set_grid_cell(bvm *vm); +extern int lvbe_obj_set_style_grid_row_dsc_array(bvm *vm); +extern int lvbe_obj_set_style_grid_column_dsc_array(bvm *vm); +extern int lvbe_obj_set_style_grid_row_align(bvm *vm); +extern int lvbe_obj_set_style_grid_column_align(bvm *vm); +extern int lvbe_obj_set_style_grid_cell_column_pos(bvm *vm); +extern int lvbe_obj_set_style_grid_cell_column_span(bvm *vm); +extern int lvbe_obj_set_style_grid_cell_row_pos(bvm *vm); +extern int lvbe_obj_set_style_grid_cell_row_span(bvm *vm); +extern int lvbe_obj_set_style_grid_cell_x_align(bvm *vm); +extern int lvbe_obj_set_style_grid_cell_y_align(bvm *vm); +extern int lvbe_obj_get_style_grid_row_dsc_array(bvm *vm); +extern int lvbe_obj_get_style_grid_column_dsc_array(bvm *vm); +extern int lvbe_obj_get_style_grid_row_align(bvm *vm); +extern int lvbe_obj_get_style_grid_column_align(bvm *vm); +extern int lvbe_obj_get_style_grid_cell_column_pos(bvm *vm); +extern int lvbe_obj_get_style_grid_cell_column_span(bvm *vm); +extern int lvbe_obj_get_style_grid_cell_row_pos(bvm *vm); +extern int lvbe_obj_get_style_grid_cell_row_span(bvm *vm); +extern int lvbe_obj_get_style_grid_cell_x_align(bvm *vm); +extern int lvbe_obj_get_style_grid_cell_y_align(bvm *vm); +extern int lvbe_obj_move_foreground(bvm *vm); +extern int lvbe_obj_move_background(bvm *vm); +extern int lvbe_obj_get_child_id(bvm *vm); /* `lv_group` external functions definitions */ extern int lvbe_group_create(bvm *vm); extern int lvbe_group_del(bvm *vm); extern int lvbe_group_set_default(bvm *vm); extern int lvbe_group_add_obj(bvm *vm); +extern int lvbe_group_swap_obj(bvm *vm); extern int lvbe_group_remove_obj(bvm *vm); extern int lvbe_group_remove_all_objs(bvm *vm); extern int lvbe_group_focus_obj(bvm *vm); @@ -520,10 +582,13 @@ extern int lvbe_chart_get_point_count(bvm *vm); extern int lvbe_chart_get_x_start_point(bvm *vm); extern int lvbe_chart_get_point_pos_by_id(bvm *vm); extern int lvbe_chart_refresh(bvm *vm); +extern int lvbe_chart_add_series(bvm *vm); extern int lvbe_chart_remove_series(bvm *vm); extern int lvbe_chart_hide_series(bvm *vm); extern int lvbe_chart_set_series_color(bvm *vm); extern int lvbe_chart_set_x_start_point(bvm *vm); +extern int lvbe_chart_get_series_next(bvm *vm); +extern int lvbe_chart_add_cursor(bvm *vm); extern int lvbe_chart_set_cursor_pos(bvm *vm); extern int lvbe_chart_set_cursor_point(bvm *vm); extern int lvbe_chart_get_cursor_point(bvm *vm); @@ -534,6 +599,8 @@ extern int lvbe_chart_set_value_by_id(bvm *vm); extern int lvbe_chart_set_value_by_id2(bvm *vm); extern int lvbe_chart_set_ext_y_array(bvm *vm); extern int lvbe_chart_set_ext_x_array(bvm *vm); +extern int lvbe_chart_get_y_array(bvm *vm); +extern int lvbe_chart_get_x_array(bvm *vm); extern int lvbe_chart_get_pressed_point(bvm *vm); /* `lv_colorwheel` external functions definitions */ @@ -550,6 +617,7 @@ extern int lvbe_colorwheel_get_color_mode_fixed(bvm *vm); /* `lv_imgbtn` external functions definitions */ extern int lvbe_imgbtn_create(bvm *vm); extern int lvbe_imgbtn_set_src(bvm *vm); +extern int lvbe_imgbtn_set_state(bvm *vm); /* `lv_led` external functions definitions */ extern int lvbe_led_create(bvm *vm); @@ -579,9 +647,12 @@ extern int lvbe_msgbox_create(bvm *vm); extern int lvbe_msgbox_get_title(bvm *vm); extern int lvbe_msgbox_get_close_btn(bvm *vm); extern int lvbe_msgbox_get_text(bvm *vm); +extern int lvbe_msgbox_get_content(bvm *vm); extern int lvbe_msgbox_get_btns(bvm *vm); +extern int lvbe_msgbox_get_active_btn(bvm *vm); extern int lvbe_msgbox_get_active_btn_text(bvm *vm); extern int lvbe_msgbox_close(bvm *vm); +extern int lvbe_msgbox_close_async(bvm *vm); /* `lv_spinbox` external functions definitions */ extern int lvbe_spinbox_create(bvm *vm); @@ -590,6 +661,8 @@ extern int lvbe_spinbox_set_rollover(bvm *vm); extern int lvbe_spinbox_set_digit_format(bvm *vm); extern int lvbe_spinbox_set_step(bvm *vm); extern int lvbe_spinbox_set_range(bvm *vm); +extern int lvbe_spinbox_set_pos(bvm *vm); +extern int lvbe_spinbox_set_digit_step_direction(bvm *vm); extern int lvbe_spinbox_get_rollover(bvm *vm); extern int lvbe_spinbox_get_value(bvm *vm); extern int lvbe_spinbox_get_step(bvm *vm); @@ -649,6 +722,7 @@ extern int lvbe_btnmatrix_set_btn_ctrl_all(bvm *vm); extern int lvbe_btnmatrix_clear_btn_ctrl_all(bvm *vm); extern int lvbe_btnmatrix_set_btn_width(bvm *vm); extern int lvbe_btnmatrix_set_one_checked(bvm *vm); +extern int lvbe_btnmatrix_get_map(bvm *vm); extern int lvbe_btnmatrix_get_selected_btn(bvm *vm); extern int lvbe_btnmatrix_get_btn_text(bvm *vm); extern int lvbe_btnmatrix_has_btn_ctrl(bvm *vm); @@ -657,9 +731,12 @@ extern int lvbe_btnmatrix_get_one_checked(bvm *vm); /* `lv_canvas` external functions definitions */ extern int lvbe_canvas_create(bvm *vm); extern int lvbe_canvas_set_buffer(bvm *vm); +extern int lvbe_canvas_set_px_color(bvm *vm); extern int lvbe_canvas_set_px(bvm *vm); +extern int lvbe_canvas_set_px_opa(bvm *vm); extern int lvbe_canvas_set_palette(bvm *vm); extern int lvbe_canvas_get_px(bvm *vm); +extern int lvbe_canvas_get_img(bvm *vm); extern int lvbe_canvas_copy_buf(bvm *vm); extern int lvbe_canvas_transform(bvm *vm); extern int lvbe_canvas_blur_hor(bvm *vm); @@ -878,10 +955,10 @@ be_local_class(lv_style, NULL, be_nested_map(4, ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("init", 380752755, 4, -1), be_const_func(lvs_init) }, - { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lvs_tostring) }, + { be_nested_key("init", 380752755, 4, -1), be_const_func(lv_be_style_init) }, + { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lv_x_tostring) }, { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, - { be_nested_key("member", 719708611, 6, 0), be_const_func(lvx_member) }, + { be_nested_key("member", 719708611, 6, 0), be_const_func(lv_x_member) }, })), (be_nested_const_str("lv_style", -143355747, 8)) ); @@ -895,8 +972,8 @@ be_local_class(lv_obj, NULL, be_nested_map(5, ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("tostring", -1995258651, 8, 3), be_const_func(lvx_tostring) }, - { be_nested_key("member", 719708611, 6, -1), be_const_func(lvx_member) }, + { be_nested_key("tostring", -1995258651, 8, 3), be_const_func(lv_x_tostring) }, + { be_nested_key("member", 719708611, 6, -1), be_const_func(lv_x_member) }, { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, { be_nested_key("init", 380752755, 4, 4), be_const_func(be_ntv_lv_obj_init) }, { be_nested_key("_class", -1562820946, 6, -1), be_const_comptr(&lv_obj_class) }, @@ -914,9 +991,9 @@ be_local_class(lv_group, be_nested_map(4, ( (struct bmapnode*) &(const bmapnode[]) { { be_nested_key("init", 380752755, 4, -1), be_const_func(be_ntv_lv_group_init) }, - { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lvx_tostring) }, + { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lv_x_tostring) }, { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, - { be_nested_key("member", 719708611, 6, 0), be_const_func(lvx_member) }, + { be_nested_key("member", 719708611, 6, 0), be_const_func(lv_x_member) }, })), (be_nested_const_str("lv_group", -442928277, 8)) ); @@ -931,9 +1008,9 @@ be_local_class(lv_indev, be_nested_map(4, ( (struct bmapnode*) &(const bmapnode[]) { { be_nested_key("init", 380752755, 4, -1), be_const_func(lv0_init) }, - { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lvx_tostring) }, + { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lv_x_tostring) }, { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, - { be_nested_key("member", 719708611, 6, 0), be_const_func(lvx_member) }, + { be_nested_key("member", 719708611, 6, 0), be_const_func(lv_x_member) }, })), (be_nested_const_str("lv_indev", 225602374, 8)) ); @@ -948,9 +1025,9 @@ be_local_class(lv_disp, be_nested_map(4, ( (struct bmapnode*) &(const bmapnode[]) { { be_nested_key("init", 380752755, 4, -1), be_const_func(lv0_init) }, - { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lvx_tostring) }, + { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lv_x_tostring) }, { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, - { be_nested_key("member", 719708611, 6, 0), be_const_func(lvx_member) }, + { be_nested_key("member", 719708611, 6, 0), be_const_func(lv_x_member) }, })), (be_nested_const_str("lv_disp", 609712084, 8)) ); @@ -965,7 +1042,7 @@ be_local_class(lv_font, be_nested_map(3, ( (struct bmapnode*) &(const bmapnode[]) { { be_nested_key("init", 380752755, 4, -1), be_const_func(lvbe_font_create) }, - { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lvx_tostring) }, + { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lv_x_tostring) }, { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, })), (be_nested_const_str("lv_font", 1550958453, 7)) @@ -981,7 +1058,7 @@ be_local_class(lv_theme, be_nested_map(3, ( (struct bmapnode*) &(const bmapnode[]) { { be_nested_key("init", 380752755, 4, -1), be_const_func(lvbe_theme_create) }, - { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lvx_tostring) }, + { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lv_x_tostring) }, { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, })), (be_nested_const_str("lv_theme", 1550958453, 7)) @@ -1559,6 +1636,3 @@ void be_load_lv_textarea_class(bvm *vm) { be_pop(vm, 1); } - -#endif // USE_LVGL - diff --git a/lib/libesp32_lvgl/lv_berry/library.json b/lib/libesp32_lvgl/lv_berry/library.json new file mode 100644 index 000000000..7074359ab --- /dev/null +++ b/lib/libesp32_lvgl/lv_berry/library.json @@ -0,0 +1,25 @@ +{ + "name": "Berry mapping to LVGL", + "version": "1.0", + "description": "Mapping of LVGL functions to Berry. Currently supporting LVGL 8.0.2", + "license": "MIT", + "homepage": "https://github.com/lvgl/lv_berry", + "frameworks": "arduino", + "platforms": "espressif32", + "authors": + { + "name": "Stephan Hadinger", + "maintainer": true + }, + "build": { + "srcFilter": [ + "+<*.c>", + "+<../generate/*.c>", + "+<../generate/*.cpp>", + "+<../generate/*.hpp>", + "+<*.cpp>", + "+<*.h>" + ], + "flags": [ "-I$PROJECT_DIR/include", "-includetasmota_options.h" ] + } + } \ No newline at end of file diff --git a/tools/lv_berry/lv_enum.h b/lib/libesp32_lvgl/lv_berry/mapping/lv_enum.h similarity index 70% rename from tools/lv_berry/lv_enum.h rename to lib/libesp32_lvgl/lv_berry/mapping/lv_enum.h index 85df942f5..2e3a56461 100644 --- a/tools/lv_berry/lv_enum.h +++ b/lib/libesp32_lvgl/lv_berry/mapping/lv_enum.h @@ -2,17 +2,7 @@ // Functions // ====================================================================== -register_button_encoder=&lv0_register_button_encoder - -montserrat_font=&lv0_load_montserrat_font -seg7_font=&lv0_load_seg7_font -font_montserrat=&lv0_load_montserrat_font -font_seg7=&lv0_load_seg7_font -font_robotocondensed_latin1=&lv0_load_robotocondensed_latin1_font load_font=&lv0_load_font -load_freetype_font=&lv0_load_freetype_font - -screenshot=&lv0_screenshot // ====================================================================== // Colors @@ -37,6 +27,11 @@ COLOR_NAVY=0x000080 COLOR_MAGENTA=0xFF00FF COLOR_PURPLE=0x800080 +// Freetype +FT_FONT_STYLE_NORMAL=FT_FONT_STYLE_NORMAL +FT_FONT_STYLE_ITALIC=FT_FONT_STYLE_ITALIC +FT_FONT_STYLE_BOLD=FT_FONT_STYLE_BOLD + // following are #define, not enum LV_RADIUS_CIRCLE LV_TEXTAREA_CURSOR_LAST @@ -44,6 +39,12 @@ LV_STYLE_PROP_ANY LV_SIZE_CONTENT +LV_GRID_FR=LV_GRID_FR(0) +LV_GRID_CONTENT +LV_GRID_TEMPLATE_LAST + +LV_OBJ_FLAG_FLEX_IN_NEW_TRACK + // ====================================================================== // Symbols // ====================================================================== @@ -114,6 +115,7 @@ SYMBOL_BULLET="\xE2\x80\xA2" // Generated from headers // ====================================================================== +// File: ../../lvgl/src/core/lv_disp.h LV_SCR_LOAD_ANIM_NONE LV_SCR_LOAD_ANIM_OVER_LEFT LV_SCR_LOAD_ANIM_OVER_RIGHT @@ -125,6 +127,7 @@ LV_SCR_LOAD_ANIM_MOVE_TOP LV_SCR_LOAD_ANIM_MOVE_BOTTOM LV_SCR_LOAD_ANIM_FADE_ON +// File: ../../lvgl/src/core/lv_event.h LV_EVENT_ALL LV_EVENT_PRESSED LV_EVENT_PRESSING @@ -160,10 +163,17 @@ LV_EVENT_READY LV_EVENT_CANCEL LV_EVENT_DELETE LV_EVENT_CHILD_CHANGED +LV_EVENT_CHILD_CREATED +LV_EVENT_CHILD_DELETED +LV_EVENT_SCREEN_UNLOAD_START +LV_EVENT_SCREEN_LOAD_START +LV_EVENT_SCREEN_LOADED +LV_EVENT_SCREEN_UNLOADED LV_EVENT_SIZE_CHANGED LV_EVENT_STYLE_CHANGED LV_EVENT_LAYOUT_CHANGED LV_EVENT_GET_SELF_SIZE +// File: ../../lvgl/src/core/lv_group.h LV_KEY_UP LV_KEY_DOWN LV_KEY_RIGHT @@ -179,6 +189,9 @@ LV_KEY_END LV_GROUP_REFOCUS_POLICY_NEXT LV_GROUP_REFOCUS_POLICY_PREV +// File: ../../lvgl/src/core/lv_indev.h +// File: ../../lvgl/src/core/lv_indev_scroll.h +// File: ../../lvgl/src/core/lv_obj.h LV_STATE_DEFAULT LV_STATE_CHECKED LV_STATE_FOCUSED @@ -215,7 +228,7 @@ LV_OBJ_FLAG_SCROLL_MOMENTUM LV_OBJ_FLAG_SCROLL_ONE LV_OBJ_FLAG_SCROLL_CHAIN LV_OBJ_FLAG_SCROLL_ON_FOCUS -LV_OBJ_FLAG_SNAPABLE +LV_OBJ_FLAG_SNAPPABLE LV_OBJ_FLAG_PRESS_LOCK LV_OBJ_FLAG_EVENT_BUBBLE LV_OBJ_FLAG_GESTURE_BUBBLE @@ -231,6 +244,11 @@ LV_OBJ_FLAG_USER_2 LV_OBJ_FLAG_USER_3 LV_OBJ_FLAG_USER_4 +LV_OBJ_DRAW_PART_RECTANGLE +LV_OBJ_DRAW_PART_BORDER_POST +LV_OBJ_DRAW_PART_SCROLLBAR + +// File: ../../lvgl/src/core/lv_obj_class.h LV_OBJ_CLASS_EDITABLE_INHERIT LV_OBJ_CLASS_EDITABLE_TRUE LV_OBJ_CLASS_EDITABLE_FALSE @@ -239,10 +257,13 @@ LV_OBJ_CLASS_GROUP_DEF_INHERIT LV_OBJ_CLASS_GROUP_DEF_TRUE LV_OBJ_CLASS_GROUP_DEF_FALSE +// File: ../../lvgl/src/core/lv_obj_draw.h LV_COVER_RES_COVER LV_COVER_RES_NOT_COVER LV_COVER_RES_MASKED +// File: ../../lvgl/src/core/lv_obj_pos.h +// File: ../../lvgl/src/core/lv_obj_scroll.h LV_SCROLLBAR_MODE_OFF LV_SCROLLBAR_MODE_ON LV_SCROLLBAR_MODE_ACTIVE @@ -252,11 +273,23 @@ LV_SCROLL_SNAP_NONE LV_SCROLL_SNAP_START LV_SCROLL_SNAP_END LV_SCROLL_SNAP_CENTER +// File: ../../lvgl/src/core/lv_obj_style.h +// File: ../../lvgl/src/core/lv_obj_style_gen.h +// File: ../../lvgl/src/core/lv_obj_tree.h LV_OBJ_TREE_WALK_NEXT LV_OBJ_TREE_WALK_SKIP_CHILDREN LV_OBJ_TREE_WALK_END +// File: ../../lvgl/src/core/lv_refr.h +// File: ../../lvgl/src/core/lv_theme.h +// File: ../../lvgl/src/draw/lv_draw.h +// File: ../../lvgl/src/draw/lv_draw_arc.h +// File: ../../lvgl/src/draw/lv_draw_blend.h +// File: ../../lvgl/src/draw/lv_draw_img.h +// File: ../../lvgl/src/draw/lv_draw_label.h +// File: ../../lvgl/src/draw/lv_draw_line.h +// File: ../../lvgl/src/draw/lv_draw_mask.h LV_DRAW_MASK_RES_TRANSP LV_DRAW_MASK_RES_FULL_COVER LV_DRAW_MASK_RES_CHANGED @@ -272,6 +305,9 @@ LV_DRAW_MASK_LINE_SIDE_RIGHT LV_DRAW_MASK_LINE_SIDE_TOP LV_DRAW_MASK_LINE_SIDE_BOTTOM +// File: ../../lvgl/src/draw/lv_draw_rect.h +// File: ../../lvgl/src/draw/lv_draw_triangle.h +// File: ../../lvgl/src/draw/lv_img_buf.h LV_IMG_CF_UNKNOWN LV_IMG_CF_RAW LV_IMG_CF_RAW_ALPHA @@ -288,11 +324,14 @@ LV_IMG_CF_ALPHA_2BIT LV_IMG_CF_ALPHA_4BIT LV_IMG_CF_ALPHA_8BIT +// File: ../../lvgl/src/draw/lv_img_cache.h +// File: ../../lvgl/src/draw/lv_img_decoder.h LV_IMG_SRC_VARIABLE LV_IMG_SRC_FILE LV_IMG_SRC_SYMBOL LV_IMG_SRC_UNKNOWN +// File: ../../lvgl/src/extra/layouts/flex/lv_flex.h LV_FLEX_ALIGN_START LV_FLEX_ALIGN_END LV_FLEX_ALIGN_CENTER @@ -309,6 +348,7 @@ LV_FLEX_FLOW_COLUMN_WRAP LV_FLEX_FLOW_COLUMN_REVERSE LV_FLEX_FLOW_COLUMN_WRAP_REVERSE +// File: ../../lvgl/src/extra/layouts/grid/lv_grid.h LV_GRID_ALIGN_START LV_GRID_ALIGN_CENTER LV_GRID_ALIGN_END @@ -317,8 +357,14 @@ LV_GRID_ALIGN_SPACE_EVENLY LV_GRID_ALIGN_SPACE_AROUND LV_GRID_ALIGN_SPACE_BETWEEN +// File: ../../lvgl/src/extra/layouts/lv_layouts.h +// File: ../../lvgl/src/extra/widgets/animimg/lv_animimg.h LV_ANIM_IMG_PART_MAIN +// File: ../../lvgl/src/extra/widgets/calendar/lv_calendar.h +// File: ../../lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.h +// File: ../../lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.h +// File: ../../lvgl/src/extra/widgets/chart/lv_chart.h LV_CHART_TYPE_NONE LV_CHART_TYPE_LINE LV_CHART_TYPE_BAR @@ -331,9 +377,19 @@ LV_CHART_AXIS_PRIMARY_Y LV_CHART_AXIS_SECONDARY_Y LV_CHART_AXIS_PRIMARY_X LV_CHART_AXIS_SECONDARY_X +LV_CHART_DRAW_PART_DIV_LINE_INIT +LV_CHART_DRAW_PART_DIV_LINE_HOR +LV_CHART_DRAW_PART_DIV_LINE_VER +LV_CHART_DRAW_PART_LINE_AND_POINT +LV_CHART_DRAW_PART_BAR +LV_CHART_DRAW_PART_CURSOR +LV_CHART_DRAW_PART_TICK_LABEL + +// File: ../../lvgl/src/extra/widgets/colorwheel/lv_colorwheel.h LV_COLORWHEEL_MODE_HUE LV_COLORWHEEL_MODE_SATURATION LV_COLORWHEEL_MODE_VALUE +// File: ../../lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h LV_IMGBTN_STATE_RELEASED LV_IMGBTN_STATE_PRESSED LV_IMGBTN_STATE_DISABLED @@ -341,12 +397,26 @@ LV_IMGBTN_STATE_CHECKED_RELEASED LV_IMGBTN_STATE_CHECKED_PRESSED LV_IMGBTN_STATE_CHECKED_DISABLED +// File: ../../lvgl/src/extra/widgets/keyboard/lv_keyboard.h +// File: ../../lvgl/src/extra/widgets/led/lv_led.h +LV_LED_DRAW_PART_RECTANGLE + +// File: ../../lvgl/src/extra/widgets/list/lv_list.h +// File: ../../lvgl/src/extra/widgets/lv_widgets.h +// File: ../../lvgl/src/extra/widgets/meter/lv_meter.h LV_METER_INDICATOR_TYPE_NEEDLE_IMG LV_METER_INDICATOR_TYPE_NEEDLE_LINE LV_METER_INDICATOR_TYPE_SCALE_LINES LV_METER_INDICATOR_TYPE_ARC +LV_METER_DRAW_PART_ARC +LV_METER_DRAW_PART_NEEDLE_LINE +LV_METER_DRAW_PART_NEEDLE_IMG +LV_METER_DRAW_PART_TICK + +// File: ../../lvgl/src/extra/widgets/msgbox/lv_msgbox.h +// File: ../../lvgl/src/extra/widgets/span/lv_span.h LV_SPAN_OVERFLOW_CLIP LV_SPAN_OVERFLOW_ELLIPSIS @@ -354,14 +424,18 @@ LV_SPAN_MODE_FIXED LV_SPAN_MODE_EXPAND LV_SPAN_MODE_BREAK - - - - +// File: ../../lvgl/src/extra/widgets/spinbox/lv_spinbox.h +// File: ../../lvgl/src/extra/widgets/spinner/lv_spinner.h +// File: ../../lvgl/src/extra/widgets/tabview/lv_tabview.h +// File: ../../lvgl/src/extra/widgets/tileview/lv_tileview.h +// File: ../../lvgl/src/extra/widgets/win/lv_win.h +// File: ../../lvgl/src/hal/lv_hal.h +// File: ../../lvgl/src/hal/lv_hal_disp.h LV_DISP_ROT_NONE LV_DISP_ROT_90 LV_DISP_ROT_180 LV_DISP_ROT_270 +// File: ../../lvgl/src/hal/lv_hal_indev.h LV_INDEV_TYPE_NONE LV_INDEV_TYPE_POINTER LV_INDEV_TYPE_KEYPAD @@ -370,9 +444,13 @@ LV_INDEV_TYPE_ENCODER LV_INDEV_STATE_RELEASED LV_INDEV_STATE_PRESSED +// File: ../../lvgl/src/hal/lv_hal_tick.h +// File: ../../lvgl/src/misc/lv_anim.h LV_ANIM_OFF LV_ANIM_ON +// File: ../../lvgl/src/misc/lv_anim_timeline.h +// File: ../../lvgl/src/misc/lv_area.h LV_ALIGN_DEFAULT LV_ALIGN_TOP_LEFT LV_ALIGN_TOP_MID @@ -405,12 +483,16 @@ LV_DIR_HOR LV_DIR_VER LV_DIR_ALL +// File: ../../lvgl/src/misc/lv_assert.h +// File: ../../lvgl/src/misc/lv_async.h +// File: ../../lvgl/src/misc/lv_bidi.h LV_BASE_DIR_LTR LV_BASE_DIR_RTL LV_BASE_DIR_AUTO LV_BASE_DIR_NEUTRAL LV_BASE_DIR_WEAK +// File: ../../lvgl/src/misc/lv_color.h LV_OPA_TRANSP LV_OPA_0 LV_OPA_10 @@ -446,6 +528,7 @@ LV_PALETTE_BLUE_GREY LV_PALETTE_GREY LV_PALETTE_NONE +// File: ../../lvgl/src/misc/lv_fs.h LV_FS_RES_OK LV_FS_RES_HW_ERR LV_FS_RES_FS_ERR @@ -467,9 +550,17 @@ LV_FS_SEEK_SET LV_FS_SEEK_CUR LV_FS_SEEK_END +// File: ../../lvgl/src/misc/lv_gc.h +// File: ../../lvgl/src/misc/lv_ll.h +// File: ../../lvgl/src/misc/lv_log.h +// File: ../../lvgl/src/misc/lv_math.h +// File: ../../lvgl/src/misc/lv_mem.h +// File: ../../lvgl/src/misc/lv_printf.h +// File: ../../lvgl/src/misc/lv_style.h LV_BLEND_MODE_NORMAL LV_BLEND_MODE_ADDITIVE LV_BLEND_MODE_SUBTRACTIVE +LV_BLEND_MODE_MULTIPLY LV_TEXT_DECOR_NONE LV_TEXT_DECOR_UNDERLINE @@ -578,6 +669,11 @@ LV_STYLE_BLEND_MODE LV_STYLE_LAYOUT LV_STYLE_BASE_DIR LV_STYLE_PROP_ANY +// File: ../../lvgl/src/misc/lv_style_gen.h +// File: ../../lvgl/src/misc/lv_templ.h +// File: ../../lvgl/src/misc/lv_timer.h +// File: ../../lvgl/src/misc/lv_tlsf.h +// File: ../../lvgl/src/misc/lv_txt.h LV_TEXT_FLAG_NONE LV_TEXT_FLAG_RECOLOR LV_TEXT_FLAG_EXPAND @@ -592,37 +688,72 @@ LV_TEXT_ALIGN_LEFT LV_TEXT_ALIGN_CENTER LV_TEXT_ALIGN_RIGHT +// File: ../../lvgl/src/misc/lv_txt_ap.h +// File: ../../lvgl/src/misc/lv_types.h LV_RES_INV LV_RES_OK +// File: ../../lvgl/src/misc/lv_utils.h +// File: ../../lvgl/src/widgets/lv_arc.h LV_ARC_MODE_NORMAL LV_ARC_MODE_SYMMETRICAL LV_ARC_MODE_REVERSE +LV_ARC_DRAW_PART_BACKGROUND +LV_ARC_DRAW_PART_FOREGROUND +LV_ARC_DRAW_PART_KNOB + +// File: ../../lvgl/src/widgets/lv_bar.h LV_BAR_MODE_NORMAL LV_BAR_MODE_SYMMETRICAL LV_BAR_MODE_RANGE +LV_BAR_DRAW_PART_INDICATOR + +// File: ../../lvgl/src/widgets/lv_btn.h +// File: ../../lvgl/src/widgets/lv_btnmatrix.h LV_BTNMATRIX_CTRL_HIDDEN LV_BTNMATRIX_CTRL_NO_REPEAT LV_BTNMATRIX_CTRL_DISABLED LV_BTNMATRIX_CTRL_CHECKABLE LV_BTNMATRIX_CTRL_CHECKED LV_BTNMATRIX_CTRL_CLICK_TRIG +LV_BTNMATRIX_CTRL_POPOVER LV_BTNMATRIX_CTRL_RECOLOR LV_BTNMATRIX_CTRL_CUSTOM_1 LV_BTNMATRIX_CTRL_CUSTOM_2 +LV_BTNMATRIX_DRAW_PART_BTN + +// File: ../../lvgl/src/widgets/lv_canvas.h +// File: ../../lvgl/src/widgets/lv_checkbox.h +LV_CHECKBOX_DRAW_PART_BOX + +// File: ../../lvgl/src/widgets/lv_dropdown.h +// File: ../../lvgl/src/widgets/lv_img.h +LV_IMG_SIZE_MODE_VIRTUAL +LV_IMG_SIZE_MODE_REAL + +// File: ../../lvgl/src/widgets/lv_label.h LV_LABEL_LONG_WRAP LV_LABEL_LONG_DOT LV_LABEL_LONG_SCROLL LV_LABEL_LONG_SCROLL_CIRCULAR LV_LABEL_LONG_CLIP +// File: ../../lvgl/src/widgets/lv_line.h +// File: ../../lvgl/src/widgets/lv_objx_templ.h +// File: ../../lvgl/src/widgets/lv_roller.h LV_ROLLER_MODE_NORMAL LV_ROLLER_MODE_INFINITE +// File: ../../lvgl/src/widgets/lv_slider.h LV_SLIDER_MODE_NORMAL LV_SLIDER_MODE_SYMMETRICAL LV_SLIDER_MODE_RANGE +LV_SLIDER_DRAW_PART_KNOB +LV_SLIDER_DRAW_PART_KNOB_LEFT + +// File: ../../lvgl/src/widgets/lv_switch.h +// File: ../../lvgl/src/widgets/lv_table.h LV_TABLE_CELL_CTRL_MERGE_RIGHT LV_TABLE_CELL_CTRL_TEXT_CROP LV_TABLE_CELL_CTRL_CUSTOM_1 @@ -630,5 +761,8 @@ LV_TABLE_CELL_CTRL_CUSTOM_2 LV_TABLE_CELL_CTRL_CUSTOM_3 LV_TABLE_CELL_CTRL_CUSTOM_4 +LV_TABLE_DRAW_PART_CELL + +// File: ../../lvgl/src/widgets/lv_textarea.h LV_PART_TEXTAREA_PLACEHOLDER diff --git a/tools/lv_berry/lv_funcs.h b/lib/libesp32_lvgl/lv_berry/mapping/lv_funcs.h similarity index 83% rename from tools/lv_berry/lv_funcs.h rename to lib/libesp32_lvgl/lv_berry/mapping/lv_funcs.h index 31367d8bf..6f38c63ee 100644 --- a/tools/lv_berry/lv_funcs.h +++ b/lib/libesp32_lvgl/lv_berry/mapping/lv_funcs.h @@ -4,6 +4,7 @@ // Custom Tasmota functions void lv_img_set_tasmota_logo(lv_obj_t * img); +lv_ts_calibration_t * lv_get_ts_calibration(void); // ====================================================================== // Artificial @@ -28,7 +29,7 @@ lv_coord_t lv_get_ver_res(void); // ====================================================================== -// ../../lib/libesp32_lvgl/LVGL8/src/core/lv_disp.h +// ../../lvgl/src/core/lv_disp.h lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp) lv_obj_t * lv_disp_get_scr_prev(lv_disp_t * disp) void lv_disp_load_scr(lv_obj_t * scr) @@ -50,22 +51,24 @@ static inline void lv_scr_load(lv_obj_t * scr) static inline lv_coord_t lv_dpx(lv_coord_t n) static inline lv_coord_t lv_disp_dpx(const lv_disp_t * disp, lv_coord_t n) -// ../../lib/libesp32_lvgl/LVGL8/src/core/lv_event.h +// ../../lvgl/src/core/lv_event.h lv_res_t lv_event_send(struct _lv_obj_t * obj, lv_event_code_t event_code, void * param) lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e) uint32_t lv_event_register_id(void) struct _lv_event_dsc_t * lv_obj_add_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data) bool lv_obj_remove_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb) +bool lv_obj_remove_event_cb_with_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb, const void * event_user_data) bool lv_obj_remove_event_dsc(struct _lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc) void lv_event_set_ext_draw_size(lv_event_t * e, lv_coord_t size) void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res) -// ../../lib/libesp32_lvgl/LVGL8/src/core/lv_group.h +// ../../lvgl/src/core/lv_group.h lv_group_t * lv_group_create(void) void lv_group_del(lv_group_t * group) void lv_group_set_default(lv_group_t * group) lv_group_t * lv_group_get_default(void) void lv_group_add_obj(lv_group_t * group, struct _lv_obj_t * obj) +void lv_group_swap_obj(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2) void lv_group_remove_obj(struct _lv_obj_t * obj) void lv_group_remove_all_objs(lv_group_t * group) void lv_group_focus_obj(struct _lv_obj_t * obj) @@ -83,7 +86,7 @@ bool lv_group_get_editing(const lv_group_t * group) bool lv_group_get_wrap(lv_group_t * group) uint32_t lv_group_get_obj_count(lv_group_t * group) -// ../../lib/libesp32_lvgl/LVGL8/src/core/lv_indev.h +// ../../lvgl/src/core/lv_indev.h void lv_indev_read_timer_cb(lv_timer_t * timer) void lv_indev_enable(lv_indev_t * indev, bool en) lv_indev_t * lv_indev_get_act(void) @@ -104,9 +107,10 @@ lv_obj_t * lv_indev_get_obj_act(void) lv_timer_t * lv_indev_get_read_timer(lv_disp_t * indev) lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point) -// ../../lib/libesp32_lvgl/LVGL8/src/core/lv_indev_scroll.h +// ../../lvgl/src/core/lv_indev_scroll.h -// ../../lib/libesp32_lvgl/LVGL8/src/core/lv_obj.h +// ../../lvgl/src/core/lv_obj.h +bool lv_is_initialized(void) lv_obj_t * lv_obj_create(lv_obj_t * parent) void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f) void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f) @@ -126,13 +130,13 @@ const lv_obj_class_t * lv_obj_get_class(const lv_obj_t * obj) bool lv_obj_is_valid(const lv_obj_t * obj) static inline lv_coord_t lv_obj_dpx(const lv_obj_t * obj, lv_coord_t n) -// ../../lib/libesp32_lvgl/LVGL8/src/core/lv_obj_class.h +// ../../lvgl/src/core/lv_obj_class.h struct _lv_obj_t * lv_obj_class_create_obj(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * parent) void lv_obj_class_init_obj(struct _lv_obj_t * obj) bool lv_obj_is_editable(struct _lv_obj_t * obj) bool lv_obj_is_group_def(struct _lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/core/lv_obj_draw.h +// ../../lvgl/src/core/lv_obj_draw.h void lv_obj_init_draw_rect_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t * draw_dsc) void lv_obj_init_draw_label_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc) void lv_obj_init_draw_img_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc) @@ -140,9 +144,10 @@ void lv_obj_init_draw_line_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_li void lv_obj_init_draw_arc_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc) lv_coord_t lv_obj_calculate_ext_draw_size(struct _lv_obj_t * obj, uint32_t part) void lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc, const lv_area_t * clip_area) +bool lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc, const struct _lv_obj_class_t * class_p, uint32_t type) void lv_obj_refresh_ext_draw_size(struct _lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/core/lv_obj_pos.h +// ../../lvgl/src/core/lv_obj_pos.h void lv_obj_set_pos(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y) void lv_obj_set_x(struct _lv_obj_t * obj, lv_coord_t x) void lv_obj_set_y(struct _lv_obj_t * obj, lv_coord_t y) @@ -187,7 +192,7 @@ bool lv_obj_hit_test(struct _lv_obj_t * obj, const lv_point_t * point) lv_coord_t lv_clamp_width(lv_coord_t width, lv_coord_t min_width, lv_coord_t max_width, lv_coord_t ref_width) lv_coord_t lv_clamp_height(lv_coord_t height, lv_coord_t min_height, lv_coord_t max_height, lv_coord_t ref_height) -// ../../lib/libesp32_lvgl/LVGL8/src/core/lv_obj_scroll.h +// ../../lvgl/src/core/lv_obj_scroll.h void lv_obj_set_scrollbar_mode(struct _lv_obj_t * obj, lv_scrollbar_mode_t mode) void lv_obj_set_scroll_dir(struct _lv_obj_t * obj, lv_dir_t dir) void lv_obj_set_scroll_snap_x(struct _lv_obj_t * obj, lv_scroll_snap_t align) @@ -215,7 +220,7 @@ void lv_obj_get_scrollbar_area(struct _lv_obj_t * obj, lv_area_t * hor, lv_area_ void lv_obj_scrollbar_invalidate(struct _lv_obj_t * obj) void lv_obj_readjust_scroll(struct _lv_obj_t * obj, lv_anim_enable_t anim_en) -// ../../lib/libesp32_lvgl/LVGL8/src/core/lv_obj_style.h +// ../../lvgl/src/core/lv_obj_style.h void lv_obj_add_style(struct _lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector) void lv_obj_remove_style(struct _lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector) static inline void lv_obj_remove_style_all(struct _lv_obj_t * obj) @@ -235,8 +240,11 @@ static inline void lv_obj_set_style_pad_hor(struct _lv_obj_t * obj, lv_coord_t v static inline void lv_obj_set_style_pad_ver(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) static inline void lv_obj_set_style_pad_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) static inline void lv_obj_set_style_size(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +lv_text_align_t lv_obj_calculate_style_text_align(const struct _lv_obj_t * obj, lv_part_t part, const char * txt) +static inline lv_coord_t lv_obj_get_x_aligned(const struct _lv_obj_t * obj) +static inline lv_coord_t lv_obj_get_y_aligned(const struct _lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/core/lv_obj_style_gen.h +// ../../lvgl/src/core/lv_obj_style_gen.h static inline lv_coord_t lv_obj_get_style_width(const struct _lv_obj_t * obj, uint32_t part) static inline lv_coord_t lv_obj_get_style_min_width(const struct _lv_obj_t * obj, uint32_t part) static inline lv_coord_t lv_obj_get_style_max_width(const struct _lv_obj_t * obj, uint32_t part) @@ -316,12 +324,12 @@ static inline lv_opa_t lv_obj_get_style_shadow_opa(const struct _lv_obj_t * obj, static inline lv_coord_t lv_obj_get_style_line_width(const struct _lv_obj_t * obj, uint32_t part) static inline lv_coord_t lv_obj_get_style_line_dash_width(const struct _lv_obj_t * obj, uint32_t part) static inline lv_coord_t lv_obj_get_style_line_dash_gap(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_line_rounded(const struct _lv_obj_t * obj, uint32_t part) +static inline bool lv_obj_get_style_line_rounded(const struct _lv_obj_t * obj, uint32_t part) static inline lv_color_t lv_obj_get_style_line_color(const struct _lv_obj_t * obj, uint32_t part) static inline lv_color_t lv_obj_get_style_line_color_filtered(const struct _lv_obj_t * obj, uint32_t part) static inline lv_opa_t lv_obj_get_style_line_opa(const struct _lv_obj_t * obj, uint32_t part) static inline lv_coord_t lv_obj_get_style_arc_width(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_arc_rounded(const struct _lv_obj_t * obj, uint32_t part) +static inline bool lv_obj_get_style_arc_rounded(const struct _lv_obj_t * obj, uint32_t part) static inline lv_color_t lv_obj_get_style_arc_color(const struct _lv_obj_t * obj, uint32_t part) static inline lv_color_t lv_obj_get_style_arc_color_filtered(const struct _lv_obj_t * obj, uint32_t part) static inline lv_opa_t lv_obj_get_style_arc_opa(const struct _lv_obj_t * obj, uint32_t part) @@ -405,37 +413,38 @@ void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_styl void lv_obj_set_style_line_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_line_dash_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) void lv_obj_set_style_line_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) void lv_obj_set_style_line_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) void lv_obj_set_style_arc_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) void lv_obj_set_style_arc_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) void lv_obj_set_style_arc_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector) -// ../../lib/libesp32_lvgl/LVGL8/src/core/lv_obj_tree.h +// ../../lvgl/src/core/lv_obj_tree.h void lv_obj_del(struct _lv_obj_t * obj) void lv_obj_clean(struct _lv_obj_t * obj) +void lv_obj_del_delayed(struct _lv_obj_t * obj, uint32_t delay_ms) void lv_obj_del_anim_ready_cb(lv_anim_t * a) void lv_obj_del_async(struct _lv_obj_t * obj) void lv_obj_set_parent(struct _lv_obj_t * obj, struct _lv_obj_t * parent) -void lv_obj_move_foreground(struct _lv_obj_t * obj) -void lv_obj_move_background(struct _lv_obj_t * obj) +void lv_obj_swap(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2) +void lv_obj_move_to_index(struct _lv_obj_t * obj, int32_t index) struct _lv_obj_t * lv_obj_get_screen(const struct _lv_obj_t * obj) lv_disp_t * lv_obj_get_disp(const struct _lv_obj_t * obj) struct _lv_obj_t * lv_obj_get_parent(const struct _lv_obj_t * obj) struct _lv_obj_t * lv_obj_get_child(const struct _lv_obj_t * obj, int32_t id) uint32_t lv_obj_get_child_cnt(const struct _lv_obj_t * obj) -uint32_t lv_obj_get_child_id(const struct _lv_obj_t * obj) +uint32_t lv_obj_get_index(const struct _lv_obj_t * obj) void lv_obj_tree_walk(struct _lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data) -// ../../lib/libesp32_lvgl/LVGL8/src/core/lv_refr.h +// ../../lvgl/src/core/lv_refr.h void lv_refr_now(lv_disp_t * disp) -// ../../lib/libesp32_lvgl/LVGL8/src/core/lv_theme.h +// ../../lvgl/src/core/lv_theme.h lv_theme_t * lv_theme_get_from_obj(lv_obj_t * obj) void lv_theme_apply(lv_obj_t * obj) void lv_theme_set_parent(lv_theme_t * new_theme, lv_theme_t * parent) @@ -446,36 +455,40 @@ const lv_font_t * lv_theme_get_font_large(lv_obj_t * obj) lv_color_t lv_theme_get_color_primary(lv_obj_t * obj) lv_color_t lv_theme_get_color_secondary(lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/draw/lv_draw.h +// ../../lvgl/src/draw/lv_draw.h -// ../../lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_arc.h +// ../../lvgl/src/draw/lv_draw_arc.h void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc) void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uint16_t start_angle, uint16_t end_angle, const lv_area_t * clip_area, const lv_draw_arc_dsc_t * dsc) void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle, lv_coord_t w, bool rounded, lv_area_t * area) -// ../../lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_blend.h +// ../../lvgl/src/draw/lv_draw_blend.h -// ../../lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_img.h +// ../../lvgl/src/draw/lv_draw_img.h void lv_draw_img_dsc_init(lv_draw_img_dsc_t * dsc) void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * src, const lv_draw_img_dsc_t * dsc) lv_img_src_t lv_img_src_get_type(const void * src) -// ../../lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_label.h +// ../../lvgl/src/draw/lv_draw_label.h void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc) void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_draw_label_dsc_t * dsc, const char * txt, lv_draw_label_hint_t * hint) void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * clip_area, const lv_font_t * font_p, uint32_t letter, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode) -// ../../lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_line.h +// ../../lvgl/src/draw/lv_draw_line.h void lv_draw_line(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, const lv_draw_line_dsc_t * dsc) void lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc) -// ../../lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_mask.h +// ../../lvgl/src/draw/lv_draw_mask.h static inline uint8_t lv_draw_mask_get_cnt(void) +static inline bool lv_draw_mask_is_any(const lv_area_t * a) int16_t lv_draw_mask_add(void * param, void * custom_id) lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len) +lv_draw_mask_res_t lv_draw_mask_apply_ids(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, const int16_t *ids, int16_t ids_count) void * lv_draw_mask_remove_id(int16_t id) void * lv_draw_mask_remove_custom(void * custom_id) +void lv_draw_mask_free_param(void * p) uint8_t lv_draw_mask_get_cnt(void) +bool lv_draw_mask_is_any(const lv_area_t * a) void lv_draw_mask_line_points_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x, lv_coord_t p2y, lv_draw_mask_line_side_t side) void lv_draw_mask_line_angle_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t py, int16_t angle, lv_draw_mask_line_side_t side) void lv_draw_mask_angle_init(lv_draw_mask_angle_param_t * param, lv_coord_t vertex_x, lv_coord_t vertex_y, lv_coord_t start_angle, lv_coord_t end_angle) @@ -483,28 +496,89 @@ void lv_draw_mask_radius_init(lv_draw_mask_radius_param_t * param, const lv_area void lv_draw_mask_fade_init(lv_draw_mask_fade_param_t * param, const lv_area_t * coords, lv_opa_t opa_top, lv_coord_t y_top, lv_opa_t opa_bottom, lv_coord_t y_bottom) void lv_draw_mask_map_init(lv_draw_mask_map_param_t * param, const lv_area_t * coords, const lv_opa_t * map) -// ../../lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_rect.h +// ../../lvgl/src/draw/lv_draw_rect.h void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc) -void lv_draw_rect(const lv_area_t * coords, const lv_area_t * mask, const lv_draw_rect_dsc_t * dsc) +void lv_draw_rect(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc) -// ../../lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_triangle.h +// ../../lvgl/src/draw/lv_draw_triangle.h void lv_draw_triangle(const lv_point_t points[], const lv_area_t * clip, const lv_draw_rect_dsc_t * draw_dsc) void lv_draw_polygon(const lv_point_t points[], uint16_t point_cnt, const lv_area_t * mask, const lv_draw_rect_dsc_t * draw_dsc) -// ../../lib/libesp32_lvgl/LVGL8/src/draw/lv_img_buf.h +// ../../lvgl/src/draw/lv_img_buf.h -// ../../lib/libesp32_lvgl/LVGL8/src/draw/lv_img_cache.h +// ../../lvgl/src/draw/lv_img_cache.h -// ../../lib/libesp32_lvgl/LVGL8/src/draw/lv_img_decoder.h +// ../../lvgl/src/draw/lv_img_decoder.h -// ../../lib/libesp32_lvgl/LVGL8/src/extra/themes/default/lv_theme_default.h +// ../../lvgl/src/extra/layouts/flex/lv_flex.h +void lv_flex_init(void) +void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow) +void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place, lv_flex_align_t track_cross_place) +void lv_obj_set_flex_grow(lv_obj_t * obj, uint8_t grow) +void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value) +void lv_style_set_flex_main_place(lv_style_t * style, lv_flex_align_t value) +void lv_style_set_flex_cross_place(lv_style_t * style, lv_flex_align_t value) +void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value) +void lv_style_set_flex_grow(lv_style_t * style, uint8_t value) +void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector) +void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector) +static inline lv_flex_flow_t lv_obj_get_style_flex_flow(const lv_obj_t * obj, uint32_t part) +static inline lv_flex_align_t lv_obj_get_style_flex_main_place(const lv_obj_t * obj, uint32_t part) +static inline lv_flex_align_t lv_obj_get_style_flex_cross_place(const lv_obj_t * obj, uint32_t part) +static inline lv_flex_align_t lv_obj_get_style_flex_track_place(const lv_obj_t * obj, uint32_t part) +static inline uint8_t lv_obj_get_style_flex_grow(const lv_obj_t * obj, uint32_t part) + +// ../../lvgl/src/extra/layouts/grid/lv_grid.h +void lv_grid_init(void) +void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const lv_coord_t col_dsc[], const lv_coord_t row_dsc[]) +void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid_align_t row_align) +void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t column_align, uint8_t col_pos, uint8_t col_span, lv_grid_align_t row_align, uint8_t row_pos, uint8_t row_span) +static inline lv_coord_t lv_grid_fr(uint8_t x) +void lv_style_set_grid_row_dsc_array(lv_style_t * style, const lv_coord_t value[]) +void lv_style_set_grid_column_dsc_array(lv_style_t * style, const lv_coord_t value[]) +void lv_style_set_grid_row_align(lv_style_t * style, lv_grid_align_t value) +void lv_style_set_grid_column_align(lv_style_t * style, lv_grid_align_t value) +void lv_style_set_grid_cell_column_pos(lv_style_t * style, lv_coord_t value) +void lv_style_set_grid_cell_column_span(lv_style_t * style, lv_coord_t value) +void lv_style_set_grid_cell_row_pos(lv_style_t * style, lv_coord_t value) +void lv_style_set_grid_cell_row_span(lv_style_t * style, lv_coord_t value) +void lv_style_set_grid_cell_x_align(lv_style_t * style, lv_coord_t value) +void lv_style_set_grid_cell_y_align(lv_style_t * style, lv_coord_t value) +void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector) +void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector) +void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +static inline const lv_coord_t * lv_obj_get_style_grid_row_dsc_array(const lv_obj_t * obj, uint32_t part) +static inline const lv_coord_t * lv_obj_get_style_grid_column_dsc_array(const lv_obj_t * obj, uint32_t part) +static inline lv_grid_align_t lv_obj_get_style_grid_row_align(const lv_obj_t * obj, uint32_t part) +static inline lv_grid_align_t lv_obj_get_style_grid_column_align(const lv_obj_t * obj, uint32_t part) +static inline lv_coord_t lv_obj_get_style_grid_cell_column_pos(const lv_obj_t * obj, uint32_t part) +static inline lv_coord_t lv_obj_get_style_grid_cell_column_span(const lv_obj_t * obj, uint32_t part) +static inline lv_coord_t lv_obj_get_style_grid_cell_row_pos(const lv_obj_t * obj, uint32_t part) +static inline lv_coord_t lv_obj_get_style_grid_cell_row_span(const lv_obj_t * obj, uint32_t part) +static inline lv_coord_t lv_obj_get_style_grid_cell_x_align(const lv_obj_t * obj, uint32_t part) +static inline lv_coord_t lv_obj_get_style_grid_cell_y_align(const lv_obj_t * obj, uint32_t part) + +// ../../lvgl/src/extra/layouts/lv_layouts.h + +// ../../lvgl/src/extra/themes/default/lv_theme_default.h lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font) +lv_theme_t * lv_theme_default_get(void) bool lv_theme_default_is_inited(void) -// ../../lib/libesp32_lvgl/LVGL8/src/extra/themes/mono/lv_theme_mono.h +// ../../lvgl/src/extra/themes/mono/lv_theme_mono.h lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t * font) -// ../../lib/libesp32_lvgl/LVGL8/src/extra/widgets/chart/lv_chart.h +// ../../lvgl/src/extra/widgets/chart/lv_chart.h lv_obj_t * lv_chart_create(lv_obj_t * parent) void lv_chart_set_type(lv_obj_t * obj, lv_chart_type_t type) void lv_chart_set_point_count(lv_obj_t * obj, uint16_t cnt) @@ -542,7 +616,7 @@ lv_coord_t * lv_chart_get_y_array(const lv_obj_t * obj, lv_chart_series_t * ser) lv_coord_t * lv_chart_get_x_array(const lv_obj_t * obj, lv_chart_series_t * ser) uint32_t lv_chart_get_pressed_point(const lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/extra/widgets/colorwheel/lv_colorwheel.h +// ../../lvgl/src/extra/widgets/colorwheel/lv_colorwheel.h lv_obj_t * lv_colorwheel_create(lv_obj_t * parent, bool knob_recolor) bool lv_colorwheel_set_hsv(lv_obj_t * obj, lv_color_hsv_t hsv) bool lv_colorwheel_set_rgb(lv_obj_t * obj, lv_color_t color) @@ -553,11 +627,12 @@ lv_color_t lv_colorwheel_get_rgb(lv_obj_t * obj) lv_colorwheel_mode_t lv_colorwheel_get_color_mode(lv_obj_t * obj) bool lv_colorwheel_get_color_mode_fixed(lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/extra/widgets/imgbtn/lv_imgbtn.h +// ../../lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h lv_obj_t * lv_imgbtn_create(lv_obj_t * parent) void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_imgbtn_state_t state, const void * src_left, const void * src_mid, const void * src_right) +void lv_imgbtn_set_state(lv_obj_t * imgbtn, lv_imgbtn_state_t state) -// ../../lib/libesp32_lvgl/LVGL8/src/extra/widgets/led/lv_led.h +// ../../lvgl/src/extra/widgets/led/lv_led.h lv_obj_t * lv_led_create(lv_obj_t * parent) void lv_led_set_color(lv_obj_t * led, lv_color_t color) void lv_led_set_brightness(lv_obj_t * led, uint8_t bright) @@ -566,7 +641,7 @@ void lv_led_off(lv_obj_t * led) void lv_led_toggle(lv_obj_t * led) uint8_t lv_led_get_brightness(const lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/extra/widgets/meter/lv_meter.h +// ../../lvgl/src/extra/widgets/meter/lv_meter.h lv_obj_t * lv_meter_create(lv_obj_t * parent) lv_meter_scale_t * lv_meter_add_scale(lv_obj_t * obj) void lv_meter_set_scale_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t cnt, uint16_t width, uint16_t len, lv_color_t color) @@ -580,23 +655,28 @@ void lv_meter_set_indicator_value(lv_obj_t * obj, lv_meter_indicator_t * indic, void lv_meter_set_indicator_start_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value) void lv_meter_set_indicator_end_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value) -// ../../lib/libesp32_lvgl/LVGL8/src/extra/widgets/msgbox/lv_msgbox.h +// ../../lvgl/src/extra/widgets/msgbox/lv_msgbox.h lv_obj_t * lv_msgbox_create(lv_obj_t * parent, const char * title, const char * txt, const char * btn_txts[], bool add_close_btn) -lv_obj_t * lv_msgbox_get_title(lv_obj_t * mbox) -lv_obj_t * lv_msgbox_get_close_btn(lv_obj_t * mbox) -lv_obj_t * lv_msgbox_get_text(lv_obj_t * mbox) -lv_obj_t * lv_msgbox_get_btns(lv_obj_t * mbox) +lv_obj_t * lv_msgbox_get_title(lv_obj_t * obj) +lv_obj_t * lv_msgbox_get_close_btn(lv_obj_t * obj) +lv_obj_t * lv_msgbox_get_text(lv_obj_t * obj) +lv_obj_t * lv_msgbox_get_content(lv_obj_t * obj) +lv_obj_t * lv_msgbox_get_btns(lv_obj_t * obj) +uint16_t lv_msgbox_get_active_btn(lv_obj_t * mbox) const char * lv_msgbox_get_active_btn_text(lv_obj_t * mbox) void lv_msgbox_close(lv_obj_t * mbox) +void lv_msgbox_close_async(lv_obj_t * mbox) -// ../../lib/libesp32_lvgl/LVGL8/src/extra/widgets/spinbox/lv_spinbox.h +// ../../lvgl/src/extra/widgets/spinbox/lv_spinbox.h lv_obj_t * lv_spinbox_create(lv_obj_t * parent) void lv_spinbox_set_value(lv_obj_t * obj, int32_t i) void lv_spinbox_set_rollover(lv_obj_t * obj, bool b) void lv_spinbox_set_digit_format(lv_obj_t * obj, uint8_t digit_count, uint8_t separator_position) void lv_spinbox_set_step(lv_obj_t * obj, uint32_t step) void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max) -bool lv_spinbox_get_rollover(lv_obj_t * obj) +void lv_spinbox_set_pos(lv_obj_t * obj, uint8_t pos) +void lv_spinbox_set_digit_step_direction(lv_obj_t * obj, lv_dir_t direction) +bool lv_spinbox_get_rollover(lv_obj_t *obj) int32_t lv_spinbox_get_value(lv_obj_t * obj) int32_t lv_spinbox_get_step(lv_obj_t * obj) void lv_spinbox_step_next(lv_obj_t * obj) @@ -604,10 +684,44 @@ void lv_spinbox_step_prev(lv_obj_t * obj) void lv_spinbox_increment(lv_obj_t * obj) void lv_spinbox_decrement(lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/extra/widgets/spinner/lv_spinner.h +// ../../lvgl/src/extra/widgets/spinner/lv_spinner.h lv_obj_t * lv_spinner_create(lv_obj_t * parent, uint32_t time, uint32_t arc_length) -// ../../lib/libesp32_lvgl/LVGL8/src/misc/lv_style_gen.h +// ../../lvgl/src/lv_api_map.h +static inline uint32_t lv_task_handler(void) +static inline void lv_obj_move_foreground(lv_obj_t * obj) +static inline void lv_obj_move_background(lv_obj_t * obj) +static inline uint32_t lv_obj_get_child_id(const struct _lv_obj_t * obj) + +// ../../lvgl/src/misc/lv_color.h +static inline uint8_t lv_color_to1(lv_color_t color) +static inline uint8_t lv_color_to8(lv_color_t color) +static inline uint16_t lv_color_to16(lv_color_t color) +static inline uint32_t lv_color_to32(lv_color_t color) +static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix) +static inline void lv_color_premult(lv_color_t c, uint8_t mix, uint16_t * out) +static inline lv_color_t lv_color_mix_premult(uint16_t * premult_c1, lv_color_t c2, uint8_t mix) +static inline void lv_color_mix_with_alpha(lv_color_t bg_color, lv_opa_t bg_opa, lv_color_t fg_color, lv_opa_t fg_opa, lv_color_t * res_color, lv_opa_t * res_opa) +static inline uint8_t lv_color_brightness(lv_color_t color) +static inline lv_color_t lv_color_make(uint8_t r, uint8_t g, uint8_t b) +static inline lv_color_t lv_color_hex(uint32_t c) +static inline lv_color_t lv_color_hex3(uint32_t c) +static inline void lv_color_filter_dsc_init(lv_color_filter_dsc_t * dsc, lv_color_filter_cb_t cb) +void lv_color_fill(lv_color_t * buf, lv_color_t color, uint32_t px_num) +lv_color_t lv_color_lighten(lv_color_t c, lv_opa_t lvl) +lv_color_t lv_color_darken(lv_color_t c, lv_opa_t lvl) +lv_color_t lv_color_change_lightness(lv_color_t c, lv_opa_t lvl) +lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v) +lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8) +lv_color_hsv_t lv_color_to_hsv(lv_color_t color) +static inline lv_color_t lv_color_chroma_key(void) +lv_color_t lv_palette_main(lv_palette_t p) +static inline lv_color_t lv_color_white(void) +static inline lv_color_t lv_color_black(void) +lv_color_t lv_palette_lighten(lv_palette_t p, uint8_t lvl) +lv_color_t lv_palette_darken(lv_palette_t p, uint8_t lvl) + +// ../../lvgl/src/misc/lv_style_gen.h void lv_style_set_width(lv_style_t * style, lv_coord_t value) void lv_style_set_min_width(lv_style_t * style, lv_coord_t value) void lv_style_set_max_width(lv_style_t * style, lv_coord_t value) @@ -687,18 +801,18 @@ void lv_style_set_shadow_opa(lv_style_t * style, lv_opa_t value) void lv_style_set_line_width(lv_style_t * style, lv_coord_t value) void lv_style_set_line_dash_width(lv_style_t * style, lv_coord_t value) void lv_style_set_line_dash_gap(lv_style_t * style, lv_coord_t value) -void lv_style_set_line_rounded(lv_style_t * style, lv_coord_t value) +void lv_style_set_line_rounded(lv_style_t * style, bool value) void lv_style_set_line_color(lv_style_t * style, lv_color_t value) void lv_style_set_line_color_filtered(lv_style_t * style, lv_color_t value) void lv_style_set_line_opa(lv_style_t * style, lv_opa_t value) void lv_style_set_arc_width(lv_style_t * style, lv_coord_t value) -void lv_style_set_arc_rounded(lv_style_t * style, lv_coord_t value) +void lv_style_set_arc_rounded(lv_style_t * style, bool value) void lv_style_set_arc_color(lv_style_t * style, lv_color_t value) void lv_style_set_arc_color_filtered(lv_style_t * style, lv_color_t value) void lv_style_set_arc_opa(lv_style_t * style, lv_opa_t value) void lv_style_set_arc_img_src(lv_style_t * style, const void * value) -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_arc.h +// ../../lvgl/src/widgets/lv_arc.h lv_obj_t * lv_arc_create(lv_obj_t * parent) void lv_arc_set_start_angle(lv_obj_t * arc, uint16_t start) void lv_arc_set_end_angle(lv_obj_t * arc, uint16_t end) @@ -720,7 +834,7 @@ int16_t lv_arc_get_min_value(const lv_obj_t * obj) int16_t lv_arc_get_max_value(const lv_obj_t * obj) lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_bar.h +// ../../lvgl/src/widgets/lv_bar.h lv_obj_t * lv_bar_create(lv_obj_t * parent) void lv_bar_set_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim) void lv_bar_set_start_value(lv_obj_t * obj, int32_t start_value, lv_anim_enable_t anim) @@ -732,16 +846,16 @@ int32_t lv_bar_get_min_value(const lv_obj_t * obj) int32_t lv_bar_get_max_value(const lv_obj_t * obj) lv_bar_mode_t lv_bar_get_mode(lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_btn.h +// ../../lvgl/src/widgets/lv_btn.h lv_obj_t * lv_btn_create(lv_obj_t * parent) -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_btnmatrix.h +// ../../lvgl/src/widgets/lv_btnmatrix.h lv_obj_t * lv_btnmatrix_create(lv_obj_t * parent) void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]) void lv_btnmatrix_set_ctrl_map(lv_obj_t * obj, const lv_btnmatrix_ctrl_t ctrl_map[]) void lv_btnmatrix_set_selected_btn(lv_obj_t * obj, uint16_t btn_id) void lv_btnmatrix_set_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl) -void lv_btnmatrix_clear_btn_ctrl(const lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl) +void lv_btnmatrix_clear_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl) void lv_btnmatrix_set_btn_ctrl_all(lv_obj_t * obj, lv_btnmatrix_ctrl_t ctrl) void lv_btnmatrix_clear_btn_ctrl_all(lv_obj_t * obj, lv_btnmatrix_ctrl_t ctrl) void lv_btnmatrix_set_btn_width(lv_obj_t * obj, uint16_t btn_id, uint8_t width) @@ -752,10 +866,12 @@ const char * lv_btnmatrix_get_btn_text(const lv_obj_t * obj, uint16_t btn_id) bool lv_btnmatrix_has_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl) bool lv_btnmatrix_get_one_checked(const lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_canvas.h +// ../../lvgl/src/widgets/lv_canvas.h lv_obj_t * lv_canvas_create(lv_obj_t * parent) void lv_canvas_set_buffer(lv_obj_t * canvas, void * buf, lv_coord_t w, lv_coord_t h, lv_img_cf_t cf) -void lv_canvas_set_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c) +void lv_canvas_set_px_color(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c) +static inline void lv_canvas_set_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c) +void lv_canvas_set_px_opa(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_opa_t opa) void lv_canvas_set_palette(lv_obj_t * canvas, uint8_t id, lv_color_t c) lv_color_t lv_canvas_get_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y) lv_img_dsc_t * lv_canvas_get_img(lv_obj_t * canvas) @@ -771,13 +887,13 @@ void lv_canvas_draw_line(lv_obj_t * canvas, const lv_point_t points[], uint32_t void lv_canvas_draw_polygon(lv_obj_t * canvas, const lv_point_t points[], uint32_t point_cnt, const lv_draw_rect_dsc_t * draw_dsc) void lv_canvas_draw_arc(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t r, int32_t start_angle, int32_t end_angle, const lv_draw_arc_dsc_t * draw_dsc) -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_checkbox.h +// ../../lvgl/src/widgets/lv_checkbox.h lv_obj_t * lv_checkbox_create(lv_obj_t * parent) void lv_checkbox_set_text(lv_obj_t * obj, const char * txt) void lv_checkbox_set_text_static(lv_obj_t * obj, const char * txt) const char * lv_checkbox_get_text(const lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_dropdown.h +// ../../lvgl/src/widgets/lv_dropdown.h lv_obj_t * lv_dropdown_create(lv_obj_t * parent) void lv_dropdown_set_text(lv_obj_t * obj, const char * txt) void lv_dropdown_set_options(lv_obj_t * obj, const char * options) @@ -800,7 +916,7 @@ lv_dir_t lv_dropdown_get_dir(const lv_obj_t * obj) void lv_dropdown_open(lv_obj_t * dropdown_obj) void lv_dropdown_close(lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_img.h +// ../../lvgl/src/widgets/lv_img.h lv_obj_t * lv_img_create(lv_obj_t * parent) void lv_img_set_src(lv_obj_t * obj, const void * src) void lv_img_set_offset_x(lv_obj_t * obj, lv_coord_t x) @@ -809,6 +925,7 @@ void lv_img_set_angle(lv_obj_t * obj, int16_t angle) void lv_img_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) void lv_img_set_zoom(lv_obj_t * obj, uint16_t zoom) void lv_img_set_antialias(lv_obj_t * obj, bool antialias) +void lv_img_set_size_mode(lv_obj_t * obj, lv_img_size_mode_t mode) const void * lv_img_get_src(lv_obj_t * obj) lv_coord_t lv_img_get_offset_x(lv_obj_t * obj) lv_coord_t lv_img_get_offset_y(lv_obj_t * obj) @@ -816,8 +933,9 @@ uint16_t lv_img_get_angle(lv_obj_t * obj) void lv_img_get_pivot(lv_obj_t * obj, lv_point_t * pivot) uint16_t lv_img_get_zoom(lv_obj_t * obj) bool lv_img_get_antialias(lv_obj_t * obj) +lv_img_size_mode_t lv_img_get_size_mode(lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_label.h +// ../../lvgl/src/widgets/lv_label.h lv_obj_t * lv_label_create(lv_obj_t * parent) void lv_label_set_text(lv_obj_t * obj, const char * text) void lv_label_set_text_fmt(lv_obj_t * obj, const char * fmt, ...) LV_FORMAT_ATTRIBUTE(2, 3) @@ -837,15 +955,15 @@ uint32_t lv_label_get_text_selection_end(const lv_obj_t * obj) void lv_label_ins_text(lv_obj_t * obj, uint32_t pos, const char * txt) void lv_label_cut_text(lv_obj_t * obj, uint32_t pos, uint32_t cnt) -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_line.h +// ../../lvgl/src/widgets/lv_line.h lv_obj_t * lv_line_create(lv_obj_t * parent) void lv_line_set_points(lv_obj_t * obj, const lv_point_t points[], uint16_t point_num) void lv_line_set_y_invert(lv_obj_t * obj, bool en) bool lv_line_get_y_invert(const lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_objx_templ.h +// ../../lvgl/src/widgets/lv_objx_templ.h -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_roller.h +// ../../lvgl/src/widgets/lv_roller.h lv_obj_t * lv_roller_create(lv_obj_t * parent) void lv_roller_set_options(lv_obj_t * obj, const char * options, lv_roller_mode_t mode) void lv_roller_set_selected(lv_obj_t * obj, uint16_t sel_opt, lv_anim_enable_t anim) @@ -855,7 +973,7 @@ void lv_roller_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_s const char * lv_roller_get_options(const lv_obj_t * obj) uint16_t lv_roller_get_option_cnt(const lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_slider.h +// ../../lvgl/src/widgets/lv_slider.h lv_obj_t * lv_slider_create(lv_obj_t * parent) static inline void lv_slider_set_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim) static inline void lv_slider_set_left_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim) @@ -868,10 +986,10 @@ static inline int32_t lv_slider_get_max_value(const lv_obj_t * obj) bool lv_slider_is_dragged(const lv_obj_t * obj) static inline lv_slider_mode_t lv_slider_get_mode(lv_obj_t * slider) -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_switch.h +// ../../lvgl/src/widgets/lv_switch.h lv_obj_t * lv_switch_create(lv_obj_t * parent) -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_table.h +// ../../lvgl/src/widgets/lv_table.h lv_obj_t * lv_table_create(lv_obj_t * parent) void lv_table_set_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col, const char * txt) void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, const char * fmt, ...) @@ -887,7 +1005,7 @@ lv_coord_t lv_table_get_col_width(lv_obj_t * obj, uint16_t col) bool lv_table_has_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl) void lv_table_get_selected_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col) -// ../../lib/libesp32_lvgl/LVGL8/src/widgets/lv_textarea.h +// ../../lvgl/src/widgets/lv_textarea.h lv_obj_t * lv_textarea_create(lv_obj_t * parent) void lv_textarea_add_char(lv_obj_t * obj, uint32_t c) void lv_textarea_add_text(lv_obj_t * obj, const char * txt) @@ -923,7 +1041,7 @@ void lv_textarea_cursor_left(lv_obj_t * obj) void lv_textarea_cursor_down(lv_obj_t * obj) void lv_textarea_cursor_up(lv_obj_t * obj) -// ../../lib/libesp32_lvgl/LVGL_assets/src/lv_theme_openhasp.h +// ../../LVGL_assets/src/lv_theme_openhasp.h lv_theme_t * lv_theme_openhasp_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font) bool lv_theme_openhasp_is_inited(void) diff --git a/lib/libesp32_lvgl/lv_berry/src/be_lv_extra.c b/lib/libesp32_lvgl/lv_berry/src/be_lv_extra.c new file mode 100644 index 000000000..109a5cf0a --- /dev/null +++ b/lib/libesp32_lvgl/lv_berry/src/be_lv_extra.c @@ -0,0 +1,244 @@ +/******************************************************************** + * Tasmota LVGL lv_signal_bars widget + *******************************************************************/ +#include "be_constobj.h" + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(lv_coord_arr_init, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str(instance), + /* K1 */ be_nested_str(value_error), + /* K2 */ be_nested_str(argument_X20must_X20be_X20a_X20list), + /* K3 */ be_nested_str(init), + /* K4 */ be_const_int(2), + /* K5 */ be_nested_str(add), + /* K6 */ be_nested_str(stop_iteration), + }), + &be_const_str_init, + &be_const_str_solidified, + ( &(const binstruction[37]) { /* code */ + 0x60080004, // 0000 GETGBL R2 G4 + 0x5C0C0200, // 0001 MOVE R3 R1 + 0x7C080200, // 0002 CALL R2 1 + 0x20080500, // 0003 NE R2 R2 K0 + 0x740A0004, // 0004 JMPT R2 #000A + 0x6008000F, // 0005 GETGBL R2 G15 + 0x5C0C0200, // 0006 MOVE R3 R1 + 0x60100012, // 0007 GETGBL R4 G18 + 0x7C080400, // 0008 CALL R2 2 + 0x740A0000, // 0009 JMPT R2 #000B + 0xB0060302, // 000A RAISE 1 K1 K2 + 0x60080003, // 000B GETGBL R2 G3 + 0x5C0C0000, // 000C MOVE R3 R0 + 0x7C080200, // 000D CALL R2 1 + 0x8C080503, // 000E GETMET R2 R2 K3 + 0x6010000C, // 000F GETGBL R4 G12 + 0x5C140200, // 0010 MOVE R5 R1 + 0x7C100200, // 0011 CALL R4 1 + 0x08100904, // 0012 MUL R4 R4 K4 + 0x7C080400, // 0013 CALL R2 2 + 0x60080010, // 0014 GETGBL R2 G16 + 0x5C0C0200, // 0015 MOVE R3 R1 + 0x7C080200, // 0016 CALL R2 1 + 0xA8020008, // 0017 EXBLK 0 #0021 + 0x5C0C0400, // 0018 MOVE R3 R2 + 0x7C0C0000, // 0019 CALL R3 0 + 0x8C100105, // 001A GETMET R4 R0 K5 + 0x60180009, // 001B GETGBL R6 G9 + 0x5C1C0600, // 001C MOVE R7 R3 + 0x7C180200, // 001D CALL R6 1 + 0x581C0004, // 001E LDCONST R7 K4 + 0x7C100600, // 001F CALL R4 3 + 0x7001FFF6, // 0020 JMP #0018 + 0x58080006, // 0021 LDCONST R2 K6 + 0xAC080200, // 0022 CATCH R2 1 0 + 0xB0080000, // 0023 RAISE 2 R0 R0 + 0x80000000, // 0024 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: lv_coord_arr +********************************************************************/ +extern const bclass be_class_bytes; +be_local_class(lv_coord_arr, + 0, + &be_class_bytes, + be_nested_map(1, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key(init, -1), be_const_closure(lv_coord_arr_init_closure) }, + })), + be_str_literal("lv_coord_arr") +); + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(lv_point_arr_init, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[12]) { /* constants */ + /* K0 */ be_nested_str(instance), + /* K1 */ be_nested_str(value_error), + /* K2 */ be_nested_str(argument_X20must_X20be_X20a_X20list), + /* K3 */ be_nested_str(init), + /* K4 */ be_nested_str(lv), + /* K5 */ be_nested_str(lv_point), + /* K6 */ be_nested_str(elements_X20must_X20be_X20a_X20lv_point), + /* K7 */ be_nested_str(add), + /* K8 */ be_nested_str(x), + /* K9 */ be_const_int(2), + /* K10 */ be_nested_str(y), + /* K11 */ be_nested_str(stop_iteration), + }), + &be_const_str_init, + &be_const_str_solidified, + ( &(const binstruction[52]) { /* code */ + 0x60080004, // 0000 GETGBL R2 G4 + 0x5C0C0200, // 0001 MOVE R3 R1 + 0x7C080200, // 0002 CALL R2 1 + 0x20080500, // 0003 NE R2 R2 K0 + 0x740A0004, // 0004 JMPT R2 #000A + 0x6008000F, // 0005 GETGBL R2 G15 + 0x5C0C0200, // 0006 MOVE R3 R1 + 0x60100012, // 0007 GETGBL R4 G18 + 0x7C080400, // 0008 CALL R2 2 + 0x740A0000, // 0009 JMPT R2 #000B + 0xB0060302, // 000A RAISE 1 K1 K2 + 0x60080003, // 000B GETGBL R2 G3 + 0x5C0C0000, // 000C MOVE R3 R0 + 0x7C080200, // 000D CALL R2 1 + 0x8C080503, // 000E GETMET R2 R2 K3 + 0x6010000C, // 000F GETGBL R4 G12 + 0x5C140200, // 0010 MOVE R5 R1 + 0x7C100200, // 0011 CALL R4 1 + 0x54160003, // 0012 LDINT R5 4 + 0x08100805, // 0013 MUL R4 R4 R5 + 0x7C080400, // 0014 CALL R2 2 + 0x60080010, // 0015 GETGBL R2 G16 + 0x5C0C0200, // 0016 MOVE R3 R1 + 0x7C080200, // 0017 CALL R2 1 + 0xA8020016, // 0018 EXBLK 0 #0030 + 0x5C0C0400, // 0019 MOVE R3 R2 + 0x7C0C0000, // 001A CALL R3 0 + 0x60100004, // 001B GETGBL R4 G4 + 0x5C140600, // 001C MOVE R5 R3 + 0x7C100200, // 001D CALL R4 1 + 0x20100900, // 001E NE R4 R4 K0 + 0x74120005, // 001F JMPT R4 #0026 + 0x6010000F, // 0020 GETGBL R4 G15 + 0x5C140600, // 0021 MOVE R5 R3 + 0xB81A0800, // 0022 GETNGBL R6 K4 + 0x88180D05, // 0023 GETMBR R6 R6 K5 + 0x7C100400, // 0024 CALL R4 2 + 0x74120000, // 0025 JMPT R4 #0027 + 0xB0060306, // 0026 RAISE 1 K1 K6 + 0x8C100107, // 0027 GETMET R4 R0 K7 + 0x88180708, // 0028 GETMBR R6 R3 K8 + 0x581C0009, // 0029 LDCONST R7 K9 + 0x7C100600, // 002A CALL R4 3 + 0x8C100107, // 002B GETMET R4 R0 K7 + 0x8818070A, // 002C GETMBR R6 R3 K10 + 0x581C0009, // 002D LDCONST R7 K9 + 0x7C100600, // 002E CALL R4 3 + 0x7001FFE8, // 002F JMP #0019 + 0x5808000B, // 0030 LDCONST R2 K11 + 0xAC080200, // 0031 CATCH R2 1 0 + 0xB0080000, // 0032 RAISE 2 R0 R0 + 0x80000000, // 0033 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: lv_point_arr +********************************************************************/ +extern const bclass be_class_bytes; +be_local_class(lv_point_arr, + 0, + &be_class_bytes, + be_nested_map(1, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key(init, -1), be_const_closure(lv_point_arr_init_closure) }, + })), + be_str_literal("lv_point_arr") +); + +/******************************************************************** +** Solidified function: _anonymous_ +********************************************************************/ +be_local_closure(lv_extra__anonymous_, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str(global), + /* K1 */ be_nested_str(lv), + /* K2 */ be_nested_str(lv_coord_arr), + /* K3 */ be_nested_str(lv_point_arr), + /* K4 */ be_nested_str(coord_arr), + /* K5 */ be_nested_str(point_arr), + }), + &be_const_str__anonymous_, + &be_const_str_solidified, + ( &(const binstruction[11]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x88080301, // 0001 GETMBR R2 R1 K1 + 0x880C0102, // 0002 GETMBR R3 R0 K2 + 0x900A0403, // 0003 SETMBR R2 K2 R3 + 0x880C0103, // 0004 GETMBR R3 R0 K3 + 0x900A0603, // 0005 SETMBR R2 K3 R3 + 0x880C0102, // 0006 GETMBR R3 R0 K2 + 0x900A0803, // 0007 SETMBR R2 K4 R3 + 0x880C0103, // 0008 GETMBR R3 R0 K3 + 0x900A0A03, // 0009 SETMBR R2 K5 R3 + 0x80040000, // 000A RET 1 R0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified module: lv_extra +********************************************************************/ +be_local_module(lv_extra, + "lv_extra", + be_nested_map(3, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key(init, -1), be_const_closure(lv_extra__anonymous__closure) }, + { be_const_key(lv_point_arr, -1), be_const_class(be_class_lv_point_arr) }, + { be_const_key(lv_coord_arr, 1), be_const_class(be_class_lv_coord_arr) }, + })) +); +BE_EXPORT_VARIABLE be_define_const_native_module(lv_extra); +/********************************************************************/ diff --git a/lib/libesp32/Berry/default/be_lvgl_ctypes_definitions.c b/lib/libesp32_lvgl/lv_berry/src/be_lvgl_ctypes_definitions.c similarity index 81% rename from lib/libesp32/Berry/default/be_lvgl_ctypes_definitions.c rename to lib/libesp32_lvgl/lv_berry/src/be_lvgl_ctypes_definitions.c index bb1ffb65c..58101069e 100644 --- a/lib/libesp32/Berry/default/be_lvgl_ctypes_definitions.c +++ b/lib/libesp32_lvgl/lv_berry/src/be_lvgl_ctypes_definitions.c @@ -3,10 +3,8 @@ *******************************************************************/ #include "be_ctypes.h" -#ifdef USE_LVGL - #include "lvgl.h" -#include "be_lvgl.h" +#include "be_mapping.h" /******************************************************************** * Generated code, don't edit @@ -404,6 +402,36 @@ const be_ctypes_structure_t be_lv_meter_indicator_scale_lines = { { "width_mod", 16, 0, 0, ctypes_i16, 0 }, }}; +const be_ctypes_structure_t be_lv_chart_series = { + 13, /* size in bytes */ + 9, /* number of elements */ + be_ctypes_instance_mappings, + (const be_ctypes_structure_item_t[9]) { + { "color", 8, 0, 0, ctypes_u16, 1 }, + { "hidden", 12, 0, 1, ctypes_bf, 0 }, + { "start_point", 10, 0, 0, ctypes_u16, 0 }, + { "x_axis_sec", 12, 3, 1, ctypes_bf, 0 }, + { "x_ext_buf_assigned", 12, 1, 1, ctypes_bf, 0 }, + { "x_points", 0, 0, 0, ctypes_ptr32, 0 }, + { "y_axis_sec", 12, 4, 1, ctypes_bf, 0 }, + { "y_ext_buf_assigned", 12, 2, 1, ctypes_bf, 0 }, + { "y_points", 4, 0, 0, ctypes_ptr32, 0 }, +}}; + +const be_ctypes_structure_t be_lv_chart_cursor = { + 14, /* size in bytes */ + 7, /* number of elements */ + be_ctypes_instance_mappings, + (const be_ctypes_structure_item_t[7]) { + { "color", 6, 0, 0, ctypes_u16, 1 }, + { "dir", 12, 0, 0, ctypes_u8, 0 }, + { "point_id", 4, 0, 0, ctypes_u16, 0 }, + { "pos_set", 13, 0, 1, ctypes_bf, 0 }, + { "pos_x", 0, 0, 0, ctypes_i16, 0 }, + { "pos_y", 2, 0, 0, ctypes_i16, 0 }, + { "ser", 8, 0, 0, ctypes_ptr32, 0 }, +}}; + const be_ctypes_structure_t be_lv_obj_class = { 27, /* size in bytes */ 10, /* number of elements */ @@ -435,12 +463,88 @@ const be_ctypes_structure_t be_lv_event = { { "user_data", 12, 0, 0, ctypes_ptr32, 0 }, }}; +const be_ctypes_structure_t be_lv_img_header = { + 4, /* size in bytes */ + 5, /* number of elements */ + be_ctypes_instance_mappings, + (const be_ctypes_structure_item_t[5]) { + { "always_zero", 0, 5, 3, ctypes_bf, 0 }, + { "cf", 0, 0, 5, ctypes_bf, 0 }, + { "h", 2, 5, 11, ctypes_bf, 0 }, + { "reserved", 1, 0, 2, ctypes_bf, 0 }, + { "w", 1, 2, 11, ctypes_bf, 0 }, +}}; + +const be_ctypes_structure_t be_lv_img_dsc = { + 16, /* size in bytes */ + 8, /* number of elements */ + be_ctypes_instance_mappings, + (const be_ctypes_structure_item_t[8]) { + { "cf", 4, 0, 5, ctypes_bf, 0 }, + { "data", 12, 0, 0, ctypes_ptr32, 0 }, + { "data_size", 8, 0, 0, ctypes_u32, 0 }, + { "header_always_zero", 0, 5, 3, ctypes_bf, 0 }, + { "header_cf", 0, 0, 5, ctypes_bf, 0 }, + { "header_h", 2, 5, 11, ctypes_bf, 0 }, + { "header_reserved", 1, 0, 2, ctypes_bf, 0 }, + { "header_w", 1, 2, 11, ctypes_bf, 0 }, +}}; + +const be_ctypes_structure_t be_lv_style_transition_dsc = { + 20, /* size in bytes */ + 5, /* number of elements */ + be_ctypes_instance_mappings, + (const be_ctypes_structure_item_t[5]) { + { "delay", 16, 0, 0, ctypes_u32, 0 }, + { "path_xcb", 8, 0, 0, ctypes_ptr32, 0 }, + { "props", 0, 0, 0, ctypes_ptr32, 0 }, + { "time", 12, 0, 0, ctypes_u32, 0 }, + { "user_data", 4, 0, 0, ctypes_ptr32, 0 }, +}}; + +const be_ctypes_structure_t be_lv_color_filter_dsc = { + 8, /* size in bytes */ + 2, /* number of elements */ + be_ctypes_instance_mappings, + (const be_ctypes_structure_item_t[2]) { + { "filter_cb", 0, 0, 0, ctypes_ptr32, 0 }, + { "user_data", 4, 0, 0, ctypes_ptr32, 0 }, +}}; + +const be_ctypes_structure_t be_lv_timer = { + 21, /* size in bytes */ + 6, /* number of elements */ + be_ctypes_instance_mappings, + (const be_ctypes_structure_item_t[6]) { + { "last_run", 4, 0, 0, ctypes_u32, 0 }, + { "paused", 20, 0, 1, ctypes_bf, 0 }, + { "period", 0, 0, 0, ctypes_u32, 0 }, + { "repeat_count", 16, 0, 0, ctypes_i32, 0 }, + { "timer_cb", 8, 0, 0, ctypes_ptr32, 0 }, + { "user_data", 12, 0, 0, ctypes_ptr32, 0 }, +}}; + +const be_ctypes_structure_t be_lv_ts_calibration = { + 12, /* size in bytes */ + 5, /* number of elements */ + be_ctypes_instance_mappings, + (const be_ctypes_structure_item_t[5]) { + { "raw_x", 0, 0, 0, ctypes_i16, 0 }, + { "raw_y", 2, 0, 0, ctypes_i16, 0 }, + { "state", 8, 0, 0, ctypes_i32, 0 }, + { "x", 4, 0, 0, ctypes_i16, 0 }, + { "y", 6, 0, 0, ctypes_i16, 0 }, +}}; + static const char * be_ctypes_instance_mappings[] = { "lv_color", NULL }; static be_define_ctypes_class(lv_area, &be_lv_area, &be_class_ctypes, "lv_area"); +static be_define_ctypes_class(lv_chart_cursor, &be_lv_chart_cursor, &be_class_ctypes, "lv_chart_cursor"); +static be_define_ctypes_class(lv_chart_series, &be_lv_chart_series, &be_class_ctypes, "lv_chart_series"); +static be_define_ctypes_class(lv_color_filter_dsc, &be_lv_color_filter_dsc, &be_class_ctypes, "lv_color_filter_dsc"); static be_define_ctypes_class(lv_draw_img_dsc, &be_lv_draw_img_dsc, &be_class_ctypes, "lv_draw_img_dsc"); static be_define_ctypes_class(lv_draw_line_dsc, &be_lv_draw_line_dsc, &be_class_ctypes, "lv_draw_line_dsc"); static be_define_ctypes_class(lv_draw_mask_angle_param, &be_lv_draw_mask_angle_param, &be_class_ctypes, "lv_draw_mask_angle_param"); @@ -457,6 +561,8 @@ static be_define_ctypes_class(lv_draw_mask_radius_param_cfg, &be_lv_draw_mask_ra static be_define_ctypes_class(lv_draw_mask_saved, &be_lv_draw_mask_saved, &be_class_ctypes, "lv_draw_mask_saved"); static be_define_ctypes_class(lv_draw_rect_dsc, &be_lv_draw_rect_dsc, &be_class_ctypes, "lv_draw_rect_dsc"); static be_define_ctypes_class(lv_event, &be_lv_event, &be_class_ctypes, "lv_event"); +static be_define_ctypes_class(lv_img_dsc, &be_lv_img_dsc, &be_class_ctypes, "lv_img_dsc"); +static be_define_ctypes_class(lv_img_header, &be_lv_img_header, &be_class_ctypes, "lv_img_header"); static be_define_ctypes_class(lv_meter_indicator, &be_lv_meter_indicator, &be_class_ctypes, "lv_meter_indicator"); static be_define_ctypes_class(lv_meter_indicator_arc, &be_lv_meter_indicator_arc, &be_class_ctypes, "lv_meter_indicator_arc"); static be_define_ctypes_class(lv_meter_indicator_needle_img, &be_lv_meter_indicator_needle_img, &be_class_ctypes, "lv_meter_indicator_needle_img"); @@ -466,9 +572,15 @@ static be_define_ctypes_class(lv_meter_scale, &be_lv_meter_scale, &be_class_ctyp static be_define_ctypes_class(lv_obj_class, &be_lv_obj_class, &be_class_ctypes, "lv_obj_class"); static be_define_ctypes_class(lv_point, &be_lv_point, &be_class_ctypes, "lv_point"); static be_define_ctypes_class(lv_sqrt_res, &be_lv_sqrt_res, &be_class_ctypes, "lv_sqrt_res"); +static be_define_ctypes_class(lv_style_transition_dsc, &be_lv_style_transition_dsc, &be_class_ctypes, "lv_style_transition_dsc"); +static be_define_ctypes_class(lv_timer, &be_lv_timer, &be_class_ctypes, "lv_timer"); +static be_define_ctypes_class(lv_ts_calibration, &be_lv_ts_calibration, &be_class_ctypes, "lv_ts_calibration"); void be_load_ctypes_lvgl_definitions_lib(bvm *vm) { ctypes_register_class(vm, &be_class_lv_area, &be_lv_area); + ctypes_register_class(vm, &be_class_lv_chart_cursor, &be_lv_chart_cursor); + ctypes_register_class(vm, &be_class_lv_chart_series, &be_lv_chart_series); + ctypes_register_class(vm, &be_class_lv_color_filter_dsc, &be_lv_color_filter_dsc); ctypes_register_class(vm, &be_class_lv_draw_img_dsc, &be_lv_draw_img_dsc); ctypes_register_class(vm, &be_class_lv_draw_line_dsc, &be_lv_draw_line_dsc); ctypes_register_class(vm, &be_class_lv_draw_mask_angle_param, &be_lv_draw_mask_angle_param); @@ -485,6 +597,8 @@ void be_load_ctypes_lvgl_definitions_lib(bvm *vm) { ctypes_register_class(vm, &be_class_lv_draw_mask_saved, &be_lv_draw_mask_saved); ctypes_register_class(vm, &be_class_lv_draw_rect_dsc, &be_lv_draw_rect_dsc); ctypes_register_class(vm, &be_class_lv_event, &be_lv_event); + ctypes_register_class(vm, &be_class_lv_img_dsc, &be_lv_img_dsc); + ctypes_register_class(vm, &be_class_lv_img_header, &be_lv_img_header); ctypes_register_class(vm, &be_class_lv_meter_indicator, &be_lv_meter_indicator); ctypes_register_class(vm, &be_class_lv_meter_indicator_arc, &be_lv_meter_indicator_arc); ctypes_register_class(vm, &be_class_lv_meter_indicator_needle_img, &be_lv_meter_indicator_needle_img); @@ -494,10 +608,16 @@ void be_load_ctypes_lvgl_definitions_lib(bvm *vm) { ctypes_register_class(vm, &be_class_lv_obj_class, &be_lv_obj_class); ctypes_register_class(vm, &be_class_lv_point, &be_lv_point); ctypes_register_class(vm, &be_class_lv_sqrt_res, &be_lv_sqrt_res); + ctypes_register_class(vm, &be_class_lv_style_transition_dsc, &be_lv_style_transition_dsc); + ctypes_register_class(vm, &be_class_lv_timer, &be_lv_timer); + ctypes_register_class(vm, &be_class_lv_ts_calibration, &be_lv_ts_calibration); } be_ctypes_class_by_name_t be_ctypes_lvgl_classes[] = { { "lv_area", &be_class_lv_area }, + { "lv_chart_cursor", &be_class_lv_chart_cursor }, + { "lv_chart_series", &be_class_lv_chart_series }, + { "lv_color_filter_dsc", &be_class_lv_color_filter_dsc }, { "lv_draw_img_dsc", &be_class_lv_draw_img_dsc }, { "lv_draw_line_dsc", &be_class_lv_draw_line_dsc }, { "lv_draw_mask_angle_param", &be_class_lv_draw_mask_angle_param }, @@ -514,6 +634,8 @@ be_ctypes_class_by_name_t be_ctypes_lvgl_classes[] = { { "lv_draw_mask_saved", &be_class_lv_draw_mask_saved }, { "lv_draw_rect_dsc", &be_class_lv_draw_rect_dsc }, { "lv_event", &be_class_lv_event }, + { "lv_img_dsc", &be_class_lv_img_dsc }, + { "lv_img_header", &be_class_lv_img_header }, { "lv_meter_indicator", &be_class_lv_meter_indicator }, { "lv_meter_indicator_arc", &be_class_lv_meter_indicator_arc }, { "lv_meter_indicator_needle_img", &be_class_lv_meter_indicator_needle_img }, @@ -523,9 +645,10 @@ be_ctypes_class_by_name_t be_ctypes_lvgl_classes[] = { { "lv_obj_class", &be_class_lv_obj_class }, { "lv_point", &be_class_lv_point }, { "lv_sqrt_res", &be_class_lv_sqrt_res }, + { "lv_style_transition_dsc", &be_class_lv_style_transition_dsc }, + { "lv_timer", &be_class_lv_timer }, + { "lv_ts_calibration", &be_class_lv_ts_calibration }, }; const size_t be_ctypes_lvgl_classes_size = sizeof(be_ctypes_lvgl_classes)/sizeof(be_ctypes_lvgl_classes[0]); /********************************************************************/ - -#endif // USE_LVGL \ No newline at end of file diff --git a/lib/libesp32/Berry/default/be_lvgl_glob_lib.c b/lib/libesp32_lvgl/lv_berry/src/be_lvgl_glob_lib.c similarity index 69% rename from lib/libesp32/Berry/default/be_lvgl_glob_lib.c rename to lib/libesp32_lvgl/lv_berry/src/be_lvgl_glob_lib.c index 01bd4ed1d..bc053a579 100644 --- a/lib/libesp32/Berry/default/be_lvgl_glob_lib.c +++ b/lib/libesp32_lvgl/lv_berry/src/be_lvgl_glob_lib.c @@ -3,10 +3,6 @@ *******************************************************************/ #include "be_constobj.h" -#ifdef USE_LVGL - -#include "lvgl.h" - /******************************************************************** ** Solidified function: get_object_from_ptr ********************************************************************/ @@ -44,11 +40,11 @@ be_local_closure(LVGL_glob_get_object_from_ptr, /* name */ /******************************************************************** -** Solidified function: widget_event_impl +** Solidified function: widget_ctor_impl ********************************************************************/ -be_local_closure(LVGL_glob_widget_event_impl, /* name */ +be_local_closure(LVGL_glob_widget_ctor_impl, /* name */ be_nested_proto( - 12, /* nstack */ + 10, /* nstack */ 3, /* argc */ 0, /* varg */ 0, /* has upvals */ @@ -60,128 +56,16 @@ be_local_closure(LVGL_glob_widget_event_impl, /* name */ /* K0 */ be_nested_str(introspect), /* K1 */ be_nested_str(lv), /* K2 */ be_nested_str(lv_obj_class), - /* K3 */ be_nested_str(lv_event), - /* K4 */ be_nested_str(target), - /* K5 */ be_nested_str(get_object_from_ptr), + /* K3 */ be_nested_str(get_object_from_ptr), + /* K4 */ be_nested_str(cb_obj), + /* K5 */ be_nested_str(find), /* K6 */ be_nested_str(instance), /* K7 */ be_nested_str(get), - /* K8 */ be_nested_str(widget_event), + /* K8 */ be_nested_str(widget_constructor), }), - &be_const_str_widget_event_impl, + &be_const_str_widget_ctor_impl, &be_const_str_solidified, - ( &(const binstruction[30]) { /* code */ - 0xA40E0000, // 0000 IMPORT R3 K0 - 0xB8120200, // 0001 GETNGBL R4 K1 - 0x8C100902, // 0002 GETMET R4 R4 K2 - 0x5C180200, // 0003 MOVE R6 R1 - 0x7C100400, // 0004 CALL R4 2 - 0xB8160200, // 0005 GETNGBL R5 K1 - 0x8C140B03, // 0006 GETMET R5 R5 K3 - 0x5C1C0400, // 0007 MOVE R7 R2 - 0x7C140400, // 0008 CALL R5 2 - 0x88180B04, // 0009 GETMBR R6 R5 K4 - 0x8C1C0105, // 000A GETMET R7 R0 K5 - 0x60240009, // 000B GETGBL R9 G9 - 0x5C280C00, // 000C MOVE R10 R6 - 0x7C240200, // 000D CALL R9 1 - 0x7C1C0400, // 000E CALL R7 2 - 0x60200004, // 000F GETGBL R8 G4 - 0x5C240E00, // 0010 MOVE R9 R7 - 0x7C200200, // 0011 CALL R8 1 - 0x1C201106, // 0012 EQ R8 R8 K6 - 0x78220008, // 0013 JMPF R8 #001D - 0x8C200707, // 0014 GETMET R8 R3 K7 - 0x5C280E00, // 0015 MOVE R10 R7 - 0x582C0008, // 0016 LDCONST R11 K8 - 0x7C200600, // 0017 CALL R8 3 - 0x78220003, // 0018 JMPF R8 #001D - 0x8C200F08, // 0019 GETMET R8 R7 K8 - 0x5C280800, // 001A MOVE R10 R4 - 0x5C2C0A00, // 001B MOVE R11 R5 - 0x7C200600, // 001C CALL R8 3 - 0x80000000, // 001D RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: lvgl_event_dispatch -********************************************************************/ -be_local_closure(LVGL_glob_lvgl_event_dispatch, /* name */ - be_nested_proto( - 10, /* nstack */ - 2, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_nested_str(introspect), - /* K1 */ be_nested_str(lv), - /* K2 */ be_nested_str(lv_event), - /* K3 */ be_nested_str(toptr), - /* K4 */ be_nested_str(target), - /* K5 */ be_nested_str(cb_event_closure), - /* K6 */ be_nested_str(get_object_from_ptr), - }), - &be_const_str_lvgl_event_dispatch, - &be_const_str_solidified, - ( &(const binstruction[20]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0xB80E0200, // 0001 GETNGBL R3 K1 - 0x8C0C0702, // 0002 GETMET R3 R3 K2 - 0x8C140503, // 0003 GETMET R5 R2 K3 - 0x5C1C0200, // 0004 MOVE R7 R1 - 0x7C140400, // 0005 CALL R5 2 - 0x7C0C0400, // 0006 CALL R3 2 - 0x60100009, // 0007 GETGBL R4 G9 - 0x88140704, // 0008 GETMBR R5 R3 K4 - 0x7C100200, // 0009 CALL R4 1 - 0x88140105, // 000A GETMBR R5 R0 K5 - 0x94140A04, // 000B GETIDX R5 R5 R4 - 0x8C180106, // 000C GETMET R6 R0 K6 - 0x5C200800, // 000D MOVE R8 R4 - 0x7C180400, // 000E CALL R6 2 - 0x5C1C0A00, // 000F MOVE R7 R5 - 0x5C200C00, // 0010 MOVE R8 R6 - 0x5C240600, // 0011 MOVE R9 R3 - 0x7C1C0400, // 0012 CALL R7 2 - 0x80000000, // 0013 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: widget_dtor_impl -********************************************************************/ -be_local_closure(LVGL_glob_widget_dtor_impl, /* name */ - be_nested_proto( - 10, /* nstack */ - 3, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_nested_str(introspect), - /* K1 */ be_nested_str(lv), - /* K2 */ be_nested_str(lv_obj_class), - /* K3 */ be_nested_str(get_object_from_ptr), - /* K4 */ be_nested_str(instance), - /* K5 */ be_nested_str(get), - /* K6 */ be_nested_str(widget_destructor), - }), - &be_const_str_widget_dtor_impl, - &be_const_str_solidified, - ( &(const binstruction[22]) { /* code */ + ( &(const binstruction[29]) { /* code */ 0xA40E0000, // 0000 IMPORT R3 K0 0xB8120200, // 0001 GETNGBL R4 K1 0x8C100902, // 0002 GETMET R4 R4 K2 @@ -190,201 +74,27 @@ be_local_closure(LVGL_glob_widget_dtor_impl, /* name */ 0x8C140103, // 0005 GETMET R5 R0 K3 0x5C1C0400, // 0006 MOVE R7 R2 0x7C140400, // 0007 CALL R5 2 - 0x60180004, // 0008 GETGBL R6 G4 - 0x5C1C0A00, // 0009 MOVE R7 R5 - 0x7C180200, // 000A CALL R6 1 - 0x1C180D04, // 000B EQ R6 R6 K4 - 0x781A0007, // 000C JMPF R6 #0015 - 0x8C180705, // 000D GETMET R6 R3 K5 - 0x5C200A00, // 000E MOVE R8 R5 - 0x58240006, // 000F LDCONST R9 K6 - 0x7C180600, // 0010 CALL R6 3 - 0x781A0002, // 0011 JMPF R6 #0015 - 0x8C180B06, // 0012 GETMET R6 R5 K6 - 0x5C200800, // 0013 MOVE R8 R4 - 0x7C180400, // 0014 CALL R6 2 - 0x80000000, // 0015 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: register_obj -********************************************************************/ -be_local_closure(LVGL_glob_register_obj, /* name */ - be_nested_proto( - 4, /* nstack */ - 2, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str(cb_obj), - /* K1 */ be_nested_str(_p), - }), - &be_const_str_register_obj, - &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x1C080403, // 0002 EQ R2 R2 R3 - 0x780A0002, // 0003 JMPF R2 #0007 - 0x60080013, // 0004 GETGBL R2 G19 - 0x7C080000, // 0005 CALL R2 0 - 0x90020002, // 0006 SETMBR R0 K0 R2 - 0x60080009, // 0007 GETGBL R2 G9 - 0x880C0301, // 0008 GETMBR R3 R1 K1 - 0x7C080200, // 0009 CALL R2 1 - 0x880C0100, // 000A GETMBR R3 R0 K0 - 0x980C0401, // 000B SETIDX R3 R2 R1 - 0x80000000, // 000C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: gen_cb -********************************************************************/ -be_local_closure(LVGL_glob_gen_cb, /* name */ - be_nested_proto( - 8, /* nstack */ - 5, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 1]) { - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str(lvgl_event_dispatch), - }), - &be_const_str__X3Clambda_X3E, - &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x68040000, // 0000 GETUPV R1 U0 - 0x8C040300, // 0001 GETMET R1 R1 K0 - 0x5C0C0000, // 0002 MOVE R3 R0 - 0x7C040400, // 0003 CALL R1 2 - 0x80040200, // 0004 RET 1 R1 - }) - ), - }), - 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str(lv_event_cb), - /* K1 */ be_nested_str(cb_event_closure), - /* K2 */ be_nested_str(event_cb), - /* K3 */ be_nested_str(tasmota), - /* K4 */ be_nested_str(gen_cb), - /* K5 */ be_nested_str(register_obj), - /* K6 */ be_nested_str(null_cb), - /* K7 */ be_nested_str(cb_do_nothing), - }), - &be_const_str_gen_cb, - &be_const_str_solidified, - ( &(const binstruction[41]) { /* code */ - 0x1C140300, // 0000 EQ R5 R1 K0 - 0x78160018, // 0001 JMPF R5 #001B - 0x88140101, // 0002 GETMBR R5 R0 K1 - 0x4C180000, // 0003 LDNIL R6 - 0x1C140A06, // 0004 EQ R5 R5 R6 - 0x78160002, // 0005 JMPF R5 #0009 - 0x60140013, // 0006 GETGBL R5 G19 - 0x7C140000, // 0007 CALL R5 0 - 0x90020205, // 0008 SETMBR R0 K1 R5 - 0x88140102, // 0009 GETMBR R5 R0 K2 - 0x4C180000, // 000A LDNIL R6 - 0x1C140A06, // 000B EQ R5 R5 R6 - 0x78160004, // 000C JMPF R5 #0012 - 0xB8160600, // 000D GETNGBL R5 K3 - 0x8C140B04, // 000E GETMET R5 R5 K4 - 0x841C0000, // 000F CLOSURE R7 P0 - 0x7C140400, // 0010 CALL R5 2 - 0x90020405, // 0011 SETMBR R0 K2 R5 - 0x8C140105, // 0012 GETMET R5 R0 K5 - 0x5C1C0600, // 0013 MOVE R7 R3 - 0x7C140400, // 0014 CALL R5 2 - 0x88140101, // 0015 GETMBR R5 R0 K1 - 0x98140802, // 0016 SETIDX R5 R4 R2 - 0x88140102, // 0017 GETMBR R5 R0 K2 - 0xA0000000, // 0018 CLOSE R0 - 0x80040A00, // 0019 RET 1 R5 - 0x7002000B, // 001A JMP #0027 - 0x88140106, // 001B GETMBR R5 R0 K6 - 0x4C180000, // 001C LDNIL R6 - 0x1C140A06, // 001D EQ R5 R5 R6 - 0x78160004, // 001E JMPF R5 #0024 - 0xB8160600, // 001F GETNGBL R5 K3 - 0x8C140B04, // 0020 GETMET R5 R5 K4 - 0x881C0107, // 0021 GETMBR R7 R0 K7 - 0x7C140400, // 0022 CALL R5 2 - 0x90020C05, // 0023 SETMBR R0 K6 R5 - 0x88140106, // 0024 GETMBR R5 R0 K6 - 0xA0000000, // 0025 CLOSE R0 - 0x80040A00, // 0026 RET 1 R5 - 0xA0000000, // 0027 CLOSE R0 - 0x80000000, // 0028 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: deregister_obj -********************************************************************/ -be_local_closure(LVGL_glob_deregister_obj, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str(cb_obj), - /* K1 */ be_nested_str(remove), - /* K2 */ be_nested_str(cb_event_closure), - }), - &be_const_str_deregister_obj, - &be_const_str_solidified, - ( &(const binstruction[17]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x20080403, // 0002 NE R2 R2 R3 - 0x780A0003, // 0003 JMPF R2 #0008 - 0x88080100, // 0004 GETMBR R2 R0 K0 - 0x8C080501, // 0005 GETMET R2 R2 K1 - 0x5C100200, // 0006 MOVE R4 R1 - 0x7C080400, // 0007 CALL R2 2 - 0x88080102, // 0008 GETMBR R2 R0 K2 - 0x4C0C0000, // 0009 LDNIL R3 - 0x20080403, // 000A NE R2 R2 R3 - 0x780A0003, // 000B JMPF R2 #0010 - 0x88080102, // 000C GETMBR R2 R0 K2 - 0x8C080501, // 000D GETMET R2 R2 K1 - 0x5C100200, // 000E MOVE R4 R1 - 0x7C080400, // 000F CALL R2 2 - 0x80000000, // 0010 RET 0 + 0x88180104, // 0008 GETMBR R6 R0 K4 + 0x8C180D05, // 0009 GETMET R6 R6 K5 + 0x5C200A00, // 000A MOVE R8 R5 + 0x7C180400, // 000B CALL R6 2 + 0x781A0001, // 000C JMPF R6 #000F + 0x88180104, // 000D GETMBR R6 R0 K4 + 0x94140C05, // 000E GETIDX R5 R6 R5 + 0x60180004, // 000F GETGBL R6 G4 + 0x5C1C0A00, // 0010 MOVE R7 R5 + 0x7C180200, // 0011 CALL R6 1 + 0x1C180D06, // 0012 EQ R6 R6 K6 + 0x781A0007, // 0013 JMPF R6 #001C + 0x8C180707, // 0014 GETMET R6 R3 K7 + 0x5C200A00, // 0015 MOVE R8 R5 + 0x58240008, // 0016 LDCONST R9 K8 + 0x7C180600, // 0017 CALL R6 3 + 0x781A0002, // 0018 JMPF R6 #001C + 0x8C180B08, // 0019 GETMET R6 R5 K8 + 0x5C200800, // 001A MOVE R8 R4 + 0x7C180400, // 001B CALL R6 2 + 0x80000000, // 001C RET 0 }) ) ); @@ -396,7 +106,7 @@ be_local_closure(LVGL_glob_deregister_obj, /* name */ ********************************************************************/ be_local_closure(LVGL_glob_widget_cb, /* name */ be_nested_proto( - 4, /* nstack */ + 5, /* nstack */ 1, /* argc */ 0, /* varg */ 0, /* has upvals */ @@ -481,8 +191,8 @@ be_local_closure(LVGL_glob_widget_cb, /* name */ }), 1, /* has constants */ ( &(const bvalue[15]) { /* constants */ - /* K0 */ be_nested_str(widget_ctor_cb), - /* K1 */ be_nested_str(tasmota), + /* K0 */ be_nested_str(cb), + /* K1 */ be_nested_str(widget_ctor_cb), /* K2 */ be_nested_str(gen_cb), /* K3 */ be_nested_str(widget_dtor_cb), /* K4 */ be_nested_str(widget_event_cb), @@ -499,63 +209,61 @@ be_local_closure(LVGL_glob_widget_cb, /* name */ }), &be_const_str_widget_cb, &be_const_str_solidified, - ( &(const binstruction[56]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x4C080000, // 0001 LDNIL R2 - 0x1C040202, // 0002 EQ R1 R1 R2 - 0x78060004, // 0003 JMPF R1 #0009 - 0xB8060200, // 0004 GETNGBL R1 K1 - 0x8C040302, // 0005 GETMET R1 R1 K2 - 0x840C0000, // 0006 CLOSURE R3 P0 - 0x7C040400, // 0007 CALL R1 2 - 0x90020001, // 0008 SETMBR R0 K0 R1 - 0x88040103, // 0009 GETMBR R1 R0 K3 - 0x4C080000, // 000A LDNIL R2 - 0x1C040202, // 000B EQ R1 R1 R2 - 0x78060004, // 000C JMPF R1 #0012 - 0xB8060200, // 000D GETNGBL R1 K1 - 0x8C040302, // 000E GETMET R1 R1 K2 - 0x840C0001, // 000F CLOSURE R3 P1 - 0x7C040400, // 0010 CALL R1 2 - 0x90020601, // 0011 SETMBR R0 K3 R1 - 0x88040104, // 0012 GETMBR R1 R0 K4 - 0x4C080000, // 0013 LDNIL R2 - 0x1C040202, // 0014 EQ R1 R1 R2 - 0x78060004, // 0015 JMPF R1 #001B - 0xB8060200, // 0016 GETNGBL R1 K1 - 0x8C040302, // 0017 GETMET R1 R1 K2 - 0x840C0002, // 0018 CLOSURE R3 P2 - 0x7C040400, // 0019 CALL R1 2 - 0x90020801, // 001A SETMBR R0 K4 R1 - 0x88040105, // 001B GETMBR R1 R0 K5 - 0x4C080000, // 001C LDNIL R2 - 0x1C040202, // 001D EQ R1 R1 R2 - 0x78060016, // 001E JMPF R1 #0036 - 0xB8060C00, // 001F GETNGBL R1 K6 - 0x8C040307, // 0020 GETMET R1 R1 K7 - 0xB80E0C00, // 0021 GETNGBL R3 K6 - 0x880C0708, // 0022 GETMBR R3 R3 K8 - 0x880C0709, // 0023 GETMBR R3 R3 K9 - 0x7C040400, // 0024 CALL R1 2 - 0x8C04030A, // 0025 GETMET R1 R1 K10 - 0x7C040200, // 0026 CALL R1 1 - 0x90020A01, // 0027 SETMBR R0 K5 R1 - 0x88040105, // 0028 GETMBR R1 R0 K5 - 0xB80A0C00, // 0029 GETNGBL R2 K6 - 0x88080508, // 002A GETMBR R2 R2 K8 - 0x88080509, // 002B GETMBR R2 R2 K9 - 0x90061602, // 002C SETMBR R1 K11 R2 - 0x88040105, // 002D GETMBR R1 R0 K5 - 0x88080100, // 002E GETMBR R2 R0 K0 - 0x90061802, // 002F SETMBR R1 K12 R2 - 0x88040105, // 0030 GETMBR R1 R0 K5 - 0x88080103, // 0031 GETMBR R2 R0 K3 - 0x90061A02, // 0032 SETMBR R1 K13 R2 - 0x88040105, // 0033 GETMBR R1 R0 K5 - 0x88080104, // 0034 GETMBR R2 R0 K4 - 0x90061C02, // 0035 SETMBR R1 K14 R2 - 0xA0000000, // 0036 CLOSE R0 - 0x80000000, // 0037 RET 0 + ( &(const binstruction[54]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x88080101, // 0001 GETMBR R2 R0 K1 + 0x4C0C0000, // 0002 LDNIL R3 + 0x1C080403, // 0003 EQ R2 R2 R3 + 0x780A0003, // 0004 JMPF R2 #0009 + 0x8C080302, // 0005 GETMET R2 R1 K2 + 0x84100000, // 0006 CLOSURE R4 P0 + 0x7C080400, // 0007 CALL R2 2 + 0x90020202, // 0008 SETMBR R0 K1 R2 + 0x88080103, // 0009 GETMBR R2 R0 K3 + 0x4C0C0000, // 000A LDNIL R3 + 0x1C080403, // 000B EQ R2 R2 R3 + 0x780A0003, // 000C JMPF R2 #0011 + 0x8C080302, // 000D GETMET R2 R1 K2 + 0x84100001, // 000E CLOSURE R4 P1 + 0x7C080400, // 000F CALL R2 2 + 0x90020602, // 0010 SETMBR R0 K3 R2 + 0x88080104, // 0011 GETMBR R2 R0 K4 + 0x4C0C0000, // 0012 LDNIL R3 + 0x1C080403, // 0013 EQ R2 R2 R3 + 0x780A0003, // 0014 JMPF R2 #0019 + 0x8C080302, // 0015 GETMET R2 R1 K2 + 0x84100002, // 0016 CLOSURE R4 P2 + 0x7C080400, // 0017 CALL R2 2 + 0x90020802, // 0018 SETMBR R0 K4 R2 + 0x88080105, // 0019 GETMBR R2 R0 K5 + 0x4C0C0000, // 001A LDNIL R3 + 0x1C080403, // 001B EQ R2 R2 R3 + 0x780A0016, // 001C JMPF R2 #0034 + 0xB80A0C00, // 001D GETNGBL R2 K6 + 0x8C080507, // 001E GETMET R2 R2 K7 + 0xB8120C00, // 001F GETNGBL R4 K6 + 0x88100908, // 0020 GETMBR R4 R4 K8 + 0x88100909, // 0021 GETMBR R4 R4 K9 + 0x7C080400, // 0022 CALL R2 2 + 0x8C08050A, // 0023 GETMET R2 R2 K10 + 0x7C080200, // 0024 CALL R2 1 + 0x90020A02, // 0025 SETMBR R0 K5 R2 + 0x88080105, // 0026 GETMBR R2 R0 K5 + 0xB80E0C00, // 0027 GETNGBL R3 K6 + 0x880C0708, // 0028 GETMBR R3 R3 K8 + 0x880C0709, // 0029 GETMBR R3 R3 K9 + 0x900A1603, // 002A SETMBR R2 K11 R3 + 0x88080105, // 002B GETMBR R2 R0 K5 + 0x880C0101, // 002C GETMBR R3 R0 K1 + 0x900A1803, // 002D SETMBR R2 K12 R3 + 0x88080105, // 002E GETMBR R2 R0 K5 + 0x880C0103, // 002F GETMBR R3 R0 K3 + 0x900A1A03, // 0030 SETMBR R2 K13 R3 + 0x88080105, // 0031 GETMBR R2 R0 K5 + 0x880C0104, // 0032 GETMBR R3 R0 K4 + 0x900A1C03, // 0033 SETMBR R2 K14 R3 + 0xA0000000, // 0034 CLOSE R0 + 0x80000000, // 0035 RET 0 }) ) ); @@ -729,9 +437,90 @@ be_local_closure(LVGL_glob_create_custom_widget, /* name */ /******************************************************************** -** Solidified function: widget_ctor_impl +** Solidified function: register_obj ********************************************************************/ -be_local_closure(LVGL_glob_widget_ctor_impl, /* name */ +be_local_closure(LVGL_glob_register_obj, /* name */ + be_nested_proto( + 4, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str(cb_obj), + /* K1 */ be_nested_str(_p), + }), + &be_const_str_register_obj, + &be_const_str_solidified, + ( &(const binstruction[11]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x1C080403, // 0002 EQ R2 R2 R3 + 0x780A0002, // 0003 JMPF R2 #0007 + 0x60080013, // 0004 GETGBL R2 G19 + 0x7C080000, // 0005 CALL R2 0 + 0x90020002, // 0006 SETMBR R0 K0 R2 + 0x88080301, // 0007 GETMBR R2 R1 K1 + 0x880C0100, // 0008 GETMBR R3 R0 K0 + 0x980C0401, // 0009 SETIDX R3 R2 R1 + 0x80000000, // 000A RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: deregister_obj +********************************************************************/ +be_local_closure(LVGL_glob_deregister_obj, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str(cb_obj), + /* K1 */ be_nested_str(remove), + /* K2 */ be_nested_str(cb_event_closure), + }), + &be_const_str_deregister_obj, + &be_const_str_solidified, + ( &(const binstruction[17]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x20080403, // 0002 NE R2 R2 R3 + 0x780A0003, // 0003 JMPF R2 #0008 + 0x88080100, // 0004 GETMBR R2 R0 K0 + 0x8C080501, // 0005 GETMET R2 R2 K1 + 0x5C100200, // 0006 MOVE R4 R1 + 0x7C080400, // 0007 CALL R2 2 + 0x88080102, // 0008 GETMBR R2 R0 K2 + 0x4C0C0000, // 0009 LDNIL R3 + 0x20080403, // 000A NE R2 R2 R3 + 0x780A0003, // 000B JMPF R2 #0010 + 0x88080102, // 000C GETMBR R2 R0 K2 + 0x8C080501, // 000D GETMET R2 R2 K1 + 0x5C100200, // 000E MOVE R4 R1 + 0x7C080400, // 000F CALL R2 2 + 0x80000000, // 0010 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: widget_dtor_impl +********************************************************************/ +be_local_closure(LVGL_glob_widget_dtor_impl, /* name */ be_nested_proto( 10, /* nstack */ 3, /* argc */ @@ -741,20 +530,18 @@ be_local_closure(LVGL_glob_widget_ctor_impl, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ + ( &(const bvalue[ 7]) { /* constants */ /* K0 */ be_nested_str(introspect), /* K1 */ be_nested_str(lv), /* K2 */ be_nested_str(lv_obj_class), /* K3 */ be_nested_str(get_object_from_ptr), - /* K4 */ be_nested_str(cb_obj), - /* K5 */ be_nested_str(find), - /* K6 */ be_nested_str(instance), - /* K7 */ be_nested_str(get), - /* K8 */ be_nested_str(widget_constructor), + /* K4 */ be_nested_str(instance), + /* K5 */ be_nested_str(get), + /* K6 */ be_nested_str(widget_destructor), }), - &be_const_str_widget_ctor_impl, + &be_const_str_widget_dtor_impl, &be_const_str_solidified, - ( &(const binstruction[29]) { /* code */ + ( &(const binstruction[22]) { /* code */ 0xA40E0000, // 0000 IMPORT R3 K0 0xB8120200, // 0001 GETNGBL R4 K1 0x8C100902, // 0002 GETMET R4 R4 K2 @@ -763,27 +550,338 @@ be_local_closure(LVGL_glob_widget_ctor_impl, /* name */ 0x8C140103, // 0005 GETMET R5 R0 K3 0x5C1C0400, // 0006 MOVE R7 R2 0x7C140400, // 0007 CALL R5 2 - 0x88180104, // 0008 GETMBR R6 R0 K4 - 0x8C180D05, // 0009 GETMET R6 R6 K5 - 0x5C200A00, // 000A MOVE R8 R5 - 0x7C180400, // 000B CALL R6 2 - 0x781A0001, // 000C JMPF R6 #000F - 0x88180104, // 000D GETMBR R6 R0 K4 - 0x94140C05, // 000E GETIDX R5 R6 R5 - 0x60180004, // 000F GETGBL R6 G4 - 0x5C1C0A00, // 0010 MOVE R7 R5 - 0x7C180200, // 0011 CALL R6 1 - 0x1C180D06, // 0012 EQ R6 R6 K6 - 0x781A0007, // 0013 JMPF R6 #001C - 0x8C180707, // 0014 GETMET R6 R3 K7 - 0x5C200A00, // 0015 MOVE R8 R5 - 0x58240008, // 0016 LDCONST R9 K8 - 0x7C180600, // 0017 CALL R6 3 - 0x781A0002, // 0018 JMPF R6 #001C - 0x8C180B08, // 0019 GETMET R6 R5 K8 - 0x5C200800, // 001A MOVE R8 R4 - 0x7C180400, // 001B CALL R6 2 - 0x80000000, // 001C RET 0 + 0x60180004, // 0008 GETGBL R6 G4 + 0x5C1C0A00, // 0009 MOVE R7 R5 + 0x7C180200, // 000A CALL R6 1 + 0x1C180D04, // 000B EQ R6 R6 K4 + 0x781A0007, // 000C JMPF R6 #0015 + 0x8C180705, // 000D GETMET R6 R3 K5 + 0x5C200A00, // 000E MOVE R8 R5 + 0x58240006, // 000F LDCONST R9 K6 + 0x7C180600, // 0010 CALL R6 3 + 0x781A0002, // 0011 JMPF R6 #0015 + 0x8C180B06, // 0012 GETMET R6 R5 K6 + 0x5C200800, // 0013 MOVE R8 R4 + 0x7C180400, // 0014 CALL R6 2 + 0x80000000, // 0015 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(LVGL_glob_init, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 1]) { + be_nested_proto( + 8, /* nstack */ + 3, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(make_cb), + }), + &be_const_str__X3Clambda_X3E, + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x680C0000, // 0000 GETUPV R3 U0 + 0x8C0C0700, // 0001 GETMET R3 R3 K0 + 0x5C140000, // 0002 MOVE R5 R0 + 0x5C180200, // 0003 MOVE R6 R1 + 0x5C1C0400, // 0004 MOVE R7 R2 + 0x7C0C0800, // 0005 CALL R3 4 + 0x80040600, // 0006 RET 1 R3 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str(cb), + /* K1 */ be_nested_str(add_handler), + /* K2 */ be_nested_str(lv_extra), + }), + &be_const_str_init, + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x8C080301, // 0001 GETMET R2 R1 K1 + 0x84100000, // 0002 CLOSURE R4 P0 + 0x7C080400, // 0003 CALL R2 2 + 0xA40A0400, // 0004 IMPORT R2 K2 + 0xA0000000, // 0005 CLOSE R0 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: widget_event_impl +********************************************************************/ +be_local_closure(LVGL_glob_widget_event_impl, /* name */ + be_nested_proto( + 12, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[12]) { /* constants */ + /* K0 */ be_nested_str(introspect), + /* K1 */ be_nested_str(lv), + /* K2 */ be_nested_str(lv_obj_class), + /* K3 */ be_nested_str(lv_event), + /* K4 */ be_nested_str(target), + /* K5 */ be_nested_str(get_object_from_ptr), + /* K6 */ be_nested_str(instance), + /* K7 */ be_nested_str(code), + /* K8 */ be_nested_str(EVENT_DELETE), + /* K9 */ be_nested_str(get), + /* K10 */ be_nested_str(before_del), + /* K11 */ be_nested_str(widget_event), + }), + &be_const_str_widget_event_impl, + &be_const_str_solidified, + ( &(const binstruction[43]) { /* code */ + 0xA40E0000, // 0000 IMPORT R3 K0 + 0xB8120200, // 0001 GETNGBL R4 K1 + 0x8C100902, // 0002 GETMET R4 R4 K2 + 0x5C180200, // 0003 MOVE R6 R1 + 0x7C100400, // 0004 CALL R4 2 + 0xB8160200, // 0005 GETNGBL R5 K1 + 0x8C140B03, // 0006 GETMET R5 R5 K3 + 0x5C1C0400, // 0007 MOVE R7 R2 + 0x7C140400, // 0008 CALL R5 2 + 0x88180B04, // 0009 GETMBR R6 R5 K4 + 0x8C1C0105, // 000A GETMET R7 R0 K5 + 0x5C240C00, // 000B MOVE R9 R6 + 0x7C1C0400, // 000C CALL R7 2 + 0x60200004, // 000D GETGBL R8 G4 + 0x5C240E00, // 000E MOVE R9 R7 + 0x7C200200, // 000F CALL R8 1 + 0x1C201106, // 0010 EQ R8 R8 K6 + 0x78220017, // 0011 JMPF R8 #002A + 0x88200B07, // 0012 GETMBR R8 R5 K7 + 0xB8260200, // 0013 GETNGBL R9 K1 + 0x88241308, // 0014 GETMBR R9 R9 K8 + 0x1C201009, // 0015 EQ R8 R8 R9 + 0x78220009, // 0016 JMPF R8 #0021 + 0x8C200709, // 0017 GETMET R8 R3 K9 + 0x5C280E00, // 0018 MOVE R10 R7 + 0x582C000A, // 0019 LDCONST R11 K10 + 0x7C200600, // 001A CALL R8 3 + 0x78220004, // 001B JMPF R8 #0021 + 0x8C200F0A, // 001C GETMET R8 R7 K10 + 0x5C280800, // 001D MOVE R10 R4 + 0x5C2C0A00, // 001E MOVE R11 R5 + 0x7C200600, // 001F CALL R8 3 + 0x70020008, // 0020 JMP #002A + 0x8C200709, // 0021 GETMET R8 R3 K9 + 0x5C280E00, // 0022 MOVE R10 R7 + 0x582C000B, // 0023 LDCONST R11 K11 + 0x7C200600, // 0024 CALL R8 3 + 0x78220003, // 0025 JMPF R8 #002A + 0x8C200F0B, // 0026 GETMET R8 R7 K11 + 0x5C280800, // 0027 MOVE R10 R4 + 0x5C2C0A00, // 0028 MOVE R11 R5 + 0x7C200600, // 0029 CALL R8 3 + 0x80000000, // 002A RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: make_cb +********************************************************************/ +be_local_closure(LVGL_glob_make_cb, /* name */ + be_nested_proto( + 9, /* nstack */ + 4, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 1]) { + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(lvgl_event_dispatch), + }), + &be_const_str__X3Clambda_X3E, + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x68040000, // 0000 GETUPV R1 U0 + 0x8C040300, // 0001 GETMET R1 R1 K0 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C040400, // 0003 CALL R1 2 + 0x80040200, // 0004 RET 1 R1 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[17]) { /* constants */ + /* K0 */ be_nested_str(cb), + /* K1 */ be_nested_str(lv_event_cb), + /* K2 */ be_nested_str(cb_event_closure), + /* K3 */ be_nested_str(event_cb), + /* K4 */ be_nested_str(gen_cb), + /* K5 */ be_nested_str(register_obj), + /* K6 */ be_nested_str(contains), + /* K7 */ be_nested_str(_p), + /* K8 */ be_nested_str(tasmota), + /* K9 */ be_nested_str(log), + /* K10 */ be_nested_str(LVG_X3A_X20object_X3A), + /* K11 */ be_nested_str(has_X20already_X20an_X20event_X20callback), + /* K12 */ be_const_int(2), + /* K13 */ be_const_int(0), + /* K14 */ be_nested_str(lv_), + /* K15 */ be_nested_str(null_cb), + /* K16 */ be_nested_str(cb_do_nothing), + }), + &be_const_str_make_cb, + &be_const_str_solidified, + ( &(const binstruction[63]) { /* code */ + 0xA4120000, // 0000 IMPORT R4 K0 + 0x1C140701, // 0001 EQ R5 R3 K1 + 0x78160026, // 0002 JMPF R5 #002A + 0x88140102, // 0003 GETMBR R5 R0 K2 + 0x4C180000, // 0004 LDNIL R6 + 0x1C140A06, // 0005 EQ R5 R5 R6 + 0x78160002, // 0006 JMPF R5 #000A + 0x60140013, // 0007 GETGBL R5 G19 + 0x7C140000, // 0008 CALL R5 0 + 0x90020405, // 0009 SETMBR R0 K2 R5 + 0x88140103, // 000A GETMBR R5 R0 K3 + 0x4C180000, // 000B LDNIL R6 + 0x1C140A06, // 000C EQ R5 R5 R6 + 0x78160003, // 000D JMPF R5 #0012 + 0x8C140904, // 000E GETMET R5 R4 K4 + 0x841C0000, // 000F CLOSURE R7 P0 + 0x7C140400, // 0010 CALL R5 2 + 0x90020605, // 0011 SETMBR R0 K3 R5 + 0x8C140105, // 0012 GETMET R5 R0 K5 + 0x5C1C0400, // 0013 MOVE R7 R2 + 0x7C140400, // 0014 CALL R5 2 + 0x88140102, // 0015 GETMBR R5 R0 K2 + 0x8C140B06, // 0016 GETMET R5 R5 K6 + 0x881C0507, // 0017 GETMBR R7 R2 K7 + 0x7C140400, // 0018 CALL R5 2 + 0x78160008, // 0019 JMPF R5 #0023 + 0xB8161000, // 001A GETNGBL R5 K8 + 0x8C140B09, // 001B GETMET R5 R5 K9 + 0x601C0008, // 001C GETGBL R7 G8 + 0x5C200400, // 001D MOVE R8 R2 + 0x7C1C0200, // 001E CALL R7 1 + 0x001E1407, // 001F ADD R7 K10 R7 + 0x001C0F0B, // 0020 ADD R7 R7 K11 + 0x5820000C, // 0021 LDCONST R8 K12 + 0x7C140600, // 0022 CALL R5 3 + 0x88140507, // 0023 GETMBR R5 R2 K7 + 0x88180102, // 0024 GETMBR R6 R0 K2 + 0x98180A01, // 0025 SETIDX R6 R5 R1 + 0x88140103, // 0026 GETMBR R5 R0 K3 + 0xA0000000, // 0027 CLOSE R0 + 0x80040A00, // 0028 RET 1 R5 + 0x70020012, // 0029 JMP #003D + 0x40161B0C, // 002A CONNECT R5 K13 K12 + 0x94140605, // 002B GETIDX R5 R3 R5 + 0x1C140B0E, // 002C EQ R5 R5 K14 + 0x7816000B, // 002D JMPF R5 #003A + 0x8814010F, // 002E GETMBR R5 R0 K15 + 0x4C180000, // 002F LDNIL R6 + 0x1C140A06, // 0030 EQ R5 R5 R6 + 0x78160003, // 0031 JMPF R5 #0036 + 0x8C140904, // 0032 GETMET R5 R4 K4 + 0x881C0110, // 0033 GETMBR R7 R0 K16 + 0x7C140400, // 0034 CALL R5 2 + 0x90021E05, // 0035 SETMBR R0 K15 R5 + 0x8814010F, // 0036 GETMBR R5 R0 K15 + 0xA0000000, // 0037 CLOSE R0 + 0x80040A00, // 0038 RET 1 R5 + 0x70020002, // 0039 JMP #003D + 0x4C140000, // 003A LDNIL R5 + 0xA0000000, // 003B CLOSE R0 + 0x80040A00, // 003C RET 1 R5 + 0xA0000000, // 003D CLOSE R0 + 0x80000000, // 003E RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: lvgl_event_dispatch +********************************************************************/ +be_local_closure(LVGL_glob_lvgl_event_dispatch, /* name */ + be_nested_proto( + 10, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str(introspect), + /* K1 */ be_nested_str(lv), + /* K2 */ be_nested_str(lv_event), + /* K3 */ be_nested_str(toptr), + /* K4 */ be_nested_str(target), + /* K5 */ be_nested_str(cb_event_closure), + /* K6 */ be_nested_str(get_object_from_ptr), + }), + &be_const_str_lvgl_event_dispatch, + &be_const_str_solidified, + ( &(const binstruction[18]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0xB80E0200, // 0001 GETNGBL R3 K1 + 0x8C0C0702, // 0002 GETMET R3 R3 K2 + 0x8C140503, // 0003 GETMET R5 R2 K3 + 0x5C1C0200, // 0004 MOVE R7 R1 + 0x7C140400, // 0005 CALL R5 2 + 0x7C0C0400, // 0006 CALL R3 2 + 0x88100704, // 0007 GETMBR R4 R3 K4 + 0x88140105, // 0008 GETMBR R5 R0 K5 + 0x94140A04, // 0009 GETIDX R5 R5 R4 + 0x8C180106, // 000A GETMET R6 R0 K6 + 0x5C200800, // 000B MOVE R8 R4 + 0x7C180400, // 000C CALL R6 2 + 0x5C1C0A00, // 000D MOVE R7 R5 + 0x5C200C00, // 000E MOVE R8 R6 + 0x5C240600, // 000F MOVE R9 R3 + 0x7C1C0400, // 0010 CALL R7 2 + 0x80000000, // 0011 RET 0 }) ) ); @@ -796,28 +894,29 @@ be_local_closure(LVGL_glob_widget_ctor_impl, /* name */ be_local_class(LVGL_glob, 9, NULL, - be_nested_map(20, + be_nested_map(21, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key(widget_ctor_cb, 9), be_const_var(4) }, - { be_const_key(get_object_from_ptr, 4), be_const_closure(LVGL_glob_get_object_from_ptr_closure) }, - { be_const_key(cb_obj, 7), be_const_var(0) }, - { be_const_key(widget_struct_by_class, -1), be_const_var(8) }, - { be_const_key(widget_event_impl, -1), be_const_closure(LVGL_glob_widget_event_impl_closure) }, - { be_const_key(widget_dtor_cb, 6), be_const_var(5) }, - { be_const_key(cb_event_closure, -1), be_const_var(1) }, - { be_const_key(lvgl_event_dispatch, 16), be_const_closure(LVGL_glob_lvgl_event_dispatch_closure) }, - { be_const_key(widget_dtor_impl, -1), be_const_closure(LVGL_glob_widget_dtor_impl_closure) }, - { be_const_key(null_cb, -1), be_const_var(3) }, - { be_const_key(register_obj, 8), be_const_closure(LVGL_glob_register_obj_closure) }, - { be_const_key(gen_cb, -1), be_const_closure(LVGL_glob_gen_cb_closure) }, - { be_const_key(widget_struct_default, -1), be_const_var(7) }, - { be_const_key(deregister_obj, 12), be_const_closure(LVGL_glob_deregister_obj_closure) }, - { be_const_key(widget_event_cb, -1), be_const_var(6) }, + { be_const_key(get_object_from_ptr, 7), be_const_closure(LVGL_glob_get_object_from_ptr_closure) }, + { be_const_key(widget_ctor_impl, 6), be_const_closure(LVGL_glob_widget_ctor_impl_closure) }, { be_const_key(widget_cb, -1), be_const_closure(LVGL_glob_widget_cb_closure) }, - { be_const_key(cb_do_nothing, 3), be_const_closure(LVGL_glob__anonymous__closure) }, + { be_const_key(lvgl_event_dispatch, -1), be_const_closure(LVGL_glob_lvgl_event_dispatch_closure) }, + { be_const_key(cb_do_nothing, 10), be_const_static_closure(LVGL_glob__anonymous__closure) }, + { be_const_key(widget_struct_by_class, -1), be_const_var(8) }, + { be_const_key(cb_event_closure, 19), be_const_var(1) }, + { be_const_key(widget_dtor_impl, -1), be_const_closure(LVGL_glob_widget_dtor_impl_closure) }, + { be_const_key(register_obj, -1), be_const_closure(LVGL_glob_register_obj_closure) }, + { be_const_key(deregister_obj, -1), be_const_closure(LVGL_glob_deregister_obj_closure) }, + { be_const_key(widget_event_cb, -1), be_const_var(6) }, + { be_const_key(widget_ctor_cb, -1), be_const_var(4) }, + { be_const_key(init, -1), be_const_closure(LVGL_glob_init_closure) }, + { be_const_key(widget_event_impl, -1), be_const_closure(LVGL_glob_widget_event_impl_closure) }, + { be_const_key(widget_dtor_cb, -1), be_const_var(5) }, + { be_const_key(cb_obj, 11), be_const_var(0) }, + { be_const_key(make_cb, -1), be_const_closure(LVGL_glob_make_cb_closure) }, + { be_const_key(null_cb, -1), be_const_var(3) }, { be_const_key(event_cb, -1), be_const_var(2) }, { be_const_key(create_custom_widget, -1), be_const_closure(LVGL_glob_create_custom_widget_closure) }, - { be_const_key(widget_ctor_impl, -1), be_const_closure(LVGL_glob_widget_ctor_impl_closure) }, + { be_const_key(widget_struct_default, 3), be_const_var(7) }, })), be_str_literal("LVGL_glob") ); @@ -828,5 +927,3 @@ void be_load_LVGL_glob_class(bvm *vm) { be_setglobal(vm, "LVGL_glob"); be_pop(vm, 1); } - -#endif // USE_LVGL \ No newline at end of file diff --git a/lib/libesp32_lvgl/lv_berry/src/embedded/ctypes.be b/lib/libesp32_lvgl/lv_berry/src/embedded/ctypes.be new file mode 100644 index 000000000..6ed6226e8 --- /dev/null +++ b/lib/libesp32_lvgl/lv_berry/src/embedded/ctypes.be @@ -0,0 +1,623 @@ +#------------------------------------------------------------- +#- Ctypes for Berry +#- +#- Inspired from Python's ctypes structure +#-------------------------------------------------------------# +import string + +ctypes = module('ctypes') + +#------------------------------------------------------------- +#- Basic types for mapping +#- +#- ints of size 1/2/4 bytes (little endian by default) +#- usigned ints of size 1/2/4 bytes (little endian by default) +#- +#- (Big Endian are negative numbers) +#-------------------------------------------------------------# + +# default is little_endian +ctypes.i32 = 14 +ctypes.i16 = 12 +ctypes.i8 = 11 +ctypes.u32 = 4 +ctypes.u16 = 2 +ctypes.u8 = 1 + +# explicit little endian +ctypes.le_i32 = 14 +ctypes.le_i16 = 12 +ctypes.le_i8 = 11 +ctypes.le_u32 = 4 +ctypes.le_u16 = 2 +ctypes.le_u8 = 1 + +# big endian +ctypes.be_i32 = -14 +ctypes.be_i16 = -12 +ctypes.be_i8 = -11 +ctypes.be_u32 = -4 +ctypes.be_u16 = -2 +ctypes.be_u8 = -1 + +# floating point +ctypes.float = 5 +ctypes.double = 10 + +# pointer +ctypes.ptr32 = 9 +ctypes.ptr64 = -9 + +ctypes.bf_x = 0 # generic bitfield +# bitfields (always unsigned) +ctypes.bf_0 = 100 # serves as base +ctypes.bf_1 = 101 +ctypes.bf_2 = 102 +ctypes.bf_3 = 103 +ctypes.bf_4 = 104 +ctypes.bf_5 = 105 +ctypes.bf_6 = 106 +ctypes.bf_7 = 107 +ctypes.bf_8 = 108 +ctypes.bf_9 = 109 +ctypes.bf_10 = 110 +ctypes.bf_11 = 111 +ctypes.bf_12 = 112 +ctypes.bf_13 = 113 +ctypes.bf_14 = 114 +ctypes.bf_15 = 115 +ctypes.bf_16 = 116 + +ctypes.type_mapping = { + 14: "ctypes_i32", + 12: "ctypes_i16", + 11: "ctypes_i8", + 4: "ctypes_u32", + 2: "ctypes_u16", + 1: "ctypes_u8", + + -14:"ctypes_be_i32", # big endian + -12:"ctypes_be_i16", + -11:"ctypes_be_i8", + -4: "ctypes_be_u32", + -2: "ctypes_be_u16", + -1: "ctypes_be_u8", + + 5: "ctypes_float", + 10: "ctypes_double", + 9: "ctypes_ptr32", + -9: "ctypes_ptr64", + + 0: "ctypes_bf" # bitfield +} + +ctypes.type_to_str = def (type_num) + var type_name = ctypes.type_mapping.find(type_num) + if type_name == nil + return str(type_num) + end + return type_name +end + +def findinlist(l, x) + for i:0..size(l)-1 + if l[i] == x + return i + end + end +end + +#------------------------------------------------------------- +#- 'get_bits' function +#- +#- Reads a bit-field in a `bytes()` object +#- +#- Input: +#- b: bytes() object to read from +#- offset_bytes (int): byte offset in the bytes() object +#- offset_bits (int): bit number to start reading from (0 = LSB) +#- len_bits (int): how many bits to read +#- Output: +#- valuer (int) +#-------------------------------------------------------------# +ctypes.get_bits = def (b, offset_bytes, offset_bits, len_bits) + if !isinstance(b, bytes) raise "value_error", "first argument must be of type 'bytes'" end + if offset_bits < 0 || offset_bits > 7 raise "value_error", "offset_bits must be between 0 and 7" end + if len_bits <= 0 || len_bits > 32 raise "value_error", "length in bits must be between 0 and 32" end + var ret = 0 + + var bit_shift = 0 # bit number to write to + + while (len_bits > 0) + var block_bits = 8 - offset_bits # how many bits to read in the current block (block = byte) + if block_bits > len_bits block_bits = len_bits end + + var mask = ( (1<> offset_bits) << bit_shift) + + # move the input window + bit_shift += block_bits + len_bits -= block_bits + offset_bits = 0 # start at full next byte + offset_bytes += 1 + end + + return ret +end + +ctypes.sort = def (l) + # insertion sort + for i:1..size(l)-1 + var k = l[i] + var j = i + while (j > 0) && (l[j-1] > k) + l[j] = l[j-1] + j -= 1 + end + l[j] = k + end + return l +end + +#------------------------------------------------------------- +#- 'set_bits' function +#- +#- Writes a bit-field in a `bytes()` object +#- +#- Input: +#- b: bytes() object to write to +#- offset_bytes (int): byte offset in the bytes() object +#- offset_bits (int): bit number to start writing to (0 = LSB) +#- len_bits (int): how many bits to write +#- Output: +#- bytes() object modified (by reference) +#-------------------------------------------------------------# +ctypes.set_bits = def (b, offset_bytes, offset_bits, len_bits, val) + if !isinstance(b, bytes) raise "value_error", "first argument must be of type 'bytes'" end + if offset_bits < 0 || offset_bits > 7 raise "value_error", "offset_bits must be between 0 and 7" end + if len_bits <= 0 || len_bits > 32 raise "value_error", "length in bits must be between 0 and 32" end + + while (len_bits > 0) + var block_bits = 8 - offset_bits # how many bits to write in the current block (block = byte) + if block_bits > len_bits block_bits = len_bits end + + var mask_val = (1<>= block_bits + len_bits -= block_bits + offset_bits = 0 # start at full next byte + offset_bytes += 1 + end + return b +end + + +#- print the C types -#1 +ctypes.print_types = def () + print("/********************************************************************") + print(" * Generated code, don't edit") + print(" *******************************************************************/") + print() + print("static const char * be_ctypes_instance_mappings[]; /* forward definition */") + print() +end + +global_classes = [] # track the list of all classes and +global_mappings = [] # mapping to Berry classes, ex: lv_color + +ctypes.print_classes = def (module_name) + # print mappings + if size(global_mappings) > 7 + raise "internal_error", "too many mappings, 7 max" + end + print("static const char * be_ctypes_instance_mappings[] = {") + for n:global_mappings.iter() + print(string.format(" \"%s\",", n)) + end + print(" NULL") + print("};") + print() + + ctypes.sort(global_classes) + + for elt:global_classes + print(string.format("static be_define_ctypes_class(%s, &be_%s, &be_class_ctypes, \"%s\");", elt, elt, elt)) + end + + print() + print(string.format("void be_load_ctypes_%s_definitions_lib(bvm *vm) {", module_name)) + for elt:global_classes + print(string.format(" ctypes_register_class(vm, &be_class_%s, &be_%s);", elt, elt)) + end + print("}") + print() + print("be_ctypes_class_by_name_t be_ctypes_lvgl_classes[] = {") + for elt:global_classes + print(string.format(" { \"%s\", &be_class_%s },", elt, elt)) + end + print("};") + print("const size_t be_ctypes_lvgl_classes_size = sizeof(be_ctypes_lvgl_classes)/sizeof(be_ctypes_lvgl_classes[0]);") + print() + + print("/********************************************************************/") + print() +end + +#------------------------------------------------------------- +#- 'ctypes.structure' class +#- +#- Parses a ctypes structure descriptor and creates +#- a set of getters and setters +#- +#-------------------------------------------------------------# +class structure + var cur_offset # offset in bytes from buffer start + var bit_offset # are we intra-byte? + var get_closures # + var set_closures # + var size_bytes # size in bytes + var mapping # map to generate C binding + + # init world + def init(mapping, name) + self.cur_offset = 0 + self.bit_offset = 0 + self.size_bytes = 0 # overall size in bytes + self.get_closures = {} + self.set_closures = {} + self.mapping = {} + + # parse mapping + self.parse_mapping(mapping, name) + end + #- iteratively parse mapping + #- + #- if name is not nil, it also outputs a C structure for the mapping + #- + #-------------------------------------------------------------# + def parse_mapping(mapping, name) + for map_line: mapping + self.parse_line(map_line) + end + + # clear any outstanding bitfield + self.align(1) + self.size_bytes = self.cur_offset + + if name != nil + print(string.format("const be_ctypes_structure_t be_%s = {", name)) + print(string.format(" %i, /* size in bytes */", self.size_bytes)) + print(string.format(" %i, /* number of elements */", size(self.mapping))) + print(string.format(" be_ctypes_instance_mappings,")) + print(string.format(" (const be_ctypes_structure_item_t[%i]) {", size(self.mapping))) + # list keys for future binary search + var names = [] + for n:self.mapping.keys() names.push(n) end # convert to list + ctypes.sort(names) + for n:names + var args = self.mapping[n] + print(string.format(" { \"%s\", %i, %i, %i, %s, %i },", n, args[0], args[1], args[2], ctypes.type_to_str(args[3]), args[4])) + end + print("}};") + print() + + # retain class definition + global_classes.push(name) + end + end + + def size() + return self.size_bytes + end + + # parse a single line + def parse_line(map_line) + var type_obj = map_line[0] + var name = map_line[1] + var bits = 0 + if size(map_line) >= 3 bits = map_line[2] end + + if isinstance(type_obj, ctypes.structure) + # nested structure + self.nested(name, type_obj) + end + + var mapping_idx = 0 # mapping starts at 1 + if isinstance(type_obj, list) + # it may be a list to denote a mapping to an instance + var mapping_name = type_obj[1] + if findinlist(global_mappings, mapping_name) == nil + global_mappings.push(mapping_name) + end + mapping_idx = findinlist(global_mappings, mapping_name) + 1 + + type_obj = type_obj[0] # take the simple value of first element in the list + end + + if type(type_obj) == 'int' + # simple attibute + # TODO check actual type + if type_obj > ctypes.bf_0 + # bit field + self.get_bitfield_closure(name, type_obj - ctypes.bf_0, mapping_idx) + elif (type_obj == ctypes.ptr32) || (type_obj == ctypes.ptr64) + # pointer + self.get_ptr_closure(name, type_obj, mapping_idx) + elif (type_obj == ctypes.float) || (type_obj == ctypes.double) + # multi-bytes + self.get_float_closure(name, type_obj, mapping_idx) + else + # multi-bytes + self.get_int_closure(name, type_obj, mapping_idx) + end + end + end + + #- ensure alignment to 1/2/4 bytes -# + def align(n) + if n != 1 && n != 2 && n != 4 raise "value_error", "acceptable values are 1/2/4" end + + #- align to byte boundary if we're in a bitfield -# + if self.bit_offset != 0 + #- we are not byte aligned, let's re-aling -# + self.cur_offset += 1 + self.bit_offset = 0 + end + + #- check 2/4 bytes alignment -# + if self.cur_offset % n != 0 + # we are not aligned with current size + self.cur_offset += n - self.cur_offset % n + end + end + + def nested(name, type_obj) + var sub_size = type_obj.size() + if sub_size <= 0 raise "value_error", "empty sub-structure not supported" end + + # align to appropriate sub-size + var align_size = sub_size + if align_size == 3 || align_size > 4 align_size = 4 end + self.align(align_size) + + var offset = self.cur_offset # var for closure + + # include nested + for subname:type_obj.mapping.keys() + var val = type_obj.mapping[subname] + self.mapping[name+"_"+subname] = [val[0] + offset, val[1], val[2], val[3], val[4]] + end + # self.mapping[name] = [offset << 3, sub_size << 3] + + self.get_closures[name] = def (b, p) return ctypes.nested_buffer(type_obj, offset + p, b) end + # self.set_closures[name] = def (b, p, v) return ctypes.nested_buffer(type_obj, offset + p, b) end + + self.cur_offset += sub_size + end + + def get_int_closure(name, type, instance_mapping) # can be 1/2/4 + #- abs size -# + var size_in_bytes = type < 0 ? - type : type + var signed = size_in_bytes > 10 + var size_in_bytes_le_be = type % 10 # remove sign marker + size_in_bytes = size_in_bytes % 10 # remove sign marker + + self.align(size_in_bytes) # force alignment + var offset = self.cur_offset # prepare variable for capture in closure + + self.mapping[name] = [offset, 0, 0, type, instance_mapping] + + #- add closures -# + if signed + self.get_closures[name] = def (b, p) return b.geti(offset + p, size_in_bytes_le_be) end + else + self.get_closures[name] = def (b, p) return b.get(offset + p, size_in_bytes_le_be) end + end + self.set_closures[name] = def (b, p, v) return b.set(offset+ p, v, size_in_bytes_le_be) end + + self.cur_offset += size_in_bytes # next offset + end + + def get_ptr_closure(name, type, instance_mapping) # can be 1/2/4 + #- actual size -# + import introspect + var size_in_bytes = (type == ctypes.ptr32) ? 4 : 8 + + self.align(size_in_bytes) # force alignment + var offset = self.cur_offset # prepare variable for capture in closure + + self.mapping[name] = [offset, 0, 0, type, instance_mapping] + + #- add closures -# + # TODO no closure yet, anyways need to rethink closures, they are too heavy + # if signed + # self.get_closures[name] = def (b, p) return b.geti(offset + p, size_in_bytes_le_be) end + # else + # self.get_closures[name] = def (b, p) return b.get(offset + p, size_in_bytes_le_be) end + # end + # self.set_closures[name] = def (b, p, v) return b.set(offset+ p, v, size_in_bytes_le_be) end + + self.cur_offset += size_in_bytes # next offset + end + + def get_float_closure(name, type, instance_mapping) # can be 1/2/4 + #- actual size -# + var size_in_bytes = (type == ctypes.float) ? 4 : 8 + + self.align(size_in_bytes) # force alignment + var offset = self.cur_offset # prepare variable for capture in closure + + self.mapping[name] = [offset, 0, 0, type, instance_mapping] + + #- add closures -# + # TODO no closure yet, anyways need to rethink closures, they are too heavy + # if signed + # self.get_closures[name] = def (b, p) return b.geti(offset + p, size_in_bytes_le_be) end + # else + # self.get_closures[name] = def (b, p) return b.get(offset + p, size_in_bytes_le_be) end + # end + # self.set_closures[name] = def (b, p, v) return b.set(offset+ p, v, size_in_bytes_le_be) end + + self.cur_offset += size_in_bytes # next offset + end + + def get_bitfield_closure(name, size_in_bits, instance_mapping) # can be 1..32 + var cur_offset = self.cur_offset # prepare variable for capture in closure + var bit_offset = self.bit_offset + self.mapping[name] = [cur_offset, bit_offset, size_in_bits, 0, instance_mapping] + self.get_closures[name] = def (b, p) return ctypes.get_bits(b, cur_offset + p, bit_offset, size_in_bits) end + self.set_closures[name] = def (b, p, v) return ctypes.set_bits(b, cur_offset+ p, bit_offset, size_in_bits, v) end + + self.cur_offset += (self.bit_offset + size_in_bits) / 8 + self.bit_offset = (self.bit_offset + size_in_bits) % 8 + end +end + +ctypes.structure = structure + +#------------------------------------------------------------- +#- Structured buffer +#- +#- Inspired from Python's ctypes structure +#- +#- This class is a wrapper around `bytes()` object (actually a subclass) +#- providing virtual members mapped to the ctypes structure. +#- +#- Takes as argument a ctypes.structure and an optional bytes() object +#-------------------------------------------------------------# +class buffer : bytes + var _cs # ctypes_structure associated + + def init(cs, b) + if !isinstance(cs, ctypes.structure) raise "value_error", "first argument must be an instance of 'ctypes.structure'" end + self._cs = cs + var size = self._cs.size() # size in bytes of the structure + + super(self, bytes).init(size) # init bytes object with reserved size in memory + + if isinstance(b, bytes) + self..b + end + self.resize(size) # size once for all to the target size and complete with 00s + end + + # accessor for virtual member + def member(name) + return self._cs.get_closures[name](self, 0) + end + + # setter for virtual member + def setmember(name, value) + self._cs.set_closures[name](self, 0, value) + end +end +ctypes.buffer = buffer + +#------------------------------------------------------------- +#- Nested buffer +#- +#- Nested structures are just pointers to the master bytes() object +#-------------------------------------------------------------# +class nested_buffer + var _cs # ctypes.structure instance for this buffer + var _offset # offset un bytes() to the structure + var _bytes # reference to the overall buffer (by reference) + + def init(cs, offset, b) + if !isinstance(cs, ctypes.structure) raise "value_error", "first argument must be an instance of 'ctypes.structure'" end + if type(offset) != 'int' raise "value_error", "second argument must be of type 'int'" end + if !isinstance(b, bytes) raise "value_error", "third argument must be an instance of 'bytes'" end + self._cs = cs + self._offset = offset + self._bytes = b + end + + # accessor for virtual member + def member(name) + return self._cs.get_closures[name](self._bytes, self._offset) + end + + # setter for virtual member + def setmember(name, value) + self._cs.set_closures[name](self._bytes, self._offset, value) + end + + def tostring() + return self._bytes[self._offset..self._offset+self._cs.size()-1].tostring() + end +end +ctypes.nested_buffer = nested_buffer + + +return ctypes + +# ex = [ +# [ctypes.u32, "a"], +# [ctypes.u16, "b"], +# [ctypes.i8, "c"], +# [ctypes.i32, "d"], # should infer an empty byte +# ] + +# cs = ctypes.structure(ex) +# bb = ctypes.buffer(cs, bytes("aabb")) + +# fa = cp.get_int_closure('a', 4) +# fb = cp.get_int_closure('b', 2) +# fc = cp.get_int_closure('c', 1) +# fd = cp.get_int_closure('d', 4) + +# b = bytes("04030201AA55FFFF00010001") + +# cp.get_closures['a'](b) +# cp.get_closures['b'](b) +# cp.get_closures['c'](b) +# cp.get_closures['d'](b) + +# bb = ctypes_buffer(cp, b) + +# bb.a = 0x11223344 +# bb +# bb.a + + +# > bb = ctypes_buffer(cp, b) +# > bb.a +# 16909060 +# > bb.b +# 21930 +# > bb.c +# 255 +# > bb.d +# 16777472 +# > bb.e +# key_error: e +# stack traceback: +# : in native function +# stdin:11: in function `member` +# stdin:1: in function `main` + + +# > bb['a'] +# 16909060 +# > bb['b'] +# 21930 +# > bb['c'] +# 255 +# > bb['d'] +# 16777472 + +#- +> fa(b) +16909060 +> fb(b) +21930 +> fc(b) +255 +> fd(b) +16777472 + +-# diff --git a/lib/libesp32_lvgl/lv_berry/src/embedded/lv.be b/lib/libesp32_lvgl/lv_berry/src/embedded/lv.be new file mode 100644 index 000000000..b59331921 --- /dev/null +++ b/lib/libesp32_lvgl/lv_berry/src/embedded/lv.be @@ -0,0 +1,20 @@ +#- ------------------------------------------------------------ -# +# Module `lv` - allows to extend the soidified `lv` module +#- ------------------------------------------------------------ -# +lv = module("lv") + +# rename `lv` to `lv_ntv` and replace `lv` with `lv_tasmota` +def lv_module_init(lv_solidified) + var lv_new = module("lv") # create a dynamic module + lv_new.member = lv_solidified.member + # lv_new.lv_solidified = lv_solidified + return lv_new +end + +lv.init = lv_module_init + +def lv0_member_ntv() end + +lv.member = lv0_member_ntv + +return lv diff --git a/tasmota/berry/modules/lvgl_ctypes.be b/lib/libesp32_lvgl/lv_berry/src/embedded/lvgl_ctypes.be similarity index 80% rename from tasmota/berry/modules/lvgl_ctypes.be rename to lib/libesp32_lvgl/lv_berry/src/embedded/lvgl_ctypes.be index ee1a0e226..1ff9c2c68 100644 --- a/tasmota/berry/modules/lvgl_ctypes.be +++ b/lib/libesp32_lvgl/lv_berry/src/embedded/lvgl_ctypes.be @@ -24,11 +24,13 @@ lv_text_decor = ctypes.u8 lv_font = ctypes.u32 lv_blend_mode = ctypes.u8 lv_draw_mask_line_side = ctypes.u8 +lv_dir = ctypes.u8 uint8_t_1 = ctypes.bf_1 uint8_t_2 = ctypes.bf_2 uint8_t_3 = ctypes.bf_3 uint8_t_4 = ctypes.bf_4 uint8_t_5 = ctypes.bf_5 +uint8_t_11 = ctypes.bf_11 uint8_t = ctypes.u8 int16_t = ctypes.i16 uint16_t = ctypes.u16 @@ -335,6 +337,29 @@ lv_meter_indicator_scale_lines = [ # valid LVGL8 ] lv_meter_indicator_scale_lines = ctypes.structure(lv_meter_indicator_scale_lines, "lv_meter_indicator_scale_lines") +lv_chart_series = [ + [ptr, "x_points"], + [ptr, "y_points"], + [lv_color, "color"], + [uint16_t, "start_point"], + [uint8_t_1, "hidden"], + [uint8_t_1, "x_ext_buf_assigned"], + [uint8_t_1, "y_ext_buf_assigned"], + [uint8_t_1, "x_axis_sec"], + [uint8_t_1, "y_axis_sec"], +] +lv_chart_series = ctypes.structure(lv_chart_series, "lv_chart_series") + +lv_chart_cursor = [ + [lv_point, "pos"], + [uint16_t, "point_id"], + [lv_color, "color"], + [ptr, "ser"], + [lv_dir, "dir"], + [uint8_t_1, "pos_set"], +] +lv_chart_cursor = ctypes.structure(lv_chart_cursor, "lv_chart_cursor") + #- --------- class system --------- -# lv_obj_class_ptr = ptr lv_obj_ptr = ptr @@ -369,6 +394,75 @@ lv_event = [ # valid LVGL8 ] lv_event = ctypes.structure(lv_event, "lv_event") +####################################################################### +# lv_img structures +lv_img_header = [ # valid LVGL8 + [uint8_t_5, "cf"], + [uint8_t_3, "always_zero"], + [uint8_t_2, "reserved"], + [uint8_t_11, "w"], + [uint8_t_11, "h"], +] +lv_img_header = ctypes.structure(lv_img_header, "lv_img_header") + +lv_img_dsc = [ # valid LVGL8 + [lv_img_header, "header"], + [uint8_t_5, "cf"], + [uint32_t, "data_size"], + [ptr, "data"], +] +lv_img_dsc = ctypes.structure(lv_img_dsc, "lv_img_dsc") + +####################################################################### +# lv_style +lv_style_transition_dsc = [ # valid LVGL8 + [ptr, "props"], + [ptr, "user_data"], + [ptr, "path_xcb"], + [uint32_t, "time"], + [uint32_t, "delay"], +] +lv_style_transition_dsc = ctypes.structure(lv_style_transition_dsc, "lv_style_transition_dsc") + +####################################################################### +# lv_color +# lv_color_hsv = [ # valid LVGL8 +# [uint16_t, "h"], +# [uint8_t, "s"], +# [uint8_t, "v"], +# ] +# lv_color_hsv = ctypes.structure(lv_color_hsv, "lv_color_hsv") + +lv_color_filter_dsc = [ # valid LVGL8 + [ptr, "filter_cb"], + [ptr, "user_data"], +] +lv_color_filter_dsc = ctypes.structure(lv_color_filter_dsc, "lv_color_filter_dsc") + +####################################################################### +# lv_timer +lv_timer = [ # valid LVGL8 + [uint32_t, "period"], + [uint32_t, "last_run"], + [ptr, "timer_cb"], + [ptr, "user_data"], + [int32_t, "repeat_count"], + [uint8_t_1, "paused"], +] +lv_timer = ctypes.structure(lv_timer, "lv_timer") + +####################################################################### +# Special structure used to calibrate resistive touchscreens +####################################################################### +lv_ts_calibration = [ # valid LVGL8 + [lv_coord, "raw_x"], + [lv_coord, "raw_y"], + [lv_coord, "x"], + [lv_coord, "y"], + [int32_t, "state"], +] +lv_ts_calibration = ctypes.structure(lv_ts_calibration, "lv_ts_calibration") + # ctypes.print_classes("lvgl") diff --git a/lib/libesp32_lvgl/lv_berry/src/embedded/lvgl_extra.be b/lib/libesp32_lvgl/lv_berry/src/embedded/lvgl_extra.be new file mode 100644 index 000000000..f2bfeb337 --- /dev/null +++ b/lib/libesp32_lvgl/lv_berry/src/embedded/lvgl_extra.be @@ -0,0 +1,61 @@ +# classes for extra components + +var lv_extra = module("lv_extra") + +class lv_coord_arr : bytes + def init(l) + if type(l) != 'instance' || !isinstance(l, list) raise "value_error", "argument must be a list" end + # size of the array is 2x number of elements + super(self).init(size(l) * 2) + + for e: l + self.add(int(e), 2) + end + end +end + +class lv_point_arr : bytes + def init(l) + if type(l) != 'instance' || !isinstance(l, list) raise "value_error", "argument must be a list" end + # size of the array is 2x number of elements + super(self).init(size(l) * 4) + + for e: l + if type(e) != 'instance' || !isinstance(e, lv.lv_point) raise "value_error", "elements must be a lv_point" end + self.add(e.x, 2) + self.add(e.y, 2) + end + end +end + +lv_extra.lv_coord_arr = lv_coord_arr +lv_extra.lv_point_arr = lv_point_arr + +lv_extra.init = def (m) + import global + var lv = global.lv + + lv.lv_coord_arr = m.lv_coord_arr + lv.lv_point_arr = m.lv_point_arr + lv.coord_arr = m.lv_coord_arr + lv.point_arr = m.lv_point_arr + + return m +end + +return lv_extra + +#- + +print(lv_coord_arr([1,2,3])) +# bytes('010002000300') + +var p1 = lv.point() +p1.x = 1 +p1.y = 2 +var p2 = lv.point() +p2.x = 3 +p2.y = 4 +print(lv_point_arr([p1, p2])) + +-# \ No newline at end of file diff --git a/lib/libesp32/Berry/default/embedded/lvgl_glob.be b/lib/libesp32_lvgl/lv_berry/src/embedded/lvgl_glob.be similarity index 85% rename from lib/libesp32/Berry/default/embedded/lvgl_glob.be rename to lib/libesp32_lvgl/lv_berry/src/embedded/lvgl_glob.be index f7f6b8e84..14eb05878 100644 --- a/lib/libesp32/Berry/default/embedded/lvgl_glob.be +++ b/lib/libesp32_lvgl/lv_berry/src/embedded/lvgl_glob.be @@ -20,11 +20,18 @@ class LVGL_glob #- this is the fallback callback, if the event is unknown or unsupported -# static cb_do_nothing = def() print("LVG: call to unsupported callback") end + # register our callback handler to `module cb` + def init() + import cb + cb.add_handler(/ f, obj, name -> self.make_cb(f, obj, name)) + # load extra modules + import lv_extra + end + #- register an lv.lv_* object in the mapping -# def register_obj(obj) if self.cb_obj == nil self.cb_obj = {} end - var native_ptr = int(obj._p) - self.cb_obj[native_ptr] = obj + self.cb_obj[obj._p] = obj end def get_object_from_ptr(ptr) @@ -38,28 +45,34 @@ class LVGL_glob var event = lv.lv_event(introspect.toptr(event_ptr)) - var target = int(event.target) + var target = event.target var f = self.cb_event_closure[target] var obj = self.get_object_from_ptr(target) #print('>> lvgl_event_dispatch', f, obj, event) f(obj, event) end - def gen_cb(name, f, obj, ptr) - #print('>> gen_cb', name, obj, ptr) + def make_cb(f, obj, name) + import cb + # print('>> make_cb', f, name, obj) # record the object, whatever the callback if name == "lv_event_cb" - if self.cb_event_closure == nil self.cb_event_closure = {} end - if self.event_cb == nil self.event_cb = tasmota.gen_cb(/ event_ptr -> self.lvgl_event_dispatch(event_ptr)) end # encapsulate 'self' in closure + if self.cb_event_closure == nil self.cb_event_closure = {} end # lazy instanciation + if self.event_cb == nil self.event_cb = cb.gen_cb(/ event_ptr -> self.lvgl_event_dispatch(event_ptr)) end # encapsulate 'self' in closure - self.register_obj(obj) - self.cb_event_closure[ptr] = f + self.register_obj(obj) # keep a record of the object to prevent from being gc'ed + if self.cb_event_closure.contains(obj._p) + tasmota.log("LVG: object:" + str(obj) + "has already an event callback", 2) + end + self.cb_event_closure[obj._p] = f # keep a mapping of the closure to call, indexed by internal lvgl native pointer return self.event_cb # elif name == "" - else - if self.null_cb == nil self.null_cb = tasmota.gen_cb(self.cb_do_nothing) end + elif name[0..2] == "lv_" + if self.null_cb == nil self.null_cb = cb.gen_cb(self.cb_do_nothing) end return self.null_cb + else + return nil # the call is not for us, pass to next handler end end @@ -87,18 +100,23 @@ class LVGL_glob var cl = lv.lv_obj_class(cl_ptr) var event = lv.lv_event(e_ptr) var obj_ptr = event.target - var obj = self.get_object_from_ptr(int(obj_ptr)) - if type(obj) == 'instance' && introspect.get(obj, 'widget_event') - obj.widget_event(cl, event) + var obj = self.get_object_from_ptr(obj_ptr) + if type(obj) == 'instance' + if event.code == lv.EVENT_DELETE && introspect.get(obj, 'before_del') + obj.before_del(cl, event) + elif introspect.get(obj, 'widget_event') + obj.widget_event(cl, event) + end end # print("widget_event_impl", cl, obj_ptr, obj, event) end def widget_cb() - if self.widget_ctor_cb == nil self.widget_ctor_cb = tasmota.gen_cb(/ cl, obj -> self.widget_ctor_impl(cl, obj)) end - if self.widget_dtor_cb == nil self.widget_dtor_cb = tasmota.gen_cb(/ cl, obj -> self.widget_dtor_impl(cl, obj)) end - if self.widget_event_cb == nil self.widget_event_cb = tasmota.gen_cb(/ cl, e -> self.widget_event_impl(cl, e)) end + import cb + if self.widget_ctor_cb == nil self.widget_ctor_cb = cb.gen_cb(/ cl, obj -> self.widget_ctor_impl(cl, obj)) end + if self.widget_dtor_cb == nil self.widget_dtor_cb = cb.gen_cb(/ cl, obj -> self.widget_dtor_impl(cl, obj)) end + if self.widget_event_cb == nil self.widget_event_cb = cb.gen_cb(/ cl, e -> self.widget_event_impl(cl, e)) end if self.widget_struct_default == nil self.widget_struct_default = lv.lv_obj_class(lv.lv_obj._class).copy() diff --git a/lib/libesp32_lvgl/lv_berry/src/lv_berry.c b/lib/libesp32_lvgl/lv_berry/src/lv_berry.c new file mode 100644 index 000000000..ac003c519 --- /dev/null +++ b/lib/libesp32_lvgl/lv_berry/src/lv_berry.c @@ -0,0 +1,318 @@ +#include "lv_berry.h" +#include "be_mapping.h" + +#include "be_exec.h" +#include "be_vm.h" +#include "be_mem.h" + +#include + +#include "../generate/be_lv_c_mapping.h" + +extern void be_load_lv_color_class(bvm *vm); +extern void be_load_lv_font_class(bvm *vm); +extern void be_load_LVGL_glob_class(bvm *vm); + +/*********************************************************************************************\ + * Load all LVGL classes, including widgets +\*********************************************************************************************/ +void be_load_lvgl_classes(bvm *vm) { + be_load_lv_color_class(vm); + be_load_lv_font_class(vm); + be_load_LVGL_glob_class(vm); +} + +/*********************************************************************************************\ + * Retrieve the value of `self._p` +\*********************************************************************************************/ +// Get the `_p` member of instance at `index` +void * lv_get_arg(bvm *vm, int index) { + void * ret = NULL; + if (be_isinstance(vm, index)) { + be_getmember(vm, index, "_p"); + ret = be_tocomptr(vm, -1); + be_pop(vm, 1); // remove _p attribute + } + return ret; +} + +/*********************************************************************************************\ + * Support for lv_indev and objects that don't need creator +\*********************************************************************************************/ +int lv0_init(bvm *vm); +int lv0_init(bvm *vm) { + // "+_p" indicates that there must be an non NULL argument, either passed as comptr or returned by the function + // Here, there is no function, so calling the constructor without a non-null comptr argument is rejected + return be_call_c_func(vm, NULL, "+_p", NULL); +} + +/*********************************************************************************************\ + * Generalized tostring method, shows class and _p value +\*********************************************************************************************/ +int lv_x_tostring(bvm *vm) { + lv_obj_t * obj = (lv_obj_t*) lv_get_arg(vm, 1); + const char * classname = be_classname(vm, 1); + char s[48]; + snprintf(s, sizeof(s), "", classname, obj); + be_pushnstring(vm, s, strlen(s)); /* make escape string from buffer */ + be_return(vm); +} + +/*********************************************************************************************\ + * Support for lv_style `init()` + * + * Either encapsulate the pointer passed as `comptr` as arg1 + * Or allocate a new empty style structure in memory. In this case, it is never freed. +\*********************************************************************************************/ +int lv_be_style_init(bvm *vm) { + int argc = be_top(vm); + lv_style_t * style = NULL; + + if (argc > 1) { + style = (lv_style_t*) be_convert_single_elt(vm, 2, NULL, NULL); + } + if (style == NULL) { + // if no valid pointer passed, allocate a new empty style + style = (lv_style_t*) be_malloc(vm, sizeof(lv_style_t)); + if (style == NULL) { + be_throw(vm, BE_MALLOC_FAIL); + } + if (style != NULL) { + lv_style_init(style); + } + } + be_pushcomptr(vm, style); + be_setmember(vm, 1, "_p"); + be_return_nil(vm); +} + +// native closure to call `be_call_c_func` +int lv_x_call_c(bvm *vm) { + // berry_log_C("lv_x_call_c enter"); + // keep parameters unchanged + be_getupval(vm, 0, 0); // if index is zero, it's the current native closure + void * func = be_tocomptr(vm, -1); + be_getupval(vm, 0, 1); // if index is zero, it's the current native closure + const char * return_type = be_tostring(vm, -1); + be_getupval(vm, 0, 2); // if index is zero, it's the current native closure + const char * arg_type = be_tostring(vm, -1); + be_pop(vm, 3); // remove 3 upvals + + // berry_log_C("lv_x_call_c %p '%s' <- (%s)", func, return_type, arg_type); + return be_call_c_func(vm, func, return_type, arg_type); +} + +// virtual method, arg1: instance, arg2: name of method +int lv_x_member(bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc == 2 && be_isinstance(vm, 1) && be_isstring(vm, 2)) { + const char * method_name = be_tostring(vm, 2); // the method we are looking for + while (be_isinstance(vm, 1)) { + const char * class_name = be_classname(vm, 1); + // berry_log_C("lv_x_member looking for method '%s' of class '%s'", method_name, class_name); + + // look for class descriptor + int32_t class_idx = be_map_bin_search(class_name, &lv_classes[0].name, sizeof(lv_classes[0]), lv_classes_size); + if (class_idx >= 0) { + const be_ntv_func_def_t * methods_calls = lv_classes[class_idx].func_table; + size_t methods_size = lv_classes[class_idx].size; + + int32_t method_idx = be_map_bin_search(method_name, methods_calls, sizeof(be_ntv_func_def_t), methods_size); + if (method_idx >= 0) { + // method found + const be_ntv_func_def_t * method = &methods_calls[method_idx]; + // berry_log_C("lv_x_member method found func=%p return_type=%s arg_type=%s", method->func, method->return_type, method->arg_type); + // push native closure + be_pushntvclosure(vm, &lv_x_call_c, 3); // 3 upvals + + be_pushcomptr(vm, method->args.func); + be_setupval(vm, -2, 0); + be_pop(vm, 1); + + be_pushstring(vm, method->args.return_type); + be_setupval(vm, -2, 1); + be_pop(vm, 1); + + be_pushstring(vm, method->args.arg_type); + be_setupval(vm, -2, 2); + be_pop(vm, 1); + + // all good + be_return(vm); + } + } + + // get super if any, or nil if none + be_getsuper(vm, 1); + be_moveto(vm, -1, 1); + be_pop(vm, 1); + } + // berry_log_C("lv_x_member method not found"); + be_return_nil(vm); + } + be_raise(vm, "type_error", NULL); +} + +// lv_color +// First arg is a 24 bits RGB color +// If first arg is `nil` second arg is the native value of color +int lco_init(bvm *vm) { + int argc = be_top(vm); + uint32_t color32 = 0x000000; // default to black + + if (argc > 1) { + color32 = be_toint(vm, 2); + } + lv_color_t lv_color = lv_color_hex(color32); + if (argc > 2 && be_toint(vm, 3) == -1) { + lv_color.full = be_toint(vm, 2); + } + be_pushint(vm, lv_color_to_uint32(lv_color)); + be_setmember(vm, 1, "_p"); + be_return_nil(vm); +} + +int lco_tostring(bvm *vm) { + lv_color_t lv_color = {}; + be_getmember(vm, 1, "_p"); + uint32_t ntv_color = be_toint(vm, -1); + lv_color = lv_color_from_uint32(ntv_color); + uint32_t color = lv_color_to32(lv_color) & 0xFFFFFF; + be_pop(vm, 1); // remove attribute + char s[48]; + snprintf(s, sizeof(s), "lv_color(0x%06x - native:0x%04x)", color, ntv_color); + be_pushnstring(vm, s, strlen(s)); /* make escape string from buffer */ + be_return(vm); +} + +int lco_toint(bvm *vm) { + lv_color_t lv_color = {}; + be_getmember(vm, 1, "_p"); + uint32_t ntv_color = be_toint(vm, -1); + be_pushint(vm, ntv_color); + be_return(vm); +} + + + +// function is (void) -> lv_obt_t* +typedef lv_obj_t* (*fn_lvobj__void)(void); // f() -> newly created lv_obj() +int lv0_lvobj__void_call(bvm *vm, fn_lvobj__void func) { + lv_obj_t * obj = (*func)(); + be_find_global_or_module_member(vm, "lv.lv_obj"); + be_pushcomptr(vm, (void*) -1); // stack = class, -1 + be_pushcomptr(vm, (void*) obj); // stack = class, -1, ptr + be_call(vm, 2); // instanciate, stack = instance (don't call init() ) + be_pop(vm, 2); // stack = instance + be_return(vm); +} + +/*********************************************************************************************\ + * Support for lv_fonts +\*********************************************************************************************/ +// load font by name on file-system +int lv0_load_font(bvm *vm) { + int argc = be_top(vm); + if (argc == 1 && be_isstring(vm, 1)) { + lv_font_t * font = lv_font_load(be_tostring(vm, 1)); + if (font != NULL) { + be_find_global_or_module_member(vm, "lv.lv_font"); + be_pushcomptr(vm, font); + be_call(vm, 1); + be_pop(vm, 1); + be_return(vm); + } else { + be_return_nil(vm); + } + } + be_raise(vm, "type_error", NULL); +} + +/*********************************************************************************************\ + * Get Touch Screen calibration information +\*********************************************************************************************/ +lv_ts_calibration_t lv_ts_calibration = { + 0, 0, + 0, 0, + LV_INDEV_STATE_RELEASED +}; + +lv_ts_calibration_t * lv_get_ts_calibration(void) { + return &lv_ts_calibration; +} + +/*********************************************************************************************\ + * LVGL top level virtual members + * + * Responds to virtual constants +\*********************************************************************************************/ + +extern const be_ntv_func_def_t lv_func[]; +extern const size_t lv_func_size; + +extern const be_const_member_t lv0_constants[]; +extern const size_t lv0_constants_size; + +extern const be_ctypes_class_by_name_t be_ctypes_lvgl_classes[]; +extern const size_t be_ctypes_lvgl_classes_size; + +int lv0_member(bvm *vm); +int lv0_member(bvm *vm) { + // first try the standard way + if (be_const_module_member(vm, lv0_constants, lv0_constants_size)) { + be_return(vm); + } + // try alternative members + int32_t argc = be_top(vm); // Get the number of arguments + if (argc == 1 && be_isstring(vm, 1)) { + const char * needle = be_tostring(vm, 1); + int32_t idx; + + // search for a class with this name + char cl_prefixed[32]; + snprintf(cl_prefixed, sizeof(cl_prefixed), "lv_%s", needle); // we try both actual name and prefixed with `lv_` so both `lv.obj` and `lv.lv_obj` work + idx = be_map_bin_search(cl_prefixed, &lv_classes[0].name, sizeof(lv_classes[0]), lv_classes_size); + if (idx < 0) { + idx = be_map_bin_search(needle, &lv_classes[0].name, sizeof(lv_classes[0]), lv_classes_size); + } + if (idx >= 0) { + // we did have a match + be_pushntvclass(vm, lv_classes[idx].cl); + be_return(vm); + } + // same search for ctypes + idx = be_map_bin_search(cl_prefixed, &be_ctypes_lvgl_classes[0].name, sizeof(be_ctypes_lvgl_classes[0]), be_ctypes_lvgl_classes_size); + if (idx < 0) { + idx = be_map_bin_search(needle, &be_ctypes_lvgl_classes[0].name, sizeof(be_ctypes_lvgl_classes[0]), be_ctypes_lvgl_classes_size); + } + if (idx >= 0) { + // we did have a match + be_pushntvclass(vm, be_ctypes_lvgl_classes[idx].cl); + be_return(vm); + } + + // search for a method with this name + idx = be_map_bin_search(needle, &lv_func[0].name, sizeof(lv_func[0]), lv_func_size); + if (idx >= 0) { + const be_ntv_func_def_t * method = &lv_func[idx]; + // push native closure + be_pushntvclosure(vm, &lv_x_call_c, 3); // 3 upvals + + be_pushcomptr(vm, method->args.func); + be_setupval(vm, -2, 0); + be_pop(vm, 1); + + be_pushstring(vm, method->args.return_type); + be_setupval(vm, -2, 1); + be_pop(vm, 1); + + be_pushstring(vm, method->args.arg_type); + be_setupval(vm, -2, 2); + be_pop(vm, 1); + + // all good + be_return(vm); + } + } + be_return_nil(vm); +} diff --git a/lib/libesp32_lvgl/lv_berry/src/lv_berry.h b/lib/libesp32_lvgl/lv_berry/src/lv_berry.h new file mode 100644 index 000000000..e494e1187 --- /dev/null +++ b/lib/libesp32_lvgl/lv_berry/src/lv_berry.h @@ -0,0 +1,44 @@ + + +#ifndef __LV_BERRY__ +#define __LV_BERRY__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "berry.h" +#include "lvgl.h" + +/*********************************************************************************************\ + * Support for lv_color +\*********************************************************************************************/ +inline lv_color_t lv_color_from_uint32(uint32_t ucol) { + lv_color_t * col = (lv_color_t*) &ucol; + return *col; +} +inline uint32_t lv_color_to_uint32(lv_color_t col) { + uint16_t *p = (uint16_t*) &col; + return *p; +} + +extern void be_load_lvgl_classes(bvm *vm); + +// TODO temporary fix +extern void lv_img_set_tasmota_logo(lv_obj_t * img); + +// used for ToushScreen calibration +typedef struct lv_ts_calibration_t { + lv_coord_t raw_x; + lv_coord_t raw_y; + lv_coord_t x; + lv_coord_t y; + lv_indev_state_t state; +} lv_ts_calibration_t; +extern lv_ts_calibration_t lv_ts_calibration; + + +#ifdef __cplusplus +} +#endif +#endif // __LV_BERRY__ diff --git a/tools/lv_berry/convert.py b/lib/libesp32_lvgl/lv_berry/tools/convert.py similarity index 79% rename from tools/lv_berry/convert.py rename to lib/libesp32_lvgl/lv_berry/tools/convert.py index a814af381..63230eadb 100644 --- a/tools/lv_berry/convert.py +++ b/lib/libesp32_lvgl/lv_berry/tools/convert.py @@ -1,11 +1,11 @@ import re import sys -lv_widgets_file = "lv_funcs.h" -lv_module_file = "lv_enum.h" +lv_widgets_file = "../mapping/lv_funcs.h" +lv_module_file = "../mapping/lv_enum.h" -out_prefix = "../../tasmota/lvgl_berry/" -lvgl_prefix = "../../lib/libesp32/Berry/default/" +out_prefix = "../generate/" +lvgl_prefix = "../generate/" be_lv_defines = "be_lv_defines.h" be_lv_c_mapping = "be_lv_c_mapping.h" @@ -22,7 +22,7 @@ parse_func_def = re.compile("(.*?)\s(\w+)\((.*?)\)") # parse call argument type # Ex: 'const lv_obj_t * parent' -> 'const ', 'lv_obj_t', ' * ', 'parent' # Ex: 'bool auto_fit' -> '', 'bool', ' ', 'auto_fit' -parse_arg = re.compile("(\w+\s+)?(\w+)([\*\s]+)(\w+)") +parse_arg = re.compile("(\w+\s+)?(\w+)([\*\s]+)(\w+)(\[\])?") return_types = { "void": "", @@ -98,9 +98,21 @@ return_types = { "lv_colorwheel_mode_t": "i", "lv_scr_load_anim_t": "i", "lv_style_selector_t": "i", + "lv_draw_mask_res_t": "i", + "lv_img_size_mode_t": "i", + "lv_palette_t": "i", + # layouts + "lv_flex_align_t": "i", + "lv_flex_flow_t": "i", + "lv_grid_align_t": "i", "_lv_event_dsc_t *": "i", + # arrays + "char * []": "str_arr", + "lv_coord_t []": "lv_coord_arr", + "lv_point_t []": "lv_point_arr", + # "lv_signal_cb_t": "c", # "lv_design_cb_t": "c", # "lv_event_cb_t": "c", @@ -111,6 +123,8 @@ return_types = { "lv_meter_scale_t *": "lv_meter_scale", "lv_meter_indicator_t *": "lv_meter_indicator", "lv_obj_class_t *": "lv_obj_class", + "lv_chart_series_t *": "lv_chart_series", + "lv_chart_cursor_t *": "lv_chart_cursor", "_lv_obj_t *": "lv_obj", "lv_obj_t *": "lv_obj", @@ -121,8 +135,15 @@ return_types = { "lv_theme_t *": "lv_theme", "lv_disp_t *": "lv_disp", "lv_indev_t *": "lv_indev", - #"lv_disp_t*": "lv_disp", - #"lv_style_list_t*": "", + "lv_img_header_t *": "lv_img_header", + "lv_img_dsc_t *": "lv_img_dsc", + "lv_ts_calibration_t *": "lv_ts_calibration", + "lv_style_transition_dsc_t *": "lv_style_transition_dsc", + # "lv_color_hsv_t *": "lv_color_hsv", + "lv_color_filter_dsc_t *": "lv_color_filter_dsc", + "lv_timer_t *": "lv_timer", + "lv_coord_t *": "c", # treat as a simple pointer, decoding needs to be done at Berry level + "char **": "c", # treat as a simple pointer, decoding needs to be done at Berry level # callbacks "lv_group_focus_cb_t": "lv_group_focus_cb", @@ -196,6 +217,7 @@ with open(lv_widgets_file) as f: g = parse_func_def.search(l_raw) if g: + # print(l_raw, g.group(3)) # if match, we parse the line # Ex: 'void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent);' ret_type = g.group(1) # return type of the function @@ -215,37 +237,49 @@ with open(lv_widgets_file) as f: # convert arguments c_args = "" args_raw = [ x.strip(" \t\n\r") for x in g.group(3).split(",") ] # split by comma and strip + # print(args_raw) + func_name = g.group(2) for arg_raw in args_raw: - # Ex: 'const lv_obj_t * parent' -> 'const ', 'lv_obj_t', ' * ', 'parent' - # Ex: 'bool auto_fit' -> '', 'bool', ' ', 'auto_fit' + # Ex: 'const lv_obj_t * parent' -> 'const ', 'lv_obj_t', ' * ', 'parent', '' + # Ex: 'bool auto_fit' -> '', 'bool', ' ', 'auto_fit', '' + # Ex: 'const lv_coord_t value[]' -> 'const', 'lv_coord_t', '', 'value', '[]' ga = parse_arg.search(arg_raw) - if ga: # parsing ok? - ga_type = ga.group(2) - ga_ptr = ( ga.group(3).strip(" \t\n\r") == "*" ) # boolean - ga_name = ga.group(4) - ga_type_ptr = ga_type - if ga_ptr: ga_type_ptr += " *" - if ga_type_ptr in return_types: - ga_type = return_types[ga_type_ptr] - else: - # remove the trailing '_t' of type name if any - ga_type = re.sub(r"_t$", "", ga_type) - - # if the type is a single letter, we just add it - if len(ga_type) == 1 and ga_type != 'c': # callbacks are different - c_args += ga_type - else: - if ga_type.endswith("_cb"): - # it's a callback type, we encode it differently - if ga_type not in lv_cb_types: - lv_cb_types.append(ga_type) - c_args += "^" + ga_type + "^" + # print(f"g={g} ga={ga}") + if ga or arg_raw == '...': # parsing ok? Special case for '...' which can't be captured easily in regex + if arg_raw != '...': + ga_type = ga.group(2) + ga_ptr = ( ga.group(3).strip(" \t\n\r") == "*" ) # boolean + ga_name = ga.group(4) + ga_array = ga.group(5) + ga_type_ptr = ga_type + if ga_ptr: ga_type_ptr += " *" + if ga_array: ga_type_ptr += " []" + if ga_type_ptr in return_types: + ga_type = return_types[ga_type_ptr] else: - # we have a high-level type that we treat as a class name, enclose in parenthesis - c_args += "(" + "lv." + ga_type + ")" + # remove the trailing '_t' of type name if any + ga_type = re.sub(r"_t$", "", ga_type) + + # if the type is a single letter, we just add it + if len(ga_type) == 1 and ga_type != 'c': # callbacks are different + c_args += ga_type + else: + if ga_type.endswith("_cb"): + if 'remove_' in func_name: # if the call is to remove the cb, just treat as an 'anything' parameter + c_args += "." + else: + # it's a callback type, we encode it differently + if ga_type not in lv_cb_types: + lv_cb_types.append(ga_type) + c_args += "^" + ga_type + "^" + else: + # we have a high-level type that we treat as a class name, enclose in parenthesis + c_args += "(" + "lv." + ga_type + ")" + else: + # '...' + c_args += "[......]" # allow 6 additional parameters # analyze function name and determine if it needs to be assigned to a specific class - func_name = g.group(2) # Ex: func_name -> 'lv_obj_set_parent' if func_name.startswith("_"): continue # skip low-level if func_name.startswith("lv_debug_"): continue # skip debug @@ -320,13 +354,14 @@ extern "C" { #endif #include "be_ctypes.h" +#include "be_mapping.h" """) for subtype, flv in lv.items(): print(f"/* `lv_{subtype}` methods */") if subtype in lv_widgets: print(f"#ifdef BE_LV_WIDGET_{subtype.upper()}") - print(f"const lvbe_call_c_t lv_{subtype}_func[] = {{") + print(f"const be_ntv_func_def_t lv_{subtype}_func[] = {{") func_out = {} # used to sort output for f in flv: @@ -343,7 +378,7 @@ for subtype, flv in lv.items(): pass # c_ret_type = f"+lv_{subtype}" else: - func_out[be_name] = f" {{ \"{be_name}\", (void*) &{orig_func_name}, \"{c_ret_type}\", { c_argc if c_argc else 'nullptr'} }}," + func_out[be_name] = f" {{ \"{be_name}\", {{ (const void*) &{orig_func_name}, \"{c_ret_type}\", { c_argc if c_argc else 'nullptr'} }} }}," for be_name in sorted(func_out): print(func_out[be_name]) @@ -361,7 +396,7 @@ print() # print the global map of classes print(f""" // map of clases -const lvbe_call_c_classes_t lv_classes[] = {{""") +const be_ntv_class_def_t lv_classes[] = {{""") for subtype in sorted(lv): # for subtype, flv in lv.items(): @@ -391,7 +426,7 @@ for subtype, flv in lv.items(): if len(c_ret_type) > 1: c_ret_type = "lv." + c_ret_type if c_func_name.endswith("_create"): - c_ret_type = "+" # constructor, init method does not return any value + c_ret_type = "+_p" # constructor, init method does not return any value if subtype in lv_widgets: print(f"#ifdef BE_LV_WIDGET_{subtype.upper()}") print(f" int be_ntv_lv_{subtype}_init(bvm *vm) {{ return be_call_c_func(vm, (void*) &{orig_func_name}, \"{c_ret_type}\", { c_argc if c_argc else 'nullptr'}); }}") @@ -401,8 +436,8 @@ for subtype, flv in lv.items(): print(""" // create font either empty or from parameter on stack -int lvbe_font_create(bvm *vm) { return be_call_c_func(vm, NULL, "+lv_font", ""); } -int lvbe_theme_create(bvm *vm) { return be_call_c_func(vm, NULL, "+lv_theme", ""); } +int lvbe_font_create(bvm *vm) { return be_call_c_func(vm, NULL, "+_p", ""); } +int lvbe_theme_create(bvm *vm) { return be_call_c_func(vm, NULL, "+_p", ""); } """) print() @@ -424,8 +459,6 @@ print(""" *******************************************************************/ #include "be_constobj.h" -#ifdef USE_LVGL - #include "lvgl.h" extern int lv0_init(bvm *vm); @@ -434,11 +467,11 @@ extern int lco_init(bvm *vm); // generic function extern int lco_tostring(bvm *vm); // generic function extern int lco_toint(bvm *vm); // generic function -extern int lvx_member(bvm *vm); -extern int lvx_tostring(bvm *vm); // generic function +extern int lv_x_member(bvm *vm); +extern int lv_x_tostring(bvm *vm); // generic function -extern int lvs_init(bvm *vm); -extern int lvs_tostring(bvm *vm); +extern int lv_be_style_init(bvm *vm); +extern int lv_x_tostring(bvm *vm); BE_EXPORT_VARIABLE extern const bclass be_class_lv_obj; @@ -484,10 +517,10 @@ be_local_class(lv_style, NULL, be_nested_map(4, ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("init", 380752755, 4, -1), be_const_func(lvs_init) }, - { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lvs_tostring) }, + { be_nested_key("init", 380752755, 4, -1), be_const_func(lv_be_style_init) }, + { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lv_x_tostring) }, { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, - { be_nested_key("member", 719708611, 6, 0), be_const_func(lvx_member) }, + { be_nested_key("member", 719708611, 6, 0), be_const_func(lv_x_member) }, })), (be_nested_const_str("lv_style", -143355747, 8)) ); @@ -501,8 +534,8 @@ be_local_class(lv_obj, NULL, be_nested_map(5, ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("tostring", -1995258651, 8, 3), be_const_func(lvx_tostring) }, - { be_nested_key("member", 719708611, 6, -1), be_const_func(lvx_member) }, + { be_nested_key("tostring", -1995258651, 8, 3), be_const_func(lv_x_tostring) }, + { be_nested_key("member", 719708611, 6, -1), be_const_func(lv_x_member) }, { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, { be_nested_key("init", 380752755, 4, 4), be_const_func(be_ntv_lv_obj_init) }, { be_nested_key("_class", -1562820946, 6, -1), be_const_comptr(&lv_obj_class) }, @@ -520,9 +553,9 @@ be_local_class(lv_group, be_nested_map(4, ( (struct bmapnode*) &(const bmapnode[]) { { be_nested_key("init", 380752755, 4, -1), be_const_func(be_ntv_lv_group_init) }, - { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lvx_tostring) }, + { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lv_x_tostring) }, { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, - { be_nested_key("member", 719708611, 6, 0), be_const_func(lvx_member) }, + { be_nested_key("member", 719708611, 6, 0), be_const_func(lv_x_member) }, })), (be_nested_const_str("lv_group", -442928277, 8)) ); @@ -537,9 +570,9 @@ be_local_class(lv_indev, be_nested_map(4, ( (struct bmapnode*) &(const bmapnode[]) { { be_nested_key("init", 380752755, 4, -1), be_const_func(lv0_init) }, - { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lvx_tostring) }, + { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lv_x_tostring) }, { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, - { be_nested_key("member", 719708611, 6, 0), be_const_func(lvx_member) }, + { be_nested_key("member", 719708611, 6, 0), be_const_func(lv_x_member) }, })), (be_nested_const_str("lv_indev", 225602374, 8)) ); @@ -554,9 +587,9 @@ be_local_class(lv_disp, be_nested_map(4, ( (struct bmapnode*) &(const bmapnode[]) { { be_nested_key("init", 380752755, 4, -1), be_const_func(lv0_init) }, - { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lvx_tostring) }, + { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lv_x_tostring) }, { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, - { be_nested_key("member", 719708611, 6, 0), be_const_func(lvx_member) }, + { be_nested_key("member", 719708611, 6, 0), be_const_func(lv_x_member) }, })), (be_nested_const_str("lv_disp", 609712084, 8)) ); @@ -571,7 +604,7 @@ be_local_class(lv_font, be_nested_map(3, ( (struct bmapnode*) &(const bmapnode[]) { { be_nested_key("init", 380752755, 4, -1), be_const_func(lvbe_font_create) }, - { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lvx_tostring) }, + { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lv_x_tostring) }, { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, })), (be_nested_const_str("lv_font", 1550958453, 7)) @@ -587,7 +620,7 @@ be_local_class(lv_theme, be_nested_map(3, ( (struct bmapnode*) &(const bmapnode[]) { { be_nested_key("init", 380752755, 4, -1), be_const_func(lvbe_theme_create) }, - { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lvx_tostring) }, + { be_nested_key("tostring", -1995258651, 8, -1), be_const_func(lv_x_tostring) }, { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, })), (be_nested_const_str("lv_theme", 1550958453, 7)) @@ -641,9 +674,6 @@ be_local_class(lv_{subtype}, }} """) -print(""" -#endif // USE_LVGL -""") sys.stdout.close() @@ -657,25 +687,16 @@ print("""/******************************************************************** *******************************************************************/ #include "be_constobj.h" -#ifdef USE_LVGL - #include "lvgl.h" -#include "be_lvgl.h" +#include "be_mapping.h" +#include "lv_berry.h" #include "lv_theme_openhasp.h" extern int lv0_member(bvm *vm); // resolve virtual members - -extern int lv0_start(bvm *vm); - -extern int lv0_register_button_encoder(bvm *vm); // add buttons with encoder logic - -extern int lv0_load_montserrat_font(bvm *vm); -extern int lv0_load_seg7_font(bvm *vm); -extern int lv0_load_robotocondensed_latin1_font(bvm *vm); extern int lv0_load_font(bvm *vm); -extern int lv0_load_freetype_font(bvm *vm); -extern int lv0_screenshot(bvm *vm); +extern lv_ts_calibration_t * lv_get_ts_calibration(void); + static int lv_get_hor_res(void) { return lv_disp_get_hor_res(lv_disp_get_default()); @@ -685,7 +706,7 @@ static int lv_get_ver_res(void) { } /* `lv` methods */ -const lvbe_call_c_t lv_func[] = { +const be_ntv_func_def_t lv_func[] = { """) func_out = {} # used to sort output @@ -700,7 +721,7 @@ for f in lv0: # if c_ret_type is an object, prefix with `lv.` if len(c_ret_type) > 1: c_ret_type = "lv." + c_ret_type - func_out[be_name] = f" {{ \"{be_name}\", (void*) &{orig_func_name}, \"{c_ret_type}\", { c_argc if c_argc else 'nullptr'} }}," + func_out[be_name] = f" {{ \"{be_name}\", {{ (const void*) &{orig_func_name}, \"{c_ret_type}\", { c_argc if c_argc else 'nullptr'} }} }}," for be_name in sorted(func_out): print(func_out[be_name]) @@ -728,12 +749,7 @@ const size_t lv_func_size = sizeof(lv_func) / sizeof(lv_func[0]); print(""" -typedef struct be_constint_t { - const char * name; - int32_t value; -} be_constint_t; - -const be_constint_t lv0_constants[] = { +const be_const_member_t lv0_constants[] = { """) lv_module2 = {} @@ -761,29 +777,65 @@ for k in sorted(lv_module2): # otherwise it's an int, leave if unchanged if v is not None: v_prefix = "" - if v[0] == '"': v_prefix = "$" - if v[0] == '&': v_prefix = "&" - print(f" {{ \"{v_prefix}{k}\", (int32_t) {v} }},") + v_macro = "be_cconst_int" + if v[0] == '"': v_prefix = "$"; v_macro = "be_cconst_string" + if v[0] == '&': v_prefix = "&"; v_macro = "be_cconst_ptr" + print(f" {{ \"{v_prefix}{k}\", {v_macro}({v}) }},") else: - print(f" {{ \"{k}\", LV_{k} }},") + print(f" {{ \"{k}\", be_cconst_int(LV_{k}) }},") print(""" }; const size_t lv0_constants_size = sizeof(lv0_constants)/sizeof(lv0_constants[0]); -/* generated */ +/******************************************************************** +** Solidified function: lv_module_init +********************************************************************/ +be_local_closure(lv_lv_module_init, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str(lv), + /* K1 */ be_nested_str(member), + /* K2 */ be_nested_str(lv_solidified), + }), + &be_const_str_lv_module_init, + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x6004000B, // 0000 GETGBL R1 G11 + 0x58080000, // 0001 LDCONST R2 K0 + 0x7C040200, // 0002 CALL R1 1 + 0x88080101, // 0003 GETMBR R2 R0 K1 + 0x90060202, // 0004 SETMBR R1 K1 R2 + 0x90060400, // 0005 SETMBR R1 K2 R0 + 0x80040200, // 0006 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified module: lv +********************************************************************/ be_local_module(lv, "lv", be_nested_map(2, ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("member", 719708611, 6, -1), be_const_func(lv0_member) }, - { be_nested_key("start", 1697318111, 5, 0), be_const_func(lv0_start) }, + { be_const_key(init, -1), be_const_closure(lv_lv_module_init_closure) }, + { be_const_key(member, 0), be_const_func(lv0_member) }, })) ); BE_EXPORT_VARIABLE be_define_const_native_module(lv); - -#endif // USE_LVGL +/********************************************************************/ """) print("/********************************************************************/") diff --git a/tools/lv_berry/preprocessor.py b/lib/libesp32_lvgl/lv_berry/tools/preprocessor.py similarity index 90% rename from tools/lv_berry/preprocessor.py rename to lib/libesp32_lvgl/lv_berry/tools/preprocessor.py index 216a726fb..151727dca 100644 --- a/tools/lv_berry/preprocessor.py +++ b/lib/libesp32_lvgl/lv_berry/tools/preprocessor.py @@ -48,8 +48,9 @@ def clean_source(raw): # Parse function signatures # ################################################################################ -lv_src_prefix = "../../lib/libesp32_lvgl/LVGL8/src/" +lv_src_prefix = "../../lvgl/src/" lv_fun_globs = [ + "lv_api*.h", "widgets/*.h", # all widgets # "extra/widgets/*/*.h", "extra/widgets/chart/*.h", @@ -62,21 +63,23 @@ lv_fun_globs = [ "extra/widgets/spinner/*.h", "extra/themes/default/*.h", "extra/themes/mono/*.h", + "extra/layouts/**/*.h", "core/*.h", "draw/*.h", "misc/lv_style_gen.h", + "misc/lv_color.h", #"misc/lv_area.h", #"**/*.h", ] headers_names = list_files(lv_src_prefix, lv_fun_globs) -headers_names += list_files("../../lib/libesp32_lvgl/LVGL_assets/src/", ["lv_theme_openhasp.h"]) +headers_names += list_files("../../LVGL_assets/src/", ["lv_theme_openhasp.h"]) # headers_names += ["lv_pre_style.h"] # for LVGL v7, add pre-generated style functions from C preprocessor # unit test # headers_names = [ '../../lib/libesp32_lvgl/LVGL/src/lv_widgets/lv_btn.h' ] # headers_names = [ '../../lib/libesp32_lvgl/LVGL/src/lv_api_map.h' ] -output_filename = "lv_funcs.h" +output_filename = "../mapping/lv_funcs.h" sys.stdout = open(output_filename, 'w') print(""" @@ -85,6 +88,7 @@ print(""" // Custom Tasmota functions void lv_img_set_tasmota_logo(lv_obj_t * img); +lv_ts_calibration_t * lv_get_ts_calibration(void); // ====================================================================== // Artificial @@ -129,6 +133,8 @@ for header_name in headers_names: for fun in fun_defs: # remove LV_ATTRIBUTE_FAST_MEM fun = re.sub('LV_ATTRIBUTE_FAST_MEM ', '', fun) + # remove LV_ATTRIBUTE_TIMER_HANDLER + fun = re.sub('LV_ATTRIBUTE_TIMER_HANDLER ', '', fun) exclude = False for exclude_prefix in ["typedef", "_LV_", "LV_"]: if fun.startswith(exclude_prefix): exclude = True @@ -169,27 +175,25 @@ sys.stdout.close() # Parse 'enum' # ################################################################################ -lv_src_prefix = "../../lib/libesp32_lvgl/LVGL8/src/" -lv_fun_globs = [ "**/*.h" ] +lv_src_prefix = "../../lvgl/src/" +lv_fun_globs = [ + "core/*.h", + "draw/*.h", + "hal/*.h", + "misc/*.h", + "widgets/*.h", + "extra/widgets/**/*.h", + "extra/layouts/**/*.h", + ] headers_names = list_files(lv_src_prefix, lv_fun_globs) -output_filename = "lv_enum.h" +output_filename = "../mapping/lv_enum.h" sys.stdout = open(output_filename, 'w') print("""// ====================================================================== // Functions // ====================================================================== -register_button_encoder=&lv0_register_button_encoder - -montserrat_font=&lv0_load_montserrat_font -seg7_font=&lv0_load_seg7_font -font_montserrat=&lv0_load_montserrat_font -font_seg7=&lv0_load_seg7_font -font_robotocondensed_latin1=&lv0_load_robotocondensed_latin1_font load_font=&lv0_load_font -load_freetype_font=&lv0_load_freetype_font - -screenshot=&lv0_screenshot // ====================================================================== // Colors @@ -214,6 +218,11 @@ COLOR_NAVY=0x000080 COLOR_MAGENTA=0xFF00FF COLOR_PURPLE=0x800080 +// Freetype +FT_FONT_STYLE_NORMAL=FT_FONT_STYLE_NORMAL +FT_FONT_STYLE_ITALIC=FT_FONT_STYLE_ITALIC +FT_FONT_STYLE_BOLD=FT_FONT_STYLE_BOLD + // following are #define, not enum LV_RADIUS_CIRCLE LV_TEXTAREA_CURSOR_LAST @@ -221,6 +230,12 @@ LV_STYLE_PROP_ANY LV_SIZE_CONTENT +LV_GRID_FR=LV_GRID_FR(0) +LV_GRID_CONTENT +LV_GRID_TEMPLATE_LAST + +LV_OBJ_FLAG_FLEX_IN_NEW_TRACK + // ====================================================================== // Symbols // ====================================================================== @@ -292,12 +307,11 @@ SYMBOL_BULLET="\\xE2\\x80\\xA2" // ====================================================================== """) - - for header_name in headers_names: with open(header_name) as f: raw = clean_source(f.read()) + print(f"// File: {header_name}") # extract enums enums = re.findall('enum\s+{(.*?)}', raw, flags=re.DOTALL) for enum in enums: # iterate on all matches diff --git a/lib/libesp32_lvgl/lv_lib_freetype/README.md b/lib/libesp32_lvgl/lv_lib_freetype/README.md deleted file mode 100644 index 2bfbddb4e..000000000 --- a/lib/libesp32_lvgl/lv_lib_freetype/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# FreeType integration with LVGL -Interface to FreeType to generate font bitmaps run time - -## Install FreeType -- Download Freetype from [here](https://sourceforge.net/projects/freetype/files/) -- `make` -- `sudo make install` - -## Add FreeType to your project -- Add include path: `/usr/include/freetype2` (for GCC: `-I/usr/include/freetype2 -L/usr/local/lib`) -- Add library: `freetype` (for GCC: `-L/usr/local/lib -lfreetype`) - -## Usage in LVGL - -To enable cache, set`LV_USE_FT_CACHE_MANAGER 1`in lv_freetype.h. - -```c -/* init freetype library */ -lv_freetype_init(64, 1, 0); - -/*Create a font*/ -lv_ft_info_t info; -info.name = "./lv_lib_freetype/arial.ttf""; -info.size = 16; -info.style = FT_FONT_STYLE_NORMAL; -lv_ft_font_init(&info); - -/*Create style with the new font*/ -static lv_style_t style; -lv_style_init(&style); -lv_style_set_text_font(&style, LV_STATE_DEFAULT, info.font); - -/*Create a label with the new style*/ -lv_obj_t * label = lv_label_create(lv_scr_act(), NULL); -lv_obj_add_style(label, LV_LABEL_PART_MAIN, &style); -lv_label_set_text(label, "Hello world"); - -/* free font */ -//lv_ft_font_destroy(info.font); -``` - -## Learn more -- FreeType [tutorial](https://www.freetype.org/freetype2/docs/tutorial/step1.html) -- LVGL's [font interface](https://docs.lvgl.io/v7/en/html/overview/font.html#add-a-new-font-engine) diff --git a/lib/libesp32_lvgl/lv_lib_freetype/library.json b/lib/libesp32_lvgl/lv_lib_freetype/library.json deleted file mode 100644 index f4269fb70..000000000 --- a/lib/libesp32_lvgl/lv_lib_freetype/library.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name":"lv_lib_freetype", - "description":"Interface to FreeType to generate font bitmaps run time", - "keywords":"lvgl, freetype", - "license": "MIT License", - "repository": { - "type": "git", - "url": "https://github.com/lvgl/lv_lib_freetype" - }, - "frameworks": "arduino", - "platforms": "espressif32", - "build": { - "flags": [ "-DLV_LVGL_H_INCLUDE_SIMPLE", "-I$PROJECT_DIR/include", "-includetasmota_options.h" ] - } -} \ No newline at end of file diff --git a/lib/libesp32_lvgl/lv_lib_freetype/lv_freetype.c b/lib/libesp32_lvgl/lv_lib_freetype/lv_freetype.c deleted file mode 100644 index 3c00d8b65..000000000 --- a/lib/libesp32_lvgl/lv_lib_freetype/lv_freetype.c +++ /dev/null @@ -1,469 +0,0 @@ -/** - * @file lv_freetype.c - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "lv_freetype.h" -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/task.h" - -#if CONFIG_FREERTOS_UNICORE -#define ARDUINO_RUNNING_CORE 0 -#else -#define ARDUINO_RUNNING_CORE 1 -#endif - -/* - * FreeType requires up to 32KB of stack to run, which overflows the stack of 8KB. - * - * We delegate to a FreeRTOS sub-task with a bigger stack. - * - * Parameters are passed via a RequestQueue, and response back via ResponseQueue - * - * The function that uses this scheme is `get_glyph_dsc_cb()`` - * - */ - -QueueHandle_t FTRequestQueue; -QueueHandle_t FTResponseQueue; -TaskHandle_t FTTaskHandle; -void FT_loop_task(void *pvParameters); - -typedef struct FT_glyph_dsc_request { - const lv_font_t * font; - lv_font_glyph_dsc_t * dsc_out; - uint32_t unicode_letter; - uint32_t unicode_letter_next; -} FT_glyph_dsc_request; - -typedef bool FT_glyph_dsc_response; - - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static FT_Face face_find_in_list(lv_ft_info_t *info); -static void face_add_to_list(FT_Face face); -static void face_remove_from_list(FT_Face face); - -static void face_generic_finalizer(void* object); -static bool get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, - uint32_t unicode_letter, uint32_t unicode_letter_next); -static const uint8_t * get_glyph_bitmap_cb(const lv_font_t * font, uint32_t unicode_letter); - -#if LV_USE_FT_CACHE_MANAGER -static FT_Error font_face_requester(FTC_FaceID face_id, - FT_Library library_is,FT_Pointer req_data,FT_Face* aface); -#endif - - /********************** - * STATIC VARIABLES - **********************/ -static FT_Library library; - -#if LV_USE_FT_CACHE_MANAGER -static FTC_Manager cache_manager; -static FTC_CMapCache cmap_cache; -static FTC_SBitCache sbit_cache; -static FTC_SBit sbit; -#endif - -static lv_faces_control_t face_control; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ -bool lv_freetype_init(FT_UInt max_faces, FT_UInt max_sizes, FT_ULong max_bytes) -{ - face_control.cnt = 0; - face_control.num = max_faces; - _lv_ll_init(&face_control.face_ll, sizeof(FT_Face *)); - - FT_Error error = FT_Init_FreeType(&library); - if (error) { - LV_LOG_ERROR("init freeType error(%d)", error); - return false; - } - -#if LV_USE_FT_CACHE_MANAGER - error = FTC_Manager_New(library, max_faces, max_sizes, - max_bytes, font_face_requester, NULL, &cache_manager); - if (error) { - FT_Done_FreeType(library); - LV_LOG_ERROR("Failed to open cache manager"); - return false; - } - - error = FTC_CMapCache_New(cache_manager, &cmap_cache); - if(error) { - LV_LOG_ERROR("Failed to open Cmap Cache"); - goto Fail; - } - - error = FTC_SBitCache_New(cache_manager, &sbit_cache); - if(error){ - LV_LOG_ERROR("Failed to open sbit cache"); - goto Fail; - } - - // initialize the queues to send request and receive response - FTRequestQueue = xQueueCreate(1, sizeof(FT_glyph_dsc_request)); - FTResponseQueue = xQueueCreate(1, sizeof(FT_glyph_dsc_response)); - - xTaskCreatePinnedToCore(FT_loop_task, "FreeType_task", LV_USE_FT_STACK_SIZE, NULL, 1, &FTTaskHandle, ARDUINO_RUNNING_CORE); - - if (FTRequestQueue && FTResponseQueue) { - return true; - } -Fail: - FTC_Manager_Done(cache_manager); - FT_Done_FreeType(library); - return false; -#else - LV_UNUSED(max_sizes); - LV_UNUSED(max_bytes); - return true; -#endif/* LV_USE_FT_CACHE_MANAGER */ -} - -void lv_freetype_destroy(void) -{ -#if LV_USE_FT_CACHE_MANAGER - FTC_Manager_Done(cache_manager); -#endif - FT_Done_FreeType(library); -} - -bool lv_ft_font_init(lv_ft_info_t *info) -{ - lv_font_fmt_ft_dsc_t * dsc = lv_mem_alloc(sizeof(lv_font_fmt_ft_dsc_t)); - if(dsc == NULL) return false; - - dsc->font = lv_mem_alloc(sizeof(lv_font_t)); - if(dsc->font == NULL) { - lv_mem_free(dsc); - return false; - } - - lv_face_info_t *face_info = NULL; - FT_Face face = face_find_in_list(info); - if (face == NULL) { - if (face_control.cnt == face_control.num - 1) { - LV_LOG_WARN("face full"); - goto Fail; - } - face_info = lv_mem_alloc(sizeof(lv_face_info_t) + strlen(info->name) + 1); - if(face_info == NULL) { - goto Fail; - } - FT_Error error = FT_New_Face(library, info->name, 0, &face); - if(error){ - lv_mem_free(face_info); - LV_LOG_WARN("create face error(%d)", error); - goto Fail; - } - - face_info->name = ((char *)face_info) + sizeof(lv_face_info_t); - strcpy(face_info->name, info->name); - face_info->cnt = 1; - face->generic.data = face_info; - face->generic.finalizer = face_generic_finalizer; - face_add_to_list(face); - } - else { -#if LV_USE_FT_CACHE_MANAGER == 0 - FT_Size size; - FT_Error error = FT_New_Size(face, &size); - if (error) { - goto Fail; - } - FT_Activate_Size(size); - FT_Reference_Face(face); -#else - face_info = (lv_face_info_t *)face->generic.data; - face_info->cnt++; -#endif - } - FT_Set_Pixel_Sizes(face, 0, info->weight); - - dsc->face = face; - dsc->size = face->size; - dsc->weight = info->weight; - dsc->style = info->style; - lv_font_t *font = dsc->font; - font->user_data = dsc; - font->get_glyph_dsc = get_glyph_dsc_cb; - font->get_glyph_bitmap = get_glyph_bitmap_cb; - font->line_height = (dsc->face->size->metrics.height >> 6); - font->base_line = -(dsc->face->size->metrics.descender >> 6); - font->subpx = LV_FONT_SUBPX_NONE; - font->underline_position = dsc->face->underline_position; - font->underline_thickness = dsc->face->underline_thickness; - font->dsc = NULL; - info->font = font; - return true; - -Fail: - lv_mem_free(dsc->font); - lv_mem_free(dsc); - return false; -} - -void lv_ft_font_destroy(lv_font_t* font) -{ - if (font == NULL) { - return; - } - - lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->user_data); - if (dsc) { -#if LV_USE_FT_CACHE_MANAGER == 0 - FT_Done_Size(dsc->size); - FT_Done_Face(dsc->face); -#else - lv_face_info_t *face_info = (lv_face_info_t *)dsc->face->generic.data; - face_info->cnt--; - if(face_info->cnt == 0){ - FTC_Manager_RemoveFaceID(cache_manager, (FTC_FaceID)dsc->face); - } -#endif - lv_mem_free(dsc->font); - lv_mem_free(dsc); - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ -static void face_generic_finalizer(void* object) -{ - FT_Face face = (FT_Face)object; - face_remove_from_list(face); - if(face->generic.data){ - lv_face_info_t *face_info = (lv_face_info_t *)face->generic.data; - lv_mem_free(face_info); - } - LV_LOG_INFO("face finalizer(%p)\n", face); -} - -static FT_Face face_find_in_list(lv_ft_info_t *info) -{ - lv_face_info_t *face_info; - FT_Face *pface = _lv_ll_get_head(&face_control.face_ll); - while(pface) { - face_info = (lv_face_info_t *)(*pface)->generic.data; - if (strcmp(face_info->name, info->name) == 0) { - return *pface; - } - pface = _lv_ll_get_next(&face_control.face_ll, pface); - } - - return NULL; -} - -static void face_add_to_list(FT_Face face) -{ - FT_Face *pface; - pface = (FT_Face *)_lv_ll_ins_tail(&face_control.face_ll); - *pface = face; - face_control.cnt++; -} - -static void face_remove_from_list(FT_Face face) -{ - FT_Face *pface = _lv_ll_get_head(&face_control.face_ll); - while(pface) { - if (*pface == face) { - _lv_ll_remove(&face_control.face_ll, pface); - lv_mem_free(pface); - face_control.cnt--; - break; - } - pface = _lv_ll_get_next(&face_control.face_ll, pface); - } -} - -#if LV_USE_FT_CACHE_MANAGER - -static FT_Error font_face_requester(FTC_FaceID face_id, - FT_Library library_is,FT_Pointer req_data,FT_Face* aface) -{ - LV_UNUSED(library_is); - LV_UNUSED(req_data); - *aface = face_id; - return FT_Err_Ok; -} - -static bool get_glyph_dsc_cb_cache(const lv_font_t * font, - lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) -{ - LV_UNUSED(unicode_letter_next); - if(unicode_letter < 0x20) { - dsc_out->adv_w = 0; - dsc_out->box_h = 0; - dsc_out->box_w = 0; - dsc_out->ofs_x = 0; - dsc_out->ofs_y = 0; - dsc_out->bpp = 0; - return true; - } - - lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->user_data); - FT_Face face = dsc->face; - - static FTC_ImageTypeRec desc_sbit_type; - desc_sbit_type.face_id = (FTC_FaceID)face; - desc_sbit_type.flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL; - desc_sbit_type.height = dsc->weight; - desc_sbit_type.width = dsc->weight; - FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap); - FT_UInt glyph_index = FTC_CMapCache_Lookup(cmap_cache, (FTC_FaceID)face, charmap_index, unicode_letter); - FT_Error error = FTC_SBitCache_Lookup(sbit_cache, &desc_sbit_type, glyph_index, &sbit, NULL); - - dsc_out->adv_w = sbit->xadvance; - dsc_out->box_h = sbit->height; /*Height of the bitmap in [px]*/ - dsc_out->box_w = sbit->width; /*Width of the bitmap in [px]*/ - dsc_out->ofs_x = sbit->left; /*X offset of the bitmap in [pf]*/ - dsc_out->ofs_y = sbit->top - sbit->height; /*Y offset of the bitmap measured from the as line*/ - dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ - - return true; -} - -static const uint8_t * get_glyph_bitmap_cb_cache(const lv_font_t * font, uint32_t unicode_letter) -{ - LV_UNUSED(font); - LV_UNUSED(unicode_letter); - return (const uint8_t *)sbit->buffer; -} - -#else/* LV_USE_FT_CACHE_MANAGER */ -// extern void berry_log_C(const char * berry_buf, ...); - -static bool get_glyph_dsc_cb_nocache(const lv_font_t * font, - lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) -{ - // berry_log_C(">> get_glyph_dsc_cb_nocache %i %i", unicode_letter, unicode_letter_next); - LV_UNUSED(unicode_letter_next); - if(unicode_letter < 0x20) { - dsc_out->adv_w = 0; - dsc_out->box_h = 0; - dsc_out->box_w = 0; - dsc_out->ofs_x = 0; - dsc_out->ofs_y = 0; - dsc_out->bpp = 0; - return true; - } - - FT_Error error; - FT_Face face; - lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->user_data); - face = dsc->face; - - FT_UInt glyph_index = FT_Get_Char_Index( face, unicode_letter ); - - if (face->size != dsc->size) { - // berry_log_C(">> FT_Activate_Size %i", dsc->size); - FT_Activate_Size(dsc->size); - } - - error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT ); - // berry_log_C(">> after FT_Load_Glyph error = %i", error); - if (error){ - return false; - } - - error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL); - // berry_log_C(">> after FT_Render_Glyph error = %i", error); - if (error){ - return false; - } - - dsc_out->adv_w = (face->glyph->metrics.horiAdvance >> 6); - dsc_out->box_h = face->glyph->bitmap.rows; /*Height of the bitmap in [px]*/ - dsc_out->box_w = face->glyph->bitmap.width; /*Width of the bitmap in [px]*/ - dsc_out->ofs_x = face->glyph->bitmap_left; /*X offset of the bitmap in [pf]*/ - dsc_out->ofs_y = face->glyph->bitmap_top - face->glyph->bitmap.rows; /*Y offset of the bitmap measured from the as line*/ - dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ - - // berry_log_C("+++ adv_w %i, h %i, w %i, x %i, y %i", dsc_out->adv_w, dsc_out->box_h, dsc_out->box_w, dsc_out->ofs_x, dsc_out->ofs_y); - - return true; -} - -static const uint8_t * get_glyph_bitmap_cb_nocache(const lv_font_t * font, uint32_t unicode_letter) -{ - LV_UNUSED(unicode_letter); - lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->user_data); - FT_Face face = dsc->face; - return (const uint8_t *)(face->glyph->bitmap.buffer); -} - -#endif/* LV_USE_FT_CACHE_MANAGER */ - -static bool get_glyph_dsc_cb(const lv_font_t * font, - lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) -{ -// #if LV_USE_FT_CACHE_MANAGER -// return get_glyph_dsc_cb_cache(font, dsc_out, unicode_letter, unicode_letter_next); -// #else -// return get_glyph_dsc_cb_nocache(font, dsc_out, unicode_letter, unicode_letter_next); -// #endif - static FT_glyph_dsc_request request; - static FT_glyph_dsc_response response; - - request.font = font; - request.dsc_out = dsc_out; - request.unicode_letter = unicode_letter; - request.unicode_letter_next = unicode_letter_next; - xQueueSendToBack(FTRequestQueue, &request, portMAX_DELAY); - if (xQueueReceive(FTResponseQueue, &response, portMAX_DELAY)) { - return response; - } else { - return false; // should never happen - } -} - -static const uint8_t * get_glyph_bitmap_cb(const lv_font_t * font, uint32_t unicode_letter) -{ -#if LV_USE_FT_CACHE_MANAGER - return get_glyph_bitmap_cb_cache(font, unicode_letter); -#else - return get_glyph_bitmap_cb_nocache(font, unicode_letter); -#endif -} - -void FT_loop_task(void *pvParameters) { - (void) pvParameters; - - while (1) { - FT_glyph_dsc_request request; - FT_glyph_dsc_response response; - - if (xQueueReceive(FTRequestQueue, &request, portMAX_DELAY)) { - #if LV_USE_FT_CACHE_MANAGER - response = get_glyph_dsc_cb_cache(request.font, request.dsc_out, request.unicode_letter, request.unicode_letter_next); - #else - response = get_glyph_dsc_cb_nocache(request.font, request.dsc_out, request.unicode_letter, request.unicode_letter_next); - #endif - xQueueSendToBack(FTResponseQueue, &response, portMAX_DELAY); // send back response - } - } -} \ No newline at end of file diff --git a/lib/libesp32_lvgl/lv_lib_png/README.md b/lib/libesp32_lvgl/lv_lib_png/README.md deleted file mode 100644 index 693de2b51..000000000 --- a/lib/libesp32_lvgl/lv_lib_png/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# PNG decoder for LVGL - -Allow the use of PNG images in LVGL. This implementation uses [lodepng](https://github.com/lvandeve/lodepng) library. - -## Get started -- Download or clone this repository - - [Download from GitHub](https://github.com/littlevgl/lv_lib_lodepng/archive/master.zip) - - Clone: `git clone https://github.com/littlevgl/lv_lib_png.git` -- Include the library: `#include "lv_lib_png/lv_png.h"` -- Initalize the decocer with `lv_png_init()` -- Test with the following code: -```c - LV_IMG_DECLARE(png_decoder_test); - lv_obj_t * img = lv_img_create(lv_scr_act(), NULL); - lv_img_set_src(img, &png_decoder_test); -``` - -## Use PNG images from file -By deafult `lodepng` uses C file IO API (e.g. `fopen`) and images can be opened like this: -```c -lv_img_set_src(img, "./lv_lib_lodepng/png_decoder_test.png"); -``` - -If you want to make `lodepng` to use LVGL's file system API add `#define LV_PNG_USE_LV_FILESYSTEM 1` to the end of your`lv_conf.h`. -In this case you need to [register a driver](https://docs.lvgl.io/latest/en/html/overview/file-system.html) fo LVGL. The following functions are required: -- `open_cb()` -- `read_cb()` -- `close_cb()` -- `size_cb()` - -After that fiels can be opened like this: -```c -lv_img_set_src(img, "P:lv_lib_lodepng/png_decoder_test.png"); -``` - - -Note that the path of the file might be different. - -## Use PNG images from flash -To store a PNG image in flash it needs to be converted to C array with [Online Image converter](https://lvgl.io/tools/imageconverter). Choose `Raw with alpha` Color format and `C array` Output format. Copy the result C array to your project and use it like this: -```c - LV_IMG_DECLARE(my_test_img); - lv_obj_t * img = lv_img_create(lv_scr_act(), NULL); - lv_img_set_src(img, &my_test_img); -``` - -## Learn more -To learn more about the PNG decoder itself read [this blog post](https://blog.littlevgl.com/2018-10-05/png_converter) - -To learn more about the Image decoder interface of LittlevGL read the realevant part of the [documentation](https://docs.littlevgl.com/en/html/overview/image.html#image-decoder). diff --git a/lib/libesp32_lvgl/lv_lib_png/library.json b/lib/libesp32_lvgl/lv_lib_png/library.json deleted file mode 100644 index 61e9720e3..000000000 --- a/lib/libesp32_lvgl/lv_lib_png/library.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name":"lv_lib_png", - "description":"Allow the use of PNG images in LVGL. This implementation uses lodepng library.", - "keywords":"lvgl, png", - "license": "MIT License", - "repository": { - "type": "git", - "url": "https://github.com/lvgl/lv_lib_png" - }, - "frameworks": "arduino", - "platforms": "espressif32", - "build": { - "flags": [ "-DLV_PNG_USE_LV_FILESYSTEM=1", - "-DLODEPNG_NO_COMPILE_ALLOCATORS", - "-DLODEPNG_NO_COMPILE_ERROR_TEXT", - "-DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS", - "-DLV_LVGL_H_INCLUDE_SIMPLE", - "-I$PROJECT_DIR/include", - "-includetasmota_options.h" ] - } -} \ No newline at end of file diff --git a/lib/libesp32_lvgl/LVGL8/Kconfig b/lib/libesp32_lvgl/lvgl/Kconfig similarity index 100% rename from lib/libesp32_lvgl/LVGL8/Kconfig rename to lib/libesp32_lvgl/lvgl/Kconfig diff --git a/lib/libesp32_lvgl/LVGL8/LICENCE.txt b/lib/libesp32_lvgl/lvgl/LICENCE.txt similarity index 97% rename from lib/libesp32_lvgl/LVGL8/LICENCE.txt rename to lib/libesp32_lvgl/lvgl/LICENCE.txt index a6f7f803e..f877abb18 100644 --- a/lib/libesp32_lvgl/LVGL8/LICENCE.txt +++ b/lib/libesp32_lvgl/lvgl/LICENCE.txt @@ -1,5 +1,5 @@ MIT licence -Copyright (c) 2020 LVGL LLC +Copyright (c) 2021 LVGL Kft 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: diff --git a/lib/libesp32_lvgl/lvgl/README.md b/lib/libesp32_lvgl/lvgl/README.md new file mode 100644 index 000000000..acc5c054a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/README.md @@ -0,0 +1,181 @@ +

LVGL - Light and Versatile Graphics Library

+ +

+ +

+ +

+LVGL provides everything you need to create an embedded GUI with easy-to-use graphical elements, beautiful visual effects and a low memory footprint. +

+ +

+Website · +Docs · +Forum · +Services · +Interactive examples +

+ +--- + +#### Table of content +- [Overview](#overview) +- [Get started](#get-started) +- [Examples](#examples) +- [Services](#services) +- [Contributing](#contributing) + + +## Overview +### Features +* Powerful [building blocks](https://docs.lvgl.io/master/widgets/index.html): buttons, charts, lists, sliders, images, etc. +* Advanced graphics engine: animations, anti-aliasing, opacity, smooth scrolling, blending modes, etc +* Supports [various input devices](https://docs.lvgl.io/master/overview/indev.html): touchscreen, mouse, keyboard, encoder, buttons, etc. +* Supports [multiple displays](https://docs.lvgl.io/master/overview/display.html) +* Hardware independent, can be use with any microcontroller and display +* Scalable to operate with little memory (64 kB Flash, 16 kB RAM) +* Multi-language support with UTF-8 handling, CJK, Bidirectional and Arabic script support +* Fully customizable graphical elements via [CSS-like styles](https://docs.lvgl.io/master/overview/style.html) +* Powerful layouts inspired by CSS: [Flexbox](https://docs.lvgl.io/master/layouts/flex.html) and [Grid](https://docs.lvgl.io/master/layouts/grid.html) +* OS, External memory and GPU are supported but not required. (built in support for STM32 DMA2D, and NXP PXP and VGLite) +* Smooth rendering even with a [single frame buffer](https://docs.lvgl.io/master/porting/display.html) +* Written in C and compatibile with C++ +* Micropython Binding exposes [LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings) +* [Simulator](https://docs.lvgl.io/master/get-started/pc-simulator.html) to develop on PC without embedded hardware +* 100+ simple [Examples](https://github.com/lvgl/lvgl/tree/master/examples) +* [Documentation](http://docs.lvgl.io/) and API references online and in PDF + +### Requirements +Basically, every modern controller (which is able to drive a display) is suitable to run LVGL. The minimal requirements are: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name MinimalRecommended
Architecture16, 32 or 64 bit microcontroller or processor
Clock > 16 MHz > 48 MHz
Flash/ROM > 64 kB > 180 kB
Static RAM > 16 kB > 48 kB
Draw buffer > 1 × hor. res. pixels > 1/10 screen size
Compiler C99 or newer
+ +*Note that the memory usage might vary depending on the architecture, compiler and build options.* + +### Supported platforms +LVGL is completely platform independent and can be used with any MCU that fulfills the requirements. +Just to mention some platforms: +- NXP: Kinetis, LPC, iMX, iMX RT +- STM32F1, STM32F3, STM32F4, STM32F7, STM32L4, STM32L5, STM32H7 +- Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ +- [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb) +- [Raspberry Pi](http://www.vk3erw.com/index.php/16-software/63-raspberry-pi-official-7-touchscreen-and-littlevgl) +- [Espressif ESP32](https://github.com/lvgl/lv_port_esp32) +- [Infineon Aurix](https://github.com/lvgl/lv_port_aurix) +- Nordic NRF52 Bluetooth modules +- Quectel modems + +LVGL is also avaiable as: +- [Arduino library](https://docs.lvgl.io/master/get-started/arduino.html) +- [PlatformIO package](https://platformio.org/lib/show/12440/lvgl) +- [Zephyr library](https://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_LVGL.html) +- [ESP32 component](https://docs.lvgl.io/master/get-started/espressif.html) +- [NXP MCUXpresso component](https://www.nxp.com/design/software/embedded-software/lvgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY) +- [NuttX library](https://docs.lvgl.io/master/get-started/nuttx.html) + + +## Get started +This list shows the recommended way of learning the library: +1. Check the [Online demos](https://lvgl.io/demos) to see LVGL in action (3 minutes) +2. Read the [Introduction](https://docs.lvgl.io/master/intro/index.html) page of the documentation (5 minutes) +3. Get familiar with the basics on the [Quick overview](https://docs.lvgl.io/master/get-started/quick-overview.html) page (15 minutes) +4. Set up a [Simulator](https://docs.lvgl.io/master/get-started/pc-simulator.html) (10 minutes) +5. Try out some [Examples](https://github.com/lvgl/lvgl/tree/master/examples) +6. Port LVGL to a board. See the [Porting](https://docs.lvgl.io/master/porting/index.html) guide or check the ready to use [Projects](https://github.com/lvgl?q=lv_port_) +7. Read the [Overview](https://docs.lvgl.io/master/overview/index.html) page to get a better understanding of the library (2-3 hours) +8. Check the documentation of the [Widgets](https://docs.lvgl.io/master/widgets/index.html) to see their features and usage +9. If you have questions go to the [Forum](http://forum.lvgl.io/) +10. Read the [Contributing](https://docs.lvgl.io/master/CONTRIBUTING.html) guide to see how you can help to improve LVGL (15 minutes) + +## Examples + +For more examples see the [examples](https://github.com/lvgl/lvgl/tree/master/examples) folder. + +![LVGL button with label example](https://github.com/lvgl/lvgl/raw/master/docs/misc/btn_example.png) + +### C +```c +lv_obj_t * btn = lv_btn_create(lv_scr_act()); /*Add a button to the current screen*/ +lv_obj_set_pos(btn, 10, 10); /*Set its position*/ +lv_obj_set_size(btn, 100, 50); /*Set its size*/ +lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL); /*Assign a callback to the button*/ + +lv_obj_t * label = lv_label_create(btn); /*Add a label to the button*/ +lv_label_set_text(label, "Button"); /*Set the labels text*/ +lv_obj_center(label); /*Align the label to the center*/ +... + +void btn_event_cb(lv_event_t * e) +{ + printf("Clicked\n"); +} +``` +### Micropython +Learn more about [Micropython](https://docs.lvgl.io/master/get-started/micropython.html). +```python +def btn_event_cb(e): + print("Clicked") + +# Create a Button and a Label +btn = lv.btn(lv.scr_act()) +btn.set_pos(10, 10) +btn.set_size(100, 50) +btn.add_event_cb(btn_event_cb, lv.EVENT.CLICKED, None) + +label = lv.label(btn) +label.set_text("Button") +label.center() +``` + +## Services +LVGL Kft was established to provide a solid background for LVGL library. We offer several type of services to help you in UI development: +- Graphics design +- UI implementation +- Consulting/Support + +For more information see https://lvgl.io/services +Feel free to contact us if you have any questions. + + +## Contributing +LVGL is an open project and contribution is very welcome. There are many ways to contribute from simply speaking about your project, through writing examples, improving the documentation, fixing bugs to hosting your own project under the LVGL organization. + +For a detailed description of contribution opportunities visit the [Contributing](https://docs.lvgl.io/master/CONTRIBUTING.html) section of the documentation. + diff --git a/lib/libesp32_lvgl/LVGL8/library.json b/lib/libesp32_lvgl/lvgl/library.json similarity index 84% rename from lib/libesp32_lvgl/LVGL8/library.json rename to lib/libesp32_lvgl/lvgl/library.json index 4582bb729..f42b43d6a 100644 --- a/lib/libesp32_lvgl/LVGL8/library.json +++ b/lib/libesp32_lvgl/lvgl/library.json @@ -1,6 +1,6 @@ { - "name": "lvgl8", - "version": "8.0.2", + "name": "lvgl", + "version": "8.1.0", "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.", "repository": { @@ -12,8 +12,8 @@ }, "license": "MIT", "homepage": "https://lvgl.io", - "frameworks": "*", - "platforms": "*", + "frameworks": "arduino", + "platforms": "espressif32", "build": { "flags": [ "-I$PROJECT_DIR/tasmota/lvgl_berry" ] } diff --git a/lib/libesp32_lvgl/LVGL8/library.properties b/lib/libesp32_lvgl/lvgl/library.properties similarity index 96% rename from lib/libesp32_lvgl/LVGL8/library.properties rename to lib/libesp32_lvgl/lvgl/library.properties index 45962cb2f..cefc1def8 100644 --- a/lib/libesp32_lvgl/LVGL8/library.properties +++ b/lib/libesp32_lvgl/lvgl/library.properties @@ -1,5 +1,5 @@ name=lvgl -version=8.0.2 +version=8.1.0 author=kisvegabor maintainer=kisvegabor,embeddedt,pete-pjb sentence=Full-featured Graphics Library for Embedded Systems diff --git a/lib/libesp32_lvgl/LVGL8/lv_conf_template.h b/lib/libesp32_lvgl/lvgl/lv_conf_template.h similarity index 58% rename from lib/libesp32_lvgl/LVGL8/lv_conf_template.h rename to lib/libesp32_lvgl/lvgl/lv_conf_template.h index f7b96f182..8bdddb497 100644 --- a/lib/libesp32_lvgl/LVGL8/lv_conf_template.h +++ b/lib/libesp32_lvgl/lvgl/lv_conf_template.h @@ -1,82 +1,99 @@ /** * @file lv_conf.h - * Configuration file for v8.0.2 + * Configuration file for v8.1.0 */ /* - * COPY THIS FILE AS `lv_conf.h` NEXT TO the `lvgl` FOLDER + * Copy this file as `lv_conf.h` + * 1. simply next to the `lvgl` folder + * 2. or any other places and + * - define `LV_CONF_INCLUDE_SIMPLE` + * - add the path as include path */ +/* clang-format off */ #if 0 /*Set it to "1" to enable content*/ #ifndef LV_CONF_H #define LV_CONF_H -/*clang-format off*/ #include - /*==================== COLOR SETTINGS *====================*/ /*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/ -#define LV_COLOR_DEPTH 32 +#define LV_COLOR_DEPTH 16 -/*Swap the 2 bytes of RGB565 color. Useful if the display has a 8 bit interface (e.g. SPI)*/ -#define LV_COLOR_16_SWAP 0 +/*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/ +#define LV_COLOR_16_SWAP 0 /*Enable more complex drawing routines to manage screens transparency. *Can be used if the UI is above another layer, e.g. an OSD menu or video player. *Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to non LV_OPA_COVER value*/ -#define LV_COLOR_SCREEN_TRANSP 0 +#define LV_COLOR_SCREEN_TRANSP 0 -/*Images pixels with this color will not be drawn if they are chroma keyed)*/ -#define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/ +/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. + * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */ +#define LV_COLOR_MIX_ROUND_OFS (LV_COLOR_DEPTH == 32 ? 0: 128) + +/*Images pixels with this color will not be drawn if they are chroma keyed)*/ +#define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/ /*========================= MEMORY SETTINGS *=========================*/ /*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/ -#define LV_MEM_CUSTOM 0 +#define LV_MEM_CUSTOM 0 #if LV_MEM_CUSTOM == 0 /*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/ -# define LV_MEM_SIZE (32U * 1024U) /*[bytes]*/ +# define LV_MEM_SIZE (32U * 1024U) /*[bytes]*/ /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/ -# define LV_MEM_ADR 0 /*0: unused*/ +# define LV_MEM_ADR 0 /*0: unused*/ +/*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/ +#if LV_MEM_ADR == 0 +//#define LV_MEM_POOL_INCLUDE your_alloc_library /* Uncomment if using an external allocator*/ +//#define LV_MEM_POOL_ALLOC your_alloc /* Uncomment if using an external allocator*/ +#endif + #else /*LV_MEM_CUSTOM*/ # define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ -# define LV_MEM_CUSTOM_ALLOC malloc -# define LV_MEM_CUSTOM_FREE free -# define LV_MEM_CUSTOM_REALLOC realloc +# define LV_MEM_CUSTOM_ALLOC malloc +# define LV_MEM_CUSTOM_FREE free +# define LV_MEM_CUSTOM_REALLOC realloc #endif /*LV_MEM_CUSTOM*/ +/*Number of the intermediate memory buffer used during rendering and other internal processing mechanisms. + *You will see an error log message if there wasn't enough buffers. */ +#define LV_MEM_BUF_MAX_NUM 16 + /*Use the standard `memcpy` and `memset` instead of LVGL's own functions. (Might or might not be faster).*/ -#define LV_MEMCPY_MEMSET_STD 0 +#define LV_MEMCPY_MEMSET_STD 0 /*==================== HAL SETTINGS *====================*/ -/*Default display refresh period. LVG will redraw changed ares with this period time*/ -#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ +/*Default display refresh period. LVG will redraw changed areas with this period time*/ +#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ /*Input device read period in milliseconds*/ -#define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/ +#define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/ /*Use a custom tick source that tells the elapsed time in milliseconds. *It removes the need to manually update the tick with `lv_tick_inc()`)*/ -#define LV_TICK_CUSTOM 0 +#define LV_TICK_CUSTOM 0 #if LV_TICK_CUSTOM -#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ -#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ +#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ +#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ #endif /*LV_TICK_CUSTOM*/ /*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings. *(Not so important, you can adjust it to modify default sizes and spaces)*/ -#define LV_DPI_DEF 130 /*[px/inch]*/ +#define LV_DPI_DEF 130 /*[px/inch]*/ /*======================= * FEATURE CONFIGURATION @@ -94,7 +111,14 @@ /*Allow buffering some shadow calculation. *LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius` *Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/ -#define LV_SHADOW_CACHE_SIZE 0 +#define LV_SHADOW_CACHE_SIZE 0 + +/* Set number of maximally cached circle data. + * The circumference of 1/4 circle are saved for anti-aliasing + * radius * 4 bytes are used per circle (the most often used radiuses are saved) + * 0: to disable caching */ +#define LV_CIRCLE_CACHE_SIZE 4 + #endif /*LV_DRAW_COMPLEX*/ /*Default image cache size. Image caching keeps the images opened. @@ -102,16 +126,17 @@ *With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. *However the opened images might consume additional RAM. *0: to disable caching*/ -#define LV_IMG_CACHE_DEF_SIZE 0 +#define LV_IMG_CACHE_DEF_SIZE 0 /*Maximum buffer size to allocate for rotation. Only used if software rotation is enabled in the display driver.*/ -#define LV_DISP_ROT_MAX_BUF (10*1024) +#define LV_DISP_ROT_MAX_BUF (10*1024) + /*------------- * GPU *-----------*/ /*Use STM32's DMA2D (aka Chrom Art) GPU*/ -#define LV_USE_GPU_STM32_DMA2D 0 +#define LV_USE_GPU_STM32_DMA2D 0 #if LV_USE_GPU_STM32_DMA2D /*Must be defined to include path of CMSIS header of target processor e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ @@ -119,7 +144,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #endif /*Use NXP's PXP GPU iMX RTxxx platforms*/ -#define LV_USE_GPU_NXP_PXP 0 +#define LV_USE_GPU_NXP_PXP 0 #if LV_USE_GPU_NXP_PXP /*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c) * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS @@ -130,14 +155,23 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #endif /*Use NXP's VG-Lite GPU iMX RTxxx platforms*/ -#define LV_USE_GPU_NXP_VG_LITE 0 +#define LV_USE_GPU_NXP_VG_LITE 0 + +/*Use exnternal renderer*/ +#define LV_USE_EXTERNAL_RENDERER 0 + +/*Use SDL renderer API. Requires LV_USE_EXTERNAL_RENDERER*/ +#define LV_USE_GPU_SDL 0 +#if LV_USE_GPU_SDL +# define LV_GPU_SDL_INCLUDE_PATH +#endif /*------------- * Logging *-----------*/ /*Enable the log module*/ -#define LV_USE_LOG 0 // change to 0 in normal conditions +#define LV_USE_LOG 0 #if LV_USE_LOG /*How important log should be added: @@ -147,21 +181,21 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ *LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail *LV_LOG_LEVEL_USER Only logs added by the user *LV_LOG_LEVEL_NONE Do not log anything*/ -# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN +# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN /*1: Print the log with 'printf'; *0: User need to register a callback with `lv_log_register_print_cb()`*/ -# define LV_LOG_PRINTF 0 +# define LV_LOG_PRINTF 0 /*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/ -# define LV_LOG_TRACE_MEM 1 -# define LV_LOG_TRACE_TIMER 1 -# define LV_LOG_TRACE_INDEV 1 -# define LV_LOG_TRACE_DISP_REFR 1 -# define LV_LOG_TRACE_EVENT 1 -# define LV_LOG_TRACE_OBJ_CREATE 1 -# define LV_LOG_TRACE_LAYOUT 1 -# define LV_LOG_TRACE_ANIM 1 +# define LV_LOG_TRACE_MEM 1 +# define LV_LOG_TRACE_TIMER 1 +# define LV_LOG_TRACE_INDEV 1 +# define LV_LOG_TRACE_DISP_REFR 1 +# define LV_LOG_TRACE_EVENT 1 +# define LV_LOG_TRACE_OBJ_CREATE 1 +# define LV_LOG_TRACE_LAYOUT 1 +# define LV_LOG_TRACE_ANIM 1 #endif /*LV_USE_LOG*/ @@ -178,37 +212,43 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/ /*Add a custom handler when assert happens e.g. to restart the MCU*/ -#define LV_ASSERT_HANDLER_INCLUDE -#define LV_ASSERT_HANDLER while(1); /*Halt by default*/ +#define LV_ASSERT_HANDLER_INCLUDE +#define LV_ASSERT_HANDLER while(1); /*Halt by default*/ /*------------- * Others *-----------*/ /*1: Show CPU usage and FPS count in the right bottom corner*/ -#define LV_USE_PERF_MONITOR 0 +#define LV_USE_PERF_MONITOR 0 +#if LV_USE_PERF_MONITOR +#define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT +#endif -/*1: Show the used memory and the memory fragmentation in the left bottom corner +/*1: Show the used memory and the memory fragmentation in the left bottom corner * Requires LV_MEM_CUSTOM = 0*/ -#define LV_USE_MEM_MONITOR 0 +#define LV_USE_MEM_MONITOR 0 +#if LV_USE_PERF_MONITOR +#define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT +#endif /*1: Draw random colored rectangles over the redrawn areas*/ -#define LV_USE_REFR_DEBUG 0 +#define LV_USE_REFR_DEBUG 0 /*Change the built in (v)snprintf functions*/ -#define LV_SPRINTF_CUSTOM 0 +#define LV_SPRINTF_CUSTOM 0 #if LV_SPRINTF_CUSTOM # define LV_SPRINTF_INCLUDE -# define lv_snprintf snprintf -# define lv_vsnprintf vsnprintf +# define lv_snprintf snprintf +# define lv_vsnprintf vsnprintf #else /*LV_SPRINTF_CUSTOM*/ # define LV_SPRINTF_USE_FLOAT 0 #endif /*LV_SPRINTF_CUSTOM*/ -#define LV_USE_USER_DATA 1 +#define LV_USE_USER_DATA 1 /*Garbage Collector settings - *Used if lvgl is binded to higher level language and the memory is managed by that language*/ + *Used if lvgl is bound to higher level language and the memory is managed by that language*/ #define LV_ENABLE_GC 0 #if LV_ENABLE_GC != 0 # define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ @@ -219,7 +259,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ *====================*/ /*For big endian systems set to 1*/ -#define LV_BIG_ENDIAN_SYSTEM 0 +#define LV_BIG_ENDIAN_SYSTEM 0 /*Define a custom attribute to `lv_tick_inc` function*/ #define LV_ATTRIBUTE_TICK_INC @@ -231,7 +271,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #define LV_ATTRIBUTE_FLUSH_READY /*Required alignment size for buffers*/ -#define LV_ATTRIBUTE_MEM_ALIGN_SIZE +#define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1 /*Will be added where memories needs to be aligned (with -Os data might not be aligned to boundary by default). * E.g. __attribute__((aligned(4)))*/ @@ -254,7 +294,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/ /*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/ -#define LV_USE_LARGE_COORD 0 +#define LV_USE_LARGE_COORD 0 /*================== * FONT USAGE @@ -262,27 +302,27 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*Montserrat fonts with ASCII range and some symbols using bpp = 4 *https://fonts.google.com/specimen/Montserrat*/ -#define LV_FONT_MONTSERRAT_8 0 -#define LV_FONT_MONTSERRAT_10 0 -#define LV_FONT_MONTSERRAT_12 0 -#define LV_FONT_MONTSERRAT_14 1 -#define LV_FONT_MONTSERRAT_16 0 -#define LV_FONT_MONTSERRAT_18 0 -#define LV_FONT_MONTSERRAT_20 0 -#define LV_FONT_MONTSERRAT_22 0 -#define LV_FONT_MONTSERRAT_24 0 -#define LV_FONT_MONTSERRAT_26 0 -#define LV_FONT_MONTSERRAT_28 0 -#define LV_FONT_MONTSERRAT_30 0 -#define LV_FONT_MONTSERRAT_32 0 -#define LV_FONT_MONTSERRAT_34 0 -#define LV_FONT_MONTSERRAT_36 0 -#define LV_FONT_MONTSERRAT_38 0 -#define LV_FONT_MONTSERRAT_40 0 -#define LV_FONT_MONTSERRAT_42 0 -#define LV_FONT_MONTSERRAT_44 0 -#define LV_FONT_MONTSERRAT_46 0 -#define LV_FONT_MONTSERRAT_48 0 +#define LV_FONT_MONTSERRAT_8 0 +#define LV_FONT_MONTSERRAT_10 0 +#define LV_FONT_MONTSERRAT_12 0 +#define LV_FONT_MONTSERRAT_14 1 +#define LV_FONT_MONTSERRAT_16 0 +#define LV_FONT_MONTSERRAT_18 0 +#define LV_FONT_MONTSERRAT_20 0 +#define LV_FONT_MONTSERRAT_22 0 +#define LV_FONT_MONTSERRAT_24 0 +#define LV_FONT_MONTSERRAT_26 0 +#define LV_FONT_MONTSERRAT_28 0 +#define LV_FONT_MONTSERRAT_30 0 +#define LV_FONT_MONTSERRAT_32 0 +#define LV_FONT_MONTSERRAT_34 0 +#define LV_FONT_MONTSERRAT_36 0 +#define LV_FONT_MONTSERRAT_38 0 +#define LV_FONT_MONTSERRAT_40 0 +#define LV_FONT_MONTSERRAT_42 0 +#define LV_FONT_MONTSERRAT_44 0 +#define LV_FONT_MONTSERRAT_46 0 +#define LV_FONT_MONTSERRAT_48 0 /*Demonstrate special features*/ #define LV_FONT_MONTSERRAT_12_SUBPX 0 @@ -291,8 +331,8 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/ /*Pixel perfect monospace fonts*/ -#define LV_FONT_UNSCII_8 0 -#define LV_FONT_UNSCII_16 0 +#define LV_FONT_UNSCII_8 0 +#define LV_FONT_UNSCII_16 0 /*Optionally declare custom fonts here. *You can use these fonts as default font too and they will be available globally. @@ -305,16 +345,16 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*Enable handling large font and/or fonts with a lot of characters. *The limit depends on the font size, font face and bpp. *Compiler error will be triggered if a font needs it.*/ -#define LV_FONT_FMT_TXT_LARGE 0 +#define LV_FONT_FMT_TXT_LARGE 0 /*Enables/disables support for compressed fonts.*/ -#define LV_USE_FONT_COMPRESSED 0 +#define LV_USE_FONT_COMPRESSED 0 /*Enable subpixel rendering*/ -#define LV_USE_FONT_SUBPX 0 +#define LV_USE_FONT_SUBPX 0 #if LV_USE_FONT_SUBPX /*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/ -#define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/ +#define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/ #endif /*================= @@ -330,15 +370,15 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #define LV_TXT_ENC LV_TXT_ENC_UTF8 /*Can break (wrap) texts on these chars*/ -#define LV_TXT_BREAK_CHARS " ,.;:-_" +#define LV_TXT_BREAK_CHARS " ,.;:-_" /*If a word is at least this long, will break wherever "prettiest" *To disable, set to a value <= 0*/ -#define LV_TXT_LINE_BREAK_LONG_LEN 0 +#define LV_TXT_LINE_BREAK_LONG_LEN 0 /*Minimum number of characters in a long word to put on a line before a break. *Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/ -#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 +#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 /*Minimum number of characters in a long word to put on a line after a break. *Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/ @@ -348,15 +388,15 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #define LV_TXT_COLOR_CMD "#" /*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts. - *The direction will be processed according to the Unicode Bidirectioanl Algorithm: + *The direction will be processed according to the Unicode Bidirectional Algorithm: *https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ -#define LV_USE_BIDI 0 +#define LV_USE_BIDI 0 #if LV_USE_BIDI /*Set the default direction. Supported values: *`LV_BASE_DIR_LTR` Left-to-Right *`LV_BASE_DIR_RTL` Right-to-Left *`LV_BASE_DIR_AUTO` detect texts base direction*/ -#define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO +#define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO #endif /*Enable Arabic/Persian processing @@ -369,48 +409,47 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/ -#define LV_USE_ARC 1 +#define LV_USE_ARC 1 -#define LV_USE_ANIMIMG 1 +#define LV_USE_ANIMIMG 1 -#define LV_USE_BAR 1 +#define LV_USE_BAR 1 -#define LV_USE_BTN 1 +#define LV_USE_BTN 1 -#define LV_USE_BTNMATRIX 1 +#define LV_USE_BTNMATRIX 1 -#define LV_USE_CANVAS 1 +#define LV_USE_CANVAS 1 -#define LV_USE_CHECKBOX 1 +#define LV_USE_CHECKBOX 1 +#define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ -#define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ +#define LV_USE_IMG 1 /*Requires: lv_label*/ -#define LV_USE_IMG 1 /*Requires: lv_label*/ - -#define LV_USE_LABEL 1 +#define LV_USE_LABEL 1 #if LV_USE_LABEL -# define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ -# define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ +# define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ +# define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ #endif -#define LV_USE_LINE 1 +#define LV_USE_LINE 1 -#define LV_USE_ROLLER 1 /*Requires: lv_label*/ +#define LV_USE_ROLLER 1 /*Requires: lv_label*/ #if LV_USE_ROLLER -# define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/ +# define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/ #endif -#define LV_USE_SLIDER 1 /*Requires: lv_bar*/ +#define LV_USE_SLIDER 1 /*Requires: lv_bar*/ -#define LV_USE_SWITCH 1 +#define LV_USE_SWITCH 1 -#define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ +#define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ #if LV_USE_TEXTAREA != 0 -# define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ +# define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ #endif -#define LV_USE_TABLE 1 +#define LV_USE_TABLE 1 /*================== * EXTRA COMPONENTS @@ -419,7 +458,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*----------- * Widgets *----------*/ -#define LV_USE_CALENDAR 1 +#define LV_USE_CALENDAR 1 #if LV_USE_CALENDAR # define LV_CALENDAR_WEEK_STARTS_MONDAY 0 # if LV_CALENDAR_WEEK_STARTS_MONDAY @@ -429,81 +468,133 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # endif # define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"} -# define LV_USE_CALENDAR_HEADER_ARROW 1 -# define LV_USE_CALENDAR_HEADER_DROPDOWN 1 +# define LV_USE_CALENDAR_HEADER_ARROW 1 +# define LV_USE_CALENDAR_HEADER_DROPDOWN 1 #endif /*LV_USE_CALENDAR*/ -#define LV_USE_CHART 1 +#define LV_USE_CHART 1 -#define LV_USE_COLORWHEEL 1 +#define LV_USE_COLORWHEEL 1 -#define LV_USE_IMGBTN 1 +#define LV_USE_IMGBTN 1 -#define LV_USE_KEYBOARD 1 +#define LV_USE_KEYBOARD 1 -#define LV_USE_LED 1 +#define LV_USE_LED 1 -#define LV_USE_LIST 1 +#define LV_USE_LIST 1 -#define LV_USE_METER 1 +#define LV_USE_METER 1 -#define LV_USE_MSGBOX 1 +#define LV_USE_MSGBOX 1 -#define LV_USE_SPINBOX 1 +#define LV_USE_SPINBOX 1 -#define LV_USE_SPINNER 1 +#define LV_USE_SPINNER 1 -#define LV_USE_TABVIEW 1 +#define LV_USE_TABVIEW 1 -#define LV_USE_TILEVIEW 1 +#define LV_USE_TILEVIEW 1 -#define LV_USE_WIN 1 +#define LV_USE_WIN 1 -#define LV_USE_SPAN 1 +#define LV_USE_SPAN 1 #if LV_USE_SPAN /*A line text can contain maximum num of span descriptor */ -# define LV_SPAN_SNIPPET_STACK_SIZE 64 +# define LV_SPAN_SNIPPET_STACK_SIZE 64 #endif /*----------- * Themes *----------*/ + /*A simple, impressive and very complete theme*/ -#define LV_USE_THEME_DEFAULT 1 +#define LV_USE_THEME_DEFAULT 1 #if LV_USE_THEME_DEFAULT /*0: Light mode; 1: Dark mode*/ -# define LV_THEME_DEFAULT_DARK 0 +# define LV_THEME_DEFAULT_DARK 0 /*1: Enable grow on press*/ -# define LV_THEME_DEFAULT_GROW 1 +# define LV_THEME_DEFAULT_GROW 1 /*Default transition time in [ms]*/ -# define LV_THEME_DEFAULT_TRANSITON_TIME 80 +# define LV_THEME_DEFAULT_TRANSITION_TIME 80 #endif /*LV_USE_THEME_DEFAULT*/ -/*An very simple them that is a good starting point for a custom theme*/ - #define LV_USE_THEME_BASIC 1 +/*A very simple theme that is a good starting point for a custom theme*/ + #define LV_USE_THEME_BASIC 1 /*A theme designed for monochrome displays*/ -#define LV_USE_THEME_MONO 1 +#define LV_USE_THEME_MONO 1 /*----------- * Layouts *----------*/ /*A layout similar to Flexbox in CSS.*/ -#define LV_USE_FLEX 1 +#define LV_USE_FLEX 1 /*A layout similar to Grid in CSS.*/ -#define LV_USE_GRID 1 +#define LV_USE_GRID 1 + +/*--------------------- + * 3rd party libraries + *--------------------*/ + +/*File system interfaces for common APIs + *To enable set a driver letter for that API*/ +#define LV_USE_FS_STDIO '\0' /*Uses fopen, fread, etc*/ +//#define LV_FS_STDIO_PATH "/home/john/" /*Set the working directory. If commented it will be "./" */ + +#define LV_USE_FS_POSIX '\0' /*Uses open, read, etc*/ +//#define LV_FS_POSIX_PATH "/home/john/" /*Set the working directory. If commented it will be "./" */ + +#define LV_USE_FS_WIN32 '\0' /*Uses CreateFile, ReadFile, etc*/ +//#define LV_FS_WIN32_PATH "C:\\Users\\john\\" /*Set the working directory. If commented it will be ".\\" */ + +#define LV_USE_FS_FATFS '\0' /*Uses f_open, f_read, etc*/ + +/*PNG decoder library*/ +#define LV_USE_PNG 0 + +/*BMP decoder library*/ +#define LV_USE_BMP 0 + +/* JPG + split JPG decoder library. + * Split JPG is a custom format optimized for embedded systems. */ +#define LV_USE_SJPG 0 + +/*GIF decoder library*/ +#define LV_USE_GIF 0 + +/*QR code library*/ +#define LV_USE_QRCODE 0 + +/*FreeType library*/ +#define LV_USE_FREETYPE 0 +#if LV_USE_FREETYPE +/*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/ +# define LV_FREETYPE_CACHE_SIZE (16 * 1024) +#endif + +/*Rlottie library*/ +#define LV_USE_RLOTTIE 0 + +/*----------- + * Others + *----------*/ + +/*1: Enable API to take snapshot for object*/ +#define LV_USE_SNAPSHOT 1 + /*================== * EXAMPLES *==================*/ /*Enable the examples to be built with the library*/ -#define LV_BUILD_EXAMPLES 1 +#define LV_BUILD_EXAMPLES 1 /*--END OF LV_CONF_H--*/ diff --git a/lib/libesp32_lvgl/LVGL8/lvgl.h b/lib/libesp32_lvgl/lvgl/lvgl.h similarity index 93% rename from lib/libesp32_lvgl/LVGL8/lvgl.h rename to lib/libesp32_lvgl/lvgl/lvgl.h index 21de48a96..6717b4310 100644 --- a/lib/libesp32_lvgl/LVGL8/lvgl.h +++ b/lib/libesp32_lvgl/lvgl/lvgl.h @@ -14,8 +14,8 @@ extern "C" { * CURRENT VERSION OF LVGL ***************************/ #define LVGL_VERSION_MAJOR 8 -#define LVGL_VERSION_MINOR 0 -#define LVGL_VERSION_PATCH 2 +#define LVGL_VERSION_MINOR 1 +#define LVGL_VERSION_PATCH 0 #define LVGL_VERSION_INFO "" /********************* @@ -25,14 +25,16 @@ extern "C" { #include "src/misc/lv_log.h" #include "src/misc/lv_timer.h" #include "src/misc/lv_math.h" +#include "src/misc/lv_mem.h" #include "src/misc/lv_async.h" +#include "src/misc/lv_anim_timeline.h" +#include "src/misc/lv_printf.h" #include "src/hal/lv_hal.h" #include "src/core/lv_obj.h" #include "src/core/lv_group.h" #include "src/core/lv_indev.h" - #include "src/core/lv_refr.h" #include "src/core/lv_disp.h" #include "src/core/lv_theme.h" @@ -40,7 +42,6 @@ extern "C" { #include "src/font/lv_font.h" #include "src/font/lv_font_loader.h" #include "src/font/lv_font_fmt_txt.h" -#include "src/misc/lv_printf.h" #include "src/widgets/lv_arc.h" #include "src/widgets/lv_btn.h" @@ -69,6 +70,8 @@ extern "C" { #include "src/extra/widgets/lv_widgets.h" #include "src/extra/layouts/lv_layouts.h" #include "src/extra/themes/lv_themes.h" +#include "src/extra/others/lv_others.h" +#include "src/extra/libs/lv_libs.h" /********************* * DEFINES diff --git a/lib/libesp32_lvgl/LVGL8/lvgl.mk b/lib/libesp32_lvgl/lvgl/lvgl.mk similarity index 100% rename from lib/libesp32_lvgl/LVGL8/lvgl.mk rename to lib/libesp32_lvgl/lvgl/lvgl.mk diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_core.mk b/lib/libesp32_lvgl/lvgl/src/core/lv_core.mk similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_core.mk rename to lib/libesp32_lvgl/lvgl/src/core/lv_core.mk diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_disp.c b/lib/libesp32_lvgl/lvgl/src/core/lv_disp.c similarity index 87% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_disp.c rename to lib/libesp32_lvgl/lvgl/src/core/lv_disp.c index d8d9d9ae9..2806c4e7b 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_disp.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_disp.c @@ -82,15 +82,24 @@ void lv_disp_load_scr(lv_obj_t * scr) { lv_disp_t * d = lv_obj_get_disp(scr); if(!d) return; /*Shouldn't happen, just to be sure*/ + + lv_obj_t * old_scr = d->act_scr; + + if(d->act_scr) lv_event_send(old_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL); + if(d->act_scr) lv_event_send(scr, LV_EVENT_SCREEN_LOAD_START, NULL); + d->act_scr = scr; + if(d->act_scr) lv_event_send(scr, LV_EVENT_SCREEN_LOADED, NULL); + if(d->act_scr) lv_event_send(old_scr, LV_EVENT_SCREEN_UNLOADED, NULL); + lv_obj_invalidate(scr); } /** * Return with the top layer. (Same on every screen and it is above the normal screen layer) * @param disp pointer to display which top layer should be get. (NULL to use the default screen) - * @return pointer to the top layer object (transparent screen sized lv_obj) + * @return pointer to the top layer object (transparent screen sized lv_obj) */ lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp) { @@ -106,8 +115,8 @@ lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp) /** * Return with the sys. layer. (Same on every screen and it is above the normal screen and the top * layer) - * @param disp pointer to display which sys. layer should be get. (NULL to use the default screen) - * @return pointer to the sys layer object (transparent screen sized lv_obj) + * @param disp pointer to display which sys. layer should be retrieved. (NULL to use the default screen) + * @return pointer to the sys layer object (transparent screen sized lv_obj) */ lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp) { @@ -121,20 +130,18 @@ lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp) } /** - * Get the theme of a display + * Set the theme of a display * @param disp pointer to a display - * @return the display's theme (can be NULL) */ void lv_disp_set_theme(lv_disp_t * disp, lv_theme_t * th) { - if(disp == NULL) disp = lv_disp_get_default(); + if(disp == NULL) disp = lv_disp_get_default(); disp->theme = th; if(disp->screen_cnt == 3 && - lv_obj_get_child_cnt(disp->screens[0]) == 0 && - lv_obj_get_child_cnt(disp->screens[1]) == 0 && - lv_obj_get_child_cnt(disp->screens[2]) == 0) - { + lv_obj_get_child_cnt(disp->screens[0]) == 0 && + lv_obj_get_child_cnt(disp->screens[1]) == 0 && + lv_obj_get_child_cnt(disp->screens[2]) == 0) { lv_theme_apply(disp->screens[0]); } } @@ -145,7 +152,7 @@ void lv_disp_set_theme(lv_disp_t * disp, lv_theme_t * th) */ lv_theme_t * lv_disp_get_theme(lv_disp_t * disp) { - if(disp == NULL) disp = lv_disp_get_default(); + if(disp == NULL) disp = lv_disp_get_default(); return disp->theme; } @@ -191,7 +198,7 @@ void lv_disp_set_bg_image(lv_disp_t * disp, const void * img_src) } /** - * Opacity of the background + * Set opacity of the background * @param disp pointer to a display * @param opa opacity (0..255) */ @@ -220,16 +227,21 @@ void lv_disp_set_bg_opa(lv_disp_t * disp, lv_opa_t opa) */ void lv_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del) { + lv_disp_t * d = lv_obj_get_disp(new_scr); lv_obj_t * act_scr = lv_scr_act(); - if(d->del_prev && act_scr != d->scr_to_load && d->scr_to_load) { - lv_obj_del(act_scr); + /*If an other screen load animation is in progress + *make target screen loaded immediately. */ + if(d->scr_to_load && act_scr != d->scr_to_load) { lv_disp_load_scr(d->scr_to_load); lv_anim_del(d->scr_to_load, NULL); lv_obj_set_pos(d->scr_to_load, 0, 0); lv_obj_remove_local_style_prop(d->scr_to_load, LV_STYLE_OPA, 0); + if(d->del_prev) { + lv_obj_del(act_scr); + } act_scr = d->scr_to_load; } @@ -323,13 +335,16 @@ void lv_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t break; } + lv_event_send(act_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL); + lv_anim_start(&a_new); lv_anim_start(&a_old); + } /** * Get elapsed time since last user activity on a display (e.g. click) - * @param disp pointer to an display (NULL to get the overall smallest inactivity) + * @param disp pointer to a display (NULL to get the overall smallest inactivity) * @return elapsed ticks (milliseconds) since the last activity */ uint32_t lv_disp_get_inactive_time(const lv_disp_t * disp) @@ -350,7 +365,7 @@ uint32_t lv_disp_get_inactive_time(const lv_disp_t * disp) /** * Manually trigger an activity on a display - * @param disp pointer to an display (NULL to use the default display) + * @param disp pointer to a display (NULL to use the default display) */ void lv_disp_trig_activity(lv_disp_t * disp) { @@ -365,7 +380,7 @@ void lv_disp_trig_activity(lv_disp_t * disp) /** * Clean any CPU cache that is related to the display. - * @param disp pointer to an display (NULL to use the default display) + * @param disp pointer to a display (NULL to use the default display) */ void lv_disp_clean_dcache(lv_disp_t * disp) { @@ -403,9 +418,11 @@ lv_timer_t * _lv_disp_get_refr_timer(lv_disp_t * disp) static void scr_load_anim_start(lv_anim_t * a) { lv_disp_t * d = lv_obj_get_disp(a->var); - d->prev_scr = lv_scr_act(); - lv_disp_load_scr(a->var); + d->prev_scr = lv_scr_act(); + d->act_scr = a->var; + + lv_event_send(d->act_scr, LV_EVENT_SCREEN_LOAD_START, NULL); } static void opa_scale_anim(void * obj, int32_t v) @@ -427,6 +444,9 @@ static void scr_anim_ready(lv_anim_t * a) { lv_disp_t * d = lv_obj_get_disp(a->var); + lv_event_send(d->act_scr, LV_EVENT_SCREEN_LOADED, NULL); + lv_event_send(d->prev_scr, LV_EVENT_SCREEN_UNLOADED, NULL); + if(d->prev_scr && d->del_prev) lv_obj_del(d->prev_scr); d->prev_scr = NULL; d->scr_to_load = NULL; diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_disp.h b/lib/libesp32_lvgl/lvgl/src/core/lv_disp.h similarity index 90% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_disp.h rename to lib/libesp32_lvgl/lvgl/src/core/lv_disp.h index fdad3b7b7..01766b345 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_disp.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_disp.h @@ -67,22 +67,21 @@ void lv_disp_load_scr(lv_obj_t * scr); /** * Return with the top layer. (Same on every screen and it is above the normal screen layer) * @param disp pointer to display which top layer should be get. (NULL to use the default screen) - * @return pointer to the top layer object (transparent screen sized lv_obj) + * @return pointer to the top layer object (transparent screen sized lv_obj) */ lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp); /** * Return with the sys. layer. (Same on every screen and it is above the normal screen and the top * layer) - * @param disp pointer to display which sys. layer should be get. (NULL to use the default screen) - * @return pointer to the sys layer object (transparent screen sized lv_obj) + * @param disp pointer to display which sys. layer should be retrieved. (NULL to use the default screen) + * @return pointer to the sys layer object (transparent screen sized lv_obj) */ lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp); /** - * Get the theme of a display + * Set the theme of a display * @param disp pointer to a display - * @return the display's theme (can be NULL) */ void lv_disp_set_theme(lv_disp_t * disp, lv_theme_t * th); @@ -108,7 +107,7 @@ void lv_disp_set_bg_color(lv_disp_t * disp, lv_color_t color); void lv_disp_set_bg_image(lv_disp_t * disp, const void * img_src); /** - * Opacity of the background + * Set opacity of the background * @param disp pointer to a display * @param opa opacity (0..255) */ @@ -126,20 +125,20 @@ void lv_scr_load_anim(lv_obj_t * scr, lv_scr_load_anim_t anim_type, uint32_t tim /** * Get elapsed time since last user activity on a display (e.g. click) - * @param disp pointer to an display (NULL to get the overall smallest inactivity) + * @param disp pointer to a display (NULL to get the overall smallest inactivity) * @return elapsed ticks (milliseconds) since the last activity */ uint32_t lv_disp_get_inactive_time(const lv_disp_t * disp); /** * Manually trigger an activity on a display - * @param disp pointer to an display (NULL to use the default display) + * @param disp pointer to a display (NULL to use the default display) */ void lv_disp_trig_activity(lv_disp_t * disp); /** * Clean any CPU cache that is related to the display. - * @param disp pointer to an display (NULL to use the default display) + * @param disp pointer to a display (NULL to use the default display) */ void lv_disp_clean_dcache(lv_disp_t * disp); @@ -229,7 +228,7 @@ static inline lv_coord_t lv_dpx(lv_coord_t n) * considering the DPI of the given display. * It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the * DPI of the display. - * @param obj an display whose dpi should be considered + * @param obj a display whose dpi should be considered * @param n the number of pixels to scale * @return `n x current_dpi/160` */ diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_event.c b/lib/libesp32_lvgl/lvgl/src/core/lv_event.c similarity index 66% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_event.c rename to lib/libesp32_lvgl/lvgl/src/core/lv_event.c index 01cac5554..c9671fa8d 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_event.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_event.c @@ -17,18 +17,19 @@ /********************** * TYPEDEFS **********************/ -typedef struct _lv_event_dsc_t{ +typedef struct _lv_event_dsc_t { lv_event_cb_t cb; void * user_data; - lv_event_code_t filter :8; -}lv_event_dsc_t; + lv_event_code_t filter : 8; +} lv_event_dsc_t; /********************** * STATIC PROTOTYPES **********************/ static lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id); static lv_res_t event_send_core(lv_event_t * e); -static bool event_is_bubbled(lv_event_code_t e); +static bool event_is_bubbled(lv_event_t * e); + /********************** * STATIC VARIABLES @@ -39,9 +40,9 @@ static lv_event_t * event_head; * MACROS **********************/ #if LV_LOG_TRACE_EVENT -# define EVENT_TRACE(...) LV_LOG_TRACE( __VA_ARGS__) + #define EVENT_TRACE(...) LV_LOG_TRACE(__VA_ARGS__) #else -# define EVENT_TRACE(...) + #define EVENT_TRACE(...) #endif /********************** @@ -147,13 +148,15 @@ void _lv_event_mark_deleted(lv_obj_t * obj) } -struct _lv_event_dsc_t * lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data) +struct _lv_event_dsc_t * lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, + void * user_data) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_obj_allocate_spec_attr(obj); obj->spec_attr->event_dsc_cnt++; - obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); + obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, + obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); LV_ASSERT_MALLOC(obj->spec_attr->event_dsc); obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].cb = event_cb; @@ -170,14 +173,14 @@ bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb) int32_t i = 0; for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) { - if(obj->spec_attr->event_dsc[i].cb == event_cb) { + if(event_cb == NULL || obj->spec_attr->event_dsc[i].cb == event_cb) { /*Shift the remaining event handlers forward*/ - for(; i < (obj->spec_attr->event_dsc_cnt-1); i++) { - obj->spec_attr->event_dsc[i].cb = obj->spec_attr->event_dsc[i+1].cb; - obj->spec_attr->event_dsc[i].user_data = obj->spec_attr->event_dsc[i+1].user_data; + for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) { + obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1]; } obj->spec_attr->event_dsc_cnt--; - obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); + obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, + obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); LV_ASSERT_MALLOC(obj->spec_attr->event_dsc); return true; } @@ -187,6 +190,32 @@ bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb) return false; } +bool lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj, lv_event_cb_t event_cb, const void * user_data) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + if(obj->spec_attr == NULL) return false; + + int32_t i = 0; + for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) { + if((event_cb == NULL || obj->spec_attr->event_dsc[i].cb) && + obj->spec_attr->event_dsc[i].user_data == user_data) { + /*Shift the remaining event handlers forward*/ + for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) { + obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1]; + } + obj->spec_attr->event_dsc_cnt--; + obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, + obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); + LV_ASSERT_MALLOC(obj->spec_attr->event_dsc); + return true; + } + } + + /*No event handler found*/ + return false; +} + + bool lv_obj_remove_event_dsc(lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -196,12 +225,12 @@ bool lv_obj_remove_event_dsc(lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc) for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) { if(&obj->spec_attr->event_dsc[i] == event_dsc) { /*Shift the remaining event handlers forward*/ - for(; i < (obj->spec_attr->event_dsc_cnt-1); i++) { - obj->spec_attr->event_dsc[i].cb = obj->spec_attr->event_dsc[i+1].cb; - obj->spec_attr->event_dsc[i].user_data = obj->spec_attr->event_dsc[i+1].user_data; + for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) { + obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1]; } obj->spec_attr->event_dsc_cnt--; - obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); + obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, + obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); LV_ASSERT_MALLOC(obj->spec_attr->event_dsc); return true; } @@ -215,24 +244,24 @@ lv_indev_t * lv_event_get_indev(lv_event_t * e) { if(e->code == LV_EVENT_PRESSED || - e->code == LV_EVENT_PRESSING || - e->code == LV_EVENT_PRESS_LOST || - e->code == LV_EVENT_SHORT_CLICKED || - e->code == LV_EVENT_LONG_PRESSED || - e->code == LV_EVENT_LONG_PRESSED_REPEAT || - e->code == LV_EVENT_CLICKED || - e->code == LV_EVENT_RELEASED || - e->code == LV_EVENT_SCROLL_BEGIN || - e->code == LV_EVENT_SCROLL_END || - e->code == LV_EVENT_SCROLL || - e->code == LV_EVENT_GESTURE || - e->code == LV_EVENT_KEY || - e->code == LV_EVENT_FOCUSED || - e->code == LV_EVENT_DEFOCUSED || - e->code == LV_EVENT_LEAVE) - { + e->code == LV_EVENT_PRESSING || + e->code == LV_EVENT_PRESS_LOST || + e->code == LV_EVENT_SHORT_CLICKED || + e->code == LV_EVENT_LONG_PRESSED || + e->code == LV_EVENT_LONG_PRESSED_REPEAT || + e->code == LV_EVENT_CLICKED || + e->code == LV_EVENT_RELEASED || + e->code == LV_EVENT_SCROLL_BEGIN || + e->code == LV_EVENT_SCROLL_END || + e->code == LV_EVENT_SCROLL || + e->code == LV_EVENT_GESTURE || + e->code == LV_EVENT_KEY || + e->code == LV_EVENT_FOCUSED || + e->code == LV_EVENT_DEFOCUSED || + e->code == LV_EVENT_LEAVE) { return lv_event_get_param(e); - } else { + } + else { LV_LOG_WARN("Not interpreted with this event code"); return NULL; } @@ -240,11 +269,11 @@ lv_indev_t * lv_event_get_indev(lv_event_t * e) lv_obj_draw_part_dsc_t * lv_event_get_draw_part_dsc(lv_event_t * e) { - if(e->code == LV_EVENT_DRAW_PART_BEGIN|| - e->code == LV_EVENT_DRAW_PART_END) - { + if(e->code == LV_EVENT_DRAW_PART_BEGIN || + e->code == LV_EVENT_DRAW_PART_END) { return lv_event_get_param(e); - } else { + } + else { LV_LOG_WARN("Not interpreted with this event code"); return NULL; } @@ -253,14 +282,14 @@ lv_obj_draw_part_dsc_t * lv_event_get_draw_part_dsc(lv_event_t * e) const lv_area_t * lv_event_get_clip_area(lv_event_t * e) { if(e->code == LV_EVENT_DRAW_MAIN || - e->code == LV_EVENT_DRAW_MAIN_BEGIN || - e->code == LV_EVENT_DRAW_MAIN_END || - e->code == LV_EVENT_DRAW_POST || - e->code == LV_EVENT_DRAW_POST_BEGIN || - e->code == LV_EVENT_DRAW_POST_END) - { + e->code == LV_EVENT_DRAW_MAIN_BEGIN || + e->code == LV_EVENT_DRAW_MAIN_END || + e->code == LV_EVENT_DRAW_POST || + e->code == LV_EVENT_DRAW_POST_BEGIN || + e->code == LV_EVENT_DRAW_POST_END) { return lv_event_get_param(e); - } else { + } + else { LV_LOG_WARN("Not interpreted with this event code"); return NULL; } @@ -270,7 +299,8 @@ const lv_area_t * lv_event_get_old_size(lv_event_t * e) { if(e->code == LV_EVENT_SIZE_CHANGED) { return lv_event_get_param(e); - } else { + } + else { LV_LOG_WARN("Not interpreted with this event code"); return NULL; } @@ -282,7 +312,8 @@ uint32_t lv_event_get_key(lv_event_t * e) uint32_t * k = lv_event_get_param(e); if(k) return *k; else return 0; - } else { + } + else { LV_LOG_WARN("Not interpreted with this event code"); return 0; } @@ -292,7 +323,8 @@ lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e) { if(e->code == LV_EVENT_SCROLL_BEGIN) { return lv_event_get_param(e); - } else { + } + else { LV_LOG_WARN("Not interpreted with this event code"); return 0; } @@ -303,7 +335,8 @@ void lv_event_set_ext_draw_size(lv_event_t * e, lv_coord_t size) if(e->code == LV_EVENT_REFR_EXT_DRAW_SIZE) { lv_coord_t * cur_size = lv_event_get_param(e); *cur_size = LV_MAX(*cur_size, size); - } else { + } + else { LV_LOG_WARN("Not interpreted with this event code"); } } @@ -312,7 +345,8 @@ lv_point_t * lv_event_get_self_size_info(lv_event_t * e) { if(e->code == LV_EVENT_GET_SELF_SIZE) { return lv_event_get_param(e); - } else { + } + else { LV_LOG_WARN("Not interpreted with this event code"); return 0; } @@ -322,7 +356,8 @@ lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e) { if(e->code == LV_EVENT_HIT_TEST) { return lv_event_get_param(e); - } else { + } + else { LV_LOG_WARN("Not interpreted with this event code"); return 0; } @@ -333,7 +368,8 @@ const lv_area_t * lv_event_get_cover_area(lv_event_t * e) if(e->code == LV_EVENT_COVER_CHECK) { lv_cover_check_info_t * p = lv_event_get_param(e); return p->area; - } else { + } + else { LV_LOG_WARN("Not interpreted with this event code"); return NULL; } @@ -344,7 +380,8 @@ void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res) if(e->code == LV_EVENT_COVER_CHECK) { lv_cover_check_info_t * p = lv_event_get_param(e); if(res > p->res) p->res = res; /*Save only "stronger" results*/ - } else { + } + else { LV_LOG_WARN("Not interpreted with this event code"); } } @@ -365,7 +402,7 @@ static lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id) static lv_res_t event_send_core(lv_event_t * e) { - EVENT_TRACE("Sending event %d to %p with %p param", e->code, e->current_target, e->param); + EVENT_TRACE("Sending event %d to %p with %p param", e->code, (void *)e->current_target, e->param); /*Call the input device's feedback callback if set*/ lv_indev_t * indev_act = lv_indev_get_act(); @@ -391,39 +428,53 @@ static lv_res_t event_send_core(lv_event_t * e) event_dsc = lv_obj_get_event_dsc(e->current_target, i); } - if(res == LV_RES_OK && event_is_bubbled(e->code)) { - if(lv_obj_has_flag(e->current_target, LV_OBJ_FLAG_EVENT_BUBBLE) && e->current_target->parent) { + if(res == LV_RES_OK && e->current_target->parent && event_is_bubbled(e)) + { e->current_target = e->current_target->parent; res = event_send_core(e); if(res != LV_RES_OK) return LV_RES_INV; - } + } return res; } -static bool event_is_bubbled(lv_event_code_t e) +static bool event_is_bubbled(lv_event_t * e) { - switch(e) { - case LV_EVENT_HIT_TEST: - case LV_EVENT_COVER_CHECK: - case LV_EVENT_REFR_EXT_DRAW_SIZE: - case LV_EVENT_DRAW_MAIN_BEGIN: - case LV_EVENT_DRAW_MAIN: - case LV_EVENT_DRAW_MAIN_END: - case LV_EVENT_DRAW_POST_BEGIN: - case LV_EVENT_DRAW_POST: - case LV_EVENT_DRAW_POST_END: - case LV_EVENT_DRAW_PART_BEGIN: - case LV_EVENT_DRAW_PART_END: - case LV_EVENT_REFRESH: - case LV_EVENT_DELETE: - case LV_EVENT_CHILD_CHANGED: - case LV_EVENT_SIZE_CHANGED: - case LV_EVENT_STYLE_CHANGED: - case LV_EVENT_GET_SELF_SIZE: - return false; - default: - return true; + /*Event codes that always bubble*/ + switch(e->code) { + case LV_EVENT_CHILD_CREATED: + case LV_EVENT_CHILD_DELETED: + return true; + default: + break; + } + + /*Check other codes only if bubbling is enabled*/ + if(lv_obj_has_flag(e->current_target, LV_OBJ_FLAG_EVENT_BUBBLE) == false) return false; + + switch(e->code) { + case LV_EVENT_HIT_TEST: + case LV_EVENT_COVER_CHECK: + case LV_EVENT_REFR_EXT_DRAW_SIZE: + case LV_EVENT_DRAW_MAIN_BEGIN: + case LV_EVENT_DRAW_MAIN: + case LV_EVENT_DRAW_MAIN_END: + case LV_EVENT_DRAW_POST_BEGIN: + case LV_EVENT_DRAW_POST: + case LV_EVENT_DRAW_POST_END: + case LV_EVENT_DRAW_PART_BEGIN: + case LV_EVENT_DRAW_PART_END: + case LV_EVENT_REFRESH: + case LV_EVENT_DELETE: + case LV_EVENT_CHILD_CREATED: + case LV_EVENT_CHILD_DELETED: + case LV_EVENT_CHILD_CHANGED: + case LV_EVENT_SIZE_CHANGED: + case LV_EVENT_STYLE_CHANGED: + case LV_EVENT_GET_SELF_SIZE: + return false; + default: + return true; } } diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_event.h b/lib/libesp32_lvgl/lvgl/src/core/lv_event.h similarity index 88% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_event.h rename to lib/libesp32_lvgl/lvgl/src/core/lv_event.h index c8b60bb2f..dd425543b 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_event.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_event.h @@ -72,14 +72,20 @@ typedef enum { /** Other events*/ LV_EVENT_DELETE, /**< Object is being deleted*/ - LV_EVENT_CHILD_CHANGED, /**< Child was removed/added*/ + LV_EVENT_CHILD_CHANGED, /**< Child was removed, added, or its size, position were changed */ + LV_EVENT_CHILD_CREATED, /**< Child was created, always bubbles up to all parents*/ + LV_EVENT_CHILD_DELETED, /**< Child was deleted, always bubbles up to all parents*/ + LV_EVENT_SCREEN_UNLOAD_START, /**< A screen unload started, fired immediately when scr_load is called*/ + LV_EVENT_SCREEN_LOAD_START, /**< A screen load started, fired when the screen change delay is expired*/ + LV_EVENT_SCREEN_LOADED, /**< A screen was loaded*/ + LV_EVENT_SCREEN_UNLOADED, /**< A screen was unloaded*/ LV_EVENT_SIZE_CHANGED, /**< Object coordinates/size have changed*/ LV_EVENT_STYLE_CHANGED, /**< Object's style has changed*/ LV_EVENT_LAYOUT_CHANGED, /**< The children position has changed due to a layout recalculation*/ LV_EVENT_GET_SELF_SIZE, /**< Get the internal size of a widget*/ _LV_EVENT_LAST /** Number of default events*/ -}lv_event_code_t; +} lv_event_code_t; typedef struct _lv_event_t { struct _lv_obj_t * target; @@ -88,8 +94,8 @@ typedef struct _lv_event_t { void * user_data; void * param; struct _lv_event_t * prev; - uint8_t deleted :1; -}lv_event_t; + uint8_t deleted : 1; +} lv_event_t; /** * @brief Event callback. @@ -193,8 +199,8 @@ uint32_t lv_event_register_id(void); /** * Nested events can be called and one of them might belong to an object that is being deleted. - * Mark this object's `event_temp_data` deleted to know that it's `lv_event_send` should return `LV_RES_INV` - * @param obj pointer to an obejct to mark as deleted + * Mark this object's `event_temp_data` deleted to know that its `lv_event_send` should return `LV_RES_INV` + * @param obj pointer to an object to mark as deleted */ void _lv_event_mark_deleted(struct _lv_obj_t * obj); @@ -209,17 +215,29 @@ void _lv_event_mark_deleted(struct _lv_obj_t * obj); * @param user_data custom data data will be available in `event_cb` * @return a pointer the event descriptor. Can be used in ::lv_obj_remove_event_dsc */ -struct _lv_event_dsc_t * lv_obj_add_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data); +struct _lv_event_dsc_t * lv_obj_add_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, + void * user_data); /** * Remove an event handler function for an object. * @param obj pointer to an object - * @param event_cb the event function to remove + * @param event_cb the event function to remove, or `NULL` to remove the the firstly added event callback * @return true if any event handlers were removed */ bool lv_obj_remove_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb); /** + * Remove an event handler function with a specific user_data from an object. + * @param obj pointer to an object + * @param event_cb the event function to remove, or `NULL` only `user_data` matters. + * @param event_user_data the user_data specified in ::lv_obj_add_event_cb + * @return true if any event handlers were removed + */ +bool lv_obj_remove_event_cb_with_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb, + const void * event_user_data); + +/** + * DEPRACTED because doesn't work if multiple event handlers are added to an object. * Remove an event handler function for an object. * @param obj pointer to an object * @param event_dsc pointer to an event descriptor to remove (returned by ::lv_obj_add_event_cb) diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_group.c b/lib/libesp32_lvgl/lvgl/src/core/lv_group.c similarity index 90% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_group.c rename to lib/libesp32_lvgl/lvgl/src/core/lv_group.c index 7a9a2c846..9a1664672 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_group.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_group.c @@ -79,7 +79,7 @@ void lv_group_del(lv_group_t * group) /*Remove the objects from the group*/ lv_obj_t ** obj; _LV_LL_READ(&group->obj_ll, obj) { - if((*obj)->spec_attr) (*obj)->spec_attr->group_p = NULL; + if((*obj)->spec_attr)(*obj)->spec_attr->group_p = NULL; } _lv_ll_clear(&(group->obj_ll)); @@ -139,6 +139,25 @@ void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj) LV_LOG_TRACE("finished"); } +void lv_group_swap_obj(lv_obj_t * obj1, lv_obj_t * obj2) +{ + lv_group_t * g1 = lv_obj_get_group(obj1); + lv_group_t * g2 = lv_obj_get_group(obj2); + if(g1 != g2) return; + if(g1 == NULL) return; + + /*Do not add the object twice*/ + lv_obj_t ** obj_i; + _LV_LL_READ(&g1->obj_ll, obj_i) { + if((*obj_i) == obj1)(*obj_i) = obj2; + else if((*obj_i) == obj2)(*obj_i) = obj1; + } + + if(*g1->obj_focus == obj1) lv_group_focus_obj(obj2); + else if(*g1->obj_focus == obj2) lv_group_focus_obj(obj1); + +} + void lv_group_remove_obj(lv_obj_t * obj) { lv_group_t * g = lv_obj_get_group(obj); @@ -192,7 +211,7 @@ void lv_group_remove_all_objs(lv_group_t * group) /*Remove the objects from the group*/ lv_obj_t ** obj; _LV_LL_READ(&group->obj_ll, obj) { - if((*obj)->spec_attr) (*obj)->spec_attr->group_p = NULL; + if((*obj)->spec_attr)(*obj)->spec_attr->group_p = NULL; } _lv_ll_clear(&(group->obj_ll)); @@ -251,13 +270,7 @@ lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c) { lv_obj_t * act = lv_group_get_focused(group); if(act == NULL) return LV_RES_OK; - - lv_res_t res; - - res = lv_event_send(act, LV_EVENT_KEY, &c); - if(res != LV_RES_OK) return res; - - return res; + return lv_event_send(act, LV_EVENT_KEY, &c); } void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb) @@ -382,8 +395,18 @@ static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *) if(obj_next == NULL) continue; if(lv_obj_get_state(*obj_next) & LV_STATE_DISABLED) continue; - /*Hidden objects don't receive focus*/ - if(lv_obj_has_flag(*obj_next, LV_OBJ_FLAG_HIDDEN) == false) break; + /*Hidden objects don't receive focus. + *If any parent is hidden, the object is also hidden)*/ + lv_obj_t * parent = *obj_next; + while(parent) { + if(lv_obj_has_flag(parent, LV_OBJ_FLAG_HIDDEN)) break; + parent = lv_obj_get_parent(parent); + } + + if(parent && lv_obj_has_flag(parent, LV_OBJ_FLAG_HIDDEN)) continue; + + /*If we got her a good candidate is found*/ + break; } if(obj_next == group->obj_focus) return; /*There's only one visible object and it's already focused*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_group.h b/lib/libesp32_lvgl/lvgl/src/core/lv_group.h similarity index 95% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_group.h rename to lib/libesp32_lvgl/lvgl/src/core/lv_group.h index 63dd37800..ecf88df6b 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_group.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_group.h @@ -53,7 +53,7 @@ typedef void (*lv_group_focus_cb_t)(struct _lv_group_t *); /** * Groups can be used to logically hold objects so that they can be individually focused. - * They are NOT for laying out objects on a screen (try `lv_cont` for that). + * They are NOT for laying out objects on a screen (try layouts for that). */ typedef struct _lv_group_t { lv_ll_t obj_ll; /**< Linked list to store the objects in the group*/ @@ -76,7 +76,7 @@ typedef struct _lv_group_t { typedef enum { LV_GROUP_REFOCUS_POLICY_NEXT = 0, LV_GROUP_REFOCUS_POLICY_PREV = 1 -}lv_group_refocus_policy_t; +} lv_group_refocus_policy_t; /********************** * GLOBAL PROTOTYPES @@ -119,6 +119,13 @@ lv_group_t * lv_group_get_default(void); */ void lv_group_add_obj(lv_group_t * group, struct _lv_obj_t * obj); +/** + * Swap 2 object in a group. The object must be in the same group + * @param obj1 pointer to an object + * @param obj2 pointer to an other object + */ +void lv_group_swap_obj(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2); + /** * Remove an object from its group * @param obj pointer to an object to remove diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_indev.c b/lib/libesp32_lvgl/lvgl/src/core/lv_indev.c similarity index 88% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_indev.c rename to lib/libesp32_lvgl/lvgl/src/core/lv_indev.c index 2e16b8e5f..02a65a28f 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_indev.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_indev.c @@ -52,9 +52,9 @@ static lv_obj_t * indev_obj_act = NULL; * MACROS **********************/ #if LV_LOG_TRACE_INDEV -# define INDEV_TRACE(...) LV_LOG_TRACE( __VA_ARGS__) + #define INDEV_TRACE(...) LV_LOG_TRACE(__VA_ARGS__) #else -# define INDEV_TRACE(...) + #define INDEV_TRACE(...) #endif /********************** @@ -143,29 +143,32 @@ void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj) if(indev) { indev->proc.reset_query = 1; if(indev_act == indev) indev_obj_act = NULL; - if(obj == NULL || indev->proc.types.pointer.last_pressed == obj) { - indev->proc.types.pointer.last_pressed = NULL; - } - if(obj == NULL || indev->proc.types.pointer.act_obj == obj) { - indev->proc.types.pointer.act_obj = NULL; - } - if(obj == NULL || indev->proc.types.pointer.last_obj == obj) { - indev->proc.types.pointer.last_obj = NULL; + if(indev->driver->type == LV_INDEV_TYPE_POINTER || indev->driver->type == LV_INDEV_TYPE_KEYPAD) { + if(obj == NULL || indev->proc.types.pointer.last_pressed == obj) { + indev->proc.types.pointer.last_pressed = NULL; + } + if(obj == NULL || indev->proc.types.pointer.act_obj == obj) { + indev->proc.types.pointer.act_obj = NULL; + } + if(obj == NULL || indev->proc.types.pointer.last_obj == obj) { + indev->proc.types.pointer.last_obj = NULL; + } } } else { lv_indev_t * i = lv_indev_get_next(NULL); while(i) { i->proc.reset_query = 1; - if((i->driver->type == LV_INDEV_TYPE_POINTER || i->driver->type == LV_INDEV_TYPE_KEYPAD) && - (obj == NULL || i->proc.types.pointer.last_pressed == obj)) { - i->proc.types.pointer.last_pressed = NULL; - } - if(obj == NULL || i->proc.types.pointer.act_obj == obj) { - i->proc.types.pointer.act_obj = NULL; - } - if(obj == NULL || i->proc.types.pointer.last_obj == obj) { - i->proc.types.pointer.last_obj = NULL; + if(i->driver->type == LV_INDEV_TYPE_POINTER || i->driver->type == LV_INDEV_TYPE_KEYPAD) { + if(obj == NULL || i->proc.types.pointer.last_pressed == obj) { + i->proc.types.pointer.last_pressed = NULL; + } + if(obj == NULL || i->proc.types.pointer.act_obj == obj) { + i->proc.types.pointer.act_obj = NULL; + } + if(obj == NULL || i->proc.types.pointer.last_obj == obj) { + i->proc.types.pointer.last_obj = NULL; + } } i = lv_indev_get_next(i); } @@ -290,8 +293,9 @@ lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point) /*If the point is on this object check its children too*/ if(lv_obj_hit_test(obj, point)) { int32_t i; - for(i = lv_obj_get_child_cnt(obj) - 1; i >= 0; i--) { - lv_obj_t * child = lv_obj_get_child(obj, i); + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = child_cnt - 1; i >= 0; i--) { + lv_obj_t * child = obj->spec_attr->children[i]; found_p = lv_indev_search_obj(child, point); /*If a child was found then break*/ @@ -325,7 +329,7 @@ lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point) */ static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data) { - lv_disp_t *disp = i->driver->disp; + lv_disp_t * disp = i->driver->disp; /*Save the raw points so they can be used again in _lv_indev_read*/ i->proc.types.pointer.last_raw_point.x = data->point.x; i->proc.types.pointer.last_raw_point.y = data->point.y; @@ -342,9 +346,11 @@ static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data) /*Simple sanity check*/ if(data->point.x < 0) LV_LOG_WARN("X is %d which is smaller than zero", data->point.x); - if(data->point.x >= lv_disp_get_hor_res(i->driver->disp)) LV_LOG_WARN("X is %d which is greater than hor. res", data->point.x); + if(data->point.x >= lv_disp_get_hor_res(i->driver->disp)) LV_LOG_WARN("X is %d which is greater than hor. res", + data->point.x); if(data->point.y < 0) LV_LOG_WARN("Y is %d which is smaller than zero", data->point.y); - if(data->point.y >= lv_disp_get_ver_res(i->driver->disp)) LV_LOG_WARN("Y is %d which is greater than hor. res", data->point.y); + if(data->point.y >= lv_disp_get_ver_res(i->driver->disp)) LV_LOG_WARN("Y is %d which is greater than hor. res", + data->point.y); /*Move the cursor if set and moved*/ if(i->cursor != NULL && @@ -554,9 +560,9 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) i->proc.pr_timestamp = lv_tick_get(); if(data->key == LV_KEY_ENTER) { - bool editable = lv_obj_is_editable(indev_obj_act); - - if(lv_group_get_editing(g) == true || editable == false) { + bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) || + lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE); + if(lv_group_get_editing(g) == true || editable_or_scrollable == false) { lv_event_send(indev_obj_act, LV_EVENT_PRESSED, indev_act); if(indev_reset_check(&i->proc)) return; } @@ -590,12 +596,14 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) i->proc.longpr_rep_timestamp = lv_tick_get(); if(data->key == LV_KEY_ENTER) { - bool editable = lv_obj_is_editable(indev_obj_act); + bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) || + lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE); /*On enter long press toggle edit mode.*/ - if(editable) { + if(editable_or_scrollable) { /*Don't leave edit mode if there is only one object (nowhere to navigate)*/ if(lv_group_get_obj_count(g) > 1) { + LV_LOG_INFO("toggling edit mode"); lv_group_set_editing(g, lv_group_get_editing(g) ? false : true); /*Toggle edit mode on long press*/ lv_obj_clear_state(indev_obj_act, LV_STATE_PRESSED); /*Remove the pressed state manually*/ } @@ -639,10 +647,11 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) LV_LOG_INFO("released"); if(data->key == LV_KEY_ENTER) { - bool editable = lv_obj_is_editable(indev_obj_act); + bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) || + lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE); /*The button was released on a non-editable object. Just send enter*/ - if(editable == false) { + if(editable_or_scrollable == false) { lv_event_send(indev_obj_act, LV_EVENT_RELEASED, indev_act); if(indev_reset_check(&i->proc)) return; @@ -668,13 +677,15 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) lv_group_send_data(g, LV_KEY_ENTER); - } else { + } + else { lv_obj_clear_state(indev_obj_act, LV_STATE_PRESSED); /*Remove the pressed state manually*/ } } /*If the focused object is editable and now in navigate mode then on enter switch edit mode*/ - else if(editable && !lv_group_get_editing(g) && !i->proc.long_pr_sent) { + else if(!i->proc.long_pr_sent) { + LV_LOG_INFO("entering edit mode"); lv_group_set_editing(g, true); /*Set edit mode*/ } } @@ -686,9 +697,9 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) /*if encoder steps or simulated steps via left/right keys*/ if(data->enc_diff != 0) { - LV_LOG_INFO("rotated by %d", data->enc_diff); /*In edit mode send LEFT/RIGHT keys*/ if(lv_group_get_editing(g)) { + LV_LOG_INFO("rotated by %+d (edit)", data->enc_diff); int32_t s; if(data->enc_diff < 0) { for(s = 0; s < -data->enc_diff; s++) lv_group_send_data(g, LV_KEY_LEFT); @@ -699,6 +710,7 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) } /*In navigate mode focus on the next/prev objects*/ else { + LV_LOG_INFO("rotated by %+d (nav)", data->enc_diff); int32_t s; if(data->enc_diff < 0) { for(s = 0; s < -data->enc_diff; s++) lv_group_focus_prev(g); @@ -981,66 +993,67 @@ static void indev_proc_reset_query_handler(lv_indev_t * indev) static void indev_click_focus(_lv_indev_proc_t * proc) { /*Handle click focus*/ - lv_obj_t * obj_to_focus = indev_obj_act; - if(lv_obj_has_flag(obj_to_focus, LV_OBJ_FLAG_CLICK_FOCUSABLE) && - proc->types.pointer.last_pressed != obj_to_focus) { - lv_group_t * g_act = lv_obj_get_group(obj_to_focus); - lv_group_t * g_prev = proc->types.pointer.last_pressed ? lv_obj_get_group(proc->types.pointer.last_pressed) : NULL; + if(lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_CLICK_FOCUSABLE) == false || + proc->types.pointer.last_pressed == indev_obj_act) + { + return; + } - /*If both the last and act. obj. are in the same group (or no group but it's also the same)*/ - if(g_act == g_prev) { - /*The objects are in a group*/ - if(g_act) { - lv_group_focus_obj(obj_to_focus); - if(indev_reset_check(proc)) return; - } - /*The object are not in group*/ - else { - if(proc->types.pointer.last_pressed) { - lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act); - if(indev_reset_check(proc)) return; - } + lv_group_t * g_act = lv_obj_get_group(indev_obj_act); + lv_group_t * g_prev = proc->types.pointer.last_pressed ? lv_obj_get_group(proc->types.pointer.last_pressed) : NULL; - lv_event_send(obj_to_focus, LV_EVENT_FOCUSED, indev_act); - if(indev_reset_check(proc)) return; - } + /*If both the last and act. obj. are in the same group (or have no group)*/ + if(g_act == g_prev) { + /*The objects are in a group*/ + if(g_act) { + lv_group_focus_obj(indev_obj_act); + if(indev_reset_check(proc)) return; } - /*The object are not in the same group (in different group or one in not a group)*/ + /*The object are not in group*/ else { - /*If the prev. obj. is not in a group then defocus it.*/ - if(g_prev == NULL && proc->types.pointer.last_pressed) { + if(proc->types.pointer.last_pressed) { lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act); if(indev_reset_check(proc)) return; } - /*Focus on a non-group object*/ - else { - if(proc->types.pointer.last_pressed) { - /*If the prev. object also wasn't in a group defocus it*/ - if(g_prev == NULL) { - lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act); - if(indev_reset_check(proc)) return; - } - /*If the prev. object also was in a group at least "LEAVE" it instead of defocus*/ - else { - lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_LEAVE, indev_act); - if(indev_reset_check(proc)) return; - } + + lv_event_send(indev_obj_act, LV_EVENT_FOCUSED, indev_act); + if(indev_reset_check(proc)) return; + } + } + /*The object are not in the same group (in different groups or one has no group)*/ + else { + /*If the prev. obj. is not in a group then defocus it.*/ + if(g_prev == NULL && proc->types.pointer.last_pressed) { + lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act); + if(indev_reset_check(proc)) return; + } + /*Focus on a non-group object*/ + else { + if(proc->types.pointer.last_pressed) { + /*If the prev. object also wasn't in a group defocus it*/ + if(g_prev == NULL) { + lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act); + if(indev_reset_check(proc)) return; + } + /*If the prev. object also was in a group at least "LEAVE" it instead of defocus*/ + else { + lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_LEAVE, indev_act); + if(indev_reset_check(proc)) return; } } - - /*Focus to the act. in its group*/ - if(g_act) { - lv_group_focus_obj(obj_to_focus); - if(indev_reset_check(proc)) return; - } - else { - lv_event_send(obj_to_focus, LV_EVENT_FOCUSED, indev_act); - if(indev_reset_check(proc)) return; - } } - proc->types.pointer.last_pressed = obj_to_focus; - } + /*Focus to the act. in its group*/ + if(g_act) { + lv_group_focus_obj(indev_obj_act); + if(indev_reset_check(proc)) return; + } + else { + lv_event_send(indev_obj_act, LV_EVENT_FOCUSED, indev_act); + if(indev_reset_check(proc)) return; + } + } + proc->types.pointer.last_pressed = indev_obj_act; } /** diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_indev.h b/lib/libesp32_lvgl/lvgl/src/core/lv_indev.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_indev.h rename to lib/libesp32_lvgl/lvgl/src/core/lv_indev.h diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_indev_scroll.c b/lib/libesp32_lvgl/lvgl/src/core/lv_indev_scroll.c similarity index 72% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_indev_scroll.c rename to lib/libesp32_lvgl/lvgl/src/core/lv_indev_scroll.c index ff386aefc..bf356a87b 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_indev_scroll.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_indev_scroll.c @@ -28,7 +28,8 @@ static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coo static void scroll_limit_diff(_lv_indev_proc_t * proc, lv_coord_t * diff_x, lv_coord_t * diff_y); static lv_coord_t scroll_throw_predict_y(_lv_indev_proc_t * proc); static lv_coord_t scroll_throw_predict_x(_lv_indev_proc_t * proc); -static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_t scroll_start, lv_coord_t scroll_end, lv_dir_t dir); +static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_t scroll_start, lv_coord_t scroll_end, + lv_dir_t dir); /********************** * STATIC VARIABLES @@ -68,7 +69,8 @@ void _lv_indev_scroll_handler(_lv_indev_proc_t * proc) lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj); lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj); diff_x = elastic_diff(scroll_obj, proc->types.pointer.vect.x, sl, sr, LV_DIR_HOR); - } else { + } + else { lv_coord_t st = lv_obj_get_scroll_top(scroll_obj); lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj); diff_y = elastic_diff(scroll_obj, proc->types.pointer.vect.y, st, sb, LV_DIR_VER); @@ -113,12 +115,13 @@ void _lv_indev_scroll_throw_handler(_lv_indev_proc_t * proc) /*If no snapping "throw"*/ if(align_y == LV_SCROLL_SNAP_NONE) { proc->types.pointer.scroll_throw_vect.y = - proc->types.pointer.scroll_throw_vect.y * (100 - scroll_throw) / 100; + proc->types.pointer.scroll_throw_vect.y * (100 - scroll_throw) / 100; lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj); lv_coord_t st = lv_obj_get_scroll_top(scroll_obj); - proc->types.pointer.scroll_throw_vect.y = elastic_diff(scroll_obj, proc->types.pointer.scroll_throw_vect.y, st, sb, LV_DIR_VER); + proc->types.pointer.scroll_throw_vect.y = elastic_diff(scroll_obj, proc->types.pointer.scroll_throw_vect.y, st, sb, + LV_DIR_VER); lv_obj_scroll_by(scroll_obj, 0, proc->types.pointer.scroll_throw_vect.y, LV_ANIM_OFF); } @@ -136,12 +139,13 @@ void _lv_indev_scroll_throw_handler(_lv_indev_proc_t * proc) /*If no snapping "throw"*/ if(align_x == LV_SCROLL_SNAP_NONE) { proc->types.pointer.scroll_throw_vect.x = - proc->types.pointer.scroll_throw_vect.x * (100 - scroll_throw) / 100; + proc->types.pointer.scroll_throw_vect.x * (100 - scroll_throw) / 100; lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj); lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj); - proc->types.pointer.scroll_throw_vect.x = elastic_diff(scroll_obj, proc->types.pointer.scroll_throw_vect.x, sl ,sr, LV_DIR_HOR); + proc->types.pointer.scroll_throw_vect.x = elastic_diff(scroll_obj, proc->types.pointer.scroll_throw_vect.x, sl, sr, + LV_DIR_HOR); lv_obj_scroll_by(scroll_obj, proc->types.pointer.scroll_throw_vect.x, 0, LV_ANIM_OFF); } @@ -176,7 +180,7 @@ void _lv_indev_scroll_throw_handler(_lv_indev_proc_t * proc) if(align_x == LV_SCROLL_SNAP_NONE) { lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj); lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj); - if (sl > 0 || sr > 0) { + if(sl > 0 || sr > 0) { if(sl < 0) { lv_obj_scroll_by(scroll_obj, sl, 0, LV_ANIM_ON); } @@ -205,14 +209,14 @@ lv_coord_t lv_indev_scroll_throw_predict(lv_indev_t * indev, lv_dir_t dir) if(indev == NULL) return 0; lv_coord_t v; switch(dir) { - case LV_DIR_VER: - v = indev->proc.types.pointer.scroll_throw_vect_ori.y; - break; - case LV_DIR_HOR: - v = indev->proc.types.pointer.scroll_throw_vect_ori.x; - break; - default: - return 0; + case LV_DIR_VER: + v = indev->proc.types.pointer.scroll_throw_vect_ori.y; + break; + case LV_DIR_HOR: + v = indev->proc.types.pointer.scroll_throw_vect_ori.x; + break; + default: + return 0; } lv_coord_t scroll_throw = indev->driver->scroll_throw; @@ -242,10 +246,10 @@ static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc) lv_indev_t * indev_act = lv_indev_get_act(); lv_coord_t scroll_limit = indev_act->driver->scroll_limit; - /*Go until find an scrollable object in the current direction + /*Go until find a scrollable object in the current direction *More precisely: * 1. Check the pressed object and all of its ancestors and try to find an object which is scrollable - * 2. Scrollable means it has some content out of it's area + * 2. Scrollable means it has some content out of its area * 3. If an object can be scrolled into the current direction then use it ("real match"") * 4. If can be scrolled on the current axis (hor/ver) save it as candidate (at least show an elastic scroll effect) * 5. Use the last candidate. Always the "deepest" parent or the object from point 3*/ @@ -292,17 +296,15 @@ static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc) *is propagated to this object it can show at least elastic scroll effect. *But if not hor/ver scrollable do not scroll it at all (so it's not a good candidate)*/ if((st > 0 || sb > 0) && - ((up_en && proc->types.pointer.scroll_sum.y >= scroll_limit) || - (down_en && proc->types.pointer.scroll_sum.y <= - scroll_limit))) - { + ((up_en && proc->types.pointer.scroll_sum.y >= scroll_limit) || + (down_en && proc->types.pointer.scroll_sum.y <= - scroll_limit))) { obj_candidate = obj_act; dir_candidate = LV_DIR_VER; } if((sl > 0 || sr > 0) && - ((left_en && proc->types.pointer.scroll_sum.x >= scroll_limit) || - (right_en && proc->types.pointer.scroll_sum.x <= - scroll_limit))) - { + ((left_en && proc->types.pointer.scroll_sum.x >= scroll_limit) || + (right_en && proc->types.pointer.scroll_sum.x <= - scroll_limit))) { obj_candidate = obj_act; dir_candidate = LV_DIR_HOR; } @@ -314,10 +316,9 @@ static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc) /*If the object really can be scrolled into the current direction the use it.*/ if((left_en && proc->types.pointer.scroll_sum.x >= scroll_limit) || - (right_en && proc->types.pointer.scroll_sum.x <= - scroll_limit) || - (up_en && proc->types.pointer.scroll_sum.y >= scroll_limit) || - (down_en && proc->types.pointer.scroll_sum.y <= - scroll_limit)) - { + (right_en && proc->types.pointer.scroll_sum.x <= - scroll_limit) || + (up_en && proc->types.pointer.scroll_sum.y >= scroll_limit) || + (down_en && proc->types.pointer.scroll_sum.y <= - scroll_limit)) { proc->types.pointer.scroll_dir = hor_en ? LV_DIR_HOR : LV_DIR_VER; break; } @@ -350,45 +351,45 @@ static void init_scroll_limits(_lv_indev_proc_t * proc) /*With STOP limit the scrolling to the perv and next snap point*/ else { switch(lv_obj_get_scroll_snap_y(obj)) { - case LV_SCROLL_SNAP_START: - proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y1 + 1, LV_COORD_MAX, 0); - proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y1 - 1, 0); - break; - case LV_SCROLL_SNAP_END: - proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y2, LV_COORD_MAX, 0); - proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y2, 0); - break; - case LV_SCROLL_SNAP_CENTER: { - lv_coord_t y_mid = obj->coords.y1 + lv_area_get_height(&obj->coords) / 2; - proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, y_mid + 1, LV_COORD_MAX, 0); - proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, y_mid - 1, 0); - break; - } - default: - proc->types.pointer.scroll_area.y1 = LV_COORD_MIN; - proc->types.pointer.scroll_area.y2 = LV_COORD_MAX; - break; + case LV_SCROLL_SNAP_START: + proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y1 + 1, LV_COORD_MAX, 0); + proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y1 - 1, 0); + break; + case LV_SCROLL_SNAP_END: + proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y2, LV_COORD_MAX, 0); + proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y2, 0); + break; + case LV_SCROLL_SNAP_CENTER: { + lv_coord_t y_mid = obj->coords.y1 + lv_area_get_height(&obj->coords) / 2; + proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, y_mid + 1, LV_COORD_MAX, 0); + proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, y_mid - 1, 0); + break; + } + default: + proc->types.pointer.scroll_area.y1 = LV_COORD_MIN; + proc->types.pointer.scroll_area.y2 = LV_COORD_MAX; + break; } switch(lv_obj_get_scroll_snap_x(obj)) { - case LV_SCROLL_SNAP_START: - proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, obj->coords.x1, LV_COORD_MAX, 0); - proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, obj->coords.x1, 0); - break; - case LV_SCROLL_SNAP_END: - proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, obj->coords.x2, LV_COORD_MAX, 0); - proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, obj->coords.x2, 0); - break; - case LV_SCROLL_SNAP_CENTER: { - lv_coord_t x_mid = obj->coords.x1 + lv_area_get_width(&obj->coords) / 2; - proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, x_mid + 1, LV_COORD_MAX, 0); - proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, x_mid - 1, 0); - break; - } - default: - proc->types.pointer.scroll_area.x1 = LV_COORD_MIN; - proc->types.pointer.scroll_area.x2 = LV_COORD_MAX; - break; + case LV_SCROLL_SNAP_START: + proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, obj->coords.x1, LV_COORD_MAX, 0); + proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, obj->coords.x1, 0); + break; + case LV_SCROLL_SNAP_END: + proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, obj->coords.x2, LV_COORD_MAX, 0); + proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, obj->coords.x2, 0); + break; + case LV_SCROLL_SNAP_CENTER: { + lv_coord_t x_mid = obj->coords.x1 + lv_area_get_width(&obj->coords) / 2; + proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, x_mid + 1, LV_COORD_MAX, 0); + proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, x_mid - 1, 0); + break; + } + default: + proc->types.pointer.scroll_area.x1 = LV_COORD_MIN; + proc->types.pointer.scroll_area.x2 = LV_COORD_MAX; + break; } } @@ -402,8 +403,8 @@ static void init_scroll_limits(_lv_indev_proc_t * proc) /** * Search for snap point in the `min` - `max` range. * @param obj the object on which snap point should be found - * @param min ignore snap points smaller then this. (Absolute coordinate) - * @param max ignore snap points greater then this. (Absolute coordinate) + * @param min ignore snap points smaller than this. (Absolute coordinate) + * @param max ignore snap points greater than this. (Absolute coordinate) * @param ofs offset to snap points. Useful the get a snap point in an imagined case * what if children are already moved by this value * @return the distance of the snap point. @@ -419,27 +420,28 @@ static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coo lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); uint32_t i; - for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { - lv_obj_t * child = lv_obj_get_child(obj, i); + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; - if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPABLE)) { + if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) { lv_coord_t x_child = 0; lv_coord_t x_parent = 0; switch(align) { - case LV_SCROLL_SNAP_START: - x_child = child->coords.x1; - x_parent = obj->coords.x1 + pad_left; - break; - case LV_SCROLL_SNAP_END: - x_child = child->coords.x2; - x_parent = obj->coords.x2 - pad_right; - break; - case LV_SCROLL_SNAP_CENTER: - x_child = child->coords.x1 + lv_area_get_width(&child->coords) / 2; - x_parent = obj->coords.x1 + pad_left + (lv_area_get_width(&obj->coords) - pad_left - pad_right) / 2; - break; - default: - continue; + case LV_SCROLL_SNAP_START: + x_child = child->coords.x1; + x_parent = obj->coords.x1 + pad_left; + break; + case LV_SCROLL_SNAP_END: + x_child = child->coords.x2; + x_parent = obj->coords.x2 - pad_right; + break; + case LV_SCROLL_SNAP_CENTER: + x_child = child->coords.x1 + lv_area_get_width(&child->coords) / 2; + x_parent = obj->coords.x1 + pad_left + (lv_area_get_width(&obj->coords) - pad_left - pad_right) / 2; + break; + default: + continue; } x_child += ofs; @@ -450,15 +452,15 @@ static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coo } } - return dist == LV_COORD_MAX ? 0: -dist; + return dist == LV_COORD_MAX ? 0 : -dist; } /** * Search for snap point in the `min` - `max` range. * @param obj the object on which snap point should be found - * @param min ignore snap points smaller then this. (Absolute coordinate) - * @param max ignore snap points greater then this. (Absolute coordinate) - * @param ofs offset to snap points. Useful the get a snap point in an imagined case + * @param min ignore snap points smaller than this. (Absolute coordinate) + * @param max ignore snap points greater than this. (Absolute coordinate) + * @param ofs offset to snap points. Useful to get a snap point in an imagined case * what if children are already moved by this value * @return the distance of the snap point. */ @@ -473,27 +475,28 @@ static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coo lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); uint32_t i; - for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { - lv_obj_t * child = lv_obj_get_child(obj, i); + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; - if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPABLE)) { + if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) { lv_coord_t y_child = 0; lv_coord_t y_parent = 0; switch(align) { - case LV_SCROLL_SNAP_START: - y_child = child->coords.y1; - y_parent = obj->coords.y1 + pad_top; - break; - case LV_SCROLL_SNAP_END: - y_child = child->coords.y2; - y_parent = obj->coords.y2 - pad_bottom; - break; - case LV_SCROLL_SNAP_CENTER: - y_child = child->coords.y1 + lv_area_get_height(&child->coords) / 2; - y_parent = obj->coords.y1 + pad_top + (lv_area_get_height(&obj->coords) - pad_top - pad_bottom) / 2; - break; - default: - continue; + case LV_SCROLL_SNAP_START: + y_child = child->coords.y1; + y_parent = obj->coords.y1 + pad_top; + break; + case LV_SCROLL_SNAP_END: + y_child = child->coords.y2; + y_parent = obj->coords.y2 - pad_bottom; + break; + case LV_SCROLL_SNAP_CENTER: + y_child = child->coords.y1 + lv_area_get_height(&child->coords) / 2; + y_parent = obj->coords.y1 + pad_top + (lv_area_get_height(&obj->coords) - pad_top - pad_bottom) / 2; + break; + default: + continue; } y_child += ofs; @@ -511,7 +514,7 @@ static void scroll_limit_diff(_lv_indev_proc_t * proc, lv_coord_t * diff_x, lv_c { if(diff_y) { if(proc->types.pointer.scroll_sum.y + *diff_y < proc->types.pointer.scroll_area.y1) { - *diff_y = proc->types.pointer.scroll_area.y1 - proc->types.pointer.scroll_sum.y; + *diff_y = proc->types.pointer.scroll_area.y1 - proc->types.pointer.scroll_sum.y; } if(proc->types.pointer.scroll_sum.y + *diff_y > proc->types.pointer.scroll_area.y2) { @@ -563,7 +566,8 @@ static lv_coord_t scroll_throw_predict_x(_lv_indev_proc_t * proc) return move; } -static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_t scroll_start, lv_coord_t scroll_end, lv_dir_t dir) +static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_t scroll_start, lv_coord_t scroll_end, + lv_dir_t dir) { if(lv_obj_has_flag(scroll_obj, LV_OBJ_FLAG_SCROLL_ELASTIC)) { /*If there is snapping in the current direction don't use the elastic factor because @@ -580,36 +584,37 @@ static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_ lv_coord_t pad_right = lv_obj_get_style_pad_right(scroll_obj, LV_PART_MAIN); switch(snap) { - case LV_SCROLL_SNAP_CENTER: - snap_point = pad_left + (lv_area_get_width(&scroll_obj->coords) - pad_left - pad_right) / 2 + scroll_obj->coords.x1; - act_obj_point = lv_area_get_width(&act_obj->coords) / 2 + act_obj->coords.x1; - break; - case LV_SCROLL_SNAP_START: - snap_point = scroll_obj->coords.x1 + pad_left; - act_obj_point = act_obj->coords.x1; - break; - case LV_SCROLL_SNAP_END: - snap_point = scroll_obj->coords.x2 - pad_right; - act_obj_point = act_obj->coords.x2; - break; + case LV_SCROLL_SNAP_CENTER: + snap_point = pad_left + (lv_area_get_width(&scroll_obj->coords) - pad_left - pad_right) / 2 + scroll_obj->coords.x1; + act_obj_point = lv_area_get_width(&act_obj->coords) / 2 + act_obj->coords.x1; + break; + case LV_SCROLL_SNAP_START: + snap_point = scroll_obj->coords.x1 + pad_left; + act_obj_point = act_obj->coords.x1; + break; + case LV_SCROLL_SNAP_END: + snap_point = scroll_obj->coords.x2 - pad_right; + act_obj_point = act_obj->coords.x2; + break; } - } else { + } + else { lv_coord_t pad_top = lv_obj_get_style_pad_top(scroll_obj, LV_PART_MAIN); lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(scroll_obj, LV_PART_MAIN); switch(snap) { - case LV_SCROLL_SNAP_CENTER: - snap_point = pad_top + (lv_area_get_height(&scroll_obj->coords) - pad_top - pad_bottom) / 2 + scroll_obj->coords.y1; - act_obj_point = lv_area_get_height(&act_obj->coords) / 2 + act_obj->coords.y1; - break; - case LV_SCROLL_SNAP_START: - snap_point = scroll_obj->coords.y1 + pad_top; - act_obj_point = act_obj->coords.y1; - break; - case LV_SCROLL_SNAP_END: - snap_point = scroll_obj->coords.y2 - pad_bottom; - act_obj_point = act_obj->coords.y2; - break; + case LV_SCROLL_SNAP_CENTER: + snap_point = pad_top + (lv_area_get_height(&scroll_obj->coords) - pad_top - pad_bottom) / 2 + scroll_obj->coords.y1; + act_obj_point = lv_area_get_height(&act_obj->coords) / 2 + act_obj->coords.y1; + break; + case LV_SCROLL_SNAP_START: + snap_point = scroll_obj->coords.y1 + pad_top; + act_obj_point = act_obj->coords.y1; + break; + case LV_SCROLL_SNAP_END: + snap_point = scroll_obj->coords.y2 - pad_bottom; + act_obj_point = act_obj->coords.y2; + break; } } @@ -629,7 +634,8 @@ static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_ if(diff > 0) diff += ELASTIC_SLOWNESS_FACTOR / 2; return diff / ELASTIC_SLOWNESS_FACTOR; } - } else { + } + else { /*Scroll back to the boundary if required*/ if(scroll_end + diff < 0) diff = - scroll_end; if(scroll_start - diff < 0) diff = scroll_start; diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_indev_scroll.h b/lib/libesp32_lvgl/lvgl/src/core/lv_indev_scroll.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_indev_scroll.h rename to lib/libesp32_lvgl/lvgl/src/core/lv_indev_scroll.h diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj.c similarity index 80% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj.c rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj.c index 5066456df..8acf874d1 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj.c @@ -35,6 +35,10 @@ #include "../gpu/lv_gpu_nxp_pxp_osa.h" #endif +#if LV_USE_GPU_SDL + #include "../gpu/lv_gpu_sdl.h" +#endif + /********************* * DEFINES *********************/ @@ -84,6 +88,11 @@ const lv_obj_class_t lv_obj_class = { * GLOBAL FUNCTIONS **********************/ +bool lv_is_initialized(void) +{ + return lv_initialized; +} + void lv_init(void) { /*Do nothing if already initialized*/ @@ -116,6 +125,9 @@ void lv_init(void) for(; ;) ; } #endif +#if LV_USE_GPU_SDL + lv_gpu_sdl_init(); +#endif _lv_obj_style_init(); _lv_ll_init(&LV_GC_ROOT(_lv_disp_ll), sizeof(lv_disp_t)); @@ -133,29 +145,36 @@ void lv_init(void) uint8_t * txt_u8 = (uint8_t *)txt; if(txt_u8[0] != 0xc3 || txt_u8[1] != 0x81 || txt_u8[2] != 0x00) { - LV_LOG_WARN("The strings has no UTF-8 encoding. Non-ASCII characters won't be displayed.") + LV_LOG_WARN("The strings has no UTF-8 encoding. Non-ASCII characters won't be displayed."); } uint32_t endianess_test = 0x11223344; - uint8_t * endianess_test_p = (uint8_t*) &endianess_test; + uint8_t * endianess_test_p = (uint8_t *) &endianess_test; bool big_endian = endianess_test_p[0] == 0x11 ? true : false; if(big_endian) { - LV_ASSERT_MSG(LV_BIG_ENDIAN_SYSTEM == 1, "It's a big endian system but LV_BIG_ENDIAN_SYSTEM is not enabled in lv_conf.h"); - } else { - LV_ASSERT_MSG(LV_BIG_ENDIAN_SYSTEM == 0, "It's a little endian system but LV_BIG_ENDIAN_SYSTEM is enabled in lv_conf.h"); + LV_ASSERT_MSG(LV_BIG_ENDIAN_SYSTEM == 1, + "It's a big endian system but LV_BIG_ENDIAN_SYSTEM is not enabled in lv_conf.h"); + } + else { + LV_ASSERT_MSG(LV_BIG_ENDIAN_SYSTEM == 0, + "It's a little endian system but LV_BIG_ENDIAN_SYSTEM is enabled in lv_conf.h"); } #if LV_USE_ASSERT_MEM_INTEGRITY - LV_LOG_WARN("Memory integrity checks are enabled via LV_USE_ASSERT_MEM_INTEGRITY which makes LVGL much slower") + LV_LOG_WARN("Memory integrity checks are enabled via LV_USE_ASSERT_MEM_INTEGRITY which makes LVGL much slower"); #endif #if LV_USE_ASSERT_OBJ - LV_LOG_WARN("Object sanity checks are enabled via LV_USE_ASSERT_OBJ which makes LVGL much slower") + LV_LOG_WARN("Object sanity checks are enabled via LV_USE_ASSERT_OBJ which makes LVGL much slower"); +#endif + +#if LV_USE_ASSERT_STYLE + LV_LOG_WARN("Style sanity checks are enabled that uses more RAM"); #endif #if LV_LOG_LEVEL == LV_LOG_LEVEL_TRACE - LV_LOG_WARN("Log level is set the Trace which makes LVGL much slower") + LV_LOG_WARN("Log level is set the Trace which makes LVGL much slower"); #endif lv_extra_init(); @@ -165,10 +184,13 @@ void lv_init(void) LV_LOG_TRACE("finished"); } -#if LV_ENABLE_GC || !LV_MEM_CUSTOM +#if LV_ENABLE_GC || !LV_MEM_CUSTOM || LV_USE_GPU_SDL void lv_deinit(void) { +#if LV_USE_GPU_SDL + lv_gpu_sdl_deinit(); +#endif _lv_gc_clear_roots(); lv_disp_set_default(NULL); @@ -185,7 +207,7 @@ void lv_deinit(void) lv_obj_t * lv_obj_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -216,6 +238,13 @@ void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f) if((was_on_layout != lv_obj_is_layout_positioned(obj)) || (f & (LV_OBJ_FLAG_LAYOUT_1 | LV_OBJ_FLAG_LAYOUT_2))) { lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj)); } + + if(f & LV_OBJ_FLAG_SCROLLABLE) { + lv_area_t hor_area, ver_area; + lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area); + lv_obj_invalidate_area(obj, &hor_area); + lv_obj_invalidate_area(obj, &ver_area); + } } void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f) @@ -223,6 +252,12 @@ void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f) LV_ASSERT_OBJ(obj, MY_CLASS); bool was_on_layout = lv_obj_is_layout_positioned(obj); + if(f & LV_OBJ_FLAG_SCROLLABLE) { + lv_area_t hor_area, ver_area; + lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area); + lv_obj_invalidate_area(obj, &hor_area); + lv_obj_invalidate_area(obj, &ver_area); + } obj->flags &= (~f); @@ -381,7 +416,7 @@ static void lv_obj_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) /*Set attributes*/ obj->flags = LV_OBJ_FLAG_CLICKABLE; - obj->flags |= LV_OBJ_FLAG_SNAPABLE; + obj->flags |= LV_OBJ_FLAG_SNAPPABLE; if(parent) obj->flags |= LV_OBJ_FLAG_PRESS_LOCK; if(parent) obj->flags |= LV_OBJ_FLAG_SCROLL_CHAIN; obj->flags |= LV_OBJ_FLAG_CLICK_FOCUSABLE; @@ -451,7 +486,7 @@ static void lv_obj_draw(lv_event_t * e) if(_lv_area_is_in(info->area, &coords, r) == false) { info->res = LV_COVER_RES_NOT_COVER; - return; + return; } if(lv_obj_get_style_bg_opa(obj, LV_PART_MAIN) < LV_OPA_MAX) { @@ -493,15 +528,29 @@ static void lv_obj_draw(lv_event_t * e) coords.y1 -= h; coords.y2 += h; + lv_obj_draw_part_dsc_t part_dsc; + lv_obj_draw_dsc_init(&part_dsc, clip_area); + part_dsc.class_p = MY_CLASS; + part_dsc.type = LV_OBJ_DRAW_PART_RECTANGLE; + part_dsc.rect_dsc = &draw_dsc; + part_dsc.draw_area = &coords; + part_dsc.part = LV_PART_MAIN; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc); + lv_draw_rect(&coords, clip_area, &draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc); + #if LV_DRAW_COMPLEX if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) { - lv_draw_mask_radius_param_t * mp = lv_mem_buf_get(sizeof(lv_draw_mask_radius_param_t)); + /*If the radius is 0 the parent's coordinates will clip anyway*/ lv_coord_t r = lv_obj_get_style_radius(obj, LV_PART_MAIN); - lv_draw_mask_radius_init(mp, &obj->coords, r, false); - /*Add the mask and use `obj+8` as custom id. Don't use `obj` directly because it might be used by the user*/ - lv_draw_mask_add(mp, obj + 8); + if(r != 0) { + lv_draw_mask_radius_param_t * mp = lv_mem_buf_get(sizeof(lv_draw_mask_radius_param_t)); + lv_draw_mask_radius_init(mp, &obj->coords, r, false); + /*Add the mask and use `obj+8` as custom id. Don't use `obj` directly because it might be used by the user*/ + lv_draw_mask_add(mp, obj + 8); + } } #endif } @@ -512,7 +561,10 @@ static void lv_obj_draw(lv_event_t * e) #if LV_DRAW_COMPLEX if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) { lv_draw_mask_radius_param_t * param = lv_draw_mask_remove_custom(obj + 8); - lv_mem_buf_release(param); + if(param) { + lv_draw_mask_free_param(param); + lv_mem_buf_release(param); + } } #endif @@ -523,6 +575,7 @@ static void lv_obj_draw(lv_event_t * e) draw_dsc.bg_opa = LV_OPA_TRANSP; draw_dsc.outline_opa = LV_OPA_TRANSP; draw_dsc.shadow_opa = LV_OPA_TRANSP; + draw_dsc.bg_img_opa = LV_OPA_TRANSP; lv_obj_init_draw_rect_dsc(obj, LV_PART_MAIN, &draw_dsc); lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN); @@ -533,7 +586,18 @@ static void lv_obj_draw(lv_event_t * e) coords.x2 += w; coords.y1 -= h; coords.y2 += h; + + lv_obj_draw_part_dsc_t part_dsc; + lv_obj_draw_dsc_init(&part_dsc, clip_area); + part_dsc.class_p = MY_CLASS; + part_dsc.type = LV_OBJ_DRAW_PART_BORDER_POST; + part_dsc.rect_dsc = &draw_dsc; + part_dsc.draw_area = &coords; + part_dsc.part = LV_PART_MAIN; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc); + lv_draw_rect(&coords, clip_area, &draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc); } } } @@ -551,8 +615,25 @@ static void draw_scrollbar(lv_obj_t * obj, const lv_area_t * clip_area) lv_res_t sb_res = scrollbar_init_draw_dsc(obj, &draw_dsc); if(sb_res != LV_RES_OK) return; - if(lv_area_get_size(&hor_area) > 0) lv_draw_rect(&hor_area, clip_area, &draw_dsc); - if(lv_area_get_size(&ver_area) > 0) lv_draw_rect(&ver_area, clip_area, &draw_dsc); + lv_obj_draw_part_dsc_t part_dsc; + lv_obj_draw_dsc_init(&part_dsc, clip_area); + part_dsc.class_p = MY_CLASS; + part_dsc.type = LV_OBJ_DRAW_PART_SCROLLBAR; + part_dsc.rect_dsc = &draw_dsc; + part_dsc.part = LV_PART_SCROLLBAR; + + if(lv_area_get_size(&hor_area) > 0) { + part_dsc.draw_area = &hor_area; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc); + lv_draw_rect(&hor_area, clip_area, &draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc); + } + if(lv_area_get_size(&ver_area) > 0) { + part_dsc.draw_area = &ver_area; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc); + lv_draw_rect(&ver_area, clip_area, &draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc); + } } /** @@ -574,7 +655,8 @@ static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc dsc->border_width = lv_obj_get_style_border_width(obj, LV_PART_SCROLLBAR); if(dsc->border_width > 0) { dsc->border_color = lv_obj_get_style_border_color(obj, LV_PART_SCROLLBAR); - } else { + } + else { dsc->border_opa = LV_OPA_TRANSP; } } @@ -586,7 +668,8 @@ static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc if(dsc->shadow_width > 0) { dsc->shadow_spread = lv_obj_get_style_shadow_spread(obj, LV_PART_SCROLLBAR); dsc->shadow_color = lv_obj_get_style_shadow_color(obj, LV_PART_SCROLLBAR); - } else { + } + else { dsc->shadow_opa = LV_OPA_TRANSP; } } @@ -598,10 +681,11 @@ static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc dsc->shadow_opa = (dsc->bg_opa * opa) >> 8; } - if(dsc->bg_opa != LV_OPA_TRANSP || dsc->border_opa != LV_OPA_TRANSP || dsc->shadow_opa != LV_OPA_TRANSP ) { + if(dsc->bg_opa != LV_OPA_TRANSP || dsc->border_opa != LV_OPA_TRANSP || dsc->shadow_opa != LV_OPA_TRANSP) { dsc->radius = lv_obj_get_style_radius(obj, LV_PART_SCROLLBAR); return LV_RES_OK; - } else { + } + else { return LV_RES_INV; } #else @@ -657,6 +741,34 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e) if(res != LV_RES_OK) return; } } + else if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLLABLE) && !lv_obj_is_editable(obj)) { + /*scroll by keypad or encoder*/ + lv_anim_enable_t anim_enable = LV_ANIM_OFF; + lv_coord_t sl = lv_obj_get_scroll_left(obj); + lv_coord_t sr = lv_obj_get_scroll_right(obj); + char c = *((char *)lv_event_get_param(e)); + if(c == LV_KEY_DOWN) { + /*use scroll_to_x/y functions to enforce scroll limits*/ + lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) + lv_obj_get_height(obj) / 4, anim_enable); + } + else if(c == LV_KEY_UP) { + lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) - lv_obj_get_height(obj) / 4, anim_enable); + } + else if(c == LV_KEY_RIGHT) { + /*If the object can't be scrolled horizontally then scroll it vertically*/ + if(!((lv_obj_get_scroll_dir(obj) & LV_DIR_HOR) && (sl > 0 || sr > 0))) + lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) + lv_obj_get_height(obj) / 4, anim_enable); + else + lv_obj_scroll_to_x(obj, lv_obj_get_scroll_x(obj) + lv_obj_get_width(obj) / 4, anim_enable); + } + else if(c == LV_KEY_LEFT) { + /*If the object can't be scrolled horizontally then scroll it vertically*/ + if(!((lv_obj_get_scroll_dir(obj) & LV_DIR_HOR) && (sl > 0 || sr > 0))) + lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) - lv_obj_get_height(obj) / 4, anim_enable); + else + lv_obj_scroll_to_x(obj, lv_obj_get_scroll_x(obj) - lv_obj_get_width(obj) / 4, anim_enable); + } + } } else if(code == LV_EVENT_FOCUSED) { if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS)) { @@ -689,6 +801,12 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e) } else if(code == LV_EVENT_SCROLL_END) { lv_obj_clear_state(obj, LV_STATE_SCROLLED); + if(lv_obj_get_scrollbar_mode(obj) == LV_SCROLLBAR_MODE_ACTIVE) { + lv_area_t hor_area, ver_area; + lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area); + lv_obj_invalidate_area(obj, &hor_area); + lv_obj_invalidate_area(obj, &ver_area); + } } else if(code == LV_EVENT_DEFOCUSED) { lv_obj_clear_state(obj, LV_STATE_FOCUSED | LV_STATE_EDITED | LV_STATE_FOCUS_KEY); @@ -701,8 +819,9 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e) } uint32_t i; - for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { - lv_obj_t * child = lv_obj_get_child(obj, i); + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; lv_obj_mark_layout_as_dirty(child); } } @@ -715,11 +834,6 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_obj_mark_layout_as_dirty(obj); } } - else if(code == LV_EVENT_SCROLL_END) { - if(lv_obj_get_scrollbar_mode(obj) == LV_SCROLLBAR_MODE_ACTIVE) { - lv_obj_invalidate(obj); - } - } else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { lv_coord_t * s = lv_event_get_param(e); lv_coord_t d = lv_obj_calculate_ext_draw_size(obj, LV_PART_MAIN); @@ -790,7 +904,7 @@ static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state) } } - for(i = 0;i < tsi; i++) { + for(i = 0; i < tsi; i++) { lv_part_t part_act = lv_obj_style_get_selector_part(ts[i].selector); _lv_obj_style_create_transition(obj, part_act, prev_state, new_state, &ts[i]); } diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj.h similarity index 66% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj.h rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj.h index ccd0e5139..c92ffde8f 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj.h @@ -71,7 +71,7 @@ enum { LV_PART_INDICATOR = 0x020000, /**< Indicator, e.g. for slider, bar, switch, or the tick box of the checkbox*/ LV_PART_KNOB = 0x030000, /**< Like handle to grab to adjust the value*/ LV_PART_SELECTED = 0x040000, /**< Indicate the currently selected option or section*/ - LV_PART_ITEMS = 0x050000, /**< Used if the widget has multiple similar elements (e.g. tabel cells)*/ + LV_PART_ITEMS = 0x050000, /**< Used if the widget has multiple similar elements (e.g. table cells)*/ LV_PART_TICKS = 0x060000, /**< Ticks on scale e.g. for a chart or meter*/ LV_PART_CURSOR = 0x070000, /**< Mark a specific place e.g. for text area's cursor or on a chart*/ @@ -87,37 +87,46 @@ typedef uint32_t lv_part_t; * OR-ed values are possible */ enum { - LV_OBJ_FLAG_HIDDEN = (1 << 0), /**< Make the object hidden. (Like it wasn't there at all)*/ - LV_OBJ_FLAG_CLICKABLE = (1 << 1), /**< Make the object clickable by the input devices*/ - LV_OBJ_FLAG_CLICK_FOCUSABLE = (1 << 2), /**< Add focused state to the object when clicked*/ - LV_OBJ_FLAG_CHECKABLE = (1 << 3), /**< Toggle checked state when the object is clicked*/ - LV_OBJ_FLAG_SCROLLABLE = (1 << 4), /**< Make the object scrollable*/ - LV_OBJ_FLAG_SCROLL_ELASTIC = (1 << 5), /**< Allow scrolling inside but with slower speed*/ - LV_OBJ_FLAG_SCROLL_MOMENTUM = (1 << 6), /**< Make the object scroll further when "thrown"*/ - LV_OBJ_FLAG_SCROLL_ONE = (1 << 7), /**< Allow scrolling only one snapable children*/ - LV_OBJ_FLAG_SCROLL_CHAIN = (1 << 8), /**< Allow propagating the scroll to a parent*/ - LV_OBJ_FLAG_SCROLL_ON_FOCUS = (1 << 9), /**< Automatically scroll object to make it visible when focused*/ - LV_OBJ_FLAG_SNAPABLE = (1 << 10), /**< If scroll snap is enabled on the parent it can snap to this object*/ - LV_OBJ_FLAG_PRESS_LOCK = (1 << 11), /**< Keep the object pressed even if the press slid from the object*/ - LV_OBJ_FLAG_EVENT_BUBBLE = (1 << 12), /**< Propagate the events to the parent too*/ - LV_OBJ_FLAG_GESTURE_BUBBLE = (1 << 13), /**< Propagate the gestures to the parent*/ - LV_OBJ_FLAG_ADV_HITTEST = (1 << 14), /**< Allow performing more accurate hit (click) test. E.g. consider rounded corners.*/ - LV_OBJ_FLAG_IGNORE_LAYOUT = (1 << 15), /**< Make the object position-able by the layouts*/ - LV_OBJ_FLAG_FLOATING = (1 << 16), /**< Do not scroll the object when the parent scrolls and ignore layout*/ + LV_OBJ_FLAG_HIDDEN = (1L << 0), /**< Make the object hidden. (Like it wasn't there at all)*/ + LV_OBJ_FLAG_CLICKABLE = (1L << 1), /**< Make the object clickable by the input devices*/ + LV_OBJ_FLAG_CLICK_FOCUSABLE = (1L << 2), /**< Add focused state to the object when clicked*/ + LV_OBJ_FLAG_CHECKABLE = (1L << 3), /**< Toggle checked state when the object is clicked*/ + LV_OBJ_FLAG_SCROLLABLE = (1L << 4), /**< Make the object scrollable*/ + LV_OBJ_FLAG_SCROLL_ELASTIC = (1L << 5), /**< Allow scrolling inside but with slower speed*/ + LV_OBJ_FLAG_SCROLL_MOMENTUM = (1L << 6), /**< Make the object scroll further when "thrown"*/ + LV_OBJ_FLAG_SCROLL_ONE = (1L << 7), /**< Allow scrolling only one snappable children*/ + LV_OBJ_FLAG_SCROLL_CHAIN = (1L << 8), /**< Allow propagating the scroll to a parent*/ + LV_OBJ_FLAG_SCROLL_ON_FOCUS = (1L << 9), /**< Automatically scroll object to make it visible when focused*/ + LV_OBJ_FLAG_SNAPPABLE = (1L << 10), /**< If scroll snap is enabled on the parent it can snap to this object*/ + LV_OBJ_FLAG_PRESS_LOCK = (1L << 11), /**< Keep the object pressed even if the press slid from the object*/ + LV_OBJ_FLAG_EVENT_BUBBLE = (1L << 12), /**< Propagate the events to the parent too*/ + LV_OBJ_FLAG_GESTURE_BUBBLE = (1L << 13), /**< Propagate the gestures to the parent*/ + LV_OBJ_FLAG_ADV_HITTEST = (1L << 14), /**< Allow performing more accurate hit (click) test. E.g. consider rounded corners.*/ + LV_OBJ_FLAG_IGNORE_LAYOUT = (1L << 15), /**< Make the object position-able by the layouts*/ + LV_OBJ_FLAG_FLOATING = (1L << 16), /**< Do not scroll the object when the parent scrolls and ignore layout*/ - LV_OBJ_FLAG_LAYOUT_1 = (1 << 23), /** Custom flag, free to use by layouts*/ - LV_OBJ_FLAG_LAYOUT_2 = (1 << 24), /** Custom flag, free to use by layouts*/ + LV_OBJ_FLAG_LAYOUT_1 = (1L << 23), /**< Custom flag, free to use by layouts*/ + LV_OBJ_FLAG_LAYOUT_2 = (1L << 24), /**< Custom flag, free to use by layouts*/ - LV_OBJ_FLAG_WIDGET_1 = (1 << 25), /** Custom flag, free to use by widget*/ - LV_OBJ_FLAG_WIDGET_2 = (1 << 26), /** Custom flag, free to use by widget*/ - - LV_OBJ_FLAG_USER_1 = (1 << 27), /** Custom flag, free to use by user*/ - LV_OBJ_FLAG_USER_2 = (1 << 28), /** Custom flag, free to use by user*/ - LV_OBJ_FLAG_USER_3 = (1 << 29), /** Custom flag, free to use by user*/ - LV_OBJ_FLAG_USER_4 = (1 << 30), /** Custom flag, free to use by user*/ + LV_OBJ_FLAG_WIDGET_1 = (1L << 25), /**< Custom flag, free to use by widget*/ + LV_OBJ_FLAG_WIDGET_2 = (1L << 26), /**< Custom flag, free to use by widget*/ + LV_OBJ_FLAG_USER_1 = (1L << 27), /**< Custom flag, free to use by user*/ + LV_OBJ_FLAG_USER_2 = (1L << 28), /**< Custom flag, free to use by user*/ + LV_OBJ_FLAG_USER_3 = (1L << 29), /**< Custom flag, free to use by user*/ + LV_OBJ_FLAG_USER_4 = (1L << 30), /**< Custom flag, free to use by user*/ }; typedef uint32_t lv_obj_flag_t; +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_obj_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_OBJ_DRAW_PART_RECTANGLE, /**< The main rectangle*/ + LV_OBJ_DRAW_PART_BORDER_POST,/**< The border if style_border_post = true*/ + LV_OBJ_DRAW_PART_SCROLLBAR, /**< The scrollbar*/ +} lv_obj_draw_part_type_t; + #include "lv_obj_tree.h" #include "lv_obj_pos.h" #include "lv_obj_scroll.h" @@ -141,18 +150,18 @@ typedef struct { uint32_t child_cnt; /**< Number of children*/ lv_group_t * group_p; - struct _lv_event_dsc_t * event_dsc; /**< Dynamically allocated event callback and user data array*/ - lv_point_t scroll; /**< The current X/Y scroll offset*/ + struct _lv_event_dsc_t * event_dsc; /**< Dynamically allocated event callback and user data array*/ + lv_point_t scroll; /**< The current X/Y scroll offset*/ - lv_coord_t ext_click_pad; /**< Extra click padding in all direction*/ + lv_coord_t ext_click_pad; /**< Extra click padding in all direction*/ lv_coord_t ext_draw_size; /**< EXTend the size in every direction for drawing.*/ - lv_scrollbar_mode_t scrollbar_mode :2; /**< How to display scrollbars*/ - lv_scroll_snap_t scroll_snap_x : 2; /**< Where to align the snapable children horizontally*/ - lv_scroll_snap_t scroll_snap_y : 2; /**< Where to align the snapable children horizontally*/ - lv_dir_t scroll_dir :4; /**< The allowed scroll direction(s)*/ - uint8_t event_dsc_cnt; /**< Number of event callabcks stored in `event_cb` array*/ -}_lv_obj_spec_attr_t; + lv_scrollbar_mode_t scrollbar_mode : 2; /**< How to display scrollbars*/ + lv_scroll_snap_t scroll_snap_x : 2; /**< Where to align the snappable children horizontally*/ + lv_scroll_snap_t scroll_snap_y : 2; /**< Where to align the snappable children vertically*/ + lv_dir_t scroll_dir : 4; /**< The allowed scroll direction(s)*/ + uint8_t event_dsc_cnt; /**< Number of event callbacks stored in `event_dsc` array*/ +} _lv_obj_spec_attr_t; typedef struct _lv_obj_t { const lv_obj_class_t * class_p; @@ -165,13 +174,13 @@ typedef struct _lv_obj_t { lv_area_t coords; lv_obj_flag_t flags; lv_state_t state; - uint16_t layout_inv :1; - uint16_t scr_layout_inv :1; - uint16_t skip_trans :1; - uint16_t style_cnt :6; - uint16_t h_layout :1; - uint16_t w_layout :1; -}lv_obj_t; + uint16_t layout_inv : 1; + uint16_t scr_layout_inv : 1; + uint16_t skip_trans : 1; + uint16_t style_cnt : 6; + uint16_t h_layout : 1; + uint16_t w_layout : 1; +} lv_obj_t; /********************** @@ -184,7 +193,7 @@ typedef struct _lv_obj_t { */ void lv_init(void); -#if LV_ENABLE_GC || !LV_MEM_CUSTOM +#if LV_ENABLE_GC || !LV_MEM_CUSTOM || LV_USE_GPU_SDL /** * Deinit the 'lv' library @@ -194,10 +203,15 @@ void lv_deinit(void); #endif +/** + * Returns whether the 'lv' library is currently initialized + */ +bool lv_is_initialized(void); + /** * Create a base object (a rectangle) * @param parent pointer to a parent object. If NULL then a screen will be created. - * @return pointer to the new object + * @return pointer to the new object */ lv_obj_t * lv_obj_create(lv_obj_t * parent); @@ -314,10 +328,10 @@ static inline void * lv_obj_get_user_data(lv_obj_t * obj) void lv_obj_allocate_spec_attr(lv_obj_t * obj); /** - * Get object's and its ancestors type. Put their name in `type_buf` starting with the current type. - * E.g. buf.type[0]="lv_btn", buf.type[1]="lv_cont", buf.type[2]="lv_obj" - * @param obj pointer to an object which type should be get - * @param buf pointer to an `lv_obj_type_t` buffer to store the types + * Check the type of obj. + * @param obj pointer to an object + * @param class_p a class to check (e.g. `lv_slider_class`) + * @return true: `class_p` is the `obj` class. */ bool lv_obj_check_type(const lv_obj_t * obj, const lv_obj_class_t * class_p); @@ -332,15 +346,14 @@ bool lv_obj_has_class(const lv_obj_t * obj, const lv_obj_class_t * class_p); /** * Get the class (type) of the object - * @param obj pointer to an object - * @return the class (type) of the object + * @param obj pointer to an object + * @return the class (type) of the object */ const lv_obj_class_t * lv_obj_get_class(const lv_obj_t * obj); /** - * Check if any object is still "alive", and part of the hierarchy + * Check if any object is still "alive". * @param obj pointer to an object - * @param obj_type type of the object. (e.g. "lv_btn") * @return true: valid */ bool lv_obj_is_valid(const lv_obj_t * obj); @@ -365,16 +378,16 @@ static inline lv_coord_t lv_obj_dpx(const lv_obj_t * obj, lv_coord_t n) #if LV_USE_ASSERT_OBJ # define LV_ASSERT_OBJ(obj_p, obj_class) \ - LV_ASSERT_MSG(obj_p != NULL, "The object is NULL"); \ - LV_ASSERT_MSG(lv_obj_has_class(obj_p, obj_class) == true, "Incompatible object type."); \ - LV_ASSERT_MSG(lv_obj_is_valid(obj_p) == true, "The object is invalid, deleted or corrupted?"); + LV_ASSERT_MSG(obj_p != NULL, "The object is NULL"); \ + LV_ASSERT_MSG(lv_obj_has_class(obj_p, obj_class) == true, "Incompatible object type."); \ + LV_ASSERT_MSG(lv_obj_is_valid(obj_p) == true, "The object is invalid, deleted or corrupted?"); # else # define LV_ASSERT_OBJ(obj_p, obj_class) do{}while(0) #endif #if LV_USE_LOG && LV_LOG_TRACE_OBJ_CREATE -# define LV_TRACE_OBJ_CREATE(...) LV_LOG_TRACE( __VA_ARGS__) +# define LV_TRACE_OBJ_CREATE(...) LV_LOG_TRACE(__VA_ARGS__) #else # define LV_TRACE_OBJ_CREATE(...) #endif diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_class.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.c similarity index 95% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj_class.c rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.c index 3837639ff..40538e0f1 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_class.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.c @@ -42,7 +42,7 @@ static uint32_t get_instance_size(const lv_obj_class_t * class_p); lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * parent) { - LV_TRACE_OBJ_CREATE("Creating object with %p class on %p parent", class_p, parent); + LV_TRACE_OBJ_CREATE("Creating object with %p class on %p parent", (void *)class_p, (void *)parent); uint32_t s = get_instance_size(class_p); lv_obj_t * obj = lv_mem_alloc(s); if(obj == NULL) return NULL; @@ -63,7 +63,8 @@ lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * pa disp->screens = lv_mem_alloc(sizeof(lv_obj_t *)); disp->screens[0] = obj; disp->screen_cnt = 1; - } else { + } + else { disp->screen_cnt++; disp->screens = lv_mem_realloc(disp->screens, sizeof(lv_obj_t *) * disp->screen_cnt); disp->screens[disp->screen_cnt - 1] = obj; @@ -87,9 +88,11 @@ lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * pa parent->spec_attr->children = lv_mem_alloc(sizeof(lv_obj_t *)); parent->spec_attr->children[0] = obj; parent->spec_attr->child_cnt = 1; - } else { + } + else { parent->spec_attr->child_cnt++; - parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children, sizeof(lv_obj_t *) * parent->spec_attr->child_cnt); + parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children, + sizeof(lv_obj_t *) * parent->spec_attr->child_cnt); parent->spec_attr->children[parent->spec_attr->child_cnt - 1] = obj; } } @@ -120,6 +123,7 @@ void lv_obj_class_init_obj(lv_obj_t * obj) /*Call the ancestor's event handler to the parent to notify it about the new child. *Also triggers layout update*/ lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj); + lv_event_send(parent, LV_EVENT_CHILD_CREATED, obj); /*Invalidate the area if not screen created*/ lv_obj_invalidate(obj); diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_class.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.h similarity index 91% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj_class.h rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.h index 0bf0dad59..01a7248ba 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_class.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.h @@ -33,13 +33,13 @@ typedef enum { LV_OBJ_CLASS_EDITABLE_INHERIT, /**< Check the base class. Must have 0 value to let zero initialized class inherit*/ LV_OBJ_CLASS_EDITABLE_TRUE, LV_OBJ_CLASS_EDITABLE_FALSE, -}lv_obj_class_editable_t; +} lv_obj_class_editable_t; typedef enum { LV_OBJ_CLASS_GROUP_DEF_INHERIT, /**< Check the base class. Must have 0 value to let zero initialized class inherit*/ LV_OBJ_CLASS_GROUP_DEF_TRUE, LV_OBJ_CLASS_GROUP_DEF_FALSE, -}lv_obj_class_group_def_t; +} lv_obj_class_group_def_t; typedef void (*lv_obj_class_event_cb_t)(struct _lv_obj_class_t * class_p, struct _lv_event_t * e); /** @@ -53,13 +53,14 @@ typedef struct _lv_obj_class_t { #if LV_USE_USER_DATA void * user_data; #endif - void (*event_cb)(const struct _lv_obj_class_t * class_p, struct _lv_event_t * e); /**< Widget type specific event function*/ + void (*event_cb)(const struct _lv_obj_class_t * class_p, + struct _lv_event_t * e); /**< Widget type specific event function*/ lv_coord_t width_def; lv_coord_t height_def; uint32_t editable : 2; /**< Value from ::lv_obj_class_editable_t*/ uint32_t group_def : 2; /**< Value from ::lv_obj_class_group_def_t*/ uint32_t instance_size : 16; -}lv_obj_class_t; +} lv_obj_class_t; /********************** * GLOBAL PROTOTYPES diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_draw.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.c similarity index 91% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj_draw.c rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.c index f0d50b60b..411135f30 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_draw.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.c @@ -84,7 +84,7 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t draw_dsc->outline_opa = lv_obj_get_style_outline_opa(obj, part); if(draw_dsc->outline_opa > LV_OPA_MIN) { draw_dsc->outline_pad = lv_obj_get_style_outline_pad(obj, part); - draw_dsc->outline_color = lv_obj_get_style_outline_color(obj, part); + draw_dsc->outline_color = lv_obj_get_style_outline_color_filtered(obj, part); } } } @@ -95,10 +95,11 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t draw_dsc->bg_img_opa = lv_obj_get_style_bg_img_opa(obj, part); if(draw_dsc->bg_img_opa > LV_OPA_MIN) { if(lv_img_src_get_type(draw_dsc->bg_img_src) == LV_IMG_SRC_SYMBOL) { - draw_dsc->bg_img_symbol_font= lv_obj_get_style_text_font(obj, part); - draw_dsc->bg_img_recolor = lv_obj_get_style_text_color(obj, part); - } else { - draw_dsc->bg_img_recolor = lv_obj_get_style_bg_img_recolor(obj, part); + draw_dsc->bg_img_symbol_font = lv_obj_get_style_text_font(obj, part); + draw_dsc->bg_img_recolor = lv_obj_get_style_text_color_filtered(obj, part); + } + else { + draw_dsc->bg_img_recolor = lv_obj_get_style_bg_img_recolor_filtered(obj, part); draw_dsc->bg_img_recolor_opa = lv_obj_get_style_bg_img_recolor_opa(obj, part); draw_dsc->bg_img_tiled = lv_obj_get_style_bg_img_tiled(obj, part); } @@ -156,7 +157,7 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t draw_dsc->outline_opa = lv_obj_get_style_outline_opa(obj, part); if(draw_dsc->outline_opa > LV_OPA_MIN) { draw_dsc->outline_pad = lv_obj_get_style_outline_pad(obj, part); - draw_dsc->outline_color = lv_obj_get_style_outline_color(obj, part); + draw_dsc->outline_color = lv_obj_get_style_outline_color_filtered(obj, part); } } } @@ -167,13 +168,14 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t draw_dsc->bg_img_opa = lv_obj_get_style_bg_img_opa(obj, part); if(draw_dsc->bg_img_opa > LV_OPA_MIN) { if(lv_img_src_get_type(draw_dsc->bg_img_src) == LV_IMG_SRC_SYMBOL) { - draw_dsc->bg_img_symbol_font= lv_obj_get_style_text_font(obj, part); - draw_dsc->bg_img_recolor = lv_obj_get_style_text_color(obj, part); - } else { - draw_dsc->bg_img_recolor = lv_obj_get_style_bg_img_recolor(obj, part); - draw_dsc->bg_img_recolor_opa = lv_obj_get_style_bg_img_recolor_opa(obj, part); - draw_dsc->bg_img_tiled = lv_obj_get_style_bg_img_tiled(obj, part); - } + draw_dsc->bg_img_symbol_font = lv_obj_get_style_text_font(obj, part); + draw_dsc->bg_img_recolor = lv_obj_get_style_text_color_filtered(obj, part); + } + else { + draw_dsc->bg_img_recolor = lv_obj_get_style_bg_img_recolor_filtered(obj, part); + draw_dsc->bg_img_recolor_opa = lv_obj_get_style_bg_img_recolor_opa(obj, part); + draw_dsc->bg_img_tiled = lv_obj_get_style_bg_img_tiled(obj, part); + } } } } @@ -206,10 +208,6 @@ void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint32_t part, lv_draw_label_dsc #endif draw_dsc->align = lv_obj_get_style_text_align(obj, part); - if(draw_dsc->align == LV_TEXT_ALIGN_AUTO) { - if(draw_dsc->bidi_dir == LV_BASE_DIR_RTL) draw_dsc->align = LV_TEXT_ALIGN_RIGHT; - else draw_dsc->align = LV_TEXT_ALIGN_LEFT; - } } void lv_obj_init_draw_img_dsc(lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc) @@ -230,7 +228,7 @@ void lv_obj_init_draw_img_dsc(lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc->recolor_opa = lv_obj_get_style_img_recolor_opa(obj, part); if(draw_dsc->recolor_opa > 0) { - draw_dsc->recolor = lv_obj_get_style_img_recolor(obj, part); + draw_dsc->recolor = lv_obj_get_style_img_recolor_filtered(obj, part); } #if LV_DRAW_COMPLEX draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); @@ -251,7 +249,7 @@ void lv_obj_init_draw_line_dsc(lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t } if(draw_dsc->opa <= LV_OPA_MIN) return; - draw_dsc->color = lv_obj_get_style_line_color(obj, part); + draw_dsc->color = lv_obj_get_style_line_color_filtered(obj, part); draw_dsc->dash_width = lv_obj_get_style_line_dash_width(obj, part); if(draw_dsc->dash_width) { @@ -280,7 +278,7 @@ void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * } if(draw_dsc->opa <= LV_OPA_MIN) return; - draw_dsc->color = lv_obj_get_style_arc_color(obj, part); + draw_dsc->color = lv_obj_get_style_arc_color_filtered(obj, part); draw_dsc->img_src = lv_obj_get_style_arc_img_src(obj, part); draw_dsc->rounded = lv_obj_get_style_arc_rounded(obj, part); @@ -330,6 +328,12 @@ void lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc, const lv_area_t * clip_a dsc->clip_area = clip_area; } +bool lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc, const lv_obj_class_t * class_p, uint32_t type) +{ + if(dsc->class_p == class_p && dsc->type == type) return true; + else return false; +} + void lv_obj_refresh_ext_draw_size(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_draw.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.h similarity index 68% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj_draw.h rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.h index 4858195e8..1a9e2e5c5 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_draw.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.h @@ -24,32 +24,41 @@ extern "C" { **********************/ struct _lv_obj_t; +struct _lv_obj_class_t; /** Cover check results.*/ typedef enum { LV_COVER_RES_COVER = 0, LV_COVER_RES_NOT_COVER = 1, LV_COVER_RES_MASKED = 2, -}lv_cover_res_t; +} lv_cover_res_t; -typedef struct -{ +typedef struct { const lv_area_t * clip_area; /**< The current clip area, required if you need to draw something in the event*/ + const struct _lv_obj_class_t * class_p; /**< The class that sent the event */ + uint32_t type; /**< The type if part being draw. Element of `lv__draw_part_type_t` */ lv_area_t * draw_area; /**< The area of the part being drawn*/ - lv_draw_rect_dsc_t * rect_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for rectangle-like parts*/ - lv_draw_label_dsc_t * label_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for text-like parts*/ - lv_draw_line_dsc_t * line_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for line-like parts*/ - lv_draw_img_dsc_t * img_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for image-like parts*/ - lv_draw_arc_dsc_t * arc_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for arc-like parts*/ - const lv_point_t * p1; /**< A point calculated during drawing. E.g. a point of chart or the center of an arc.*/ + lv_draw_rect_dsc_t * + rect_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for rectangle-like parts*/ + lv_draw_label_dsc_t * + label_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for text-like parts*/ + lv_draw_line_dsc_t * + line_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for line-like parts*/ + lv_draw_img_dsc_t * + img_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for image-like parts*/ + lv_draw_arc_dsc_t * + arc_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for arc-like parts*/ + const lv_point_t * + p1; /**< A point calculated during drawing. E.g. a point of chart or the center of an arc.*/ const lv_point_t * p2; /**< A point calculated during drawing. E.g. a point of chart.*/ - char text[16]; /**< A text calculated during drawing. Can be modified. E.g. tick labels on a chart axis.*/ + char * text; /**< A text calculated during drawing. Can be modified. E.g. tick labels on a chart axis.*/ + uint32_t text_length; /**< Size of the text buffer containing null-terminated text string calculated during drawing.*/ uint32_t part; /**< The current part for which the event is sent*/ uint32_t id; /**< The index of the part. E.g. a button's index on button matrix or table cell index.*/ lv_coord_t radius; /**< E.g. the radius of an arc (not the corner radius).*/ int32_t value; /**< A value calculated during drawing. E.g. Chart's tick line value.*/ const void * sub_part_ptr; /**< A pointer the identifies something in the part. E.g. chart series. */ -}lv_obj_draw_part_dsc_t; +} lv_obj_draw_part_dsc_t; /********************** * GLOBAL PROTOTYPES @@ -59,8 +68,8 @@ typedef struct * Initialize a rectangle draw descriptor from an object's styles in its current state * @param obj pointer to an object * @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc - * @param draw_dsc the descriptor the initialize. - * If an `..._opa` filed is set to `LV_OPA_TRANSP` the related properties won't be initialized. + * @param draw_dsc the descriptor to initialize. + * If an `..._opa` field is set to `LV_OPA_TRANSP` the related properties won't be initialized. * Should be initialized with `lv_draw_rect_dsc_init(draw_dsc)`. * @note Only the relevant fields will be set. * E.g. if `border width == 0` the other border properties won't be evaluated. @@ -71,8 +80,8 @@ void lv_obj_init_draw_rect_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_re * Initialize a label draw descriptor from an object's styles in its current state * @param obj pointer to an object * @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc - * @param draw_dsc the descriptor the initialize. - * If the `opa` filed is set to or the property is equal to `LV_OPA_TRANSP` the rest won't be initialized. + * @param draw_dsc the descriptor to initialize. + * If the `opa` field is set to or the property is equal to `LV_OPA_TRANSP` the rest won't be initialized. * Should be initialized with `lv_draw_label_dsc_init(draw_dsc)`. */ void lv_obj_init_draw_label_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc); @@ -81,7 +90,7 @@ void lv_obj_init_draw_label_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_l * Initialize an image draw descriptor from an object's styles in its current state * @param obj pointer to an object * @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc - * @param draw_dsc the descriptor the initialize. + * @param draw_dsc the descriptor to initialize. * Should be initialized with `lv_draw_image_dsc_init(draw_dsc)`. */ void lv_obj_init_draw_img_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc); @@ -91,7 +100,7 @@ void lv_obj_init_draw_img_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_img * Initialize a line draw descriptor from an object's styles in its current state * @param obj pointer to an object * @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc - * @param draw_dsc the descriptor the initialize. + * @param draw_dsc the descriptor to initialize. * Should be initialized with `lv_draw_line_dsc_init(draw_dsc)`. */ void lv_obj_init_draw_line_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc); @@ -100,7 +109,7 @@ void lv_obj_init_draw_line_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_li * Initialize an arc draw descriptor from an object's styles in its current state * @param obj pointer to an object * @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc - * @param draw_dsc the descriptor the initialize. + * @param draw_dsc the descriptor to initialize. * Should be initialized with `lv_draw_arc_dsc_init(draw_dsc)`. */ void lv_obj_init_draw_arc_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc); @@ -120,6 +129,15 @@ lv_coord_t lv_obj_calculate_ext_draw_size(struct _lv_obj_t * obj, uint32_t part) */ void lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc, const lv_area_t * clip_area); +/** + * Check the type obj a part draw descriptor + * @param dsc the descriptor (normally the event parameter) + * @param class_p pointer to class to which `type` is related + * @param type element of `lv__draw_part_type_t` + * @return true if ::dsc is related to ::class_p and ::type + */ +bool lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc, const struct _lv_obj_class_t * class_p, uint32_t type); + /** * Send a 'LV_EVENT_REFR_EXT_DRAW_SIZE' Call the ancestor's event handler to the object to refresh the value of the extended draw size. * The result will be saved in `obj`. diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_pos.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.c similarity index 64% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj_pos.c rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.c index 50bbe41bb..4a8f23459 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_pos.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.c @@ -23,7 +23,8 @@ /********************** * STATIC PROTOTYPES **********************/ -static void calc_auto_size(lv_obj_t * obj, lv_coord_t * w_out, lv_coord_t * h_out); +static lv_coord_t calc_content_width(lv_obj_t * obj); +static lv_coord_t calc_content_height(lv_obj_t * obj); static void layout_update_core(lv_obj_t * obj); /********************** @@ -50,9 +51,6 @@ void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) void lv_obj_set_x(lv_obj_t * obj, lv_coord_t x) { LV_ASSERT_OBJ(obj, MY_CLASS); - if(lv_obj_is_layout_positioned(obj)) { - return; - } lv_res_t res_x; lv_style_value_t v_x; @@ -66,9 +64,6 @@ void lv_obj_set_x(lv_obj_t * obj, lv_coord_t x) void lv_obj_set_y(lv_obj_t * obj, lv_coord_t y) { - if(lv_obj_is_layout_positioned(obj)) { - return; - } LV_ASSERT_OBJ(obj, MY_CLASS); lv_res_t res_y; @@ -91,51 +86,69 @@ bool lv_obj_refr_size(lv_obj_t * obj) lv_obj_t * parent = lv_obj_get_parent(obj); if(parent == NULL) return false; - lv_coord_t w; lv_coord_t sl_ori = lv_obj_get_scroll_left(obj); - bool w_content = false; + bool w_is_content = false; + bool w_is_pct = false; + + lv_coord_t w; if(obj->w_layout) { w = lv_obj_get_width(obj); - } else { + } + else { w = lv_obj_get_style_width(obj, LV_PART_MAIN); - w_content = w == LV_SIZE_CONTENT ? true : false; - - /*Be sure the object is not scrolled when it has auto size*/ - if(w_content) { - lv_obj_scroll_to_x(obj, 0, LV_ANIM_OFF); - calc_auto_size(obj, &w, NULL); - } - - /*Calculate the sizes in percentage*/ - bool pct_w = LV_COORD_IS_PCT(w) ? true : false; - + w_is_content = w == LV_SIZE_CONTENT ? true : false; + w_is_pct = LV_COORD_IS_PCT(w) ? true : false; lv_coord_t parent_w = lv_obj_get_content_width(parent); - if(pct_w) w = (LV_COORD_GET_PCT(w) * parent_w) / 100; + + if(w_is_content) { + w = calc_content_width(obj); + } + else if(w_is_pct) { + /*If parent has content size and the child has pct size + *a circular dependency will occur. To solve it keep child size at zero */ + if(parent->w_layout == 0 && lv_obj_get_style_width(parent, 0) == LV_SIZE_CONTENT) { + lv_coord_t border_w = lv_obj_get_style_border_width(obj, 0); + w = lv_obj_get_style_pad_left(obj, 0) + border_w; + w += lv_obj_get_style_pad_right(obj, 0) + border_w; + } + else { + w = (LV_COORD_GET_PCT(w) * parent_w) / 100; + } + } lv_coord_t minw = lv_obj_get_style_min_width(obj, LV_PART_MAIN); lv_coord_t maxw = lv_obj_get_style_max_width(obj, LV_PART_MAIN); w = lv_clamp_width(w, minw, maxw, parent_w); } - lv_coord_t h; lv_coord_t st_ori = lv_obj_get_scroll_top(obj); - bool h_content = false; + lv_coord_t h; + bool h_is_content = false; + bool h_is_pct = false; if(obj->h_layout) { h = lv_obj_get_height(obj); - } else { + } + else { h = lv_obj_get_style_height(obj, LV_PART_MAIN); - h_content = h == LV_SIZE_CONTENT ? true : false; - - /*Be sure the object is not scrolled when it has auto size*/ - if(h_content) { - lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF); - calc_auto_size(obj, NULL, &h); - } - - /*Calculate the sizes in percentage*/ - bool pct_h = LV_COORD_IS_PCT(h) ? true : false; + h_is_content = h == LV_SIZE_CONTENT ? true : false; + h_is_pct = LV_COORD_IS_PCT(h) ? true : false; lv_coord_t parent_h = lv_obj_get_content_height(parent); - if(pct_h) h = (LV_COORD_GET_PCT(h) * parent_h) / 100; + + if(h_is_content) { + h = calc_content_height(obj); + } + else if(h_is_pct) { + /*If parent has content size and the child has pct size + *a circular dependency will occur. To solve it keep child size at zero */ + if(parent->h_layout == 0 && lv_obj_get_style_height(parent, 0) == LV_SIZE_CONTENT) { + lv_coord_t border_w = lv_obj_get_style_border_width(obj, 0); + h = lv_obj_get_style_pad_top(obj, 0) + border_w; + h += lv_obj_get_style_pad_bottom(obj, 0) + border_w; + } + else { + h = (LV_COORD_GET_PCT(h) * parent_h) / 100; + } + } lv_coord_t minh = lv_obj_get_style_min_height(obj, LV_PART_MAIN); lv_coord_t maxh = lv_obj_get_style_max_height(obj, LV_PART_MAIN); @@ -143,7 +156,7 @@ bool lv_obj_refr_size(lv_obj_t * obj) } /*calc_auto_size set the scroll x/y to 0 so revert the original value*/ - if(w_content || h_content) { + if(w_is_content || h_is_content) { lv_obj_scroll_to(obj, sl_ori, st_ori, LV_ANIM_OFF); } @@ -193,10 +206,6 @@ bool lv_obj_refr_size(lv_obj_t * obj) bool on2 = _lv_area_is_in(&obj->coords, &parent_fit_area, 0); if(on1 || (!on1 && on2)) lv_obj_scrollbar_invalidate(parent); - - - - return true; } @@ -277,7 +286,7 @@ void lv_obj_mark_layout_as_dirty(lv_obj_t * obj) { obj->layout_inv = 1; - /*Mark the screen as dirty too to mark that there is an something to do on this screen*/ + /*Mark the screen as dirty too to mark that there is something to do on this screen*/ lv_obj_t * scr = lv_obj_get_screen(obj); scr->scr_layout_inv = 1; @@ -290,7 +299,7 @@ void lv_obj_update_layout(const lv_obj_t * obj) { static bool mutex = false; if(mutex) { - LV_LOG_TRACE("Already running, returning") + LV_LOG_TRACE("Already running, returning"); return; } mutex = true; @@ -299,10 +308,10 @@ void lv_obj_update_layout(const lv_obj_t * obj) /*Repeat until there where layout invalidations*/ while(scr->scr_layout_inv) { - LV_LOG_INFO("Layout update begin") + LV_LOG_INFO("Layout update begin"); scr->scr_layout_inv = 0; layout_update_core(scr); - LV_LOG_TRACE("Layout update end") + LV_LOG_TRACE("Layout update end"); } mutex = false; @@ -357,110 +366,115 @@ void lv_obj_align_to(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv } switch(align) { - case LV_ALIGN_CENTER: - x = lv_obj_get_content_width(base) / 2 - lv_obj_get_width(obj) / 2 + bleft; - y = lv_obj_get_content_height(base) / 2 - lv_obj_get_height(obj) / 2 + btop; - break; - case LV_ALIGN_TOP_LEFT: - x = bleft; - y = btop; - break; - case LV_ALIGN_TOP_MID: - x = lv_obj_get_content_width(base) / 2 - lv_obj_get_width(obj) / 2 + bleft; - y = btop; - break; + case LV_ALIGN_CENTER: + x = lv_obj_get_content_width(base) / 2 - lv_obj_get_width(obj) / 2 + bleft; + y = lv_obj_get_content_height(base) / 2 - lv_obj_get_height(obj) / 2 + btop; + break; + case LV_ALIGN_TOP_LEFT: + x = bleft; + y = btop; + break; + case LV_ALIGN_TOP_MID: + x = lv_obj_get_content_width(base) / 2 - lv_obj_get_width(obj) / 2 + bleft; + y = btop; + break; - case LV_ALIGN_TOP_RIGHT: - x = lv_obj_get_content_width(base) - lv_obj_get_width(obj) + bleft; - y = btop; - break; + case LV_ALIGN_TOP_RIGHT: + x = lv_obj_get_content_width(base) - lv_obj_get_width(obj) + bleft; + y = btop; + break; - case LV_ALIGN_BOTTOM_LEFT: - x = bleft; - y = lv_obj_get_content_height(base) - lv_obj_get_height(obj) + btop; - break; - case LV_ALIGN_BOTTOM_MID: - x = lv_obj_get_content_width(base) / 2 - lv_obj_get_width(obj) / 2 + bleft; - y = lv_obj_get_content_height(base) - lv_obj_get_height(obj) + btop; - break; + case LV_ALIGN_BOTTOM_LEFT: + x = bleft; + y = lv_obj_get_content_height(base) - lv_obj_get_height(obj) + btop; + break; + case LV_ALIGN_BOTTOM_MID: + x = lv_obj_get_content_width(base) / 2 - lv_obj_get_width(obj) / 2 + bleft; + y = lv_obj_get_content_height(base) - lv_obj_get_height(obj) + btop; + break; - case LV_ALIGN_BOTTOM_RIGHT: - x = lv_obj_get_content_width(base) - lv_obj_get_width(obj) + bleft; - y = lv_obj_get_content_height(base) - lv_obj_get_height(obj) + btop; - break; + case LV_ALIGN_BOTTOM_RIGHT: + x = lv_obj_get_content_width(base) - lv_obj_get_width(obj) + bleft; + y = lv_obj_get_content_height(base) - lv_obj_get_height(obj) + btop; + break; - case LV_ALIGN_LEFT_MID: - x = bleft; - y = lv_obj_get_content_height(base) / 2 - lv_obj_get_height(obj) / 2 + btop; - break; + case LV_ALIGN_LEFT_MID: + x = bleft; + y = lv_obj_get_content_height(base) / 2 - lv_obj_get_height(obj) / 2 + btop; + break; - case LV_ALIGN_RIGHT_MID: - x = lv_obj_get_content_width(base) - lv_obj_get_width(obj) + bleft; - y = lv_obj_get_content_height(base) / 2 - lv_obj_get_height(obj) / 2 + btop; - break; + case LV_ALIGN_RIGHT_MID: + x = lv_obj_get_content_width(base) - lv_obj_get_width(obj) + bleft; + y = lv_obj_get_content_height(base) / 2 - lv_obj_get_height(obj) / 2 + btop; + break; - case LV_ALIGN_OUT_TOP_LEFT: - x = 0; - y = -lv_obj_get_height(obj); - break; + case LV_ALIGN_OUT_TOP_LEFT: + x = 0; + y = -lv_obj_get_height(obj); + break; - case LV_ALIGN_OUT_TOP_MID: - x = lv_obj_get_width(base) / 2 - lv_obj_get_width(obj) / 2; - y = -lv_obj_get_height(obj); - break; + case LV_ALIGN_OUT_TOP_MID: + x = lv_obj_get_width(base) / 2 - lv_obj_get_width(obj) / 2; + y = -lv_obj_get_height(obj); + break; - case LV_ALIGN_OUT_TOP_RIGHT: - x = lv_obj_get_width(base) - lv_obj_get_width(obj); - y = -lv_obj_get_height(obj); - break; + case LV_ALIGN_OUT_TOP_RIGHT: + x = lv_obj_get_width(base) - lv_obj_get_width(obj); + y = -lv_obj_get_height(obj); + break; - case LV_ALIGN_OUT_BOTTOM_LEFT: - x = 0; - y = lv_obj_get_height(base); - break; + case LV_ALIGN_OUT_BOTTOM_LEFT: + x = 0; + y = lv_obj_get_height(base); + break; - case LV_ALIGN_OUT_BOTTOM_MID: - x = lv_obj_get_width(base) / 2 - lv_obj_get_width(obj) / 2; - y = lv_obj_get_height(base); - break; + case LV_ALIGN_OUT_BOTTOM_MID: + x = lv_obj_get_width(base) / 2 - lv_obj_get_width(obj) / 2; + y = lv_obj_get_height(base); + break; - case LV_ALIGN_OUT_BOTTOM_RIGHT: - x = lv_obj_get_width(base) - lv_obj_get_width(obj); - y = lv_obj_get_height(base); - break; + case LV_ALIGN_OUT_BOTTOM_RIGHT: + x = lv_obj_get_width(base) - lv_obj_get_width(obj); + y = lv_obj_get_height(base); + break; - case LV_ALIGN_OUT_LEFT_TOP: - x = -lv_obj_get_width(obj); - y = 0; - break; + case LV_ALIGN_OUT_LEFT_TOP: + x = -lv_obj_get_width(obj); + y = 0; + break; - case LV_ALIGN_OUT_LEFT_MID: - x = -lv_obj_get_width(obj); - y = lv_obj_get_height(base) / 2 - lv_obj_get_height(obj) / 2; - break; + case LV_ALIGN_OUT_LEFT_MID: + x = -lv_obj_get_width(obj); + y = lv_obj_get_height(base) / 2 - lv_obj_get_height(obj) / 2; + break; - case LV_ALIGN_OUT_LEFT_BOTTOM: - x = -lv_obj_get_width(obj); - y = lv_obj_get_height(base) - lv_obj_get_height(obj); - break; + case LV_ALIGN_OUT_LEFT_BOTTOM: + x = -lv_obj_get_width(obj); + y = lv_obj_get_height(base) - lv_obj_get_height(obj); + break; - case LV_ALIGN_OUT_RIGHT_TOP: - x = lv_obj_get_width(base); - y = 0; - break; + case LV_ALIGN_OUT_RIGHT_TOP: + x = lv_obj_get_width(base); + y = 0; + break; - case LV_ALIGN_OUT_RIGHT_MID: - x = lv_obj_get_width(base); - y = lv_obj_get_height(base) / 2 - lv_obj_get_height(obj) / 2; - break; + case LV_ALIGN_OUT_RIGHT_MID: + x = lv_obj_get_width(base); + y = lv_obj_get_height(base) / 2 - lv_obj_get_height(obj) / 2; + break; - case LV_ALIGN_OUT_RIGHT_BOTTOM: - x = lv_obj_get_width(base); - y = lv_obj_get_height(base) - lv_obj_get_height(obj); - break; + case LV_ALIGN_OUT_RIGHT_BOTTOM: + x = lv_obj_get_width(base); + y = lv_obj_get_height(base) - lv_obj_get_height(obj); + break; } - x += x_ofs + base->coords.x1 - parent->coords.x1 + lv_obj_get_scroll_left(parent) - pleft; + if(lv_obj_get_style_base_dir(parent, LV_PART_MAIN) == LV_BASE_DIR_RTL) { + x += x_ofs + base->coords.x1 - parent->coords.x1 + lv_obj_get_scroll_right(parent) - pleft; + } + else { + x += x_ofs + base->coords.x1 - parent->coords.x1 + lv_obj_get_scroll_left(parent) - pleft; + } y += y_ofs + base->coords.y1 - parent->coords.y1 + lv_obj_get_scroll_top(parent) - ptop; lv_obj_set_style_align(obj, LV_ALIGN_TOP_LEFT, 0); lv_obj_set_pos(obj, x, y); @@ -577,14 +591,14 @@ void lv_obj_get_content_coords(const lv_obj_t * obj, lv_area_t * area) lv_coord_t lv_obj_get_self_width(const lv_obj_t * obj) { lv_point_t p = {0, LV_COORD_MIN}; - lv_event_send((lv_obj_t * )obj, LV_EVENT_GET_SELF_SIZE, &p); + lv_event_send((lv_obj_t *)obj, LV_EVENT_GET_SELF_SIZE, &p); return p.x; } lv_coord_t lv_obj_get_self_height(const lv_obj_t * obj) { lv_point_t p = {LV_COORD_MIN, 0}; - lv_event_send((lv_obj_t * )obj, LV_EVENT_GET_SELF_SIZE, &p); + lv_event_send((lv_obj_t *)obj, LV_EVENT_GET_SELF_SIZE, &p); return p.y; } @@ -642,36 +656,36 @@ void lv_obj_refr_pos(lv_obj_t * obj) else { switch(align) { - case LV_ALIGN_TOP_MID: - x += pw / 2 - w / 2; - break; - case LV_ALIGN_TOP_RIGHT: - x += pw - w; - break; - case LV_ALIGN_LEFT_MID: - y += ph / 2 - h / 2; - break; - case LV_ALIGN_BOTTOM_LEFT: - y += ph - h; - break; - case LV_ALIGN_BOTTOM_MID: - x += pw / 2 - w / 2; - y += ph - h; - break; - case LV_ALIGN_BOTTOM_RIGHT: - x += pw - w; - y += ph - h; - break; - case LV_ALIGN_RIGHT_MID: - x += pw - w; - y += ph / 2 - h / 2; - break; - case LV_ALIGN_CENTER: - x += pw / 2 - w / 2; - y += ph / 2 - h / 2; - break; - default: - break; + case LV_ALIGN_TOP_MID: + x += pw / 2 - w / 2; + break; + case LV_ALIGN_TOP_RIGHT: + x += pw - w; + break; + case LV_ALIGN_LEFT_MID: + y += ph / 2 - h / 2; + break; + case LV_ALIGN_BOTTOM_LEFT: + y += ph - h; + break; + case LV_ALIGN_BOTTOM_MID: + x += pw / 2 - w / 2; + y += ph - h; + break; + case LV_ALIGN_BOTTOM_RIGHT: + x += pw - w; + y += ph - h; + break; + case LV_ALIGN_RIGHT_MID: + x += pw - w; + y += ph / 2 - h / 2; + break; + case LV_ALIGN_CENTER: + x += pw / 2 - w / 2; + y += ph / 2 - h / 2; + break; + default: + break; } lv_obj_move_to(obj, x, y); } @@ -689,7 +703,8 @@ void lv_obj_move_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) if(lv_obj_has_flag(obj, LV_OBJ_FLAG_FLOATING)) { x += pad_left + parent->coords.x1; y += pad_top + parent->coords.y1; - } else { + } + else { x += pad_left + parent->coords.x1 - lv_obj_get_scroll_x(parent); y += pad_top + parent->coords.y1 - lv_obj_get_scroll_y(parent); } @@ -752,8 +767,9 @@ void lv_obj_move_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) void lv_obj_move_children_by(lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_diff, bool ignore_floating) { uint32_t i; - for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { - lv_obj_t * child = lv_obj_get_child(obj, i); + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; if(ignore_floating && lv_obj_has_flag(child, LV_OBJ_FLAG_FLOATING)) continue; child->coords.x1 += x_diff; child->coords.y1 += y_diff; @@ -803,8 +819,7 @@ bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area) if(obj_scr != lv_disp_get_scr_act(disp) && obj_scr != lv_disp_get_scr_prev(disp) && obj_scr != lv_disp_get_layer_top(disp) && - obj_scr != lv_disp_get_layer_sys(disp)) - { + obj_scr != lv_disp_get_layer_sys(disp)) { return false; } @@ -827,7 +842,8 @@ bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area) while(par != NULL) { is_common = _lv_area_intersect(area, area, &par->coords); if(is_common == false) return false; /*If no common parts with parent break;*/ - if(lv_obj_has_flag(par, LV_OBJ_FLAG_HIDDEN)) return false; /*If the parent is hidden then the child is hidden and won't be drawn*/ + if(lv_obj_has_flag(par, LV_OBJ_FLAG_HIDDEN)) return + false; /*If the parent is hidden then the child is hidden and won't be drawn*/ par = lv_obj_get_parent(par); } @@ -908,34 +924,145 @@ lv_coord_t lv_clamp_height(lv_coord_t height, lv_coord_t min_height, lv_coord_t * STATIC FUNCTIONS **********************/ -/** - * Calculate the "auto size". It's `auto_size = max(children_size, self_size)` - * @param obj pointer to an object - * @param w_out store the width here. NULL to not calculate width - * @param h_out store the height here. NULL to not calculate height - */ -static void calc_auto_size(lv_obj_t * obj, lv_coord_t * w_out, lv_coord_t * h_out) +static lv_coord_t calc_content_width(lv_obj_t * obj) { - if(!w_out && !h_out) return; - /*Get the bounding box of the children*/ - if(w_out) { - lv_coord_t scroll_right = lv_obj_get_scroll_right(obj); - lv_coord_t scroll_left = lv_obj_get_scroll_left(obj); - *w_out = lv_obj_get_width(obj) + scroll_right + scroll_left; + lv_obj_scroll_to_x(obj, 0, LV_ANIM_OFF); + + lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN) + border_width; + lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; + + lv_coord_t self_w; + self_w = lv_obj_get_self_width(obj) + pad_left + pad_right; + + lv_coord_t child_res = LV_COORD_MIN; + uint32_t i; + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + /*With RTL find the left most coordinate*/ + if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) { + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; + if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; + + if(!lv_obj_is_layout_positioned(child)) { + lv_align_t align = lv_obj_get_style_align(child, 0); + switch(align) { + case LV_ALIGN_DEFAULT: + case LV_ALIGN_TOP_RIGHT: + case LV_ALIGN_BOTTOM_RIGHT: + case LV_ALIGN_RIGHT_MID: + /*Normal right aligns. Other are ignored due to possible circular dependencies*/ + child_res = LV_MAX(child_res, obj->coords.x2 - child->coords.x1 + 1); + break; + default: + /* Consider other cases only if x=0 and use the width of the object. + * With x!=0 circular dependency could occur. */ + if(lv_obj_get_style_y(child, 0) == 0) { + child_res = LV_MAX(child_res, lv_area_get_width(&child->coords)); + } + } + } else { + child_res = LV_MAX(child_res, obj->coords.x2 - child->coords.x1 + 1); + } + } + if(child_res != LV_COORD_MIN) { + child_res += pad_left; + } + } + /*Else find the right most coordinate*/ + else { + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; + if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; + + if(!lv_obj_is_layout_positioned(child)) { + lv_align_t align = lv_obj_get_style_align(child, 0); + switch(align) { + case LV_ALIGN_DEFAULT: + case LV_ALIGN_TOP_LEFT: + case LV_ALIGN_BOTTOM_LEFT: + case LV_ALIGN_LEFT_MID: + /*Normal left aligns.*/ + child_res = LV_MAX(child_res, child->coords.x2 - obj->coords.x1 + 1); + break; + default: + /* Consider other cases only if x=0 and use the width of the object. + * With x!=0 circular dependency could occur. */ + if(lv_obj_get_style_y(child, 0) == 0) { + child_res = LV_MAX(child_res, lv_area_get_width(&child->coords)); + } + } + } else { + child_res = LV_MAX(child_res, child->coords.x2 - obj->coords.x1 + 1); + } + } + + if(child_res != LV_COORD_MIN) { + child_res += pad_right; + } } - if(h_out) { - lv_coord_t scroll_bottom = lv_obj_get_scroll_bottom(obj); - lv_coord_t scroll_top = lv_obj_get_scroll_top(obj); - *h_out = lv_obj_get_height(obj) + scroll_bottom + scroll_top; + if(child_res == LV_COORD_MIN) return self_w; + else return LV_MAX(child_res, self_w); +} + +static lv_coord_t calc_content_height(lv_obj_t * obj) +{ + lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF); + + lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; + lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN) + border_width; + + lv_coord_t self_h; + self_h = lv_obj_get_self_height(obj) + pad_top + pad_bottom; + + lv_coord_t child_res = LV_COORD_MIN; + uint32_t i; + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; + if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; + + + if(!lv_obj_is_layout_positioned(child)) { + lv_align_t align = lv_obj_get_style_align(child, 0); + switch(align) { + case LV_ALIGN_DEFAULT: + case LV_ALIGN_TOP_RIGHT: + case LV_ALIGN_TOP_MID: + case LV_ALIGN_TOP_LEFT: + /*Normal top aligns. */ + child_res = LV_MAX(child_res, child->coords.y2 - obj->coords.y1 + 1); + break; + default: + /* Consider other cases only if y=0 and use the height of the object. + * With y!=0 circular dependency could occur. */ + if(lv_obj_get_style_y(child, 0) == 0) { + child_res = LV_MAX(child_res, lv_area_get_height(&child->coords)); + } + break; + } + } else { + child_res = LV_MAX(child_res, child->coords.y2 - obj->coords.y1 + 1); + } } + + if(child_res != LV_COORD_MIN) { + child_res += pad_bottom; + return LV_MAX(child_res, self_h); + } else { + return self_h; + } + } static void layout_update_core(lv_obj_t * obj) { uint32_t i; - for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { - lv_obj_t * child = lv_obj_get_child(obj, i); + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; layout_update_core(child); } @@ -946,11 +1073,11 @@ static void layout_update_core(lv_obj_t * obj) lv_obj_refr_size(obj); lv_obj_refr_pos(obj); - if(lv_obj_get_child_cnt(obj) > 0) { + if(child_cnt > 0) { uint32_t layout_id = lv_obj_get_style_layout(obj, LV_PART_MAIN); if(layout_id > 0 && layout_id <= layout_cnt) { - void * user_data = LV_GC_ROOT(_lv_layout_list)[layout_id -1].user_data; - LV_GC_ROOT(_lv_layout_list)[layout_id -1].cb(obj, user_data); + void * user_data = LV_GC_ROOT(_lv_layout_list)[layout_id - 1].user_data; + LV_GC_ROOT(_lv_layout_list)[layout_id - 1].cb(obj, user_data); } } } diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_pos.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.h similarity index 88% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj_pos.h rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.h index 2034124bd..c73159ffd 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_pos.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.h @@ -28,7 +28,7 @@ typedef void (*lv_layout_update_cb_t)(struct _lv_obj_t *, void * user_data); typedef struct { lv_layout_update_cb_t cb; void * user_data; -}lv_layout_dsc_t; +} lv_layout_dsc_t; /********************** * GLOBAL PROTOTYPES @@ -176,7 +176,8 @@ void lv_obj_align(struct _lv_obj_t * obj, lv_align_t align, lv_coord_t x_ofs, lv * @param y_ofs y coordinate offset after alignment * @note if the position or size of `base` changes `obj` needs to be aligned manually again */ -void lv_obj_align_to(struct _lv_obj_t * obj, const struct _lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs); +void lv_obj_align_to(struct _lv_obj_t * obj, const struct _lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, + lv_coord_t y_ofs); /** * Align an object to the center on its parent. @@ -200,6 +201,8 @@ void lv_obj_get_coords(const struct _lv_obj_t * obj, lv_area_t * coords); * Get the x coordinate of object. * @param obj pointer to an object * @return distance of `obj` from the left side of its parent plus the parent's left padding + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. * @note Zero return value means the object is on the left padding of the parent, and not on the left edge. * @note Scrolling of the parent doesn't change the returned value. * @note The returned value is always the distance from the parent even if `obj` is positioned by a layout. @@ -210,6 +213,8 @@ lv_coord_t lv_obj_get_x(const struct _lv_obj_t * obj); * Get the x2 coordinate of object. * @param obj pointer to an object * @return distance of `obj` from the right side of its parent plus the parent's right padding + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. * @note Zero return value means the object is on the right padding of the parent, and not on the right edge. * @note Scrolling of the parent doesn't change the returned value. * @note The returned value is always the distance from the parent even if `obj` is positioned by a layout. @@ -220,6 +225,8 @@ lv_coord_t lv_obj_get_x2(const struct _lv_obj_t * obj); * Get the y coordinate of object. * @param obj pointer to an object * @return distance of `obj` from the top side of its parent plus the parent's top padding + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. * @note Zero return value means the object is on the top padding of the parent, and not on the top edge. * @note Scrolling of the parent doesn't change the returned value. * @note The returned value is always the distance from the parent even if `obj` is positioned by a layout. @@ -230,6 +237,8 @@ lv_coord_t lv_obj_get_y(const struct _lv_obj_t * obj); * Get the y2 coordinate of object. * @param obj pointer to an object * @return distance of `obj` from the bottom side of its parent plus the parent's bottom padding + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. * @note Zero return value means the object is on the bottom padding of the parent, and not on the bottom edge. * @note Scrolling of the parent doesn't change the returned value. * @note The returned value is always the distance from the parent even if `obj` is positioned by a layout. @@ -239,6 +248,8 @@ lv_coord_t lv_obj_get_y2(const struct _lv_obj_t * obj); /** * Get the width of an object * @param obj pointer to an object + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. * @return the width in pixels */ lv_coord_t lv_obj_get_width(const struct _lv_obj_t * obj); @@ -246,6 +257,8 @@ lv_coord_t lv_obj_get_width(const struct _lv_obj_t * obj); /** * Get the height of an object * @param obj pointer to an object + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. * @return the height in pixels */ lv_coord_t lv_obj_get_height(const struct _lv_obj_t * obj); @@ -253,13 +266,17 @@ lv_coord_t lv_obj_get_height(const struct _lv_obj_t * obj); /** * Get the width reduced by the left and right padding and the border width. * @param obj pointer to an object + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. * @return the width which still fits into its parent without causing overflow (making the parent scrollable) */ lv_coord_t lv_obj_get_content_width(const struct _lv_obj_t * obj); /** - * Get the height reduced by the top an bottom padding and the border width. + * Get the height reduced by the top and bottom padding and the border width. * @param obj pointer to an object + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. * @return the height which still fits into the parent without causing overflow (making the parent scrollable) */ lv_coord_t lv_obj_get_content_height(const struct _lv_obj_t * obj); @@ -267,6 +284,8 @@ lv_coord_t lv_obj_get_content_height(const struct _lv_obj_t * obj); /** * Get the area reduced by the paddings and the border width. * @param obj pointer to an object + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. * @param area the area which still fits into the parent without causing overflow (making the parent scrollable) */ void lv_obj_get_content_coords(const struct _lv_obj_t * obj, lv_area_t * area); @@ -361,7 +380,7 @@ bool lv_obj_hit_test(struct _lv_obj_t * obj, const lv_point_t * point); * @param min_width the minimal width * @param max_width the maximal width * @param ref_width the reference width used when min/max width is in percentage - * @return the clampled width + * @return the clamped width */ lv_coord_t lv_clamp_width(lv_coord_t width, lv_coord_t min_width, lv_coord_t max_width, lv_coord_t ref_width); @@ -371,7 +390,7 @@ lv_coord_t lv_clamp_width(lv_coord_t width, lv_coord_t min_width, lv_coord_t max * @param min_height the minimal height * @param max_height the maximal height * @param ref_height the reference height used when min/max height is in percentage - * @return the clampled height + * @return the clamped height */ lv_coord_t lv_clamp_height(lv_coord_t height, lv_coord_t min_height, lv_coord_t max_height, lv_coord_t ref_height); diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_scroll.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.c similarity index 77% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj_scroll.c rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.c index 8fafecf5e..0b2a5d26e 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_scroll.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.c @@ -35,7 +35,8 @@ static void scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y); static void scroll_x_anim(void * obj, int32_t v); static void scroll_y_anim(void * obj, int32_t v); static void scroll_anim_ready_cb(lv_anim_t * a); -static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_point_t * scroll_value, lv_anim_enable_t anim_en); +static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_point_t * scroll_value, + lv_anim_enable_t anim_en); /********************** * STATIC VARIABLES @@ -137,8 +138,9 @@ lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj) lv_coord_t child_res = LV_COORD_MIN; uint32_t i; - for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { - lv_obj_t * child = lv_obj_get_child(obj, i); + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; child_res = LV_MAX(child_res, child->coords.y2); } @@ -177,9 +179,10 @@ lv_coord_t lv_obj_get_scroll_left(lv_obj_t * obj) uint32_t i; lv_coord_t x1 = LV_COORD_MAX; - for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { - lv_obj_t * child = lv_obj_get_child(obj, i); - if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; + if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; x1 = LV_MIN(x1, child->coords.x1); } @@ -187,7 +190,8 @@ lv_coord_t lv_obj_get_scroll_left(lv_obj_t * obj) if(x1 != LV_COORD_MAX) { child_res = x1; child_res = (obj->coords.x1 + pad_left + border_width) - child_res; - } else { + } + else { child_res = LV_COORD_MIN; } @@ -212,8 +216,9 @@ lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj) /*With other base direction (LTR) scrolling to the right is normal so find the right most coordinate*/ lv_coord_t child_res = LV_COORD_MIN; uint32_t i; - for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { - lv_obj_t * child = lv_obj_get_child(obj, i); + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; child_res = LV_MAX(child_res, child->coords.x2); } @@ -282,13 +287,14 @@ void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable lv_anim_set_values(&a, -sy, -sy + y); lv_anim_set_exec_cb(&a, scroll_y_anim); lv_anim_set_path_cb(&a, lv_anim_path_ease_out); - + lv_res_t res; res = lv_event_send(obj, LV_EVENT_SCROLL_BEGIN, &a); if(res != LV_RES_OK) return; lv_anim_start(&a); } - } else { + } + else { /*Remove pending animations*/ bool y_del = lv_anim_del(obj, scroll_y_anim); bool x_del = lv_anim_del(obj, scroll_x_anim); @@ -320,7 +326,8 @@ void lv_obj_scroll_to_x(lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t anim_en) if(x > scroll_max) x = scroll_max; } - } else { + } + else { if(x > 0) x = 0; if(x < 0) { lv_coord_t scroll_max = lv_obj_get_scroll_left(obj) + lv_obj_get_scroll_right(obj); @@ -426,23 +433,25 @@ void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * bool ver_draw = false; if((dir & LV_DIR_VER) && - ((sm == LV_SCROLLBAR_MODE_ON) || - (sm == LV_SCROLLBAR_MODE_AUTO && (st > 0 || sb > 0)) || - (sm == LV_SCROLLBAR_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_DIR_VER))) { + ((sm == LV_SCROLLBAR_MODE_ON) || + (sm == LV_SCROLLBAR_MODE_AUTO && (st > 0 || sb > 0)) || + (sm == LV_SCROLLBAR_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_DIR_VER))) { ver_draw = true; } bool hor_draw = false; if((dir & LV_DIR_HOR) && - ((sm == LV_SCROLLBAR_MODE_ON) || - (sm == LV_SCROLLBAR_MODE_AUTO && (sl > 0 || sr > 0)) || - (sm == LV_SCROLLBAR_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_DIR_HOR))) { + ((sm == LV_SCROLLBAR_MODE_ON) || + (sm == LV_SCROLLBAR_MODE_AUTO && (sl > 0 || sr > 0)) || + (sm == LV_SCROLLBAR_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_DIR_HOR))) { hor_draw = true; } if(!hor_draw && !ver_draw) return; + bool rtl = lv_obj_get_style_base_dir(obj, LV_PART_SCROLLBAR) == LV_BASE_DIR_RTL ? true : false; + lv_coord_t end_space = lv_obj_get_style_pad_top(obj, LV_PART_SCROLLBAR); lv_coord_t side_space = lv_obj_get_style_pad_right(obj, LV_PART_SCROLLBAR); lv_coord_t tickness = lv_obj_get_style_width(obj, LV_PART_SCROLLBAR); @@ -462,35 +471,39 @@ void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * /*Draw horizontal scrollbar if the mode is ON or can be scrolled in this direction*/ lv_coord_t content_h = obj_h + st + sb; if(ver_draw && content_h) { - ver_area->y1 = obj->coords.y1; - ver_area->y2 = obj->coords.y2; - ver_area->x2 = obj->coords.x2 - side_space; - ver_area->x1 =ver_area->x2 - tickness; + ver_area->y1 = obj->coords.y1; + ver_area->y2 = obj->coords.y2; + if(rtl) { + ver_area->x1 = obj->coords.x1 + side_space; + ver_area->x2 = ver_area->x1 + tickness - 1; + } + else { + ver_area->x2 = obj->coords.x2 - side_space; + ver_area->x1 = ver_area->x2 - tickness + 1; + } lv_coord_t sb_h = ((obj_h - end_space * 2 - hor_req_space) * obj_h) / content_h; sb_h = LV_MAX(sb_h, SCROLLBAR_MIN_SIZE); - rem = (obj_h - end_space * 2 - hor_req_space) - sb_h; /*Remaining size from the scrollbar track that is not the scrollbar itself*/ + rem = (obj_h - end_space * 2 - hor_req_space) - + sb_h; /*Remaining size from the scrollbar track that is not the scrollbar itself*/ lv_coord_t scroll_h = content_h - obj_h; /*The size of the content which can be really scrolled*/ if(scroll_h <= 0) { - ver_area->y1 = obj->coords.y1 + end_space; - ver_area->y2 = obj->coords.y2 - end_space - hor_req_space - 1; - ver_area->x2 = obj->coords.x2 - side_space; - ver_area->x1 =ver_area->x2 - tickness + 1; - } else { + ver_area->y1 = obj->coords.y1 + end_space; + ver_area->y2 = obj->coords.y2 - end_space - hor_req_space - 1; + } + else { lv_coord_t sb_y = (rem * sb) / scroll_h; sb_y = rem - sb_y; - ver_area->y1 = obj->coords.y1 + sb_y + end_space; - ver_area->y2 =ver_area->y1 + sb_h - 1; - ver_area->x2 = obj->coords.x2 - side_space; - ver_area->x1 =ver_area->x2 - tickness; + ver_area->y1 = obj->coords.y1 + sb_y + end_space; + ver_area->y2 = ver_area->y1 + sb_h - 1; if(ver_area->y1 < obj->coords.y1 + end_space) { - ver_area->y1 = obj->coords.y1 + end_space; - if(ver_area->y1 + SCROLLBAR_MIN_SIZE >ver_area->y2)ver_area->y2 =ver_area->y1 + SCROLLBAR_MIN_SIZE; + ver_area->y1 = obj->coords.y1 + end_space; + if(ver_area->y1 + SCROLLBAR_MIN_SIZE > ver_area->y2)ver_area->y2 = ver_area->y1 + SCROLLBAR_MIN_SIZE; } if(ver_area->y2 > obj->coords.y2 - hor_req_space - end_space) { - ver_area->y2 = obj->coords.y2 - hor_req_space - end_space; - if(ver_area->y2 - SCROLLBAR_MIN_SIZE y1)ver_area->y1 =ver_area->y2 - SCROLLBAR_MIN_SIZE; + ver_area->y2 = obj->coords.y2 - hor_req_space - end_space; + if(ver_area->y2 - SCROLLBAR_MIN_SIZE < ver_area->y1)ver_area->y1 = ver_area->y2 - SCROLLBAR_MIN_SIZE; } } } @@ -499,34 +512,52 @@ void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * lv_coord_t content_w = obj_w + sl + sr; if(hor_draw && content_w) { hor_area->y2 = obj->coords.y2 - side_space; - hor_area->y1 = hor_area->y2 - tickness; + hor_area->y1 = hor_area->y2 - tickness + 1; hor_area->x1 = obj->coords.x1; hor_area->x2 = obj->coords.x2; lv_coord_t sb_w = ((obj_w - end_space * 2 - ver_reg_space) * obj_w) / content_w; sb_w = LV_MAX(sb_w, SCROLLBAR_MIN_SIZE); - rem = (obj_w - end_space * 2 - ver_reg_space) - sb_w; /*Remaining size from the scrollbar track that is not the scrollbar itself*/ + rem = (obj_w - end_space * 2 - ver_reg_space) - + sb_w; /*Remaining size from the scrollbar track that is not the scrollbar itself*/ lv_coord_t scroll_w = content_w - obj_w; /*The size of the content which can be really scrolled*/ if(scroll_w <= 0) { - hor_area->y2 = obj->coords.y2 - side_space; - hor_area->y1 = hor_area->y2 - tickness + 1; - hor_area->x1 = obj->coords.x1 + end_space; - hor_area->x2 = obj->coords.x2 - end_space - ver_reg_space - 1; - } else { + if(rtl) { + hor_area->x1 = obj->coords.x1 + end_space + ver_reg_space - 1; + hor_area->x2 = obj->coords.x2 - end_space; + } + else { + hor_area->x1 = obj->coords.x1 + end_space; + hor_area->x2 = obj->coords.x2 - end_space - ver_reg_space - 1; + } + } + else { lv_coord_t sb_x = (rem * sr) / scroll_w; sb_x = rem - sb_x; - hor_area->x1 = obj->coords.x1 + sb_x + end_space; - hor_area->x2 = hor_area->x1 + sb_w - 1; - hor_area->y2 = obj->coords.y2 - side_space; - hor_area->y1 = hor_area->y2 - tickness; - if(hor_area->x1 < obj->coords.x1 + end_space) { - hor_area->x1 = obj->coords.x1 + end_space; - if(hor_area->x1 + SCROLLBAR_MIN_SIZE > hor_area->x2) hor_area->x2 = hor_area->x1 + SCROLLBAR_MIN_SIZE; + if(rtl) { + hor_area->x1 = obj->coords.x1 + sb_x + end_space + ver_reg_space; + hor_area->x2 = hor_area->x1 + sb_w - 1; + if(hor_area->x1 < obj->coords.x1 + end_space + ver_reg_space) { + hor_area->x1 = obj->coords.x1 + end_space + ver_reg_space; + if(hor_area->x1 + SCROLLBAR_MIN_SIZE > hor_area->x2) hor_area->x2 = hor_area->x1 + SCROLLBAR_MIN_SIZE; + } + if(hor_area->x2 > obj->coords.x2 - end_space) { + hor_area->x2 = obj->coords.x2 - end_space; + if(hor_area->x2 - SCROLLBAR_MIN_SIZE < hor_area->x1) hor_area->x1 = hor_area->x2 - SCROLLBAR_MIN_SIZE; + } } - if(hor_area->x2 > obj->coords.x2 - ver_reg_space - end_space) { - hor_area->x2 = obj->coords.x2 - ver_reg_space - end_space; - if(hor_area->x2 - SCROLLBAR_MIN_SIZE < hor_area->x1) hor_area->x1 = hor_area->x2 - SCROLLBAR_MIN_SIZE; + else { + hor_area->x1 = obj->coords.x1 + sb_x + end_space; + hor_area->x2 = hor_area->x1 + sb_w - 1; + if(hor_area->x1 < obj->coords.x1 + end_space) { + hor_area->x1 = obj->coords.x1 + end_space; + if(hor_area->x1 + SCROLLBAR_MIN_SIZE > hor_area->x2) hor_area->x2 = hor_area->x1 + SCROLLBAR_MIN_SIZE; + } + if(hor_area->x2 > obj->coords.x2 - ver_reg_space - end_space) { + hor_area->x2 = obj->coords.x2 - ver_reg_space - end_space; + if(hor_area->x2 - SCROLLBAR_MIN_SIZE < hor_area->x1) hor_area->x1 = hor_area->x2 - SCROLLBAR_MIN_SIZE; + } } } } @@ -566,7 +597,8 @@ void lv_obj_readjust_scroll(lv_obj_t * obj, lv_anim_enable_t anim_en) sr = LV_MIN(sl, -sr); lv_obj_scroll_by(obj, sr, 0, anim_en); } - } else { + } + else { /*Be sure the right side is not remains scrolled in*/ if(sl < 0 && sr > 0) { sr = LV_MIN(sr, -sl); @@ -610,9 +642,12 @@ static void scroll_anim_ready_cb(lv_anim_t * a) lv_event_send(a->var, LV_EVENT_SCROLL_END, NULL); } -static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_point_t * scroll_value, lv_anim_enable_t anim_en) +static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_point_t * scroll_value, + lv_anim_enable_t anim_en) { lv_obj_t * parent = lv_obj_get_parent(child); + if(!lv_obj_has_flag(parent, LV_OBJ_FLAG_SCROLLABLE)) return; + lv_dir_t scroll_dir = lv_obj_get_scroll_dir(parent); lv_coord_t snap_goal = 0; lv_coord_t act = 0; @@ -623,12 +658,13 @@ static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_p if(snap_y != LV_SCROLL_SNAP_NONE) area_tmp = &child->coords; else area_tmp = area; - lv_coord_t ptop = lv_obj_get_style_pad_top(parent, LV_PART_MAIN); - lv_coord_t pbottom = lv_obj_get_style_pad_bottom(parent, LV_PART_MAIN); + lv_coord_t border_width = lv_obj_get_style_border_width(parent, LV_PART_MAIN); + lv_coord_t ptop = lv_obj_get_style_pad_top(parent, LV_PART_MAIN) + border_width; + lv_coord_t pbottom = lv_obj_get_style_pad_bottom(parent, LV_PART_MAIN) + border_width; lv_coord_t top_diff = parent->coords.y1 + ptop - area_tmp->y1 - scroll_value->y; lv_coord_t bottom_diff = -(parent->coords.y2 - pbottom - area_tmp->y2 - scroll_value->y); lv_coord_t parent_h = lv_obj_get_height(parent) - ptop - pbottom; - if((top_diff > 0 && bottom_diff > 0)) y_scroll = 0; + if((top_diff >= 0 && bottom_diff >= 0)) y_scroll = 0; else if(top_diff > 0) { y_scroll = top_diff; /*Do not let scrolling in*/ @@ -643,21 +679,21 @@ static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_p } switch(snap_y) { - case LV_SCROLL_SNAP_START: - snap_goal = parent->coords.y1 + ptop; - act = area_tmp->y1 + y_scroll; - y_scroll += snap_goal - act; - break; - case LV_SCROLL_SNAP_END: - snap_goal = parent->coords.y2 - pbottom; - act = area_tmp->y2 + y_scroll; - y_scroll += snap_goal - act; - break; - case LV_SCROLL_SNAP_CENTER: - snap_goal = parent->coords.y1 + ptop + parent_h / 2; - act = lv_area_get_height(area_tmp) / 2 + area_tmp->y1 + y_scroll; - y_scroll += snap_goal - act; - break; + case LV_SCROLL_SNAP_START: + snap_goal = parent->coords.y1 + ptop; + act = area_tmp->y1 + y_scroll; + y_scroll += snap_goal - act; + break; + case LV_SCROLL_SNAP_END: + snap_goal = parent->coords.y2 - pbottom; + act = area_tmp->y2 + y_scroll; + y_scroll += snap_goal - act; + break; + case LV_SCROLL_SNAP_CENTER: + snap_goal = parent->coords.y1 + ptop + parent_h / 2; + act = lv_area_get_height(area_tmp) / 2 + area_tmp->y1 + y_scroll; + y_scroll += snap_goal - act; + break; } lv_coord_t x_scroll = 0; @@ -665,11 +701,11 @@ static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_p if(snap_x != LV_SCROLL_SNAP_NONE) area_tmp = &child->coords; else area_tmp = area; - lv_coord_t pleft = lv_obj_get_style_pad_left(parent, LV_PART_MAIN); - lv_coord_t pright = lv_obj_get_style_pad_right(parent, LV_PART_MAIN); + lv_coord_t pleft = lv_obj_get_style_pad_left(parent, LV_PART_MAIN) + border_width; + lv_coord_t pright = lv_obj_get_style_pad_right(parent, LV_PART_MAIN) + border_width; lv_coord_t left_diff = parent->coords.x1 + pleft - area_tmp->x1 - scroll_value->x; - lv_coord_t right_diff = -(parent->coords.x2 - pright - area_tmp->x2- scroll_value->x); - if((left_diff > 0 && right_diff > 0)) x_scroll = 0; + lv_coord_t right_diff = -(parent->coords.x2 - pright - area_tmp->x2 - scroll_value->x); + if((left_diff >= 0 && right_diff >= 0)) x_scroll = 0; else if(left_diff > 0) { x_scroll = left_diff; /*Do not let scrolling in*/ @@ -685,21 +721,21 @@ static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_p lv_coord_t parent_w = lv_obj_get_width(parent) - pleft - pright; switch(snap_x) { - case LV_SCROLL_SNAP_START: - snap_goal = parent->coords.x1 + pleft; - act = area_tmp->x1 + x_scroll; - x_scroll += snap_goal - act; - break; - case LV_SCROLL_SNAP_END: - snap_goal = parent->coords.x2 - pright; - act = area_tmp->x2 + x_scroll; - x_scroll += snap_goal - act; - break; - case LV_SCROLL_SNAP_CENTER: - snap_goal = parent->coords.x1 + pleft + parent_w / 2; - act = lv_area_get_width(area_tmp) / 2 + area_tmp->x1 + x_scroll; - x_scroll += snap_goal - act; - break; + case LV_SCROLL_SNAP_START: + snap_goal = parent->coords.x1 + pleft; + act = area_tmp->x1 + x_scroll; + x_scroll += snap_goal - act; + break; + case LV_SCROLL_SNAP_END: + snap_goal = parent->coords.x2 - pright; + act = area_tmp->x2 + x_scroll; + x_scroll += snap_goal - act; + break; + case LV_SCROLL_SNAP_CENTER: + snap_goal = parent->coords.x1 + pleft + parent_w / 2; + act = lv_area_get_width(area_tmp) / 2 + area_tmp->x1 + x_scroll; + x_scroll += snap_goal - act; + break; } /*Remove any pending scroll animations.*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_scroll.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.h similarity index 97% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj_scroll.h rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.h index ce813cee3..fc52e8eea 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_scroll.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.h @@ -37,7 +37,7 @@ enum { typedef uint8_t lv_scrollbar_mode_t; -/** Scroll span align options. Tells where to align the snapable children when scroll stops.*/ +/** Scroll span align options. Tells where to align the snappable children when scroll stops.*/ enum { LV_SCROLL_SNAP_NONE, /**< Do not align, leave where it is*/ LV_SCROLL_SNAP_START, /**< Align to the left/top*/ @@ -172,9 +172,9 @@ lv_coord_t lv_obj_get_scroll_right(struct _lv_obj_t * obj); /** * Get the X and Y coordinates where the scrolling will end for this object if a scrolling animation is in progress. - * In no scrolling animation give the current `x` or `y` scroll position. + * If no scrolling animation, give the current `x` or `y` scroll position. * @param obj pointer to an object - * @param end poinr to point to store the result + * @param end pointer to store the result */ void lv_obj_get_scroll_end(struct _lv_obj_t * obj, lv_point_t * end); diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_style.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.c similarity index 92% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj_style.c rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.c index dde2742c4..57566fd59 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_style.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.c @@ -33,7 +33,7 @@ typedef enum { CACHE_UNSET = 2, CACHE_255 = 3, CACHE_NEED_CHECK = 4, -}cache_t; +} cache_t; /********************** * GLOBAL PROTOTYPES @@ -117,8 +117,7 @@ void lv_obj_remove_style(lv_obj_t * obj, lv_style_t * style, lv_style_selector_t lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector); if((state != LV_STATE_ANY && state_act != state) || (part != LV_PART_ANY && part_act != part) || - (style != NULL && style != obj->styles[i].style)) - { + (style != NULL && style != obj->styles[i].style)) { i++; continue; } @@ -175,11 +174,17 @@ void lv_obj_refresh_style(lv_obj_t * obj, lv_style_selector_t selector, lv_style lv_part_t part = lv_obj_style_get_selector_part(selector); - if((part == LV_PART_ANY || part == LV_PART_MAIN) && (prop == LV_STYLE_PROP_ANY || (prop & LV_STYLE_PROP_LAYOUT_REFR))) { - lv_event_send(obj, LV_EVENT_STYLE_CHANGED, NULL); - lv_obj_mark_layout_as_dirty(obj); + if(prop & LV_STYLE_PROP_LAYOUT_REFR) { + if(part == LV_PART_ANY || + part == LV_PART_MAIN || + lv_obj_get_style_height(obj, 0) == LV_SIZE_CONTENT || + lv_obj_get_style_width(obj, 0) == LV_SIZE_CONTENT) { + lv_event_send(obj, LV_EVENT_STYLE_CHANGED, NULL); + lv_obj_mark_layout_as_dirty(obj); + } } - if((part == LV_PART_ANY || part == LV_PART_MAIN) && (prop == LV_STYLE_PROP_ANY || (prop & LV_STYLE_PROP_PARENT_LAYOUT_REFR))) { + if((part == LV_PART_ANY || part == LV_PART_MAIN) && (prop == LV_STYLE_PROP_ANY || + (prop & LV_STYLE_PROP_PARENT_LAYOUT_REFR))) { lv_obj_t * parent = lv_obj_get_parent(obj); if(parent) lv_obj_mark_layout_as_dirty(parent); } @@ -190,8 +195,7 @@ void lv_obj_refresh_style(lv_obj_t * obj, lv_style_selector_t selector, lv_style lv_obj_invalidate(obj); if(prop == LV_STYLE_PROP_ANY || - ((prop & LV_STYLE_PROP_INHERIT) && ((prop & LV_STYLE_PROP_EXT_DRAW) || (prop & LV_STYLE_PROP_LAYOUT_REFR)))) - { + ((prop & LV_STYLE_PROP_INHERIT) && ((prop & LV_STYLE_PROP_EXT_DRAW) || (prop & LV_STYLE_PROP_LAYOUT_REFR)))) { if(part != LV_PART_SCROLLBAR) { refresh_children_style(obj); } @@ -233,14 +237,16 @@ lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_ while(cls) { if(prop == LV_STYLE_WIDTH) { if(cls->width_def != 0) break; - } else { + } + else { if(cls->height_def != 0) break; } cls = cls->base_class; } value_act.num = prop == LV_STYLE_WIDTH ? cls->width_def : cls->height_def; - } else { + } + else { value_act = lv_style_prop_get_default(prop); } } @@ -248,7 +254,8 @@ lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_ return value_act; } -void lv_obj_set_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value, lv_style_selector_t selector) +void lv_obj_set_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value, + lv_style_selector_t selector) { lv_style_t * style = get_local_style(obj, selector); lv_style_set_prop(style, prop, value); @@ -256,13 +263,13 @@ void lv_obj_set_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_ } -lv_res_t lv_obj_get_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, lv_style_selector_t selector) +lv_res_t lv_obj_get_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, + lv_style_selector_t selector) { uint32_t i; for(i = 0; i < obj->style_cnt; i++) { if(obj->styles[i].is_local && - obj->styles[i].selector == selector) - { + obj->styles[i].selector == selector) { return lv_style_get_prop(obj->styles[i].style, prop, value); } } @@ -289,7 +296,8 @@ bool lv_obj_remove_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_sty return lv_style_remove_prop(obj->styles[i].style, prop); } -void _lv_obj_style_create_transition(lv_obj_t * obj, lv_part_t part, lv_state_t prev_state, lv_state_t new_state, const _lv_obj_style_transition_dsc_t * tr_dsc) +void _lv_obj_style_create_transition(lv_obj_t * obj, lv_part_t part, lv_state_t prev_state, lv_state_t new_state, + const _lv_obj_style_transition_dsc_t * tr_dsc) { trans_t * tr; @@ -357,8 +365,7 @@ _lv_style_state_cmp_t _lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t sta if(obj->styles[i].is_trans) continue; lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector); - lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector); - /*The style is valid for a stat but not the other*/ + /*The style is valid for a state but not the other*/ bool valid1 = state_act & (~state1) ? false : true; bool valid2 = state_act & (~state2) ? false : true; if(valid1 != valid2) { @@ -382,15 +389,11 @@ _lv_style_state_cmp_t _lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t sta else if(lv_style_get_prop(style, LV_STYLE_MIN_HEIGHT, &v)) layout_diff = true; else if(lv_style_get_prop(style, LV_STYLE_MAX_HEIGHT, &v)) layout_diff = true; else if(lv_style_get_prop(style, LV_STYLE_BORDER_WIDTH, &v)) layout_diff = true; + else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ANGLE, &v)) layout_diff = true; + else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ZOOM, &v)) layout_diff = true; if(layout_diff) { - if(part_act == LV_PART_MAIN) { - return _LV_STYLE_STATE_CMP_DIFF_LAYOUT; - } - else { - res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; - continue; - } + return _LV_STYLE_STATE_CMP_DIFF_LAYOUT; } /*Check for draw pad changes*/ @@ -449,6 +452,15 @@ lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector) return selector & 0xFF0000; } + +lv_text_align_t lv_obj_calculate_style_text_align(const struct _lv_obj_t * obj, lv_part_t part, const char * txt) +{ + lv_text_align_t align = lv_obj_get_style_text_align(obj, part); + lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, part); + lv_bidi_calculate_align(&align, &base_dir, txt); + return align; +} + /********************** * STATIC FUNCTIONS **********************/ @@ -466,8 +478,7 @@ static lv_style_t * get_local_style(lv_obj_t * obj, lv_style_selector_t selecto uint32_t i; for(i = 0; i < obj->style_cnt; i++) { if(obj->styles[i].is_local && - obj->styles[i].selector == selector) - { + obj->styles[i].selector == selector) { return obj->styles[i].style; } } @@ -613,8 +624,9 @@ static void report_style_change_core(void * style, lv_obj_t * obj) } } - for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { - report_style_change_core(style, lv_obj_get_child(obj, i)); + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + report_style_change_core(style, obj->spec_attr->children[i]); } } @@ -626,8 +638,9 @@ static void report_style_change_core(void * style, lv_obj_t * obj) static void refresh_children_style(lv_obj_t * obj) { uint32_t i; - for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { - lv_obj_t * child = lv_obj_get_child(obj, i); + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; lv_obj_invalidate(child); lv_event_send(child, LV_EVENT_STYLE_CHANGED, NULL); lv_obj_invalidate(child); @@ -687,7 +700,7 @@ static void trans_anim_cb(void * _tr, int32_t v) if(obj->styles[i].is_trans == 0 || obj->styles[i].selector != tr->selector) continue; lv_style_value_t value_final; - switch (tr->prop) { + switch(tr->prop) { case LV_STYLE_BORDER_SIDE: case LV_STYLE_BORDER_POST: @@ -727,12 +740,13 @@ static void trans_anim_cb(void * _tr, int32_t v) lv_style_value_t old_value; bool refr = true; if(lv_style_get_prop(obj->styles[i].style, tr->prop, &old_value)) { - if(value_final.ptr == old_value.ptr && value_final.color.full == old_value.color.full && value_final.num == old_value.num) { + if(value_final.ptr == old_value.ptr && value_final.color.full == old_value.color.full && + value_final.num == old_value.num) { refr = false; } } lv_style_set_prop(obj->styles[i].style, tr->prop, value_final); - if (refr) lv_obj_refresh_style(tr->obj, tr->selector, tr->prop); + if(refr) lv_obj_refresh_style(tr->obj, tr->selector, tr->prop); break; } diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_style.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.h similarity index 86% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj_style.h rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.h index 0ccbb23f4..d21f40cec 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_style.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.h @@ -38,10 +38,10 @@ typedef uint32_t lv_style_selector_t; typedef struct { lv_style_t * style; - uint32_t selector :24; - uint32_t is_local :1; - uint32_t is_trans :1; -}_lv_obj_style_t; + uint32_t selector : 24; + uint32_t is_local : 1; + uint32_t is_trans : 1; +} _lv_obj_style_t; typedef struct { uint16_t time; @@ -52,7 +52,7 @@ typedef struct { #if LV_USE_USER_DATA void * user_data; #endif -}_lv_obj_style_transition_dsc_t; +} _lv_obj_style_transition_dsc_t; /********************** * GLOBAL PROTOTYPES @@ -138,9 +138,11 @@ lv_style_value_t lv_obj_get_style_prop(const struct _lv_obj_t * obj, lv_part_t p * @param prop the property * @param value value of the property. The correct element should be set according to the type of the property */ -void lv_obj_set_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value, lv_style_selector_t selector); +void lv_obj_set_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value, + lv_style_selector_t selector); -lv_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, lv_style_selector_t selector); +lv_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, + lv_style_selector_t selector); /** * Remove a local style property from a part of an object with a given state. @@ -153,14 +155,15 @@ lv_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t pro bool lv_obj_remove_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector); /** - * Used internally to create a style tarnsition + * Used internally to create a style transition * @param obj * @param part * @param prev_state * @param new_state * @param tr */ -void _lv_obj_style_create_transition(struct _lv_obj_t * obj, lv_part_t part, lv_state_t prev_state, lv_state_t new_state, const _lv_obj_style_transition_dsc_t * tr); +void _lv_obj_style_create_transition(struct _lv_obj_t * obj, lv_part_t part, lv_state_t prev_state, + lv_state_t new_state, const _lv_obj_style_transition_dsc_t * tr); /** * Used internally to compare the appearance of an object in 2 states @@ -193,33 +196,50 @@ lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector); #include "lv_obj_style_gen.h" -static inline void lv_obj_set_style_pad_all(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) { +static inline void lv_obj_set_style_pad_all(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ lv_obj_set_style_pad_left(obj, value, selector); lv_obj_set_style_pad_right(obj, value, selector); lv_obj_set_style_pad_top(obj, value, selector); lv_obj_set_style_pad_bottom(obj, value, selector); } -static inline void lv_obj_set_style_pad_hor(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) { +static inline void lv_obj_set_style_pad_hor(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ lv_obj_set_style_pad_left(obj, value, selector); lv_obj_set_style_pad_right(obj, value, selector); } -static inline void lv_obj_set_style_pad_ver(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) { +static inline void lv_obj_set_style_pad_ver(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ lv_obj_set_style_pad_top(obj, value, selector); lv_obj_set_style_pad_bottom(obj, value, selector); } -static inline void lv_obj_set_style_pad_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) { +static inline void lv_obj_set_style_pad_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ lv_obj_set_style_pad_row(obj, value, selector); lv_obj_set_style_pad_column(obj, value, selector); } -static inline void lv_obj_set_style_size(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) { +static inline void lv_obj_set_style_size(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ lv_obj_set_style_width(obj, value, selector); lv_obj_set_style_height(obj, value, selector); } +lv_text_align_t lv_obj_calculate_style_text_align(const struct _lv_obj_t * obj, lv_part_t part, const char * txt); + +static inline lv_coord_t lv_obj_get_x_aligned(const struct _lv_obj_t * obj) +{ + return lv_obj_get_style_x(obj, LV_PART_MAIN); +} + +static inline lv_coord_t lv_obj_get_y_aligned(const struct _lv_obj_t * obj) +{ + return lv_obj_get_style_y(obj, LV_PART_MAIN); +} + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_style_gen.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.c similarity index 99% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj_style_gen.c rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.c index 47038e1a0..4cf91b329 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_style_gen.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.c @@ -631,7 +631,7 @@ void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_DASH_GAP, v, selector); } -void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -671,7 +671,7 @@ void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_sty lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_WIDTH, v, selector); } -void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_style_gen.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.h similarity index 98% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj_style_gen.h rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.h index a0c53525a..40e490ea0 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_style_gen.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.h @@ -472,10 +472,10 @@ static inline lv_coord_t lv_obj_get_style_line_dash_gap(const struct _lv_obj_t * return (lv_coord_t)v.num; } -static inline lv_coord_t lv_obj_get_style_line_rounded(const struct _lv_obj_t * obj, uint32_t part) +static inline bool lv_obj_get_style_line_rounded(const struct _lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_ROUNDED); - return (lv_coord_t)v.num; + return (bool)v.num; } static inline lv_color_t lv_obj_get_style_line_color(const struct _lv_obj_t * obj, uint32_t part) @@ -502,10 +502,10 @@ static inline lv_coord_t lv_obj_get_style_arc_width(const struct _lv_obj_t * obj return (lv_coord_t)v.num; } -static inline lv_coord_t lv_obj_get_style_arc_rounded(const struct _lv_obj_t * obj, uint32_t part) +static inline bool lv_obj_get_style_arc_rounded(const struct _lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_ROUNDED); - return (lv_coord_t)v.num; + return (bool)v.num; } static inline lv_color_t lv_obj_get_style_arc_color(const struct _lv_obj_t * obj, uint32_t part) @@ -611,12 +611,12 @@ void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_styl void lv_obj_set_style_line_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_line_dash_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); void lv_obj_set_style_line_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); void lv_obj_set_style_line_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); void lv_obj_set_style_arc_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); void lv_obj_set_style_arc_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_tree.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.c similarity index 74% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj_tree.c rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.c index 4d3709aaa..3adf72183 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_tree.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.c @@ -6,6 +6,8 @@ /********************* * INCLUDES *********************/ +#include + #include "lv_obj.h" #include "lv_indev.h" #include "../misc/lv_anim.h" @@ -17,10 +19,6 @@ *********************/ #define MY_CLASS &lv_obj_class -#if defined(LV_USER_DATA_FREE_INCLUDE) - #include LV_USER_DATA_FREE_INCLUDE -#endif /*LV_USE_USER_DATA_FREE*/ - /********************** * TYPEDEFS **********************/ @@ -46,7 +44,7 @@ static lv_obj_tree_walk_res_t walk_core(lv_obj_t * obj, lv_obj_tree_walk_cb_t cb void lv_obj_del(lv_obj_t * obj) { - LV_LOG_TRACE("begin (delete %p)", obj) + LV_LOG_TRACE("begin (delete %p)", (void *)obj); LV_ASSERT_OBJ(obj, MY_CLASS); lv_obj_invalidate(obj); @@ -70,21 +68,22 @@ void lv_obj_del(lv_obj_t * obj) lv_obj_readjust_scroll(par, LV_ANIM_OFF); lv_obj_scrollbar_invalidate(par); lv_event_send(par, LV_EVENT_CHILD_CHANGED, NULL); + lv_event_send(par, LV_EVENT_CHILD_DELETED, NULL); } /*Handle if the active screen was deleted*/ - if(act_scr_del) { - LV_LOG_WARN("the active screen was deleted") + if(act_scr_del) { + LV_LOG_WARN("the active screen was deleted"); disp->act_scr = NULL; } LV_ASSERT_MEM_INTEGRITY(); - LV_LOG_TRACE("finished (delete %p)", obj) + LV_LOG_TRACE("finished (delete %p)", (void *)obj); } void lv_obj_clean(lv_obj_t * obj) { - LV_LOG_TRACE("begin (delete %p)", obj) + LV_LOG_TRACE("begin (delete %p)", (void *)obj); LV_ASSERT_OBJ(obj, MY_CLASS); lv_obj_invalidate(obj); @@ -103,7 +102,19 @@ void lv_obj_clean(lv_obj_t * obj) LV_ASSERT_MEM_INTEGRITY(); - LV_LOG_TRACE("finished (delete %p)", obj) + LV_LOG_TRACE("finished (delete %p)", (void *)obj); +} + +void lv_obj_del_delayed(lv_obj_t * obj, uint32_t delay_ms) +{ + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, obj); + lv_anim_set_exec_cb(&a, NULL); + lv_anim_set_time(&a, 1); + lv_anim_set_delay(&a, delay_ms); + lv_anim_set_ready_cb(&a, lv_obj_del_anim_ready_cb); + lv_anim_start(&a); } void lv_obj_del_anim_ready_cb(lv_anim_t * a) @@ -137,90 +148,101 @@ void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent) lv_obj_allocate_spec_attr(parent); lv_obj_t * old_parent = obj->parent; - lv_point_t old_pos; - old_pos.y = lv_obj_get_y(obj); - - lv_base_dir_t new_base_dir = lv_obj_get_style_base_dir(parent, LV_PART_MAIN); - - if(new_base_dir != LV_BASE_DIR_RTL) old_pos.x = lv_obj_get_x(obj); - else old_pos.x = old_parent->coords.x2 - obj->coords.x2; - /*Remove the object from the old parent's child list*/ int32_t i; - for(i = lv_obj_get_child_id(obj); i <= (int32_t)lv_obj_get_child_cnt(old_parent) - 2; i++) { - old_parent->spec_attr->children[i] = old_parent->spec_attr->children[i+1]; + for(i = lv_obj_get_index(obj); i <= (int32_t)lv_obj_get_child_cnt(old_parent) - 2; i++) { + old_parent->spec_attr->children[i] = old_parent->spec_attr->children[i + 1]; } old_parent->spec_attr->child_cnt--; if(old_parent->spec_attr->child_cnt) { - old_parent->spec_attr->children = lv_mem_realloc(old_parent->spec_attr->children, old_parent->spec_attr->child_cnt * (sizeof(lv_obj_t *))); - } else { + old_parent->spec_attr->children = lv_mem_realloc(old_parent->spec_attr->children, + old_parent->spec_attr->child_cnt * (sizeof(lv_obj_t *))); + } + else { lv_mem_free(old_parent->spec_attr->children); old_parent->spec_attr->children = NULL; } /*Add the child to the new parent as the last (newest child)*/ parent->spec_attr->child_cnt++; - parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children, parent->spec_attr->child_cnt * (sizeof(lv_obj_t *))); + parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children, + parent->spec_attr->child_cnt * (sizeof(lv_obj_t *))); parent->spec_attr->children[lv_obj_get_child_cnt(parent) - 1] = obj; obj->parent = parent; - if(new_base_dir != LV_BASE_DIR_RTL) { - lv_obj_set_pos(obj, old_pos.x, old_pos.y); - } - else { - /*Align to the right in case of RTL base dir*/ - lv_coord_t new_x = lv_obj_get_width(parent) - old_pos.x - lv_obj_get_width(obj); - lv_obj_set_pos(obj, new_x, old_pos.y); - } - /*Notify the original parent because one of its children is lost*/ lv_event_send(old_parent, LV_EVENT_CHILD_CHANGED, obj); + lv_event_send(old_parent, LV_EVENT_CHILD_DELETED, NULL); /*Notify the new parent about the child*/ lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj); + lv_event_send(parent, LV_EVENT_CHILD_CREATED, NULL); + + lv_obj_mark_layout_as_dirty(obj); lv_obj_invalidate(obj); } -void lv_obj_move_foreground(lv_obj_t * obj) +void lv_obj_move_to_index(lv_obj_t * obj, int32_t index) { LV_ASSERT_OBJ(obj, MY_CLASS); + const int32_t old_index = lv_obj_get_index(obj); + lv_obj_t * parent = lv_obj_get_parent(obj); - lv_obj_invalidate(parent); + if(index < 0) return; + if(index >= (int32_t) lv_obj_get_child_cnt(parent)) return; + if(index == old_index) return; - uint32_t i; - for(i = lv_obj_get_child_id(obj); i < lv_obj_get_child_cnt(parent) - 1; i++) { - parent->spec_attr->children[i] = parent->spec_attr->children[i + 1]; + int32_t i = old_index; + if(index < old_index) { + while(i > index) { + parent->spec_attr->children[i] = parent->spec_attr->children[i - 1]; + i--; + } + } + else { + while(i < index) { + parent->spec_attr->children[i] = parent->spec_attr->children[i + 1]; + i++; + } } - parent->spec_attr->children[lv_obj_get_child_cnt(parent) - 1] = obj; - - /*Notify the new parent about the child*/ - lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj); + parent->spec_attr->children[index] = obj; + lv_event_send(parent, LV_EVENT_CHILD_CHANGED, NULL); lv_obj_invalidate(parent); } -void lv_obj_move_background(lv_obj_t * obj) +void lv_obj_swap(lv_obj_t * obj1, lv_obj_t * obj2) { - LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_OBJ(obj1, MY_CLASS); + LV_ASSERT_OBJ(obj2, MY_CLASS); - lv_obj_t * parent = lv_obj_get_parent(obj); + lv_obj_t * parent = lv_obj_get_parent(obj1); + lv_obj_t * parent2 = lv_obj_get_parent(obj2); + + uint_fast32_t index1 = lv_obj_get_index(obj1); + uint_fast32_t index2 = lv_obj_get_index(obj2); + + lv_event_send(parent2, LV_EVENT_CHILD_DELETED, obj2); + lv_event_send(parent, LV_EVENT_CHILD_DELETED, obj1); + + parent->spec_attr->children[index1] = obj2; + parent2->spec_attr->children[index2] = obj1; + + lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj2); + lv_event_send(parent, LV_EVENT_CHILD_CREATED, obj2); + lv_event_send(parent2, LV_EVENT_CHILD_CHANGED, obj1); + lv_event_send(parent2, LV_EVENT_CHILD_CREATED, obj1); lv_obj_invalidate(parent); - int32_t i; - for(i = lv_obj_get_child_id(obj); i > 0; i--) { - parent->spec_attr->children[i] = parent->spec_attr->children[i-1]; + if(parent != parent2) { + lv_obj_invalidate(parent2); } - parent->spec_attr->children[0] = obj; - - /*Notify the new parent about the child*/ - lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj); - - lv_obj_invalidate(parent); + lv_group_swap_obj(obj1, obj2); } lv_obj_t * lv_obj_get_screen(const lv_obj_t * obj) @@ -232,10 +254,10 @@ lv_obj_t * lv_obj_get_screen(const lv_obj_t * obj) do { act_par = par; - par = lv_obj_get_parent(act_par); + par = lv_obj_get_parent(act_par); } while(par != NULL); - return (lv_obj_t*)act_par; + return (lv_obj_t *)act_par; } lv_disp_t * lv_obj_get_disp(const lv_obj_t * obj) @@ -255,7 +277,7 @@ lv_disp_t * lv_obj_get_disp(const lv_obj_t * obj) } } - LV_LOG_WARN("No screen found") + LV_LOG_WARN("No screen found"); return NULL; } @@ -278,7 +300,8 @@ lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, int32_t id) id = obj->spec_attr->child_cnt + id; if(id < 0) return NULL; idu = (uint32_t) id; - } else { + } + else { idu = id; } @@ -293,7 +316,7 @@ uint32_t lv_obj_get_child_cnt(const lv_obj_t * obj) return obj->spec_attr->child_cnt; } -uint32_t lv_obj_get_child_id(const lv_obj_t * obj) +uint32_t lv_obj_get_index(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -308,7 +331,6 @@ uint32_t lv_obj_get_child_id(const lv_obj_t * obj) return 0xFFFFFFFF; /*Shouldn't happen*/ } - void lv_obj_tree_walk(lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data) { walk_core(start_obj, cb, user_data); @@ -377,13 +399,14 @@ static void obj_del_core(lv_obj_t * obj) } /*Remove the object from the child list of its parent*/ else { - uint32_t id = lv_obj_get_child_id(obj); + uint32_t id = lv_obj_get_index(obj); uint32_t i; for(i = id; i < obj->parent->spec_attr->child_cnt - 1; i++) { obj->parent->spec_attr->children[i] = obj->parent->spec_attr->children[i + 1]; } obj->parent->spec_attr->child_cnt--; - obj->parent->spec_attr->children = lv_mem_realloc(obj->parent->spec_attr->children, obj->parent->spec_attr->child_cnt * sizeof(lv_obj_t *)); + obj->parent->spec_attr->children = lv_mem_realloc(obj->parent->spec_attr->children, + obj->parent->spec_attr->child_cnt * sizeof(lv_obj_t *)); } /*Free the object itself*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_tree.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.h similarity index 78% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_obj_tree.h rename to lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.h index 7cb241eaf..1c714c420 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_obj_tree.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.h @@ -41,7 +41,7 @@ typedef lv_obj_tree_walk_res_t (*lv_obj_tree_walk_cb_t)(struct _lv_obj_t *, void **********************/ /** - * Delete an object and all of it's children. + * Delete an object and all of its children. * Also remove the objects from their group and remove all animations (if any). * Send `LV_EVENT_DELETED` to deleted objects. * @param obj pointer to an object @@ -56,6 +56,13 @@ void lv_obj_del(struct _lv_obj_t * obj); */ void lv_obj_clean(struct _lv_obj_t * obj); +/** + * Delete an object after some delay + * @param obj pointer to an object + * @param delay_ms time to wait before delete in milliseconds + */ +void lv_obj_del_delayed(struct _lv_obj_t * obj, uint32_t delay_ms); + /** * A function to be easily used in animation ready callback to delete an object when the animation is ready * @param a pointer to the animation @@ -79,32 +86,34 @@ void lv_obj_del_async(struct _lv_obj_t * obj); void lv_obj_set_parent(struct _lv_obj_t * obj, struct _lv_obj_t * parent); /** - * Move the object to the foreground. - * It will look like if it was created as the last child of its parent. - * It also means it can cover any of the siblings. - * @param obj pointer to an object + * Swap the positions of two objects. + * When used in listboxes, it can be used to sort the listbox items. + * @param obj1 pointer to the first object + * @param obj2 pointer to the second object */ -void lv_obj_move_foreground(struct _lv_obj_t * obj); +void lv_obj_swap(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2); /** - * Move the object to the background. - * It will look like if it was created as the first child of its parent. - * It also means any of the siblings can cover the object. - * @param obj pointer to an object + * moves the object to the given index in its parent. + * When used in listboxes, it can be used to sort the listbox items. + * @param obj pointer to the object to be moved. + * @param index new index in parent. + * @note to move to the foreground: lv_obj_move_to_index(obj, 0) + * @note to move forward (up): lv_obj_move_to_index(obj, lv_obj_get_index(obj) - 1) */ -void lv_obj_move_background(struct _lv_obj_t * obj); +void lv_obj_move_to_index(struct _lv_obj_t * obj, int32_t index); /** * Get the screen of an object * @param obj pointer to an object - * @return pointer to the obejct's screen + * @return pointer to the object's screen */ struct _lv_obj_t * lv_obj_get_screen(const struct _lv_obj_t * obj); /** * Get the display of the object * @param obj pointer to an object - * @return pointer to the obejct's display + * @return pointer to the object's display */ lv_disp_t * lv_obj_get_disp(const struct _lv_obj_t * obj); @@ -137,11 +146,11 @@ uint32_t lv_obj_get_child_cnt(const struct _lv_obj_t * obj); /** * Get the index of a child. - * @param obj pointer to an obejct + * @param obj pointer to an object * @return the child index of the object. * E.g. 0: the oldest (firstly created child) */ -uint32_t lv_obj_get_child_id(const struct _lv_obj_t * obj); +uint32_t lv_obj_get_index(const struct _lv_obj_t * obj); /** * Iterate through all children of any object. diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_refr.c b/lib/libesp32_lvgl/lvgl/src/core/lv_refr.c similarity index 83% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_refr.c rename to lib/libesp32_lvgl/lvgl/src/core/lv_refr.c index abd3976ad..a44060a5e 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_refr.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_refr.c @@ -57,9 +57,9 @@ static lv_disp_t * disp_refr; /*Display being refreshed*/ * MACROS **********************/ #if LV_LOG_TRACE_DISP_REFR -# define TRACE_REFR(...) LV_LOG_TRACE( __VA_ARGS__) + #define REFR_TRACE(...) LV_LOG_TRACE(__VA_ARGS__) #else -# define TRACE_REFR(...) + #define REFR_TRACE(...) #endif /********************** @@ -181,10 +181,10 @@ void _lv_refr_set_disp_refreshing(lv_disp_t * disp) */ void _lv_disp_refr_timer(lv_timer_t * tmr) { - TRACE_REFR("begin"); + REFR_TRACE("begin"); uint32_t start = lv_tick_get(); - uint32_t elaps = 0; + volatile uint32_t elaps = 0; disp_refr = tmr->user_data; @@ -207,7 +207,7 @@ void _lv_disp_refr_timer(lv_timer_t * tmr) if(disp_refr->act_scr == NULL) { disp_refr->inv_p = 0; LV_LOG_WARN("there is no active screen"); - TRACE_REFR("finished"); + REFR_TRACE("finished"); return; } @@ -236,6 +236,10 @@ void _lv_disp_refr_timer(lv_timer_t * tmr) lv_mem_buf_free_all(); _lv_font_clean_up_fmt_txt(); +#if LV_DRAW_COMPLEX + _lv_draw_mask_cleanup(); +#endif + #if LV_USE_PERF_MONITOR && LV_USE_LABEL static lv_obj_t * perf_label = NULL; if(perf_label == NULL) { @@ -249,7 +253,7 @@ void _lv_disp_refr_timer(lv_timer_t * tmr) lv_obj_set_style_pad_right(perf_label, 3, 0); lv_obj_set_style_text_align(perf_label, LV_TEXT_ALIGN_RIGHT, 0); lv_label_set_text(perf_label, "?"); - lv_obj_align(perf_label, LV_ALIGN_BOTTOM_RIGHT, 0, 0); + lv_obj_align(perf_label, LV_USE_PERF_MONITOR_POS, 0, 0); } static uint32_t perf_last_time = 0; @@ -264,7 +268,7 @@ void _lv_disp_refr_timer(lv_timer_t * tmr) else { perf_last_time = lv_tick_get(); uint32_t fps_limit = 1000 / disp_refr->refr_timer->period; - uint32_t fps; + unsigned int fps; if(elaps_sum == 0) elaps_sum = 1; if(frame_cnt == 0) fps = fps_limit; @@ -275,8 +279,8 @@ void _lv_disp_refr_timer(lv_timer_t * tmr) fps_sum_all += fps; fps_sum_cnt ++; - uint32_t cpu = 100 - lv_timer_get_idle(); - lv_label_set_text_fmt(perf_label, "%d FPS\n%d%% CPU", fps, cpu); + unsigned int cpu = 100 - lv_timer_get_idle(); + lv_label_set_text_fmt(perf_label, "%u FPS\n%u%% CPU", fps, cpu); } #endif @@ -292,7 +296,7 @@ void _lv_disp_refr_timer(lv_timer_t * tmr) lv_obj_set_style_pad_left(mem_label, 3, 0); lv_obj_set_style_pad_right(mem_label, 3, 0); lv_label_set_text(mem_label, "?"); - lv_obj_align(mem_label, LV_ALIGN_BOTTOM_LEFT, 0, 0); + lv_obj_align(mem_label, LV_USE_MEM_MONITOR_POS, 0, 0); } static uint32_t mem_last_time = 0; @@ -303,11 +307,13 @@ void _lv_disp_refr_timer(lv_timer_t * tmr) uint32_t used_size = mon.total_size - mon.free_size;; uint32_t used_kb = used_size / 1024; uint32_t used_kb_tenth = (used_size - (used_kb * 1024)) / 102; - lv_label_set_text_fmt(mem_label, "%d.%d kB used (%d %%)\n%d%% frag.", used_kb, used_kb_tenth, mon.used_pct, mon.frag_pct); + lv_label_set_text_fmt(mem_label, "%" LV_PRIu32 ".%" LV_PRIu32 " kB used (%d %%)\n" \ + "%d%% frag.", used_kb, used_kb_tenth, mon.used_pct, + mon.frag_pct); } #endif - TRACE_REFR("finished"); + REFR_TRACE("finished"); } #if LV_USE_PERF_MONITOR @@ -417,7 +423,7 @@ static void lv_refr_area(const lv_area_t * area_p) lv_coord_t w = lv_area_get_width(area_p); lv_coord_t h = lv_area_get_height(area_p); lv_coord_t y2 = area_p->y2 >= lv_disp_get_ver_res(disp_refr) ? - lv_disp_get_ver_res(disp_refr) - 1 : area_p->y2; + lv_disp_get_ver_res(disp_refr) - 1 : area_p->y2; int32_t max_row = (uint32_t)draw_buf->size / w; @@ -452,31 +458,43 @@ static void lv_refr_area(const lv_area_t * area_p) } } - /*Always use the full row*/ - lv_coord_t row; - lv_coord_t row_last = 0; - for(row = area_p->y1; row + max_row - 1 <= y2; row += max_row) { - /*Calc. the next y coordinates of draw_buf*/ - draw_buf->area.x1 = area_p->x1; - draw_buf->area.x2 = area_p->x2; - draw_buf->area.y1 = row; - draw_buf->area.y2 = row + max_row - 1; - if(draw_buf->area.y2 > y2) draw_buf->area.y2 = y2; - row_last = draw_buf->area.y2; - if(y2 == row_last) disp_refr->driver->draw_buf->last_part = 1; + /*In direct mode draw directly on the absolute coordinates of the buffer*/ + if(disp_refr->driver->direct_mode) { + draw_buf->area.x1 = 0; + draw_buf->area.x2 = lv_disp_get_hor_res(disp_refr) - 1; + draw_buf->area.y1 = 0; + draw_buf->area.y2 = lv_disp_get_ver_res(disp_refr) - 1; + disp_refr->driver->draw_buf->last_part = disp_refr->driver->draw_buf->last_area; lv_refr_area_part(area_p); } + /*Else assume the buffer starts at the given area*/ + else { + /*Always use the full row*/ + lv_coord_t row; + lv_coord_t row_last = 0; + for(row = area_p->y1; row + max_row - 1 <= y2; row += max_row) { + /*Calc. the next y coordinates of draw_buf*/ + draw_buf->area.x1 = area_p->x1; + draw_buf->area.x2 = area_p->x2; + draw_buf->area.y1 = row; + draw_buf->area.y2 = row + max_row - 1; + if(draw_buf->area.y2 > y2) draw_buf->area.y2 = y2; + row_last = draw_buf->area.y2; + if(y2 == row_last) disp_refr->driver->draw_buf->last_part = 1; + lv_refr_area_part(area_p); + } - /*If the last y coordinates are not handled yet ...*/ - if(y2 != row_last) { - /*Calc. the next y coordinates of draw_buf*/ - draw_buf->area.x1 = area_p->x1; - draw_buf->area.x2 = area_p->x2; - draw_buf->area.y1 = row; - draw_buf->area.y2 = y2; + /*If the last y coordinates are not handled yet ...*/ + if(y2 != row_last) { + /*Calc. the next y coordinates of draw_buf*/ + draw_buf->area.x1 = area_p->x1; + draw_buf->area.x2 = area_p->x2; + draw_buf->area.y1 = row; + draw_buf->area.y2 = y2; - disp_refr->driver->draw_buf->last_part = 1; - lv_refr_area_part(area_p); + disp_refr->driver->draw_buf->last_part = 1; + lv_refr_area_part(area_p); + } } } @@ -488,8 +506,12 @@ static void lv_refr_area_part(const lv_area_t * area_p) { lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr); - while(draw_buf->flushing) { - if(disp_refr->driver->wait_cb) disp_refr->driver->wait_cb(disp_refr->driver); + /* Below the `area_p` area will be redrawn into the draw buffer. + * In single buffered mode wait here until the buffer is freed.*/ + if(draw_buf->buf1 && !draw_buf->buf2) { + while(draw_buf->flushing) { + if(disp_refr->driver->wait_cb) disp_refr->driver->wait_cb(disp_refr->driver); + } } lv_obj_t * top_act_scr = NULL; @@ -508,7 +530,9 @@ static void lv_refr_area_part(const lv_area_t * area_p) /*Draw a display background if there is no top object*/ if(top_act_scr == NULL && top_prev_scr == NULL) { - if(disp_refr->bg_img) { + if(disp_refr->bg_fn) { + disp_refr->bg_fn(&start_mask); + } else if(disp_refr->bg_img) { lv_draw_img_dsc_t dsc; lv_draw_img_dsc_init(&dsc); dsc.opa = disp_refr->bg_opa; @@ -521,7 +545,7 @@ static void lv_refr_area_part(const lv_area_t * area_p) lv_draw_img(&a, &start_mask, disp_refr->bg_img, &dsc); } else { - LV_LOG_WARN("Can't draw the background image") + LV_LOG_WARN("Can't draw the background image"); } } else { @@ -580,8 +604,9 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj) if(info.res == LV_COVER_RES_MASKED) return NULL; uint32_t i; - for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { - lv_obj_t * child = lv_obj_get_child(obj, i); + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; found_p = lv_refr_get_top_obj(area_p, child); /*If a children is ok then break*/ @@ -627,20 +652,22 @@ static void lv_refr_obj_and_children(lv_obj_t * top_p, const lv_area_t * mask_p) while(par != NULL) { bool go = false; uint32_t i; - for(i = 0; i < lv_obj_get_child_cnt(par); i++) { - lv_obj_t * child = lv_obj_get_child(par, i); + uint32_t child_cnt = lv_obj_get_child_cnt(par); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = par->spec_attr->children[i]; if(!go) { if(child == border_p) go = true; - } else { + } + else { /*Refresh the objects*/ lv_refr_obj(child, mask_p); } } /*Call the post draw draw function of the parents of the to object*/ - lv_event_send(par, LV_EVENT_DRAW_POST_BEGIN, (void*)mask_p); - lv_event_send(par, LV_EVENT_DRAW_POST, (void*)mask_p); - lv_event_send(par, LV_EVENT_DRAW_POST_END, (void*)mask_p); + lv_event_send(par, LV_EVENT_DRAW_POST_BEGIN, (void *)mask_p); + lv_event_send(par, LV_EVENT_DRAW_POST, (void *)mask_p); + lv_event_send(par, LV_EVENT_DRAW_POST_END, (void *)mask_p); /*The new border will be the last parents, *so the 'younger' brothers of parent will be refreshed*/ @@ -699,8 +726,9 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p) lv_area_t mask_child; /*Mask from obj and its child*/ lv_area_t child_area; uint32_t i; - for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { - lv_obj_t * child = lv_obj_get_child(obj, i); + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; lv_obj_get_coords(child, &child_area); ext_size = _lv_obj_get_ext_draw_size(child); child_area.x1 -= ext_size; @@ -726,7 +754,8 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p) } } -static void draw_buf_rotate_180(lv_disp_drv_t *drv, lv_area_t *area, lv_color_t *color_p) { +static void draw_buf_rotate_180(lv_disp_drv_t * drv, lv_area_t * area, lv_color_t * color_p) +{ lv_coord_t area_w = lv_area_get_width(area); lv_coord_t area_h = lv_area_get_height(area); uint32_t total = area_w * area_h; @@ -749,7 +778,9 @@ static void draw_buf_rotate_180(lv_disp_drv_t *drv, lv_area_t *area, lv_color_t area->x1 = drv->hor_res - tmp_coord - 1; } -static LV_ATTRIBUTE_FAST_MEM void draw_buf_rotate_90(bool invert_i, lv_coord_t area_w, lv_coord_t area_h, lv_color_t *orig_color_p, lv_color_t *rot_buf) { +static LV_ATTRIBUTE_FAST_MEM void draw_buf_rotate_90(bool invert_i, lv_coord_t area_w, lv_coord_t area_h, + lv_color_t * orig_color_p, lv_color_t * rot_buf) +{ uint32_t invert = (area_w * area_h) - 1; uint32_t initial_i = ((area_w - 1) * area_h); @@ -770,7 +801,8 @@ static LV_ATTRIBUTE_FAST_MEM void draw_buf_rotate_90(bool invert_i, lv_coord_t a /** * Helper function for draw_buf_rotate_90_sqr. Given a list of four numbers, rotate the entire list to the left. */ -static inline void draw_buf_rotate4(lv_color_t *a, lv_color_t *b, lv_color_t * c, lv_color_t * d) { +static inline void draw_buf_rotate4(lv_color_t * a, lv_color_t * b, lv_color_t * c, lv_color_t * d) +{ lv_color_t tmp; tmp = *a; *a = *b; @@ -783,9 +815,10 @@ static inline void draw_buf_rotate4(lv_color_t *a, lv_color_t *b, lv_color_t * c * Rotate a square image 90/270 degrees in place. * @note inspired by https://stackoverflow.com/a/43694906 */ -static void draw_buf_rotate_90_sqr(bool is_270, lv_coord_t w, lv_color_t * color_p) { - for(lv_coord_t i = 0; i < w/2; i++) { - for(lv_coord_t j = 0; j < (w + 1)/2; j++) { +static void draw_buf_rotate_90_sqr(bool is_270, lv_coord_t w, lv_color_t * color_p) +{ + for(lv_coord_t i = 0; i < w / 2; i++) { + for(lv_coord_t j = 0; j < (w + 1) / 2; j++) { lv_coord_t inv_i = (w - 1) - i; lv_coord_t inv_j = (w - 1) - j; if(is_270) { @@ -795,7 +828,8 @@ static void draw_buf_rotate_90_sqr(bool is_270, lv_coord_t w, lv_color_t * color &color_p[inv_i * w + inv_j], &color_p[j * w + inv_i] ); - } else { + } + else { draw_buf_rotate4( &color_p[i * w + j], &color_p[j * w + inv_i], @@ -811,7 +845,8 @@ static void draw_buf_rotate_90_sqr(bool is_270, lv_coord_t w, lv_color_t * color /** * Rotate the draw_buf to the display's native orientation. */ -static void draw_buf_rotate(lv_area_t *area, lv_color_t *color_p) { +static void draw_buf_rotate(lv_area_t * area, lv_color_t * color_p) +{ lv_disp_drv_t * drv = disp_refr->driver; if(disp_refr->driver->full_refresh && drv->sw_rotate) { LV_LOG_ERROR("cannot rotate a full refreshed display!"); @@ -820,14 +855,15 @@ static void draw_buf_rotate(lv_area_t *area, lv_color_t *color_p) { if(drv->rotated == LV_DISP_ROT_180) { draw_buf_rotate_180(drv, area, color_p); call_flush_cb(drv, area, color_p); - } else if(drv->rotated == LV_DISP_ROT_90 || drv->rotated == LV_DISP_ROT_270) { + } + else if(drv->rotated == LV_DISP_ROT_90 || drv->rotated == LV_DISP_ROT_270) { /*Allocate a temporary buffer to store rotated image*/ lv_color_t * rot_buf = NULL; lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr); lv_coord_t area_w = lv_area_get_width(area); lv_coord_t area_h = lv_area_get_height(area); /*Determine the maximum number of rows that can be rotated at a time*/ - lv_coord_t max_row = LV_MIN((lv_coord_t)((LV_DISP_ROT_MAX_BUF/sizeof(lv_color_t)) / area_w), area_h); + lv_coord_t max_row = LV_MIN((lv_coord_t)((LV_DISP_ROT_MAX_BUF / sizeof(lv_color_t)) / area_w), area_h); lv_coord_t init_y_off; init_y_off = area->y1; if(drv->rotated == LV_DISP_ROT_90) { @@ -838,11 +874,11 @@ static void draw_buf_rotate(lv_area_t *area, lv_color_t *color_p) { area->y1 = area->x1; area->y2 = area->y1 + area_w - 1; } - draw_buf->flushing = 0; + /*Rotate the screen in chunks, flushing after each one*/ lv_coord_t row = 0; while(row < area_h) { - lv_coord_t height = LV_MIN(max_row, area_h-row); + lv_coord_t height = LV_MIN(max_row, area_h - row); draw_buf->flushing = 1; if((row == 0) && (area_h >= area_w)) { /*Rotate the initial area as a square*/ @@ -871,6 +907,16 @@ static void draw_buf_rotate(lv_area_t *area, lv_color_t *color_p) { area->x1 = area->x2 - height + 1; } } + + /* The original part (chunk of the current area) were split into more parts here. + * Set the original last_part flag on the last part of rotation. */ + if(row + height >= area_h && draw_buf->last_area && draw_buf->last_part) { + draw_buf->flushing_last = 1; + } + else { + draw_buf->flushing_last = 0; + } + /*Flush the completed area to the display*/ call_flush_cb(drv, area, rot_buf == NULL ? color_p : rot_buf); /*FIXME: Rotation forces legacy behavior where rendering and flushing are done serially*/ @@ -893,20 +939,29 @@ static void draw_buf_flush(void) lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr); lv_color_t * color_p = draw_buf->buf_act; + /*Flush the rendered content to the display*/ + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + if(disp->driver->gpu_wait_cb) disp->driver->gpu_wait_cb(disp->driver); + + /* In double buffered mode wait until the other buffer is freed + * and driver is ready to receive the new buffer */ + if(draw_buf->buf1 && draw_buf->buf2) { + while(draw_buf->flushing) { + if(disp_refr->driver->wait_cb) disp_refr->driver->wait_cb(disp_refr->driver); + } + } + draw_buf->flushing = 1; if(disp_refr->driver->draw_buf->last_area && disp_refr->driver->draw_buf->last_part) draw_buf->flushing_last = 1; else draw_buf->flushing_last = 0; - /*Flush the rendered content to the display*/ - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - if(disp->driver->gpu_wait_cb) disp->driver->gpu_wait_cb(disp->driver); - if(disp->driver->flush_cb) { /*Rotate the buffer to the display's native orientation if necessary*/ if(disp->driver->rotated != LV_DISP_ROT_NONE && disp->driver->sw_rotate) { draw_buf_rotate(&draw_buf->area, draw_buf->buf_act); - } else { + } + else { call_flush_cb(disp->driver, &draw_buf->area, color_p); } } @@ -920,6 +975,15 @@ static void draw_buf_flush(void) static void call_flush_cb(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p) { - TRACE_REFR("Calling flush_cb on (%d;%d)(%d;%d) area with %p image pointer", area->x1, area->y1, area->x2, area->y2, color_p); - drv->flush_cb(drv, area, color_p); + REFR_TRACE("Calling flush_cb on (%d;%d)(%d;%d) area with %p image pointer", area->x1, area->y1, area->x2, area->y2, + (void *)color_p); + + lv_area_t offset_area = { + .x1 = area->x1 + drv->offset_x, + .y1 = area->y1 + drv->offset_y, + .x2 = area->x2 + drv->offset_x, + .y2 = area->y2 + drv->offset_y + }; + + drv->flush_cb(drv, &offset_area, color_p); } diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_refr.h b/lib/libesp32_lvgl/lvgl/src/core/lv_refr.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_refr.h rename to lib/libesp32_lvgl/lvgl/src/core/lv_refr.h diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_theme.c b/lib/libesp32_lvgl/lvgl/src/core/lv_theme.c similarity index 98% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_theme.c rename to lib/libesp32_lvgl/lvgl/src/core/lv_theme.c index f8a0f50ae..b46cdcc4c 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_theme.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_theme.c @@ -33,7 +33,7 @@ static void apply_theme(lv_theme_t * th, lv_obj_t * obj); * GLOBAL FUNCTIONS **********************/ -lv_theme_t * lv_theme_get_from_obj(lv_obj_t * obj) +lv_theme_t * lv_theme_get_from_obj(lv_obj_t * obj) { lv_disp_t * disp = obj ? lv_obj_get_disp(obj) : lv_disp_get_default(); return lv_disp_get_theme(disp); diff --git a/lib/libesp32_lvgl/LVGL8/src/core/lv_theme.h b/lib/libesp32_lvgl/lvgl/src/core/lv_theme.h similarity index 98% rename from lib/libesp32_lvgl/LVGL8/src/core/lv_theme.h rename to lib/libesp32_lvgl/lvgl/src/core/lv_theme.h index f287a2c61..f2f390728 100644 --- a/lib/libesp32_lvgl/LVGL8/src/core/lv_theme.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_theme.h @@ -50,7 +50,7 @@ typedef struct _lv_theme_t { * @param obj pointer to object * @return the theme of the object's display (can be NULL) */ -lv_theme_t * lv_theme_get_from_obj(lv_obj_t * obj); +lv_theme_t * lv_theme_get_from_obj(lv_obj_t * obj); /** * Apply the active theme on an object diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw.h rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw.h diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw.mk b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.mk similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw.mk rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw.mk diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_arc.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.c similarity index 91% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_arc.c rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.c index b3c975a1b..44084f4d1 100644 --- a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_arc.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.c @@ -16,7 +16,7 @@ /********************* * DEFINES *********************/ -#define SPLIT_RADIUS_LIMIT 10 /*With radius greater then this the arc will drawn in quarters. A quarter is drawn only if there is arc in it*/ +#define SPLIT_RADIUS_LIMIT 10 /*With radius greater than this the arc will drawn in quarters. A quarter is drawn only if there is arc in it*/ #define SPLIT_ANGLE_GAP_LIMIT 60 /*With small gaps in the arc don't bother with splitting because there is nothing to skip.*/ /********************** @@ -40,11 +40,11 @@ typedef struct { * STATIC PROTOTYPES **********************/ #if LV_DRAW_COMPLEX -static void draw_quarter_0(quarter_draw_dsc_t * q); -static void draw_quarter_1(quarter_draw_dsc_t * q); -static void draw_quarter_2(quarter_draw_dsc_t * q); -static void draw_quarter_3(quarter_draw_dsc_t * q); -static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t thickness, lv_area_t * res_area); + static void draw_quarter_0(quarter_draw_dsc_t * q); + static void draw_quarter_1(quarter_draw_dsc_t * q); + static void draw_quarter_2(quarter_draw_dsc_t * q); + static void draw_quarter_3(quarter_draw_dsc_t * q); + static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t thickness, lv_area_t * res_area); #endif /*LV_DRAW_COMPLEX*/ /********************** @@ -85,7 +85,8 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uin cir_dsc.bg_opa = LV_OPA_TRANSP; cir_dsc.bg_img_src = dsc->img_src; cir_dsc.bg_img_opa = dsc->opa; - } else { + } + else { cir_dsc.bg_opa = dsc->opa; cir_dsc.bg_color = dsc->color; } @@ -104,9 +105,12 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uin area_in.y2 -= dsc->width; /*Create inner the mask*/ + int16_t mask_in_id = LV_MASK_ID_INV; lv_draw_mask_radius_param_t mask_in_param; - lv_draw_mask_radius_init(&mask_in_param, &area_in, LV_RADIUS_CIRCLE, true); - int16_t mask_in_id = lv_draw_mask_add(&mask_in_param, NULL); + if(lv_area_get_width(&area_in) > 0 && lv_area_get_height(&area_in) > 0) { + lv_draw_mask_radius_init(&mask_in_param, &area_in, LV_RADIUS_CIRCLE, true); + mask_in_id = lv_draw_mask_add(&mask_in_param, NULL); + } lv_draw_mask_radius_param_t mask_out_param; lv_draw_mask_radius_init(&mask_out_param, &area_out, LV_RADIUS_CIRCLE, false); @@ -118,7 +122,7 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uin lv_draw_rect(&area_out, clip_area, &cir_dsc); lv_draw_mask_remove_id(mask_out_id); - lv_draw_mask_remove_id(mask_in_id); + if(mask_in_id != LV_MASK_ID_INV) lv_draw_mask_remove_id(mask_in_id); return; } @@ -159,9 +163,14 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uin else { lv_draw_rect(&area_out, clip_area, &cir_dsc); } + + lv_draw_mask_free_param(&mask_angle_param); + lv_draw_mask_free_param(&mask_out_param); + lv_draw_mask_free_param(&mask_in_param); + lv_draw_mask_remove_id(mask_angle_id); lv_draw_mask_remove_id(mask_out_id); - lv_draw_mask_remove_id(mask_in_id); + if(mask_in_id != LV_MASK_ID_INV) lv_draw_mask_remove_id(mask_in_id); if(dsc->rounded) { @@ -180,6 +189,7 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uin lv_draw_rect(&area_out, &clip_area2, &cir_dsc); lv_draw_mask_remove_id(mask_end_id); + lv_draw_mask_free_param(&mask_end_param); } get_rounded_area(end_angle, radius, width, &round_area); @@ -193,6 +203,7 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uin lv_draw_rect(&area_out, &clip_area2, &cir_dsc); lv_draw_mask_remove_id(mask_end_id); + lv_draw_mask_free_param(&mask_end_param); } } #else @@ -207,14 +218,31 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uin #endif /*LV_DRAW_COMPLEX*/ } -void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle, lv_coord_t w, bool rounded, lv_area_t * area) +void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle, + lv_coord_t w, bool rounded, lv_area_t * area) { lv_coord_t rout = radius; + + /*Special case: full arc invalidation */ + if(end_angle == start_angle + 360) { + area->x1 = x - rout; + area->y1 = y - rout; + area->x2 = x + rout; + area->y2 = y + rout; + return; + } + + if(start_angle > 360) start_angle -= 360; + if(end_angle > 360) end_angle -= 360; + lv_coord_t rin = radius - w; - lv_coord_t extra_area = rounded ? w : 0; + lv_coord_t extra_area = rounded ? w / 2 + 1 : 0; uint8_t start_quarter = start_angle / 90; uint8_t end_quarter = end_angle / 90; + /*360 deg still counts as quarter 3 (360 / 90 would be 4)*/ + if(start_quarter == 4) start_quarter = 3; + if(end_quarter == 4) end_quarter = 3; if(start_quarter == end_quarter && start_angle <= end_angle) { if(start_quarter == 0) { @@ -249,7 +277,7 @@ void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t else if(start_quarter == 0 && end_quarter == 1) { area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area; area->y1 = y + ((LV_MIN(lv_trigo_sin(end_angle), - lv_trigo_sin(start_angle)) * rin) >> LV_TRIGO_SHIFT) - extra_area; + lv_trigo_sin(start_angle)) * rin) >> LV_TRIGO_SHIFT) - extra_area; area->x2 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area; area->y2 = y + rout + extra_area; } @@ -257,7 +285,7 @@ void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t area->x1 = x - rout - extra_area; area->y1 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area; area->x2 = x + ((LV_MAX(lv_trigo_sin(start_angle + 90), - lv_trigo_sin(end_angle + 90)) * rin) >> LV_TRIGO_SHIFT) + extra_area; + lv_trigo_sin(end_angle + 90)) * rin) >> LV_TRIGO_SHIFT) + extra_area; area->y2 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area; } else if(start_quarter == 2 && end_quarter == 3) { @@ -265,11 +293,11 @@ void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t area->y1 = y - rout - extra_area; area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area; area->y2 = y + (LV_MAX(lv_trigo_sin(end_angle) * rin, - lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area; + lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area; } else if(start_quarter == 3 && end_quarter == 0) { area->x1 = x + ((LV_MIN(lv_trigo_sin(end_angle + 90), - lv_trigo_sin(start_angle + 90)) * rin) >> LV_TRIGO_SHIFT) - extra_area; + lv_trigo_sin(start_angle + 90)) * rin) >> LV_TRIGO_SHIFT) - extra_area; area->y1 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area; area->x2 = x + rout + extra_area; area->y2 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area; diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_arc.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.h similarity index 94% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_arc.h rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.h index ed8170936..8868b0fe9 100644 --- a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_arc.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.h @@ -62,7 +62,8 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uin * @param rounded true: the arc is rounded * @param area store the area to invalidate here */ -void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle, lv_coord_t w, bool rounded, lv_area_t * area); +void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle, + lv_coord_t w, bool rounded, lv_area_t * area); /********************** * MACROS diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_blend.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_blend.c similarity index 89% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_blend.c rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw_blend.c index 46ba49891..4d26160e3 100644 --- a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_blend.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_blend.c @@ -33,6 +33,7 @@ * STATIC PROTOTYPES **********************/ +#if LV_USE_EXTERNAL_RENDERER == 0 static void fill_set_px(const lv_area_t * disp_area, lv_color_t * disp_buf, const lv_area_t * draw_area, lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_draw_mask_res_t mask_res); @@ -64,7 +65,9 @@ static void map_blended(const lv_area_t * disp_area, lv_color_t * disp_buf, con static inline lv_color_t color_blend_true_color_additive(lv_color_t fg, lv_color_t bg, lv_opa_t opa); static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_color_t bg, lv_opa_t opa); +static inline lv_color_t color_blend_true_color_multiply(lv_color_t fg, lv_color_t bg, lv_opa_t opa); #endif +#endif //LV_USE_GPU_SDL_RENDER /********************** * STATIC VARIABLES @@ -73,22 +76,21 @@ static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_co /********************** * MACROS **********************/ +#if LV_COLOR_SCREEN_TRANSP == 0 +#define FILL_NORMAL_MASK_PX(color) \ + if(*mask == LV_OPA_COVER) *disp_buf_first = color; \ + else *disp_buf_first = lv_color_mix(color, *disp_buf_first, *mask); \ + mask++; \ + disp_buf_first++; -#define FILL_NORMAL_MASK_PX(out_x, color) \ - if(*mask_tmp_x) { \ - if(*mask_tmp_x == LV_OPA_COVER) disp_buf_first[out_x] = color; \ - else disp_buf_first[out_x] = lv_color_mix(color, disp_buf_first[out_x], *mask_tmp_x); \ - } \ - mask_tmp_x++; - -#define FILL_NORMAL_MASK_PX_SCR_TRANSP(out_x, color) \ - if(*mask_tmp_x) { \ - if(*mask_tmp_x == LV_OPA_COVER) disp_buf_first[out_x] = color; \ - else if(disp->driver->screen_transp) lv_color_mix_with_alpha(disp_buf_first[out_x], disp_buf_first[out_x].ch.alpha, \ - color, *mask_tmp_x, &disp_buf_first[out_x], &disp_buf_first[out_x].ch.alpha); \ - else disp_buf_first[out_x] = lv_color_mix(color, disp_buf_first[out_x], *mask_tmp_x); \ - } \ - mask_tmp_x++; +#else +#define FILL_NORMAL_MASK_PX(color) \ + if(*mask == LV_OPA_COVER) *disp_buf_first = color; \ + else if(disp->driver->screen_transp) lv_color_mix_with_alpha(*disp_buf_first, disp_buf_first->ch.alpha, color, *mask, disp_buf_first, &disp_buf_first->ch.alpha); \ + else *disp_buf_first = lv_color_mix(color, *disp_buf_first, *mask); \ + mask++; \ + disp_buf_first++; +#endif #define MAP_NORMAL_MASK_PX(x) \ if(*mask_tmp_x) { \ @@ -101,7 +103,7 @@ static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_co if(*mask_tmp_x) { \ if(*mask_tmp_x == LV_OPA_COVER) disp_buf_first[x] = map_buf_first[x]; \ else if(disp->driver->screen_transp) lv_color_mix_with_alpha(disp_buf_first[x], disp_buf_first[x].ch.alpha, \ - map_buf_first[x], *mask_tmp_x, &disp_buf_first[x], &disp_buf_first[x].ch.alpha); \ + map_buf_first[x], *mask_tmp_x, &disp_buf_first[x], &disp_buf_first[x].ch.alpha); \ else disp_buf_first[x] = lv_color_mix(map_buf_first[x], disp_buf_first[x], *mask_tmp_x); \ } \ mask_tmp_x++; @@ -110,6 +112,7 @@ static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_co * GLOBAL FUNCTIONS **********************/ +#if LV_USE_EXTERNAL_RENDERER == 0 /** * Fill and area in the display buffer. * @param clip_area clip the fill to this area (absolute coordinates) @@ -141,16 +144,11 @@ LV_ATTRIBUTE_FAST_MEM void _lv_blend_fill(const lv_area_t * clip_area, const lv_ /*Get clipped fill area which is the real draw area. *It is always the same or inside `fill_area`*/ lv_area_t draw_area; - bool is_common; - is_common = _lv_area_intersect(&draw_area, clip_area, fill_area); - if(!is_common) return; + if(!_lv_area_intersect(&draw_area, clip_area, fill_area)) return; /*Now `draw_area` has absolute coordinates. - *Make it relative to `disp_area` to simplify draw to `disp_buf`*/ - draw_area.x1 -= disp_area->x1; - draw_area.y1 -= disp_area->y1; - draw_area.x2 -= disp_area->x1; - draw_area.y2 -= disp_area->y1; + *Make it relative to `disp_area` to simplify the drawing to `disp_buf`*/ + lv_area_move(&draw_area, -disp_area->x1, -disp_area->y1); /*Round the values in the mask if anti-aliasing is disabled*/ if(mask && disp->driver->antialiasing == 0 && mask) { @@ -216,8 +214,7 @@ LV_ATTRIBUTE_FAST_MEM void _lv_blend_map(const lv_area_t * clip_area, const lv_a draw_area.y2 -= disp_area->y1; /*Round the values in the mask if anti-aliasing is disabled*/ - if(mask && disp->driver->antialiasing == 0) - { + if(mask && disp->driver->antialiasing == 0) { int32_t mask_w = lv_area_get_width(&draw_area); int32_t i; for(i = 0; i < mask_w; i++) mask[i] = mask[i] > 128 ? LV_OPA_COVER : LV_OPA_TRANSP; @@ -272,7 +269,7 @@ static void fill_set_px(const lv_area_t * disp_area, lv_color_t * disp_buf, con for(x = draw_area->x1; x <= draw_area->x2; x++) { if(mask_tmp[x]) { disp->driver->set_px_cb(disp->driver, (void *)disp_buf, disp_w, x, y, color, - (uint32_t)((uint32_t)opa * mask_tmp[x]) >> 8); + (uint32_t)((uint32_t)opa * mask_tmp[x]) >> 8); } } mask_tmp += draw_area_w; @@ -280,6 +277,7 @@ static void fill_set_px(const lv_area_t * disp_area, lv_color_t * disp_buf, con } } +#if LV_USE_EXTERNAL_RENDERER == 0 /** * Fill an area with a color * @param disp_area the current display area (destination area) @@ -326,7 +324,6 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co if(lv_gpu_nxp_vglite_fill(disp_buf, disp_w, lv_area_get_height(disp_area), draw_area, color, opa) == LV_RES_OK) { return; } - /*Fall down to SW render in case of error*/ } #elif LV_USE_GPU_STM32_DMA2D if(lv_area_get_size(draw_area) >= 240) { @@ -392,79 +389,71 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co } /*Masked*/ else { - /*Buffer the result color to avoid recalculating the same color*/ - lv_color_t last_dest_color; - lv_color_t last_res_color; - lv_opa_t last_mask = LV_OPA_TRANSP; - last_dest_color.full = disp_buf_first[0].full; - last_res_color.full = disp_buf_first[0].full; - int32_t x_end4 = draw_area_w - 4; +#if LV_COLOR_DEPTH == 16 + uint32_t c32 = color.full + ((uint32_t)color.full << 16); +#endif + /*Only the mask matters*/ if(opa > LV_OPA_MAX) { for(y = 0; y < draw_area_h; y++) { - const lv_opa_t * mask_tmp_x = mask; -#if 0 - for(x = 0; x < draw_area_w; x++) { -#if LV_COLOR_SCREEN_TRANSP - FILL_NORMAL_MASK_PX_SCR_TRANSP(x, color) -#else - FILL_NORMAL_MASK_PX(x, color) -#endif - } -#else - for(x = 0; x < draw_area_w && ((lv_uintptr_t)mask_tmp_x & 0x3); x++) { -#if LV_COLOR_SCREEN_TRANSP - FILL_NORMAL_MASK_PX_SCR_TRANSP(x, color) -#else - FILL_NORMAL_MASK_PX(x, color) -#endif + for(x = 0; x < draw_area_w && ((lv_uintptr_t)(mask) & 0x3); x++) { + FILL_NORMAL_MASK_PX(color) } - uint32_t * mask32 = (uint32_t *)mask_tmp_x; for(; x <= x_end4; x += 4) { - if(*mask32) { - if((*mask32) == 0xFFFFFFFF) { - disp_buf_first[x] = color; - disp_buf_first[x + 1] = color; - disp_buf_first[x + 2] = color; - disp_buf_first[x + 3] = color; + uint32_t mask32 = *((uint32_t *)mask); + if(mask32 == 0xFFFFFFFF) { +#if LV_COLOR_DEPTH == 16 + if((lv_uintptr_t)disp_buf_first & 0x3) { + *(disp_buf_first + 0) = color; + uint32_t * d = (uint32_t *)(disp_buf_first + 1); + *d = c32; + *(disp_buf_first + 3) = color; } else { - mask_tmp_x = (const lv_opa_t *)mask32; -#if LV_COLOR_SCREEN_TRANSP - FILL_NORMAL_MASK_PX_SCR_TRANSP(x, color) - FILL_NORMAL_MASK_PX_SCR_TRANSP(x + 1, color) - FILL_NORMAL_MASK_PX_SCR_TRANSP(x + 2, color) - FILL_NORMAL_MASK_PX_SCR_TRANSP(x + 3, color) -#else - FILL_NORMAL_MASK_PX(x, color) - FILL_NORMAL_MASK_PX(x + 1, color) - FILL_NORMAL_MASK_PX(x + 2, color) - FILL_NORMAL_MASK_PX(x + 3, color) -#endif + uint32_t * d = (uint32_t *)disp_buf_first; + *d = c32; + *(d + 1) = c32; } +#else + disp_buf_first[0] = color; + disp_buf_first[1] = color; + disp_buf_first[2] = color; + disp_buf_first[3] = color; +#endif + disp_buf_first += 4; + mask += 4; + } + else if(mask32) { + FILL_NORMAL_MASK_PX(color) + FILL_NORMAL_MASK_PX(color) + FILL_NORMAL_MASK_PX(color) + FILL_NORMAL_MASK_PX(color) + } + else { + mask += 4; + disp_buf_first += 4; } - mask32++; } - mask_tmp_x = (const lv_opa_t *)mask32; for(; x < draw_area_w ; x++) { -#if LV_COLOR_SCREEN_TRANSP - FILL_NORMAL_MASK_PX_SCR_TRANSP(x, color) -#else - FILL_NORMAL_MASK_PX(x, color) -#endif + FILL_NORMAL_MASK_PX(color) } -#endif - disp_buf_first += disp_w; - mask += draw_area_w; + disp_buf_first += (disp_w - draw_area_w); } } /*Handle opa and mask values too*/ else { + /*Buffer the result color to avoid recalculating the same color*/ + lv_color_t last_dest_color; + lv_color_t last_res_color; + lv_opa_t last_mask = LV_OPA_TRANSP; + last_dest_color.full = disp_buf_first[0].full; + last_res_color.full = disp_buf_first[0].full; lv_opa_t opa_tmp = LV_OPA_TRANSP; + for(y = draw_area->y1; y <= draw_area->y2; y++) { const lv_opa_t * mask_tmp_x = mask; for(x = 0; x < draw_area_w; x++) { @@ -530,6 +519,9 @@ static void fill_blended(const lv_area_t * disp_area, lv_color_t * disp_buf, co case LV_BLEND_MODE_SUBTRACTIVE: blend_fp = color_blend_true_color_subtractive; break; + case LV_BLEND_MODE_MULTIPLY: + blend_fp = color_blend_true_color_multiply; + break; default: LV_LOG_WARN("fill_blended: unsupported blend mode"); return; @@ -588,6 +580,7 @@ static void fill_blended(const lv_area_t * disp_area, lv_color_t * disp_buf, co } } #endif +#endif // LV_USE_GPU_SDL_RENDER static void map_set_px(const lv_area_t * disp_area, lv_color_t * disp_buf, const lv_area_t * draw_area, const lv_area_t * map_area, const lv_color_t * map_buf, lv_opa_t opa, @@ -631,7 +624,7 @@ static void map_set_px(const lv_area_t * disp_area, lv_color_t * disp_buf, cons for(x = draw_area->x1; x <= draw_area->x2; x++) { if(mask_tmp[x]) { disp->driver->set_px_cb(disp->driver, (void *)disp_buf, disp_w, x, y, map_buf_tmp[x], - (uint32_t)((uint32_t)opa * mask_tmp[x]) >> 8); + (uint32_t)((uint32_t)opa * mask_tmp[x]) >> 8); } } mask_tmp += draw_area_w; @@ -701,8 +694,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col blit.src_stride = lv_area_get_width(map_area) * sizeof(lv_color_t); blit.src_area.x1 = (draw_area->x1 - (map_area->x1 - disp_area->x1)); blit.src_area.y1 = (draw_area->y1 - (map_area->y1 - disp_area->y1)); - blit.src_area.x2 = blit.src_area.x1 + draw_area_w - 1; - blit.src_area.y2 = blit.src_area.y1 + draw_area_h - 1; + blit.src_area.x2 = blit.src_area.x1 + draw_area_w; + blit.src_area.y2 = blit.src_area.y1 + draw_area_h; blit.dst = disp_buf; blit.dst_width = lv_area_get_width(disp_area); @@ -710,8 +703,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col blit.dst_stride = lv_area_get_width(disp_area) * sizeof(lv_color_t); blit.dst_area.x1 = draw_area->x1; blit.dst_area.y1 = draw_area->y1; - blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w - 1; - blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h - 1; + blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w; + blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h; blit.opa = opa; @@ -751,8 +744,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col blit.src_stride = lv_area_get_width(map_area) * sizeof(lv_color_t); blit.src_area.x1 = (draw_area->x1 - (map_area->x1 - disp_area->x1)); blit.src_area.y1 = (draw_area->y1 - (map_area->y1 - disp_area->y1)); - blit.src_area.x2 = blit.src_area.x1 + draw_area_w - 1; - blit.src_area.y2 = blit.src_area.y1 + draw_area_h - 1; + blit.src_area.x2 = blit.src_area.x1 + draw_area_w; + blit.src_area.y2 = blit.src_area.y1 + draw_area_h; blit.dst = disp_buf; blit.dst_width = lv_area_get_width(disp_area); @@ -760,8 +753,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col blit.dst_stride = lv_area_get_width(disp_area) * sizeof(lv_color_t); blit.dst_area.x1 = draw_area->x1; blit.dst_area.y1 = draw_area->y1; - blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w - 1; - blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h - 1; + blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w; + blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h; blit.opa = opa; @@ -915,6 +908,9 @@ static void map_blended(const lv_area_t * disp_area, lv_color_t * disp_buf, con case LV_BLEND_MODE_SUBTRACTIVE: blend_fp = color_blend_true_color_subtractive; break; + case LV_BLEND_MODE_MULTIPLY: + blend_fp = color_blend_true_color_multiply; + break; default: LV_LOG_WARN("fill_blended: unsupported blend mode"); return; @@ -1015,7 +1011,6 @@ static inline lv_color_t color_blend_true_color_additive(lv_color_t fg, lv_color static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_color_t bg, lv_opa_t opa) { - if(opa <= LV_OPA_MIN) return bg; int32_t tmp; @@ -1039,4 +1034,30 @@ static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_co return lv_color_mix(fg, bg, opa); } + +static inline lv_color_t color_blend_true_color_multiply(lv_color_t fg, lv_color_t bg, lv_opa_t opa) +{ + if(opa <= LV_OPA_MIN) return bg; + +#if LV_COLOR_DEPTH == 32 + fg.ch.red = (fg.ch.red * bg.ch.red) >> 8; + fg.ch.green = (fg.ch.green * bg.ch.green) >> 8; + fg.ch.blue = (fg.ch.blue * bg.ch.blue) >> 8; +#elif LV_COLOR_DEPTH == 16 + fg.ch.red = (fg.ch.red * bg.ch.red) >> 5; + fg.ch.blue = (fg.ch.blue * bg.ch.blue) >> 5; + LV_COLOR_SET_G(fg, (LV_COLOR_GET_G(fg) * LV_COLOR_GET_G(bg)) >> 6); +#elif LV_COLOR_DEPTH == 8 + fg.ch.red = (fg.ch.red * bg.ch.red) >> 3; + fg.ch.green = (fg.ch.green * bg.ch.green) >> 3; + fg.ch.blue = (fg.ch.blue * bg.ch.blue) >> 2; #endif + + if(opa == LV_OPA_COVER) return fg; + + return lv_color_mix(fg, bg, opa); +} + +#endif + +#endif // LV_USE_GPU_SDL_RENDER diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_blend.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_blend.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_blend.h rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw_blend.h diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_img.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.c similarity index 93% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_img.c rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.c index ec5799e57..35ece92d1 100644 --- a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_img.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.c @@ -30,6 +30,7 @@ /********************** * STATIC PROTOTYPES **********************/ +#if LV_USE_EXTERNAL_RENDERER == 0 LV_ATTRIBUTE_FAST_MEM static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * clip_area, const void * src, const lv_draw_img_dsc_t * draw_dsc); @@ -41,6 +42,7 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const static void show_error(const lv_area_t * coords, const lv_area_t * clip_area, const char * msg); static void draw_cleanup(_lv_img_cache_entry_t * cache); +#endif /********************** * STATIC VARIABLES @@ -63,6 +65,7 @@ void lv_draw_img_dsc_init(lv_draw_img_dsc_t * dsc) dsc->antialias = LV_COLOR_DEPTH > 8 ? 1 : 0; } +#if LV_USE_EXTERNAL_RENDERER == 0 /** * Draw an image * @param coords the coordinates of the image @@ -89,6 +92,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * return; } } +#endif //LV_USE_GPU_SDL_RENDER /** * Get the pixel size of a color format in bits @@ -229,6 +233,7 @@ lv_img_src_t lv_img_src_get_type(const void * src) * STATIC FUNCTIONS **********************/ +#if LV_USE_EXTERNAL_RENDERER == 0 LV_ATTRIBUTE_FAST_MEM static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * clip_area, const void * src, const lv_draw_img_dsc_t * draw_dsc) @@ -289,7 +294,7 @@ LV_ATTRIBUTE_FAST_MEM static lv_res_t lv_img_draw_core(const lv_area_t * coords, int32_t width = lv_area_get_width(&mask_com); uint8_t * buf = lv_mem_buf_get(lv_area_get_width(&mask_com) * - LV_IMG_PX_SIZE_ALPHA_BYTE); /*+1 because of the possible alpha byte*/ + LV_IMG_PX_SIZE_ALPHA_BYTE); /*+1 because of the possible alpha byte*/ lv_area_t line; lv_area_copy(&line, &mask_com); @@ -326,11 +331,11 @@ LV_ATTRIBUTE_FAST_MEM static lv_res_t lv_img_draw_core(const lv_area_t * coords, /** * Draw a color map to the display (image) - * @param cords_p coordinates the color map - * @param mask_p the map will drawn only on this area (truncated to draw_buf area) + * @param map_area coordinates the color map + * @param clip_area the map will drawn only on this area (truncated to draw_buf area) * @param map_p pointer to a lv_color_t array * @param draw_dsc pointer to an initialized `lv_draw_img_dsc_t` variable - * @param chroma_keyed true: enable transparency of LV_IMG_LV_COLOR_TRANSP color pixels + * @param chroma_key true: enable transparency of LV_IMG_LV_COLOR_TRANSP color pixels * @param alpha_byte true: extra alpha byte is inserted for every pixel */ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, @@ -353,10 +358,10 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const draw_area.x2 -= disp_area->x1; draw_area.y2 -= disp_area->y1; - uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); + bool mask_any = lv_draw_mask_is_any(clip_area); /*The simplest case just copy the pixels into the draw_buf*/ - if(other_mask_cnt == 0 && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && + if(!mask_any && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && chroma_key == false && alpha_byte == false && draw_dsc->recolor_opa == LV_OPA_TRANSP) { _lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, draw_dsc->opa, draw_dsc->blend_mode); @@ -364,14 +369,14 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const #if LV_USE_GPU_NXP_PXP /*Simple case without masking and transformations*/ - else if(other_mask_cnt == 0 && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && alpha_byte == false && + else if(!mask_any && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && alpha_byte == false && chroma_key == true && draw_dsc->recolor_opa == LV_OPA_TRANSP) { /*copy with color keying (+ alpha)*/ lv_gpu_nxp_pxp_enable_color_key(); _lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, draw_dsc->opa, draw_dsc->blend_mode); lv_gpu_nxp_pxp_disable_color_key(); } - else if(other_mask_cnt == 0 && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && alpha_byte == false && + else if(!mask_any && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && alpha_byte == false && chroma_key == false && draw_dsc->recolor_opa != LV_OPA_TRANSP) { /*copy with recolor (+ alpha)*/ lv_gpu_nxp_pxp_enable_recolor(draw_dsc->recolor, draw_dsc->recolor_opa); _lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, draw_dsc->opa, @@ -381,7 +386,7 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const #endif /*In the other cases every pixel need to be checked one-by-one*/ else { -//#if LV_DRAW_COMPLEX + //#if LV_DRAW_COMPLEX /*The pixel size in byte is different if an alpha byte is added too*/ uint8_t px_size_byte = alpha_byte ? LV_IMG_PX_SIZE_ALPHA_BYTE : sizeof(lv_color_t); @@ -397,18 +402,18 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const const uint8_t * map_px; - lv_area_t blend_area; - blend_area.x1 = draw_area.x1 + disp_area->x1; - blend_area.x2 = blend_area.x1 + lv_area_get_width(&draw_area) - 1; - blend_area.y1 = disp_area->y1 + draw_area.y1; - blend_area.y2 = blend_area.y1; - lv_coord_t draw_area_h = lv_area_get_height(&draw_area); lv_coord_t draw_area_w = lv_area_get_width(&draw_area); + lv_area_t blend_area; + blend_area.x1 = draw_area.x1 + disp_area->x1; + blend_area.x2 = blend_area.x1 + draw_area_w - 1; + blend_area.y1 = disp_area->y1 + draw_area.y1; + blend_area.y2 = blend_area.y1; + bool transform = draw_dsc->angle != 0 || draw_dsc->zoom != LV_IMG_ZOOM_NONE ? true : false; /*Simple ARGB image. Handle it as special case because it's very common*/ - if(other_mask_cnt == 0 && !transform && !chroma_key && draw_dsc->recolor_opa == LV_OPA_TRANSP && alpha_byte) { + if(!mask_any && !transform && !chroma_key && draw_dsc->recolor_opa == LV_OPA_TRANSP && alpha_byte) { #if LV_USE_GPU_STM32_DMA2D && LV_COLOR_DEPTH == 32 /*Blend ARGB images directly*/ if(lv_area_get_size(&draw_area) > 240) { @@ -447,7 +452,7 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const } map_buf_tmp += map_w * px_size_byte; - if(px_i + lv_area_get_width(&draw_area) < mask_buf_size) { + if(px_i + draw_area_w < mask_buf_size) { blend_area.y2 ++; } else { @@ -509,7 +514,7 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; /*Prepare the `mask_buf`if there are other masks*/ - if(other_mask_cnt) { + if(mask_any) { lv_memset_ff(mask_buf, mask_buf_size); } @@ -589,12 +594,13 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const } #if LV_DRAW_COMPLEX /*Apply the masks if any*/ - if(other_mask_cnt) { + if(mask_any) { lv_draw_mask_res_t mask_res_sub; - mask_res_sub = lv_draw_mask_apply(mask_buf + px_i_start, draw_area.x1 + draw_buf->area.x1, y + draw_area.y1 + draw_buf->area.y1, - lv_area_get_width(&draw_area)); + mask_res_sub = lv_draw_mask_apply(mask_buf + px_i_start, draw_area.x1 + draw_buf->area.x1, + y + draw_area.y1 + draw_buf->area.y1, + draw_area_w); if(mask_res_sub == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(mask_buf + px_i_start, lv_area_get_width(&draw_area)); + lv_memset_00(mask_buf + px_i_start, draw_area_w); mask_res = LV_DRAW_MASK_RES_CHANGED; } else if(mask_res_sub == LV_DRAW_MASK_RES_CHANGED) { @@ -604,7 +610,7 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const #endif map_buf_tmp += map_w * px_size_byte; - if(px_i + lv_area_get_width(&draw_area) < mask_buf_size) { + if(px_i + draw_area_w < mask_buf_size) { blend_area.y2 ++; } else { @@ -619,7 +625,7 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; /*Prepare the `mask_buf`if there are other masks*/ - if(other_mask_cnt) { + if(mask_any) { lv_memset_ff(mask_buf, mask_buf_size); } } @@ -658,3 +664,5 @@ static void draw_cleanup(_lv_img_cache_entry_t * cache) LV_UNUSED(cache); #endif } + +#endif //LV_USE_GPU_SDL_RENDER \ No newline at end of file diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_img.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_img.h rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.h diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_label.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.c similarity index 95% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_label.c rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.c index 1c686e1e3..3ae4f0e5b 100644 --- a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_label.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.c @@ -13,6 +13,9 @@ #include "../misc/lv_bidi.h" #include "../misc/lv_assert.h" +#if LV_USE_GPU_SDL + #include "../gpu/lv_gpu_sdl.h" +#endif /********************* * DEFINES *********************/ @@ -32,13 +35,18 @@ typedef uint8_t cmd_state_t; /********************** * STATIC PROTOTYPES **********************/ + +#if LV_USE_EXTERNAL_RENDERER == 0 LV_ATTRIBUTE_FAST_MEM static void draw_letter_normal(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_dsc_t * g, const lv_area_t * clip_area, const uint8_t * map_p, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode); + #if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX static void draw_letter_subpx(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_dsc_t * g, const lv_area_t * clip_area, const uint8_t * map_p, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode); -#endif +#endif /*LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX*/ +#endif /*LV_USE_EXTERNAL_RENDERER*/ + static uint8_t hex_char_to_num(char hex); /********************** @@ -121,13 +129,18 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area int32_t w; /*No need to waste processor time if string is empty*/ - if (txt == NULL || txt[0] == '\0') + if(txt == NULL || txt[0] == '\0') return; lv_area_t clipped_area; bool clip_ok = _lv_area_intersect(&clipped_area, coords, mask); if(!clip_ok) return; + lv_text_align_t align = dsc->align; + lv_base_dir_t base_dir = dsc->bidi_dir; + + lv_bidi_calculate_align(&align, &base_dir, txt); + if((dsc->flag & LV_TEXT_FLAG_EXPAND) == 0) { /*Normally use the label's width as width*/ w = lv_area_get_width(coords); @@ -136,7 +149,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area /*If EXAPND is enabled then not limit the text's width to the object's width*/ lv_point_t p; lv_txt_get_size(&p, txt, dsc->font, dsc->letter_space, dsc->line_space, LV_COORD_MAX, - dsc->flag); + dsc->flag); w = p.x; } @@ -193,14 +206,14 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area } /*Align to middle*/ - if(dsc->align == LV_TEXT_ALIGN_CENTER) { + if(align == LV_TEXT_ALIGN_CENTER) { line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag); pos.x += (lv_area_get_width(coords) - line_width) / 2; } /*Align to the right*/ - else if(dsc->align == LV_TEXT_ALIGN_RIGHT) { + else if(align == LV_TEXT_ALIGN_RIGHT) { line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag); pos.x += lv_area_get_width(coords) - line_width; } @@ -244,7 +257,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area i = 0; #if LV_USE_BIDI char * bidi_txt = lv_mem_buf_get(line_end - line_start + 1); - _lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, dsc->bidi_dir, NULL, 0); + _lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, base_dir, NULL, 0); #else const char * bidi_txt = txt + line_start; #endif @@ -255,7 +268,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area #if LV_USE_BIDI logical_char_pos = _lv_txt_encoded_get_char_id(txt, line_start); uint32_t t = _lv_txt_encoded_get_char_id(bidi_txt, i); - logical_char_pos += _lv_bidi_get_logical_pos(bidi_txt, NULL, line_end - line_start, dsc->bidi_dir, t, NULL); + logical_char_pos += _lv_bidi_get_logical_pos(bidi_txt, NULL, line_end - line_start, base_dir, t, NULL); #else logical_char_pos = _lv_txt_encoded_get_char_id(txt, line_start + i); #endif @@ -359,7 +372,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area pos.x = coords->x1; /*Align to middle*/ - if(dsc->align == LV_TEXT_ALIGN_CENTER) { + if(align == LV_TEXT_ALIGN_CENTER) { line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag); @@ -367,7 +380,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area } /*Align to the right*/ - else if(dsc->align == LV_TEXT_ALIGN_RIGHT) { + else if(align == LV_TEXT_ALIGN_RIGHT) { line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag); pos.x += lv_area_get_width(coords) - line_width; @@ -382,6 +395,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area LV_ASSERT_MEM_INTEGRITY(); } +#if LV_USE_EXTERNAL_RENDERER == 0 /********************** * STATIC FUNCTIONS **********************/ @@ -414,9 +428,9 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_letter(const lv_point_t * pos_p, const lv_are /*Add warning if the dsc is not found *but do not print warning for non printable ASCII chars (e.g. '\n')*/ if(letter >= 0x20 && - letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/ - letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/ - LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%X", letter); + letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/ + letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/ + LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%X", (unsigned int)letter); } return; } @@ -443,11 +457,12 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_letter(const lv_point_t * pos_p, const lv_are if(font_p->subpx) { #if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX - draw_letter_subpx(pos_x, pos_y, &g, clip_area, map_p, color, opa, blend_mode); + draw_letter_subpx(pos_x, pos_y, &g, clip_area, map_p, color, opa, blend_mode); #else - LV_LOG_WARN("Can't draw sub-pixel rendered letter because LV_USE_FONT_SUBPX == 0 in lv_conf.h"); + LV_LOG_WARN("Can't draw sub-pixel rendered letter because LV_USE_FONT_SUBPX == 0 in lv_conf.h"); #endif - } else { + } + else { draw_letter_normal(pos_x, pos_y, &g, clip_area, map_p, color, opa, blend_mode); } } @@ -534,7 +549,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_letter_normal(lv_coord_t pos_x, lv_coord_ fill_area.y1 = row_start + pos_y; fill_area.y2 = fill_area.y1; #if LV_DRAW_COMPLEX - uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); + bool mask_any = lv_draw_mask_is_any(&fill_area); #endif uint32_t col_bit_max = 8 - bpp; @@ -572,7 +587,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_letter_normal(lv_coord_t pos_x, lv_coord_ #if LV_DRAW_COMPLEX /*Apply masks if any*/ - if(other_mask_cnt) { + if(mask_any) { lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, fill_area.x1, fill_area.y2, lv_area_get_width(&fill_area)); if(mask_res == LV_DRAW_MASK_RES_TRANSP) { @@ -690,8 +705,7 @@ static void draw_letter_subpx(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_ /*If the letter is partially out of mask the move there on draw_buf*/ disp_buf_buf_tmp += (row_start * disp_buf_width) + col_start / 3; - uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); - + bool mask_any = lv_draw_mask_is_any(&map_area); uint8_t font_rgb[3]; #if LV_COLOR_16_SWAP == 0 @@ -779,7 +793,7 @@ static void draw_letter_subpx(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_ } /*Apply masks if any*/ - if(other_mask_cnt) { + if(mask_any) { lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, map_area.x1, map_area.y2, lv_area_get_width(&map_area)); if(mask_res == LV_DRAW_MASK_RES_TRANSP) { @@ -816,8 +830,9 @@ static void draw_letter_subpx(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_ lv_mem_buf_release(mask_buf); lv_mem_buf_release(color_buf); } -#endif +#endif /*LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX*/ +#endif /*LV_USE_EXTERNAL_RENDERER*/ /** * Convert a hexadecimal characters to a number (0..15) * @param hex Pointer to a hexadecimal character (0..9, A..F) @@ -860,3 +875,4 @@ static uint8_t hex_char_to_num(char hex) return result; } + diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_label.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.h similarity index 99% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_label.h rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.h index fb71210d5..f4cc1fb88 100644 --- a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_label.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.h @@ -40,8 +40,8 @@ typedef struct { lv_coord_t ofs_y; lv_opa_t opa; lv_base_dir_t bidi_dir; + lv_text_align_t align; lv_text_flag_t flag; - lv_text_align_t align :2; lv_text_decor_t decor : 3; lv_blend_mode_t blend_mode: 3; } lv_draw_label_dsc_t; diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_line.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_line.c similarity index 96% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_line.c rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw_line.c index ae0501544..407a280a7 100644 --- a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_line.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_line.c @@ -34,7 +34,6 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_hor(const lv_point_t * point1, const LV_ATTRIBUTE_FAST_MEM static void draw_line_ver(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, const lv_draw_line_dsc_t * dsc); - /********************** * STATIC VARIABLES **********************/ @@ -117,6 +116,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_line(const lv_point_t * point1, const lv_poin * STATIC FUNCTIONS **********************/ + LV_ATTRIBUTE_FAST_MEM static void draw_line_hor(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, const lv_draw_line_dsc_t * dsc) @@ -127,11 +127,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_hor(const lv_point_t * point1, const int32_t w_half0 = w >> 1; int32_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/ - bool dashed = dsc->dash_gap && dsc->dash_width ? true : false; - bool simple_mode = true; - if(lv_draw_mask_get_cnt()) simple_mode = false; - else if(dashed) simple_mode = false; lv_area_t draw_area; draw_area.x1 = LV_MIN(point1->x, point2->x); @@ -139,6 +135,11 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_hor(const lv_point_t * point1, const draw_area.y1 = point1->y - w_half1; draw_area.y2 = point1->y + w_half0; + bool dashed = dsc->dash_gap && dsc->dash_width ? true : false; + bool simple_mode = true; + if(lv_draw_mask_is_any(&draw_area)) simple_mode = false; + else if(dashed) simple_mode = false; + /*If there is no mask then simply draw a rectangle*/ if(simple_mode) { _lv_blend_fill(clip, &draw_area, @@ -181,7 +182,8 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_hor(const lv_point_t * point1, const int32_t h; for(h = draw_area.y1; h <= draw_area.y2; h++) { lv_memset_ff(mask_buf, draw_area_w); - lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf, draw_buf->area.x1 + draw_area.x1, draw_buf->area.y1 + h, draw_area_w); + lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf, draw_buf->area.x1 + draw_area.x1, draw_buf->area.y1 + h, + draw_area_w); if(dashed) { if(mask_res != LV_DRAW_MASK_RES_TRANSP) { @@ -227,18 +229,17 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_ver(const lv_point_t * point1, const int32_t w_half0 = w >> 1; int32_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/ - bool dashed = dsc->dash_gap && dsc->dash_width ? true : false; - - bool simple_mode = true; - if(lv_draw_mask_get_cnt()) simple_mode = false; - else if(dashed) simple_mode = false; - lv_area_t draw_area; draw_area.x1 = point1->x - w_half1; draw_area.x2 = point1->x + w_half0; draw_area.y1 = LV_MIN(point1->y, point2->y); draw_area.y2 = LV_MAX(point1->y, point2->y) - 1; + bool dashed = dsc->dash_gap && dsc->dash_width ? true : false; + bool simple_mode = true; + if(lv_draw_mask_is_any(&draw_area)) simple_mode = false; + else if(dashed) simple_mode = false; + /*If there is no mask then simply draw a rectangle*/ if(simple_mode) { _lv_blend_fill(clip, &draw_area, @@ -285,7 +286,8 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_ver(const lv_point_t * point1, const int32_t h; for(h = draw_area.y1; h <= draw_area.y2; h++) { lv_memset_ff(mask_buf, draw_area_w); - lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf, draw_buf->area.x1 + draw_area.x1, draw_buf->area.y1 + h, draw_area_w); + lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf, draw_buf->area.x1 + draw_area.x1, draw_buf->area.y1 + h, + draw_area_w); if(dashed) { if(mask_res != LV_DRAW_MASK_RES_TRANSP) { @@ -474,6 +476,10 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_skew(const lv_point_t * point1, cons lv_mem_buf_release(mask_buf); + lv_draw_mask_free_param(&mask_left_param); + lv_draw_mask_free_param(&mask_right_param); + if(mask_top_id != LV_MASK_ID_INV) lv_draw_mask_free_param(&mask_top_param); + if(mask_bottom_id != LV_MASK_ID_INV) lv_draw_mask_free_param(&mask_bottom_param); lv_draw_mask_remove_id(mask_left_id); lv_draw_mask_remove_id(mask_right_id); lv_draw_mask_remove_id(mask_top_id); diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_line.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_line.h similarity index 96% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_line.h rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw_line.h index 660c765a6..111bced52 100644 --- a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_line.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_line.h @@ -31,7 +31,7 @@ typedef struct { lv_blend_mode_t blend_mode : 2; uint8_t round_start : 1; uint8_t round_end : 1; - uint8_t raw_end : 1; /*Do not bother with perpendicular line ending is it's not visible for any reason*/ + uint8_t raw_end : 1; /*Do not bother with perpendicular line ending if it's not visible for any reason*/ } lv_draw_line_dsc_t; /********************** diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_mask.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.c similarity index 72% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_mask.c rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.c index 2d8c862fe..0197f22d1 100644 --- a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_mask.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.c @@ -6,8 +6,6 @@ /********************* * INCLUDES *********************/ - - #include "lv_draw_mask.h" #if LV_DRAW_COMPLEX #include "../misc/lv_math.h" @@ -18,6 +16,8 @@ /********************* * DEFINES *********************/ +#define CIRCLE_CACHE_LIFE_MAX 1000 +#define CIRCLE_CACHE_AGING(life, r) life = LV_MIN(life + (r < 16 ? 1 : (r >> 4)), 1000) /********************** * TYPEDEFS @@ -49,8 +49,13 @@ LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_ lv_coord_t len, lv_draw_mask_line_param_t * p); +static void circ_init(lv_point_t * c, lv_coord_t * tmp, lv_coord_t radius); +static bool circ_cont(lv_point_t * c); +static void circ_next(lv_point_t * c, lv_coord_t * tmp); +static void circ_calc_aa4(_lv_draw_mask_radius_circle_dsc_t * c, lv_coord_t radius); +static lv_opa_t * get_next_line(_lv_draw_mask_radius_circle_dsc_t * c, lv_coord_t y, lv_coord_t * len, + lv_coord_t * x_start); LV_ATTRIBUTE_FAST_MEM static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new); -LV_ATTRIBUTE_FAST_MEM static inline void sqrt_approx(lv_sqrt_res_t * q, lv_sqrt_res_t * ref, uint32_t x); /********************** * STATIC VARIABLES @@ -121,6 +126,39 @@ LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, return changed ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; } +/** + * Apply the specified buffers on a line. Used internally by the library's drawing routines. + * @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`. + * @param abs_x absolute X coordinate where the line to calculate start + * @param abs_y absolute Y coordinate where the line to calculate start + * @param len length of the line to calculate (in pixel count) + * @param ids ID array of added buffers + * @param ids_count number of ID array + * @return One of these values: + * - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero + * - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged + * - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line + */ +LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply_ids(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, + lv_coord_t len, const int16_t *ids, int16_t ids_count) +{ + bool changed = false; + _lv_draw_mask_common_dsc_t * dsc; + + for (int i = 0; i < ids_count; i++) { + int16_t id = ids[i]; + if (id == LV_MASK_ID_INV) continue; + dsc = LV_GC_ROOT(_lv_draw_mask_list[id]).param; + if (!dsc) continue; + lv_draw_mask_res_t res = LV_DRAW_MASK_RES_FULL_COVER; + res = dsc->cb(mask_buf, abs_x, abs_y, len, dsc); + if(res == LV_DRAW_MASK_RES_TRANSP) return LV_DRAW_MASK_RES_TRANSP; + else if(res == LV_DRAW_MASK_RES_CHANGED) changed = true; + } + + return changed ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; +} + /** * Remove a mask with a given ID * @param id the ID of the mask. Returned by `lv_draw_mask_add` @@ -129,7 +167,7 @@ LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, */ void * lv_draw_mask_remove_id(int16_t id) { - void * p = NULL; + _lv_draw_mask_common_dsc_t * p = NULL; if(id != LV_MASK_ID_INV) { p = LV_GC_ROOT(_lv_draw_mask_list[id]).param; @@ -148,18 +186,52 @@ void * lv_draw_mask_remove_id(int16_t id) */ void * lv_draw_mask_remove_custom(void * custom_id) { - void * p = NULL; + _lv_draw_mask_common_dsc_t * p = NULL; uint8_t i; for(i = 0; i < _LV_MASK_MAX_NUM; i++) { if(LV_GC_ROOT(_lv_draw_mask_list[i]).custom_id == custom_id) { p = LV_GC_ROOT(_lv_draw_mask_list[i]).param; - LV_GC_ROOT(_lv_draw_mask_list[i]).param = NULL; - LV_GC_ROOT(_lv_draw_mask_list[i]).custom_id = NULL; + lv_draw_mask_remove_id(i); } } return p; } +/** + * Free the data from the parameter. + * It's called inside `lv_draw_mask_remove_id` and `lv_draw_mask_remove_custom` + * Needs to be called only in special cases when the mask is not added by `lv_draw_mask_add` + * and not removed by `lv_draw_mask_remove_id` or `lv_draw_mask_remove_custom` + * @param p pointer to a mask parameter + */ +void lv_draw_mask_free_param(void * p) +{ + _lv_draw_mask_common_dsc_t * pdsc = p; + if(pdsc->type == LV_DRAW_MASK_TYPE_RADIUS) { + lv_draw_mask_radius_param_t * radius_p = (lv_draw_mask_radius_param_t *) p; + if(radius_p->circle) { + if(radius_p->circle->life < 0) { + lv_mem_free(radius_p->circle->cir_opa); + lv_mem_free(radius_p->circle); + } + else { + radius_p->circle->used_cnt--; + } + } + } +} + +void _lv_draw_mask_cleanup(void) +{ + uint8_t i; + for(i = 0; i < LV_CIRCLE_CACHE_SIZE; i++) { + if(LV_GC_ROOT(_lv_circle_cache[i]).buf) { + lv_mem_free(LV_GC_ROOT(_lv_circle_cache[i]).buf); + } + lv_memset_00(&LV_GC_ROOT(_lv_circle_cache[i]), sizeof(LV_GC_ROOT(_lv_circle_cache[i]))); + } +} + /** * Count the currently added masks * @return number of active masks @@ -174,6 +246,32 @@ LV_ATTRIBUTE_FAST_MEM uint8_t lv_draw_mask_get_cnt(void) return cnt; } +bool lv_draw_mask_is_any(const lv_area_t * a) +{ + if(a == NULL) return LV_GC_ROOT(_lv_draw_mask_list[0]).param ? true : false; + + uint8_t i; + for(i = 0; i < _LV_MASK_MAX_NUM; i++) { + _lv_draw_mask_common_dsc_t * comm_param = LV_GC_ROOT(_lv_draw_mask_list[i]).param; + if(comm_param == NULL) continue; + if(comm_param->type == LV_DRAW_MASK_TYPE_RADIUS) { + lv_draw_mask_radius_param_t * radius_param = LV_GC_ROOT(_lv_draw_mask_list[i]).param; + if(radius_param->cfg.outer) { + if(!_lv_area_is_out(a, &radius_param->cfg.rect, radius_param->cfg.radius)) return true; + } + else { + if(!_lv_area_is_in(a, &radius_param->cfg.rect, radius_param->cfg.radius)) return true; + } + } + else { + return true; + } + } + + return false; + +} + /** *Initialize a line mask from two points. * @param param pointer to a `lv_draw_mask_param_t` to initialize @@ -228,12 +326,12 @@ void lv_draw_mask_line_points_init(lv_draw_mask_line_param_t * param, lv_coord_t int32_t m; if(dx) { - m = (1 << 20) / dx; /*m is multiplier to normalize y (upscaled by 1024)*/ + m = (1L << 20) / dx; /*m is multiplier to normalize y (upscaled by 1024)*/ param->yx_steep = (m * dy) >> 10; } if(dy) { - m = (1 << 20) / dy; /*m is multiplier to normalize x (upscaled by 1024)*/ + m = (1L << 20) / dy; /*m is multiplier to normalize x (upscaled by 1024)*/ param->xy_steep = (m * dx) >> 10; } param->steep = param->yx_steep; @@ -243,12 +341,12 @@ void lv_draw_mask_line_points_init(lv_draw_mask_line_param_t * param, lv_coord_t int32_t m; if(dy) { - m = (1 << 20) / dy; /*m is multiplier to normalize x (upscaled by 1024)*/ + m = (1L << 20) / dy; /*m is multiplier to normalize x (upscaled by 1024)*/ param->xy_steep = (m * dx) >> 10; } if(dx) { - m = (1 << 20) / dx; /*m is multiplier to normalize x (upscaled by 1024)*/ + m = (1L << 20) / dx; /*m is multiplier to normalize x (upscaled by 1024)*/ param->yx_steep = (m * dy) >> 10; } param->steep = param->xy_steep; @@ -373,6 +471,7 @@ void lv_draw_mask_radius_init(lv_draw_mask_radius_param_t * param, const lv_area { lv_coord_t w = lv_area_get_width(rect); lv_coord_t h = lv_area_get_height(rect); + if(radius < 0) radius = 0; int32_t short_side = LV_MIN(w, h); if(radius > short_side >> 1) radius = short_side >> 1; @@ -381,9 +480,48 @@ void lv_draw_mask_radius_init(lv_draw_mask_radius_param_t * param, const lv_area param->cfg.outer = inv ? 1 : 0; param->dsc.cb = (lv_draw_mask_xcb_t)lv_draw_mask_radius; param->dsc.type = LV_DRAW_MASK_TYPE_RADIUS; - param->y_prev = INT32_MIN; - param->y_prev_x.f = 0; - param->y_prev_x.i = 0; + + if(radius == 0) { + param->circle = NULL; + return; + } + + uint32_t i; + + /*Try to reuse a circle cache entry*/ + for(i = 0; i < LV_CIRCLE_CACHE_SIZE; i++) { + if(LV_GC_ROOT(_lv_circle_cache[i]).radius == radius) { + LV_GC_ROOT(_lv_circle_cache[i]).used_cnt++; + CIRCLE_CACHE_AGING(LV_GC_ROOT(_lv_circle_cache[i]).life, radius); + param->circle = &LV_GC_ROOT(_lv_circle_cache[i]); + return; + } + } + + /*If not found find a free entry with lowest life*/ + _lv_draw_mask_radius_circle_dsc_t * entry = NULL; + for(i = 0; i < LV_CIRCLE_CACHE_SIZE; i++) { + if(LV_GC_ROOT(_lv_circle_cache[i]).used_cnt == 0) { + if(!entry) entry = &LV_GC_ROOT(_lv_circle_cache[i]); + else if(LV_GC_ROOT(_lv_circle_cache[i]).life < entry->life) entry = &LV_GC_ROOT(_lv_circle_cache[i]); + } + } + + if(!entry) { + entry = lv_mem_alloc(sizeof(_lv_draw_mask_radius_circle_dsc_t)); + LV_ASSERT_MALLOC(entry); + lv_memset_00(entry, sizeof(_lv_draw_mask_radius_circle_dsc_t)); + entry->life = -1; + } + else { + entry->used_cnt++; + entry->life = 0; + CIRCLE_CACHE_AGING(entry->life, radius); + } + + param->circle = entry; + + circ_calc_aa4(param->circle, radius); } /** @@ -515,7 +653,7 @@ LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t line_mask_flat(lv_opa_t * mask_b } } - /*At the end of the mask if the limit line is smaller then the mask's y. + /*At the end of the mask if the limit line is smaller than the mask's y. *Then the mask is in the "good" area*/ y_at_x = (int32_t)((int32_t)p->yx_steep * (abs_x + len)) >> 10; if(p->yx_steep > 0) { @@ -608,7 +746,7 @@ LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_ { int32_t k; int32_t x_at_y; - /*At the beginning of the mask if the limit line is greater then the mask's y. + /*At the beginning of the mask if the limit line is greater than the mask's y. *Then the mask is in the "wrong" area*/ x_at_y = (int32_t)((int32_t)p->xy_steep * abs_y) >> 10; if(p->xy_steep > 0) x_at_y++; @@ -621,7 +759,7 @@ LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_ } } - /*At the end of the mask if the limit line is smaller then the mask's y. + /*At the end of the mask if the limit line is smaller than the mask's y. *Then the mask is in the "good" area*/ x_at_y = (int32_t)((int32_t)p->xy_steep * (abs_y)) >> 10; if(x_at_y > abs_x + len) { @@ -881,6 +1019,8 @@ LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * ma } } + + LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_radius_param_t * p) @@ -891,7 +1031,7 @@ LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * m lv_area_copy(&rect, &p->cfg.rect); if(outer == false) { - if(abs_y < rect.y1 || abs_y > rect.y2) { + if((abs_y < rect.y1 || abs_y > rect.y2)) { return LV_DRAW_MASK_RES_TRANSP; } } @@ -932,6 +1072,13 @@ LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * m } return LV_DRAW_MASK_RES_CHANGED; } + // printf("exec: x:%d.. %d, y:%d: r:%d, %s\n", abs_x, abs_x + len - 1, abs_y, p->cfg.radius, p->cfg.outer ? "inv" : "norm"); + + + // if( abs_x == 276 && abs_x + len - 1 == 479 && abs_y == 63 && p->cfg.radius == 5 && p->cfg.outer == 1) { + // char x = 0; + // } + //exec: x:276.. 479, y:63: r:5, inv) int32_t k = rect.x1 - abs_x; /*First relevant coordinate on the of the mask*/ int32_t w = lv_area_get_width(&rect); @@ -939,194 +1086,53 @@ LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * m abs_x -= rect.x1; abs_y -= rect.y1; - uint32_t r2 = p->cfg.radius * p->cfg.radius; + lv_coord_t aa_len; + lv_coord_t x_start; + lv_coord_t cir_y; + if(abs_y < radius) { + cir_y = radius - abs_y - 1; + } + else { + cir_y = abs_y - (h - radius); + } + lv_opa_t * aa_opa = get_next_line(p->circle, cir_y, &aa_len, &x_start); + lv_coord_t cir_x_right = k + w - radius + x_start; + lv_coord_t cir_x_left = k + radius - x_start - 1; + lv_coord_t i; - /*Handle corner areas*/ - if(abs_y < radius || abs_y > h - radius - 1) { - - uint32_t sqrt_mask; - if(radius <= 32) sqrt_mask = 0x200; - if(radius <= 256) sqrt_mask = 0x800; - else sqrt_mask = 0x8000; - - lv_sqrt_res_t x0; - lv_sqrt_res_t x1; - /*y = 0 should mean the top of the circle*/ - int32_t y; - if(abs_y < radius) { - y = radius - abs_y; - - /*Get the x intersection points for `abs_y` and `abs_y-1` - *Use the circle's equation x = sqrt(r^2 - y^2) - *Try to use the values from the previous run*/ - if(y == p->y_prev) { - x0.f = p->y_prev_x.f; - x0.i = p->y_prev_x.i; + if(outer == false) { + for(i = 0; i < aa_len; i++) { + lv_opa_t opa = aa_opa[aa_len - i - 1]; + if(cir_x_right + i >= 0 && cir_x_right + i < len) { + mask_buf[cir_x_right + i] = mask_mix(opa, mask_buf[cir_x_right + i]); } - else { - lv_sqrt(r2 - (y * y), &x0, sqrt_mask); - } - lv_sqrt(r2 - ((y - 1) * (y - 1)), &x1, sqrt_mask); - p->y_prev = y - 1; - p->y_prev_x.f = x1.f; - p->y_prev_x.i = x1.i; - } - else { - y = radius - (h - abs_y) + 1; - - /*Get the x intersection points for `abs_y` and `abs_y-1` - *Use the circle's equation x = sqrt(r^2 - y^2) - *Try to use the values from the previous run*/ - if((y - 1) == p->y_prev) { - x1.f = p->y_prev_x.f; - x1.i = p->y_prev_x.i; - } - else { - lv_sqrt(r2 - ((y - 1) * (y - 1)), &x1, sqrt_mask); - } - - lv_sqrt(r2 - (y * y), &x0, sqrt_mask); - p->y_prev = y; - p->y_prev_x.f = x0.f; - p->y_prev_x.i = x0.i; - } - - /*If x1 is on the next round coordinate (e.g. x0: 3.5, x1:4.0) - *then treat x1 as x1: 3.99 to handle them as they were on the same pixel*/ - if(x0.i == x1.i - 1 && x1.f == 0) { - x1.i--; - x1.f = 0xFF; - } - - /*If the two x intersections are on the same x then just get average of the fractions*/ - if(x0.i == x1.i) { - lv_opa_t m = (x0.f + x1.f) >> 1; - if(outer) m = 255 - m; - int32_t ofs = radius - x0.i - 1; - - /*Left corner*/ - int32_t kl = k + ofs; - - if(kl >= 0 && kl < len) { - mask_buf[kl] = mask_mix(mask_buf[kl], m); - } - - /*Right corner*/ - int32_t kr = k + (w - ofs - 1); - if(kr >= 0 && kr < len) { - mask_buf[kr] = mask_mix(mask_buf[kr], m); - } - - /*Clear the unused parts*/ - if(outer == false) { - kr++; - if(kl > len) { - return LV_DRAW_MASK_RES_TRANSP; - } - if(kl >= 0) { - lv_memset_00(&mask_buf[0], kl); - } - if(kr < 0) { - return LV_DRAW_MASK_RES_TRANSP; - } - if(kr <= len) { - lv_memset_00(&mask_buf[kr], len - kr); - } - } - else { - kl++; - int32_t first = kl; - if(first < 0) first = 0; - - int32_t len_tmp = kr - first; - if(len_tmp + first > len) len_tmp = len - first; - if(first < len && len_tmp >= 0) { - lv_memset_00(&mask_buf[first], len_tmp); - } + if(cir_x_left - i >= 0 && cir_x_left - i < len) { + mask_buf[cir_x_left - i] = mask_mix(opa, mask_buf[cir_x_left - i]); } } - /*Multiple pixels are affected. Get y intersection of the pixels*/ - else { - int32_t ofs = radius - (x0.i + 1); - int32_t kl = k + ofs; - int32_t kr = k + (w - ofs - 1); - if(outer) { - int32_t first = kl + 1; - if(first < 0) first = 0; + /*Clean the right side*/ + cir_x_right = LV_CLAMP(0, cir_x_right + i, len); + lv_memset_00(&mask_buf[cir_x_right], len - cir_x_right); - int32_t len_tmp = kr - first; - if(len_tmp + first > len) len_tmp = len - first; - if(first < len && len_tmp >= 0) { - lv_memset_00(&mask_buf[first], len_tmp); - } + /*Clean the left side*/ + cir_x_left = LV_CLAMP(0, cir_x_left - aa_len + 1, len); + lv_memset_00(&mask_buf[0], cir_x_left); + } + else { + for(i = 0; i < aa_len; i++) { + lv_opa_t opa = 255 - (aa_opa[aa_len - 1 - i]); + if(cir_x_right + i >= 0 && cir_x_right + i < len) { + mask_buf[cir_x_right + i] = mask_mix(opa, mask_buf[cir_x_right + i]); } - - uint32_t i = x0.i + 1; - lv_opa_t m; - lv_sqrt_res_t y_prev; - lv_sqrt_res_t y_next; - - lv_sqrt(r2 - (x0.i * x0.i), &y_prev, sqrt_mask); - - if(y_prev.f == 0) { - y_prev.i--; - y_prev.f = 0xFF; - } - - /*The first y intersection is special as it might be in the previous line*/ - if(y_prev.i >= y) { - lv_sqrt(r2 - (i * i), &y_next, sqrt_mask); - m = 255 - (((255 - x0.f) * (255 - y_next.f)) >> 9); - - if(outer) m = 255 - m; - if(kl >= 0 && kl < len) mask_buf[kl] = mask_mix(mask_buf[kl], m); - if(kr >= 0 && kr < len) mask_buf[kr] = mask_mix(mask_buf[kr], m); - kl--; - kr++; - y_prev.f = y_next.f; - i++; - } - - /*Set all points which are crossed by the circle*/ - for(; i <= x1.i; i++) { - /*These values are very close to each other. It's enough to approximate sqrt - *The non-approximated version is lv_sqrt(r2 - (i * i), &y_next, sqrt_mask);*/ - sqrt_approx(&y_next, &y_prev, r2 - (i * i)); - - m = (y_prev.f + y_next.f) >> 1; - if(outer) m = 255 - m; - if(kl >= 0 && kl < len) mask_buf[kl] = mask_mix(mask_buf[kl], m); - if(kr >= 0 && kr < len) mask_buf[kr] = mask_mix(mask_buf[kr], m); - kl--; - kr++; - y_prev.f = y_next.f; - } - - /*If the last pixel was left in its middle therefore - * the circle still has parts on the next one*/ - if(y_prev.f) { - m = (y_prev.f * x1.f) >> 9; - if(outer) m = 255 - m; - if(kl >= 0 && kl < len) mask_buf[kl] = mask_mix(mask_buf[kl], m); - if(kr >= 0 && kr < len) mask_buf[kr] = mask_mix(mask_buf[kr], m); - kl--; - kr++; - } - - if(outer == 0) { - kl++; - if(kl > len) { - return LV_DRAW_MASK_RES_TRANSP; - } - if(kl >= 0) lv_memset_00(&mask_buf[0], kl); - - if(kr < 0) { - return LV_DRAW_MASK_RES_TRANSP; - } - if(kr < len) lv_memset_00(&mask_buf[kr], len - kr); + if(cir_x_left - i >= 0 && cir_x_left - i < len) { + mask_buf[cir_x_left - i] = mask_mix(opa, mask_buf[cir_x_left - i]); } } + + lv_coord_t clr_start = LV_CLAMP(0, cir_x_left + 1, len); + lv_coord_t clr_len = LV_CLAMP(0, cir_x_right - clr_start, len - clr_start); + lv_memset_00(&mask_buf[clr_start], clr_len); } return LV_DRAW_MASK_RES_CHANGED; @@ -1212,6 +1218,204 @@ LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_map(lv_opa_t * mask return LV_DRAW_MASK_RES_CHANGED; } +/** + * Initialize the circle drawing + * @param c pointer to a point. The coordinates will be calculated here + * @param tmp point to a variable. It will store temporary data + * @param radius radius of the circle + */ +static void circ_init(lv_point_t * c, lv_coord_t * tmp, lv_coord_t radius) +{ + c->x = radius; + c->y = 0; + *tmp = 1 - radius; +} + +/** + * Test the circle drawing is ready or not + * @param c same as in circ_init + * @return true if the circle is not ready yet + */ +static bool circ_cont(lv_point_t * c) +{ + return c->y <= c->x ? true : false; +} + +/** + * Get the next point from the circle + * @param c same as in circ_init. The next point stored here. + * @param tmp same as in circ_init. + */ +static void circ_next(lv_point_t * c, lv_coord_t * tmp) +{ + + if(*tmp <= 0) { + (*tmp) += 2 * c->y + 3; /*Change in decision criterion for y -> y+1*/ + } + else { + (*tmp) += 2 * (c->y - c->x) + 5; /*Change for y -> y+1, x -> x-1*/ + c->x--; + } + c->y++; +} + +static void circ_calc_aa4(_lv_draw_mask_radius_circle_dsc_t * c, lv_coord_t radius) +{ + if(radius == 0) return; + c->radius = radius; + + /*Allocate buffers*/ + if(c->buf) lv_mem_free(c->buf); + + c->buf = lv_mem_alloc(radius * 6 + 6); /*Use uint16_t for opa_start_on_y and x_start_on_y*/ + LV_ASSERT_MALLOC(c->buf); + c->cir_opa = c->buf; + c->opa_start_on_y = (uint16_t *)(c->buf + 2 * radius + 2); + c->x_start_on_y = (uint16_t *)(c->buf + 4 * radius + 4); + + /*Special case, handle manually*/ + if(radius == 1) { + c->cir_opa[0] = 180; + c->opa_start_on_y[0] = 0; + c->opa_start_on_y[1] = 1; + c->x_start_on_y[0] = 0; + return; + } + + lv_coord_t * cir_x = lv_mem_buf_get((radius + 1) * 2 * 2 * sizeof(lv_coord_t)); + lv_coord_t * cir_y = &cir_x[(radius + 1) * 2]; + + uint32_t y_8th_cnt = 0; + lv_point_t cp; + lv_coord_t tmp; + circ_init(&cp, &tmp, radius * 4); /*Upscale by 4*/ + int32_t i; + + uint32_t x_int[4]; + uint32_t x_fract[4]; + lv_coord_t cir_size = 0; + x_int[0] = cp.x >> 2; + x_fract[0] = 0; + + /*Calculate an 1/8 circle*/ + while(circ_cont(&cp)) { + /*Calculate 4 point of the circle */ + for(i = 0; i < 4; i++) { + circ_next(&cp, &tmp); + if(circ_cont(&cp) == false) break; + x_int[i] = cp.x >> 2; + x_fract[i] = cp.x & 0x3; + } + if(i != 4) break; + + /*All lines on the same x when downscaled*/ + if(x_int[0] == x_int[3]) { + cir_x[cir_size] = x_int[0]; + cir_y[cir_size] = y_8th_cnt; + c->cir_opa[cir_size] = x_fract[0] + x_fract[1] + x_fract[2] + x_fract[3]; + c->cir_opa[cir_size] *= 16; + cir_size++; + } + /*Second line on new x when downscaled*/ + else if(x_int[0] != x_int[1]) { + cir_x[cir_size] = x_int[0]; + cir_y[cir_size] = y_8th_cnt; + c->cir_opa[cir_size] = x_fract[0]; + c->cir_opa[cir_size] *= 16; + cir_size++; + + cir_x[cir_size] = x_int[0] - 1; + cir_y[cir_size] = y_8th_cnt; + c->cir_opa[cir_size] = 1 * 4 + x_fract[1] + x_fract[2] + x_fract[3];; + c->cir_opa[cir_size] *= 16; + cir_size++; + } + /*Third line on new x when downscaled*/ + else if(x_int[0] != x_int[2]) { + cir_x[cir_size] = x_int[0]; + cir_y[cir_size] = y_8th_cnt; + c->cir_opa[cir_size] = x_fract[0] + x_fract[1]; + c->cir_opa[cir_size] *= 16; + cir_size++; + + cir_x[cir_size] = x_int[0] - 1; + cir_y[cir_size] = y_8th_cnt; + c->cir_opa[cir_size] = 2 * 4 + x_fract[2] + x_fract[3];; + c->cir_opa[cir_size] *= 16; + cir_size++; + } + /*Forth line on new x when downscaled*/ + else { + cir_x[cir_size] = x_int[0]; + cir_y[cir_size] = y_8th_cnt; + c->cir_opa[cir_size] = x_fract[0] + x_fract[1] + x_fract[2]; + c->cir_opa[cir_size] *= 16; + cir_size++; + + cir_x[cir_size] = x_int[0] - 1; + cir_y[cir_size] = y_8th_cnt; + c->cir_opa[cir_size] = 3 * 4 + x_fract[3];; + c->cir_opa[cir_size] *= 16; + cir_size++; + } + + y_8th_cnt++; + } + + /*The point on the 1/8 circle is special, calculate it manually*/ + int32_t mid = radius * 723; + int32_t mid_int = mid >> 10; + if(cir_x[cir_size - 1] != mid_int || cir_y[cir_size - 1] != mid_int) { + int32_t tmp_val = mid - (mid_int << 10); + if(tmp_val <= 512) { + tmp_val = tmp_val * tmp_val * 2; + tmp_val = tmp_val >> (10 + 6); + } + else { + tmp_val = 1024 - tmp_val; + tmp_val = tmp_val * tmp_val * 2; + tmp_val = tmp_val >> (10 + 6); + tmp_val = 15 - tmp_val; + } + + cir_x[cir_size] = mid_int; + cir_y[cir_size] = mid_int; + c->cir_opa[cir_size] = tmp_val; + c->cir_opa[cir_size] *= 16; + cir_size++; + } + + /*Build the second octet by mirroring the first*/ + for(i = cir_size - 2; i >= 0; i--, cir_size++) { + cir_x[cir_size] = cir_y[i]; + cir_y[cir_size] = cir_x[i]; + c->cir_opa[cir_size] = c->cir_opa[i]; + } + + lv_coord_t y = 0; + i = 0; + c->opa_start_on_y[0] = 0; + while(i < cir_size) { + c->opa_start_on_y[y] = i; + c->x_start_on_y[y] = cir_x[i]; + for(; cir_y[i] == y && i < (int32_t)cir_size; i++) { + c->x_start_on_y[y] = LV_MIN(c->x_start_on_y[y], cir_x[i]); + } + y++; + } + + lv_mem_buf_release(cir_x); +} + +static lv_opa_t * get_next_line(_lv_draw_mask_radius_circle_dsc_t * c, lv_coord_t y, lv_coord_t * len, + lv_coord_t * x_start) +{ + *len = c->opa_start_on_y[y + 1] - c->opa_start_on_y[y]; + *x_start = c->x_start_on_y[y]; + return &c->cir_opa[c->opa_start_on_y[y]]; +} + + LV_ATTRIBUTE_FAST_MEM static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new) { if(mask_new >= LV_OPA_MAX) return mask_act; @@ -1220,24 +1424,5 @@ LV_ATTRIBUTE_FAST_MEM static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_ return LV_UDIV255(mask_act * mask_new);// >> 8); } -/** - * Approximate the sqrt near to an already calculated value - * @param q store the result here - * @param ref the reference point (already calculated sqrt) - * @param x the value which sqrt should be approximated - */ -LV_ATTRIBUTE_FAST_MEM static inline void sqrt_approx(lv_sqrt_res_t * q, lv_sqrt_res_t * ref, uint32_t x) -{ - x = x << 8; /*Upscale for extra precision*/ - - uint32_t raw = (ref->i << 4) + (ref->f >> 4); - uint32_t raw2 = raw * raw; - - int32_t d = x - raw2; - d = (int32_t)d / (int32_t)(2 * raw) + raw; - - q->i = d >> 4; - q->f = (d & 0xF) << 4; -} #endif /*LV_DRAW_COMPLEX*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_mask.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.h similarity index 78% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_mask.h rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.h index 893040494..123cd9163 100644 --- a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_mask.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.h @@ -55,9 +55,17 @@ typedef _lv_draw_mask_saved_t _lv_draw_mask_saved_arr_t[_LV_MASK_MAX_NUM]; #if LV_DRAW_COMPLEX == 0 -static inline uint8_t lv_draw_mask_get_cnt(void) { +static inline uint8_t lv_draw_mask_get_cnt(void) +{ return 0; } + +static inline bool lv_draw_mask_is_any(const lv_area_t * a) +{ + LV_UNUSED(a); + return false; +} + #endif #if LV_DRAW_COMPLEX @@ -147,6 +155,18 @@ typedef struct { uint16_t delta_deg; } lv_draw_mask_angle_param_t; +typedef struct { + uint8_t * buf; + lv_opa_t * cir_opa; /*Opacity of values on the circumference of an 1/4 circle*/ + uint16_t * x_start_on_y; /*The x coordinate of the circle for each y value*/ + uint16_t * opa_start_on_y; /*The index of `cir_opa` for each y value*/ + int32_t life; /*How many times the entry way used*/ + uint32_t used_cnt; /*Like a semaphore to count the referencing masks*/ + lv_coord_t radius; /*The radius of the entry*/ +} _lv_draw_mask_radius_circle_dsc_t; + +typedef _lv_draw_mask_radius_circle_dsc_t _lv_draw_mask_radius_circle_dsc_arr_t[LV_CIRCLE_CACHE_SIZE]; + typedef struct { /*The first element must be the common descriptor*/ _lv_draw_mask_common_dsc_t dsc; @@ -157,9 +177,8 @@ typedef struct { /*Invert the mask. 0: Keep the pixels inside.*/ uint8_t outer: 1; } cfg; - int32_t y_prev; - lv_sqrt_res_t y_prev_x; + _lv_draw_mask_radius_circle_dsc_t * circle; } lv_draw_mask_radius_param_t; @@ -217,6 +236,22 @@ int16_t lv_draw_mask_add(void * param, void * custom_id); LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len); +/** + * Apply the specified buffers on a line. Used internally by the library's drawing routines. + * @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`. + * @param abs_x absolute X coordinate where the line to calculate start + * @param abs_y absolute Y coordinate where the line to calculate start + * @param len length of the line to calculate (in pixel count) + * @param ids ID array of added buffers + * @param ids_count number of ID array + * @return One of these values: + * - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero + * - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged + * - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line + */ +LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply_ids(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, + lv_coord_t len, const int16_t *ids, int16_t ids_count); + //! @endcond /** @@ -235,6 +270,21 @@ void * lv_draw_mask_remove_id(int16_t id); */ void * lv_draw_mask_remove_custom(void * custom_id); +/** + * Free the data from the parameter. + * It's called inside `lv_draw_mask_remove_id` and `lv_draw_mask_remove_custom` + * Needs to be called only in special cases when the mask is not added by `lv_draw_mask_add` + * and not removed by `lv_draw_mask_remove_id` or `lv_draw_mask_remove_custom` + * @param p pointer to a mask parameter + */ +void lv_draw_mask_free_param(void * p); + +/** + * Called by LVGL the rendering of a screen is ready to clean up + * the temporal (cache) data of the masks + */ +void _lv_draw_mask_cleanup(void); + //! @cond Doxygen_Suppress /** @@ -243,6 +293,14 @@ void * lv_draw_mask_remove_custom(void * custom_id); */ LV_ATTRIBUTE_FAST_MEM uint8_t lv_draw_mask_get_cnt(void); + +/** + * Check if there is any added draw mask + * @param a an area to test for affecting masks. + * @return true: there is t least 1 draw mask; false: there are no draw masks + */ +bool lv_draw_mask_is_any(const lv_area_t * a); + //! @endcond /** diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.c new file mode 100644 index 000000000..5778737fe --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.c @@ -0,0 +1,1341 @@ +/** + * @file lv_draw_rect.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_rect.h" +#include "lv_draw_blend.h" +#include "lv_draw_mask.h" +#include "../misc/lv_math.h" +#include "../misc/lv_txt_ap.h" +#include "../core/lv_refr.h" +#include "../misc/lv_assert.h" + +/********************* + * DEFINES + *********************/ +#define SHADOW_UPSCALE_SHIFT 6 +#define SHADOW_ENHANCE 1 +#define SPLIT_LIMIT 50 + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +#if LV_USE_EXTERNAL_RENDERER == 0 +LV_ATTRIBUTE_FAST_MEM static void draw_bg(const lv_area_t * coords, const lv_area_t * clip_area, + const lv_draw_rect_dsc_t * dsc); +LV_ATTRIBUTE_FAST_MEM static void draw_bg_img(const lv_area_t * coords, const lv_area_t * clip, + const lv_draw_rect_dsc_t * dsc); +LV_ATTRIBUTE_FAST_MEM static void draw_border(const lv_area_t * coords, const lv_area_t * clip, + const lv_draw_rect_dsc_t * dsc); + +static void draw_outline(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc); + +#if LV_DRAW_COMPLEX +LV_ATTRIBUTE_FAST_MEM static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, + const lv_draw_rect_dsc_t * dsc); +LV_ATTRIBUTE_FAST_MEM static void shadow_draw_corner_buf(const lv_area_t * coords, uint16_t * sh_buf, lv_coord_t s, + lv_coord_t r); +LV_ATTRIBUTE_FAST_MEM static void shadow_blur_corner(lv_coord_t size, lv_coord_t sw, uint16_t * sh_ups_buf); +#endif + +void draw_border_generic(const lv_area_t * clip_area, const lv_area_t * outer_area, const lv_area_t * inner_area, + lv_coord_t rout, lv_coord_t rin, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode); + +static void draw_border_simple(const lv_area_t * clip, const lv_area_t * outer_area, const lv_area_t * inner_area, + lv_color_t color, lv_opa_t opa); + +#if LV_DRAW_COMPLEX + LV_ATTRIBUTE_FAST_MEM static inline lv_color_t grad_get(const lv_draw_rect_dsc_t * dsc, lv_coord_t s, lv_coord_t i); +#endif +#endif + +/********************** + * STATIC VARIABLES + **********************/ +#if defined(LV_SHADOW_CACHE_SIZE) && LV_SHADOW_CACHE_SIZE > 0 + static uint8_t sh_cache[LV_SHADOW_CACHE_SIZE * LV_SHADOW_CACHE_SIZE]; + static int32_t sh_cache_size = -1; + static int32_t sh_cache_r = -1; +#endif + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +LV_ATTRIBUTE_FAST_MEM void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc) +{ + lv_memset_00(dsc, sizeof(lv_draw_rect_dsc_t)); + dsc->bg_color = lv_color_white(); + dsc->bg_grad_color = lv_color_black(); + dsc->border_color = lv_color_black(); + dsc->shadow_color = lv_color_black(); + dsc->bg_grad_color_stop = 0xFF; + dsc->bg_img_symbol_font = LV_FONT_DEFAULT; + dsc->bg_opa = LV_OPA_COVER; + dsc->bg_img_opa = LV_OPA_COVER; + dsc->outline_opa = LV_OPA_COVER; + dsc->border_opa = LV_OPA_COVER; + dsc->shadow_opa = LV_OPA_COVER; + dsc->border_side = LV_BORDER_SIDE_FULL; +} + +#if LV_USE_EXTERNAL_RENDERER == 0 +/** + * Draw a rectangle + * @param coords the coordinates of the rectangle + * @param mask the rectangle will be drawn only in this mask + * @param dsc pointer to an initialized `lv_draw_rect_dsc_t` variable + */ +void lv_draw_rect(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc) +{ + if(lv_area_get_height(coords) < 1 || lv_area_get_width(coords) < 1) return; +#if LV_DRAW_COMPLEX + draw_shadow(coords, clip, dsc); +#endif + + draw_bg(coords, clip, dsc); + draw_bg_img(coords, clip, dsc); + + draw_border(coords, clip, dsc); + + draw_outline(coords, clip, dsc); + + LV_ASSERT_MEM_INTEGRITY(); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +LV_ATTRIBUTE_FAST_MEM static void draw_bg(const lv_area_t * coords, const lv_area_t * clip_area, + const lv_draw_rect_dsc_t * dsc) +{ + if(dsc->bg_opa <= LV_OPA_MIN) return; + + lv_area_t coords_bg; + lv_area_copy(&coords_bg, coords); + + /*If the border fully covers make the bg area 1px smaller to avoid artifacts on the corners*/ + if(dsc->border_width > 1 && dsc->border_opa >= LV_OPA_MAX && dsc->radius != 0) { + coords_bg.x1 += (dsc->border_side & LV_BORDER_SIDE_LEFT) ? 1 : 0; + coords_bg.y1 += (dsc->border_side & LV_BORDER_SIDE_TOP) ? 1 : 0; + coords_bg.x2 -= (dsc->border_side & LV_BORDER_SIDE_RIGHT) ? 1 : 0; + coords_bg.y2 -= (dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? 1 : 0; + } + + lv_opa_t opa = dsc->bg_opa >= LV_OPA_MAX ? LV_OPA_COVER : dsc->bg_opa; + lv_grad_dir_t grad_dir = dsc->bg_grad_dir; + if(dsc->bg_color.full == dsc->bg_grad_color.full) grad_dir = LV_GRAD_DIR_NONE; + + bool mask_any = lv_draw_mask_is_any(&coords_bg); + + /*Most simple case: just a plain rectangle*/ + if(!mask_any && dsc->radius == 0 && (grad_dir == LV_GRAD_DIR_NONE)) { + _lv_blend_fill(clip_area, &coords_bg, dsc->bg_color, NULL, + LV_DRAW_MASK_RES_FULL_COVER, opa, dsc->blend_mode); + return; + } + + /*Complex case: there is gradient, mask, or radius*/ +#if LV_DRAW_COMPLEX == 0 + LV_LOG_WARN("Can't draw complex rectangle because LV_DRAW_COMPLEX = 0"); +#else + /*Get clipped fill area which is the real draw area. + *It is always the same or inside `fill_area`*/ + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, &coords_bg, clip_area)) return; + + /*Get the real radius. Can't be larger than the half of the shortest side */ + lv_coord_t coords_w = lv_area_get_width(&coords_bg); + lv_coord_t coords_h = lv_area_get_height(&coords_bg); + int32_t short_side = LV_MIN(coords_w, coords_h); + int32_t rout = LV_MIN(dsc->radius, short_side >> 1); + + /*Add a radius mask if there is radius*/ + int32_t draw_area_w = lv_area_get_width(&draw_area); + int16_t mask_rout_id = LV_MASK_ID_INV; + lv_opa_t * mask_buf = NULL; + lv_draw_mask_radius_param_t mask_rout_param; + if(rout > 0 || mask_any) { + mask_buf = lv_mem_buf_get(draw_area_w); + lv_draw_mask_radius_init(&mask_rout_param, &coords_bg, rout, false); + mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); + } + + /*In case of horizontal gradient pre-compute a line with a gradient*/ + lv_color_t * grad_map = NULL; + lv_color_t * grad_map_ofs = NULL; + if(grad_dir == LV_GRAD_DIR_HOR) { + grad_map = lv_mem_buf_get(coords_w * sizeof(lv_color_t)); + int32_t i; + for(i = 0; i < coords_w; i++) { + grad_map[i] = grad_get(dsc, coords_w, i); + } + grad_map_ofs = grad_map; + if(dsc->bg_grad_dir == LV_GRAD_DIR_HOR) grad_map_ofs += draw_area.x1 - coords_bg.x1; + } + + int32_t h; + lv_draw_mask_res_t mask_res; + lv_area_t blend_area; + blend_area.x1 = draw_area.x1; + blend_area.x2 = draw_area.x2; + + /*There is another mask too. Draw line by line. */ + if(mask_any) { + for(h = draw_area.y1; h <= draw_area.y2; h++) { + blend_area.y1 = h; + blend_area.y2 = h; + + /* Initialize the mask to opa instead of 0xFF and blend with LV_OPA_COVER. + * It saves calculating the final opa in _lv_blend_fill*/ + lv_memset(mask_buf, opa, draw_area_w); + mask_res = lv_draw_mask_apply(mask_buf, draw_area.x1, h, draw_area_w); + if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; + + if(grad_dir == LV_GRAD_DIR_NONE) { + _lv_blend_fill(clip_area, &blend_area, dsc->bg_color, mask_buf, mask_res, LV_OPA_COVER, dsc->blend_mode); + } + else if(grad_dir == LV_GRAD_DIR_HOR) { + _lv_blend_map(clip_area, &blend_area, grad_map_ofs, mask_buf, mask_res, LV_OPA_COVER, dsc->blend_mode); + } + else if(grad_dir == LV_GRAD_DIR_VER) { + lv_color_t c = grad_get(dsc, coords_h, h - coords_bg.y1); + _lv_blend_fill(clip_area, &blend_area, c, mask_buf, mask_res, LV_OPA_COVER, dsc->blend_mode); + } + } + goto bg_clean_up; + } + + + /* Draw the top of the rectangle line by line and mirror it to the bottom. + * If there is no radius this cycle won't run because `h` is always `>= h_end`*/ + blend_area.x1 = draw_area.x1; + blend_area.x2 = draw_area.x2; + for(h = 0; h < rout; h++) { + lv_coord_t top_y = coords_bg.y1 + h; + lv_coord_t bottom_y = coords_bg.y2 - h; + if(top_y < draw_area.y1 && bottom_y > draw_area.y2) continue; /*This line is clipped now*/ + + /* Initialize the mask to opa instead of 0xFF and blend with LV_OPA_COVER. + * It saves calculating the final opa in _lv_blend_fill*/ + lv_memset(mask_buf, opa, draw_area_w); + mask_res = lv_draw_mask_apply(mask_buf, blend_area.x1, top_y, draw_area_w); + + if(top_y >= draw_area.y1) { + blend_area.y1 = top_y; + blend_area.y2 = top_y; + + if(grad_dir == LV_GRAD_DIR_NONE) { + _lv_blend_fill(clip_area, &blend_area, dsc->bg_color, mask_buf, mask_res, LV_OPA_COVER, dsc->blend_mode); + } + else if(grad_dir == LV_GRAD_DIR_HOR) { + _lv_blend_map(clip_area, &blend_area, grad_map_ofs, mask_buf, mask_res, LV_OPA_COVER, dsc->blend_mode); + } + else if(grad_dir == LV_GRAD_DIR_VER) { + lv_color_t c = grad_get(dsc, coords_h, top_y - coords_bg.y1); + _lv_blend_fill(clip_area, &blend_area, c, mask_buf, mask_res, LV_OPA_COVER, dsc->blend_mode); + } + } + + if(bottom_y <= draw_area.y2) { + blend_area.y1 = bottom_y; + blend_area.y2 = bottom_y; + + if(grad_dir == LV_GRAD_DIR_NONE) { + _lv_blend_fill(clip_area, &blend_area, dsc->bg_color, mask_buf, mask_res, LV_OPA_COVER, dsc->blend_mode); + } + else if(grad_dir == LV_GRAD_DIR_HOR) { + _lv_blend_map(clip_area, &blend_area, grad_map_ofs, mask_buf, mask_res, LV_OPA_COVER, dsc->blend_mode); + } + else if(grad_dir == LV_GRAD_DIR_VER) { + lv_color_t c = grad_get(dsc, coords_h, bottom_y - coords_bg.y1); + _lv_blend_fill(clip_area, &blend_area, c, mask_buf, mask_res, LV_OPA_COVER, dsc->blend_mode); + } + } + } + + /* Draw the center of the rectangle.*/ + + /*If no other masks and no gradient, the center is a simple rectangle*/ + if(!mask_any && grad_dir == LV_GRAD_DIR_NONE) { + blend_area.y1 = coords_bg.y1 + rout; + blend_area.y2 = coords_bg.y2 - rout; + _lv_blend_fill(clip_area, &blend_area, dsc->bg_color, mask_buf, LV_DRAW_MASK_RES_FULL_COVER, opa, dsc->blend_mode); + } + /*With gradient and/or mask draw line by line*/ + else { + mask_res = LV_DRAW_MASK_RES_FULL_COVER; + int32_t h_end = coords_bg.y2 - rout; + for(h = coords_bg.y1 + rout; h <= h_end; h++) { + /*If there is no other mask do not apply mask as in the center there is no radius to mask*/ + if(mask_any) { + lv_memset_ff(mask_buf, draw_area_w); + mask_res = lv_draw_mask_apply(mask_buf, draw_area.x1, h, draw_area_w); + } + + blend_area.y1 = h; + blend_area.y2 = h; + if(grad_dir == LV_GRAD_DIR_NONE) { + _lv_blend_fill(clip_area, &blend_area, dsc->bg_color, mask_buf, mask_res, opa, dsc->blend_mode); + } + else if(grad_dir == LV_GRAD_DIR_HOR) { + _lv_blend_map(clip_area, &blend_area, grad_map_ofs, mask_buf, mask_res, opa, dsc->blend_mode); + } + else if(grad_dir == LV_GRAD_DIR_VER) { + lv_color_t c = grad_get(dsc, coords_h, h - coords_bg.y1); + _lv_blend_fill(clip_area, &blend_area, c, mask_buf, mask_res, opa, dsc->blend_mode); + } + } + } + + +bg_clean_up: + if(grad_map) lv_mem_buf_release(grad_map); + if(mask_buf) lv_mem_buf_release(mask_buf); + if(mask_rout_id != LV_MASK_ID_INV) { + lv_draw_mask_remove_id(mask_rout_id); + lv_draw_mask_free_param(&mask_rout_param); + } + +#endif +} + +LV_ATTRIBUTE_FAST_MEM static void draw_bg_img(const lv_area_t * coords, const lv_area_t * clip, + const lv_draw_rect_dsc_t * dsc) +{ + if(dsc->bg_img_src == NULL) return; + if(dsc->bg_img_opa <= LV_OPA_MIN) return; + + lv_img_src_t src_type = lv_img_src_get_type(dsc->bg_img_src); + if(src_type == LV_IMG_SRC_SYMBOL) { + lv_point_t size; + lv_txt_get_size(&size, dsc->bg_img_src, dsc->bg_img_symbol_font, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + lv_area_t a; + a.x1 = coords->x1 + lv_area_get_width(coords) / 2 - size.x / 2; + a.x2 = a.x1 + size.x - 1; + a.y1 = coords->y1 + lv_area_get_height(coords) / 2 - size.y / 2; + a.y2 = a.y1 + size.y - 1; + + lv_draw_label_dsc_t label_draw_dsc; + lv_draw_label_dsc_init(&label_draw_dsc); + label_draw_dsc.font = dsc->bg_img_symbol_font; + label_draw_dsc.color = dsc->bg_img_recolor; + label_draw_dsc.opa = dsc->bg_img_opa; + lv_draw_label(&a, clip, &label_draw_dsc, dsc->bg_img_src, NULL); + } + else { + lv_img_header_t header; + lv_res_t res = lv_img_decoder_get_info(dsc->bg_img_src, &header); + if(res != LV_RES_OK) { + LV_LOG_WARN("Couldn't read the background image"); + return; + } + + lv_draw_img_dsc_t img_dsc; + lv_draw_img_dsc_init(&img_dsc); + img_dsc.blend_mode = dsc->blend_mode; + img_dsc.recolor = dsc->bg_img_recolor; + img_dsc.recolor_opa = dsc->bg_img_recolor_opa; + img_dsc.opa = dsc->bg_img_opa; + + /*Center align*/ + if(dsc->bg_img_tiled == false) { + lv_area_t area; + area.x1 = coords->x1 + lv_area_get_width(coords) / 2 - header.w / 2; + area.y1 = coords->y1 + lv_area_get_height(coords) / 2 - header.h / 2; + area.x2 = area.x1 + header.w - 1; + area.y2 = area.y1 + header.h - 1; + + lv_draw_img(&area, clip, dsc->bg_img_src, &img_dsc); + } + else { + lv_area_t area; + area.y1 = coords->y1; + area.y2 = area.y1 + header.h - 1; + + for(; area.y1 <= coords->y2; area.y1 += header.h, area.y2 += header.h) { + + area.x1 = coords->x1; + area.x2 = area.x1 + header.w - 1; + for(; area.x1 <= coords->x2; area.x1 += header.w, area.x2 += header.w) { + lv_draw_img(&area, clip, dsc->bg_img_src, &img_dsc); + } + } + } + } +} + +LV_ATTRIBUTE_FAST_MEM static void draw_border(const lv_area_t * coords, const lv_area_t * clip, + const lv_draw_rect_dsc_t * dsc) +{ + if(dsc->border_opa <= LV_OPA_MIN) return; + if(dsc->border_width == 0) return; + if(dsc->border_side == LV_BORDER_SIDE_NONE) return; + if(dsc->border_post) return; + + int32_t coords_w = lv_area_get_width(coords); + int32_t coords_h = lv_area_get_height(coords); + int32_t rout = dsc->radius; + int32_t short_side = LV_MIN(coords_w, coords_h); + if(rout > short_side >> 1) rout = short_side >> 1; + + /*Get the inner area*/ + lv_area_t area_inner; + lv_area_copy(&area_inner, coords); + area_inner.x1 += ((dsc->border_side & LV_BORDER_SIDE_LEFT) ? dsc->border_width : - (dsc->border_width + rout)); + area_inner.x2 -= ((dsc->border_side & LV_BORDER_SIDE_RIGHT) ? dsc->border_width : - (dsc->border_width + rout)); + area_inner.y1 += ((dsc->border_side & LV_BORDER_SIDE_TOP) ? dsc->border_width : - (dsc->border_width + rout)); + area_inner.y2 -= ((dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? dsc->border_width : - (dsc->border_width + rout)); + + lv_coord_t rin = rout - dsc->border_width; + if(rin < 0) rin = 0; + + draw_border_generic(clip, coords, &area_inner, rout, rin, dsc->border_color, dsc->border_opa, dsc->blend_mode); + +} + + +#if LV_DRAW_COMPLEX +LV_ATTRIBUTE_FAST_MEM static inline lv_color_t grad_get(const lv_draw_rect_dsc_t * dsc, lv_coord_t s, lv_coord_t i) +{ + int32_t min = (dsc->bg_main_color_stop * s) >> 8; + if(i <= min) return dsc->bg_color; + + int32_t max = (dsc->bg_grad_color_stop * s) >> 8; + if(i >= max) return dsc->bg_grad_color; + + int32_t d = dsc->bg_grad_color_stop - dsc->bg_main_color_stop; + d = (s * d) >> 8; + i -= min; + lv_opa_t mix = (i * 255) / d; + return lv_color_mix(dsc->bg_grad_color, dsc->bg_color, mix); +} + +LV_ATTRIBUTE_FAST_MEM static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, + const lv_draw_rect_dsc_t * dsc) +{ + /*Check whether the shadow is visible*/ + if(dsc->shadow_width == 0) return; + if(dsc->shadow_opa <= LV_OPA_MIN) return; + + if(dsc->shadow_width == 1 && dsc->shadow_spread <= 0 && + dsc->shadow_ofs_x == 0 && dsc->shadow_ofs_y == 0) { + return; + } + + /*Calculate the rectangle which is blurred to get the shadow in `shadow_area`*/ + lv_area_t core_area; + core_area.x1 = coords->x1 + dsc->shadow_ofs_x - dsc->shadow_spread; + core_area.x2 = coords->x2 + dsc->shadow_ofs_x + dsc->shadow_spread; + core_area.y1 = coords->y1 + dsc->shadow_ofs_y - dsc->shadow_spread; + core_area.y2 = coords->y2 + dsc->shadow_ofs_y + dsc->shadow_spread; + + /*Calculate the bounding box of the shadow*/ + lv_area_t shadow_area; + shadow_area.x1 = core_area.x1 - dsc->shadow_width / 2 - 1; + shadow_area.x2 = core_area.x2 + dsc->shadow_width / 2 + 1; + shadow_area.y1 = core_area.y1 - dsc->shadow_width / 2 - 1; + shadow_area.y2 = core_area.y2 + dsc->shadow_width / 2 + 1; + + lv_opa_t opa = dsc->shadow_opa; + if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; + + /*Get clipped draw area which is the real draw area. + *It is always the same or inside `shadow_area`*/ + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, &shadow_area, clip)) return; + + /*Consider 1 px smaller bg to be sure the edge will be covered by the shadow*/ + lv_area_t bg_area; + lv_area_copy(&bg_area, coords); + lv_area_increase(&bg_area, -1, -1); + + /*Get the clamped radius*/ + int32_t r_bg = dsc->radius; + lv_coord_t short_side = LV_MIN(lv_area_get_width(&bg_area), lv_area_get_height(&bg_area)); + if(r_bg > short_side >> 1) r_bg = short_side >> 1; + + /*Get the clamped radius*/ + int32_t r_sh = dsc->radius; + short_side = LV_MIN(lv_area_get_width(&core_area), lv_area_get_height(&core_area)); + if(r_sh > short_side >> 1) r_sh = short_side >> 1; + + /*Get how many pixels are affected by the blur on the corners*/ + int32_t corner_size = dsc->shadow_width + r_sh; + + lv_opa_t * sh_buf; + +#if LV_SHADOW_CACHE_SIZE + if(sh_cache_size == corner_size && sh_cache_r == r_sh) { + /*Use the cache if available*/ + sh_buf = lv_mem_buf_get(corner_size * corner_size); + lv_memcpy(sh_buf, sh_cache, corner_size * corner_size); + } + else { + /*A larger buffer is required for calculation*/ + sh_buf = lv_mem_buf_get(corner_size * corner_size * sizeof(uint16_t)); + shadow_draw_corner_buf(&core_area, (uint16_t *)sh_buf, dsc->shadow_width, r_sh); + + /*Cache the corner if it fits into the cache size*/ + if((uint32_t)corner_size * corner_size < sizeof(sh_cache)) { + lv_memcpy(sh_cache, sh_buf, corner_size * corner_size); + sh_cache_size = corner_size; + sh_cache_r = r_sh; + } + } +#else + sh_buf = lv_mem_buf_get(corner_size * corner_size * sizeof(uint16_t)); + shadow_draw_corner_buf(&core_area, (uint16_t *)sh_buf, dsc->shadow_width, r_sh); +#endif + + /*Skip a lot of masking if the background will cover the shadow that would be masked out*/ + bool mask_any = lv_draw_mask_is_any(&shadow_area); + bool simple = true; + if(mask_any || dsc->bg_opa < LV_OPA_COVER) simple = false; + + /*Create a radius mask to clip remove shadow on the bg area*/ + lv_draw_mask_res_t mask_res; + + lv_draw_mask_radius_param_t mask_rout_param; + int16_t mask_rout_id = LV_MASK_ID_INV; + if(!simple) { + lv_draw_mask_radius_init(&mask_rout_param, &bg_area, r_bg, true); + mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); + } + lv_opa_t * mask_buf = lv_mem_buf_get(lv_area_get_width(&shadow_area)); + lv_area_t blend_area; + lv_area_t clip_area_sub; + lv_opa_t ** mask_act; + lv_opa_t * sh_buf_tmp; + lv_coord_t y; + bool simple_sub; + + lv_coord_t w_half = shadow_area.x1 + lv_area_get_width(&shadow_area) / 2; + lv_coord_t h_half = shadow_area.y1 + lv_area_get_height(&shadow_area) / 2; + + /*Draw the corners if they are on the current clip area and not fully covered by the bg*/ + + /*Top right corner*/ + blend_area.x2 = shadow_area.x2; + blend_area.x1 = shadow_area.x2 - corner_size + 1; + blend_area.y1 = shadow_area.y1; + blend_area.y2 = shadow_area.y1 + corner_size - 1; + /*Do not overdraw the top other corners*/ + blend_area.x1 = LV_MAX(blend_area.x1, w_half); + blend_area.y2 = LV_MIN(blend_area.y2, h_half); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, clip) && !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + lv_coord_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (clip_area_sub.y1 - shadow_area.y1) * corner_size; + sh_buf_tmp += clip_area_sub.x1 - (shadow_area.x2 - corner_size + 1); + + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + mask_act = simple_sub ? &sh_buf_tmp : &mask_buf; + if(w > 0) { + mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ + for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { + blend_area.y1 = y; + blend_area.y2 = y; + + if(!simple_sub) { + lv_memcpy(mask_buf, sh_buf_tmp, corner_size); + mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); + if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; + } + _lv_blend_fill(&clip_area_sub, &blend_area, dsc->shadow_color, *mask_act, mask_res, dsc->shadow_opa, dsc->blend_mode); + sh_buf_tmp += corner_size; + } + } + } + + /*Bottom right corner. + *Almost the same as top right just read the lines of `sh_buf` from then end*/ + blend_area.x2 = shadow_area.x2; + blend_area.x1 = shadow_area.x2 - corner_size + 1; + blend_area.y1 = shadow_area.y2 - corner_size + 1; + blend_area.y2 = shadow_area.y2; + /*Do not overdraw the other corners*/ + blend_area.x1 = LV_MAX(blend_area.x1, w_half); + blend_area.y1 = LV_MAX(blend_area.y1, h_half + 1); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, clip) && !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + lv_coord_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (blend_area.y2 - clip_area_sub.y2) * corner_size; + sh_buf_tmp += clip_area_sub.x1 - (shadow_area.x2 - corner_size + 1); + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + mask_act = simple_sub ? &sh_buf_tmp : &mask_buf; + + if(w > 0) { + mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ + for(y = clip_area_sub.y2; y >= clip_area_sub.y1; y--) { + blend_area.y1 = y; + blend_area.y2 = y; + + if(!simple_sub) { + lv_memcpy(mask_buf, sh_buf_tmp, corner_size); + mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); + if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; + } + _lv_blend_fill(&clip_area_sub, &blend_area, dsc->shadow_color, *mask_act, mask_res, dsc->shadow_opa, dsc->blend_mode); + sh_buf_tmp += corner_size; + } + } + } + + /*Top side*/ + blend_area.x1 = shadow_area.x1 + corner_size; + blend_area.x2 = shadow_area.x2 - corner_size; + blend_area.y1 = shadow_area.y1; + blend_area.y2 = shadow_area.y1 + corner_size - 1; + blend_area.y2 = LV_MIN(blend_area.y2, h_half); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, clip) && !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + lv_coord_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (clip_area_sub.y1 - blend_area.y1) * corner_size; + + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + + if(w > 0) { + mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ + for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { + blend_area.y1 = y; + blend_area.y2 = y; + + if(!simple_sub) { + lv_memset(mask_buf, sh_buf_tmp[0], w); + mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); + if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; + _lv_blend_fill(&clip_area_sub, &blend_area, dsc->shadow_color, mask_buf, mask_res, dsc->shadow_opa, dsc->blend_mode); + } + else { + lv_opa_t line_opa = opa == LV_OPA_COVER ? sh_buf_tmp[0] : (sh_buf_tmp[0] * dsc->shadow_opa) >> 8; + _lv_blend_fill(&clip_area_sub, &blend_area, dsc->shadow_color, NULL, LV_DRAW_MASK_RES_FULL_COVER, line_opa, + dsc->blend_mode); + } + sh_buf_tmp += corner_size; + } + } + } + + /*Bottom side*/ + blend_area.x1 = shadow_area.x1 + corner_size; + blend_area.x2 = shadow_area.x2 - corner_size; + blend_area.y1 = shadow_area.y2 - corner_size + 1; + blend_area.y2 = shadow_area.y2; + blend_area.y1 = LV_MAX(blend_area.y1, h_half + 1); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, clip) && !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + lv_coord_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (blend_area.y2 - clip_area_sub.y2) * corner_size; + if(w > 0) { + mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ + for(y = clip_area_sub.y2; y >= clip_area_sub.y1; y--) { + blend_area.y1 = y; + blend_area.y2 = y; + + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + + if(!simple_sub) { + lv_memset(mask_buf, sh_buf_tmp[0], w); + mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); + if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; + _lv_blend_fill(&clip_area_sub, &blend_area, dsc->shadow_color, mask_buf, mask_res, dsc->shadow_opa, dsc->blend_mode); + } + else { + lv_opa_t line_opa = opa == LV_OPA_COVER ? sh_buf_tmp[0] : (sh_buf_tmp[0] * dsc->shadow_opa) >> 8; + _lv_blend_fill(&clip_area_sub, &blend_area, dsc->shadow_color, NULL, LV_DRAW_MASK_RES_FULL_COVER, line_opa, + dsc->blend_mode); + + } + sh_buf_tmp += corner_size; + } + } + } + + /*Right side*/ + blend_area.x1 = shadow_area.x2 - corner_size + 1; + blend_area.x2 = shadow_area.x2; + blend_area.y1 = shadow_area.y1 + corner_size; + blend_area.y2 = shadow_area.y2 - corner_size; + /*Do not overdraw the other corners*/ + blend_area.y1 = LV_MIN(blend_area.y1, h_half + 1); + blend_area.y2 = LV_MAX(blend_area.y2, h_half); + blend_area.x1 = LV_MAX(blend_area.x1, w_half); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, clip) && !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + lv_coord_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (corner_size - 1) * corner_size; + sh_buf_tmp += clip_area_sub.x1 - (shadow_area.x2 - corner_size + 1); + + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + mask_act = simple_sub ? &sh_buf_tmp : &mask_buf; + + if(w > 0) { + mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ + for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { + blend_area.y1 = y; + blend_area.y2 = y; + + if(!simple_sub) { + lv_memcpy(mask_buf, sh_buf_tmp, w); + mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); + if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; + } + _lv_blend_fill(&clip_area_sub, &blend_area, dsc->shadow_color, *mask_act, mask_res, dsc->shadow_opa, dsc->blend_mode); + } + } + } + + /*Mirror the shadow corner buffer horizontally*/ + sh_buf_tmp = sh_buf ; + for(y = 0; y < corner_size; y++) { + int32_t x; + lv_opa_t * start = sh_buf_tmp; + lv_opa_t * end = sh_buf_tmp + corner_size - 1; + for(x = 0; x < corner_size / 2; x++) { + lv_opa_t tmp = *start; + *start = *end; + *end = tmp; + + start++; + end--; + } + sh_buf_tmp += corner_size; + } + + /*Left side*/ + blend_area.x1 = shadow_area.x1; + blend_area.x2 = shadow_area.x1 + corner_size - 1; + blend_area.y1 = shadow_area.y1 + corner_size; + blend_area.y2 = shadow_area.y2 - corner_size; + /*Do not overdraw the other corners*/ + blend_area.y1 = LV_MIN(blend_area.y1, h_half + 1); + blend_area.y2 = LV_MAX(blend_area.y2, h_half); + blend_area.x2 = LV_MIN(blend_area.x2, w_half - 1); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, clip) && !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + lv_coord_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (corner_size - 1) * corner_size; + sh_buf_tmp += clip_area_sub.x1 - blend_area.x1; + + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + mask_act = simple_sub ? &sh_buf_tmp : &mask_buf; + if(w > 0) { + mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ + for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { + blend_area.y1 = y; + blend_area.y2 = y; + + if(!simple_sub) { + lv_memcpy(mask_buf, sh_buf_tmp, w); + mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); + if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; + } + _lv_blend_fill(&clip_area_sub, &blend_area, dsc->shadow_color, *mask_act, mask_res, dsc->shadow_opa, dsc->blend_mode); + } + } + } + + /*Top left corner*/ + blend_area.x1 = shadow_area.x1; + blend_area.x2 = shadow_area.x1 + corner_size - 1; + blend_area.y1 = shadow_area.y1; + blend_area.y2 = shadow_area.y1 + corner_size - 1; + /*Do not overdraw the other corners*/ + blend_area.x2 = LV_MIN(blend_area.x2, w_half - 1); + blend_area.y2 = LV_MIN(blend_area.y2, h_half); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, clip) && !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + lv_coord_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (clip_area_sub.y1 - blend_area.y1) * corner_size; + sh_buf_tmp += clip_area_sub.x1 - blend_area.x1; + + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + mask_act = simple_sub ? &sh_buf_tmp : &mask_buf; + + if(w > 0) { + mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ + for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { + blend_area.y1 = y; + blend_area.y2 = y; + + if(!simple_sub) { + lv_memcpy(mask_buf, sh_buf_tmp, corner_size); + mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); + if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; + } + _lv_blend_fill(&clip_area_sub, &blend_area, dsc->shadow_color, *mask_act, mask_res, dsc->shadow_opa, dsc->blend_mode); + sh_buf_tmp += corner_size; + } + } + } + + /*Bottom left corner. + *Almost the same as bottom right just read the lines of `sh_buf` from then end*/ + blend_area.x1 = shadow_area.x1 ; + blend_area.x2 = shadow_area.x1 + corner_size - 1; + blend_area.y1 = shadow_area.y2 - corner_size + 1; + blend_area.y2 = shadow_area.y2; + /*Do not overdraw the other corners*/ + blend_area.y1 = LV_MAX(blend_area.y1, h_half + 1); + blend_area.x2 = LV_MIN(blend_area.x2, w_half - 1); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, clip) && !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + lv_coord_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (blend_area.y2 - clip_area_sub.y2) * corner_size; + sh_buf_tmp += clip_area_sub.x1 - blend_area.x1; + + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + mask_act = simple_sub ? &sh_buf_tmp : &mask_buf; + if(w > 0) { + mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ + for(y = clip_area_sub.y2; y >= clip_area_sub.y1; y--) { + blend_area.y1 = y; + blend_area.y2 = y; + + if(!simple_sub) { + lv_memcpy(mask_buf, sh_buf_tmp, corner_size); + mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); + if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; + } + _lv_blend_fill(&clip_area_sub, &blend_area, dsc->shadow_color, *mask_act, mask_res, dsc->shadow_opa, dsc->blend_mode); + sh_buf_tmp += corner_size; + } + } + } + + /*Draw the center rectangle.*/ + blend_area.x1 = shadow_area.x1 + corner_size ; + blend_area.x2 = shadow_area.x2 - corner_size; + blend_area.y1 = shadow_area.y1 + corner_size; + blend_area.y2 = shadow_area.y2 - corner_size; + + if(_lv_area_intersect(&clip_area_sub, &blend_area, clip) && !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + lv_coord_t w = lv_area_get_width(&clip_area_sub); + if(w > 0) { + for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { + blend_area.y1 = y; + blend_area.y2 = y; + + lv_memset_ff(mask_buf, w); + mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); + _lv_blend_fill(&clip_area_sub, &blend_area, dsc->shadow_color, mask_buf, mask_res, dsc->shadow_opa, dsc->blend_mode); + } + } + } + + if(!simple) { + lv_draw_mask_free_param(&mask_rout_param); + lv_draw_mask_remove_id(mask_rout_id); + } + lv_mem_buf_release(sh_buf); + lv_mem_buf_release(mask_buf); +} + +/** + * Calculate a blurred corner + * @param coords Coordinates of the shadow + * @param sh_buf a buffer to store the result. Its size should be `(sw + r)^2 * 2` + * @param sw shadow width + * @param r radius + */ +LV_ATTRIBUTE_FAST_MEM static void shadow_draw_corner_buf(const lv_area_t * coords, uint16_t * sh_buf, lv_coord_t sw, + lv_coord_t r) +{ + int32_t sw_ori = sw; + int32_t size = sw_ori + r; + + lv_area_t sh_area; + lv_area_copy(&sh_area, coords); + sh_area.x2 = sw / 2 + r - 1 - ((sw & 1) ? 0 : 1); + sh_area.y1 = sw / 2 + 1; + + sh_area.x1 = sh_area.x2 - lv_area_get_width(coords); + sh_area.y2 = sh_area.y1 + lv_area_get_height(coords); + + lv_draw_mask_radius_param_t mask_param; + lv_draw_mask_radius_init(&mask_param, &sh_area, r, false); + +#if SHADOW_ENHANCE + /*Set half shadow width width because blur will be repeated*/ + if(sw_ori == 1) sw = 1; + else sw = sw_ori >> 1; +#endif + + int32_t y; + lv_opa_t * mask_line = lv_mem_buf_get(size); + uint16_t * sh_ups_tmp_buf = (uint16_t *)sh_buf; + for(y = 0; y < size; y++) { + lv_memset_ff(mask_line, size); + lv_draw_mask_res_t mask_res = mask_param.dsc.cb(mask_line, 0, y, size, &mask_param); + if(mask_res == LV_DRAW_MASK_RES_TRANSP) { + lv_memset_00(sh_ups_tmp_buf, size * sizeof(sh_ups_tmp_buf[0])); + } + else { + int32_t i; + sh_ups_tmp_buf[0] = (mask_line[0] << SHADOW_UPSCALE_SHIFT) / sw; + for(i = 1; i < size; i++) { + if(mask_line[i] == mask_line[i - 1]) sh_ups_tmp_buf[i] = sh_ups_tmp_buf[i - 1]; + else sh_ups_tmp_buf[i] = (mask_line[i] << SHADOW_UPSCALE_SHIFT) / sw; + } + } + + sh_ups_tmp_buf += size; + } + lv_mem_buf_release(mask_line); + + lv_draw_mask_free_param(&mask_param); + + if(sw == 1) { + int32_t i; + lv_opa_t * res_buf = (lv_opa_t *)sh_buf; + for(i = 0; i < size * size; i++) { + res_buf[i] = (sh_buf[i] >> SHADOW_UPSCALE_SHIFT); + } + return; + } + + shadow_blur_corner(size, sw, sh_buf); + +#if SHADOW_ENHANCE == 0 + /*The result is required in lv_opa_t not uint16_t*/ + uint32_t x; + lv_opa_t * res_buf = (lv_opa_t *)sh_buf; + for(x = 0; x < size * size; x++) { + res_buf[x] = sh_buf[x]; + } +#else + sw += sw_ori & 1; + if(sw > 1) { + uint32_t i; + uint32_t max_v_div = (LV_OPA_COVER << SHADOW_UPSCALE_SHIFT) / sw; + for(i = 0; i < (uint32_t)size * size; i++) { + if(sh_buf[i] == 0) continue; + else if(sh_buf[i] == LV_OPA_COVER) sh_buf[i] = max_v_div; + else sh_buf[i] = (sh_buf[i] << SHADOW_UPSCALE_SHIFT) / sw; + } + + shadow_blur_corner(size, sw, sh_buf); + } + int32_t x; + lv_opa_t * res_buf = (lv_opa_t *)sh_buf; + for(x = 0; x < size * size; x++) { + res_buf[x] = sh_buf[x]; + } +#endif + +} + +LV_ATTRIBUTE_FAST_MEM static void shadow_blur_corner(lv_coord_t size, lv_coord_t sw, uint16_t * sh_ups_buf) +{ + int32_t s_left = sw >> 1; + int32_t s_right = (sw >> 1); + if((sw & 1) == 0) s_left--; + + /*Horizontal blur*/ + uint16_t * sh_ups_blur_buf = lv_mem_buf_get(size * sizeof(uint16_t)); + + int32_t x; + int32_t y; + + uint16_t * sh_ups_tmp_buf = sh_ups_buf; + + for(y = 0; y < size; y++) { + int32_t v = sh_ups_tmp_buf[size - 1] * sw; + for(x = size - 1; x >= 0; x--) { + sh_ups_blur_buf[x] = v; + + /*Forget the right pixel*/ + uint32_t right_val = 0; + if(x + s_right < size) right_val = sh_ups_tmp_buf[x + s_right]; + v -= right_val; + + /*Add the left pixel*/ + uint32_t left_val; + if(x - s_left - 1 < 0) left_val = sh_ups_tmp_buf[0]; + else left_val = sh_ups_tmp_buf[x - s_left - 1]; + v += left_val; + } + lv_memcpy(sh_ups_tmp_buf, sh_ups_blur_buf, size * sizeof(uint16_t)); + sh_ups_tmp_buf += size; + } + + /*Vertical blur*/ + uint32_t i; + uint32_t max_v = LV_OPA_COVER << SHADOW_UPSCALE_SHIFT; + uint32_t max_v_div = max_v / sw; + for(i = 0; i < (uint32_t)size * size; i++) { + if(sh_ups_buf[i] == 0) continue; + else if(sh_ups_buf[i] == max_v) sh_ups_buf[i] = max_v_div; + else sh_ups_buf[i] = sh_ups_buf[i] / sw; + } + + for(x = 0; x < size; x++) { + sh_ups_tmp_buf = &sh_ups_buf[x]; + int32_t v = sh_ups_tmp_buf[0] * sw; + for(y = 0; y < size ; y++, sh_ups_tmp_buf += size) { + sh_ups_blur_buf[y] = v < 0 ? 0 : (v >> SHADOW_UPSCALE_SHIFT); + + /*Forget the top pixel*/ + uint32_t top_val; + if(y - s_right <= 0) top_val = sh_ups_tmp_buf[0]; + else top_val = sh_ups_buf[(y - s_right) * size + x]; + v -= top_val; + + /*Add the bottom pixel*/ + uint32_t bottom_val; + if(y + s_left + 1 < size) bottom_val = sh_ups_buf[(y + s_left + 1) * size + x]; + else bottom_val = sh_ups_buf[(size - 1) * size + x]; + v += bottom_val; + } + + /*Write back the result into `sh_ups_buf`*/ + sh_ups_tmp_buf = &sh_ups_buf[x]; + for(y = 0; y < size; y++, sh_ups_tmp_buf += size) { + (*sh_ups_tmp_buf) = sh_ups_blur_buf[y]; + } + } + + lv_mem_buf_release(sh_ups_blur_buf); +} + +#endif + +static void draw_outline(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc) +{ + if(dsc->outline_opa <= LV_OPA_MIN) return; + if(dsc->outline_width == 0) return; + + lv_opa_t opa = dsc->outline_opa; + + if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; + + /*Get the inner radius*/ + lv_area_t area_inner; + lv_area_copy(&area_inner, coords); + + /*Extend the outline into the background area if it's overlapping the edge*/ + lv_coord_t pad = (dsc->outline_pad == 0 ? (dsc->outline_pad - 1) : dsc->outline_pad); + area_inner.x1 -= pad; + area_inner.y1 -= pad; + area_inner.x2 += pad; + area_inner.y2 += pad; + + lv_area_t area_outer; + lv_area_copy(&area_outer, &area_inner); + + area_outer.x1 -= dsc->outline_width; + area_outer.x2 += dsc->outline_width; + area_outer.y1 -= dsc->outline_width; + area_outer.y2 += dsc->outline_width; + + + int32_t inner_w = lv_area_get_width(&area_inner); + int32_t inner_h = lv_area_get_height(&area_inner); + int32_t rin = dsc->radius; + int32_t short_side = LV_MIN(inner_w, inner_h); + if(rin > short_side >> 1) rin = short_side >> 1; + + lv_coord_t rout = rin + dsc->outline_width; + + draw_border_generic(clip, &area_outer, &area_inner, rout, rin, dsc->outline_color, dsc->outline_opa, dsc->blend_mode); +} + +void draw_border_generic(const lv_area_t * clip_area, const lv_area_t * outer_area, const lv_area_t * inner_area, + lv_coord_t rout, lv_coord_t rin, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode) +{ + opa = opa >= LV_OPA_COVER ? LV_OPA_COVER : opa; + + bool mask_any = lv_draw_mask_is_any(outer_area); + + if(!mask_any && rout == 0 && rin == 0) { + draw_border_simple(clip_area, outer_area, inner_area, color, opa); + return; + } + +#if LV_DRAW_COMPLEX + /*Get clipped draw area which is the real draw area. + *It is always the same or inside `coords`*/ + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, outer_area, clip_area)) return; + int32_t draw_area_w = lv_area_get_width(&draw_area); + + /*Create a mask if there is a radius*/ + lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w); + + /*Create mask for the outer area*/ + int16_t mask_rout_id = LV_MASK_ID_INV; + lv_draw_mask_radius_param_t mask_rout_param; + if(rout > 0) { + lv_draw_mask_radius_init(&mask_rout_param, outer_area, rout, false); + mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); + } + + /*Create mask for the inner mask*/ + lv_draw_mask_radius_param_t mask_rin_param; + lv_draw_mask_radius_init(&mask_rin_param, inner_area, rin, true); + int16_t mask_rin_id = lv_draw_mask_add(&mask_rin_param, NULL); + + int32_t h; + lv_draw_mask_res_t mask_res; + lv_area_t blend_area; + + /*Calculate the x and y coordinates where the straight parts area*/ + lv_area_t core_area; + core_area.x1 = LV_MAX(outer_area->x1 + rout, inner_area->x1); + core_area.x2 = LV_MIN(outer_area->x2 - rout, inner_area->x2); + core_area.y1 = LV_MAX(outer_area->y1 + rout, inner_area->y1); + core_area.y2 = LV_MIN(outer_area->y2 - rout, inner_area->y2); + lv_coord_t core_w = lv_area_get_width(&core_area); + + bool top_side = outer_area->y1 <= inner_area->y1 ? true : false; + bool bottom_side = outer_area->y2 >= inner_area->y2 ? true : false; + + /*If there is other masks, need to draw line by line*/ + if(mask_any) { + blend_area.x1 = draw_area.x1; + blend_area.x2 = draw_area.x2; + for(h = draw_area.y1; h <= draw_area.y2; h++) { + if(!top_side && h < core_area.y1) continue; + if(!bottom_side && h > core_area.y2) break; + + blend_area.y1 = h; + blend_area.y2 = h; + + lv_memset_ff(mask_buf, draw_area_w); + mask_res = lv_draw_mask_apply(mask_buf, draw_area.x1, h, draw_area_w); + _lv_blend_fill(clip_area, &blend_area, color, mask_buf, mask_res, opa, blend_mode); + } + + lv_draw_mask_free_param(&mask_rin_param); + lv_draw_mask_remove_id(mask_rin_id); + lv_draw_mask_free_param(&mask_rout_param); + lv_draw_mask_remove_id(mask_rout_id); + lv_mem_buf_release(mask_buf); + return; + } + + /*No masks*/ + bool left_side = outer_area->x1 <= inner_area->x1 ? true : false; + bool right_side = outer_area->x2 >= inner_area->x2 ? true : false; + + bool split_hor = true; + if(left_side && right_side && top_side && bottom_side && + core_w < SPLIT_LIMIT) { + split_hor = false; + } + + /*Draw the straight lines first if they are long enough*/ + if(top_side && split_hor) { + blend_area.x1 = core_area.x1; + blend_area.x2 = core_area.x2; + blend_area.y1 = outer_area->y1; + blend_area.y2 = inner_area->y1 - 1; + _lv_blend_fill(clip_area, &blend_area, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode); + } + + if(bottom_side && split_hor) { + blend_area.x1 = core_area.x1; + blend_area.x2 = core_area.x2; + blend_area.y1 = inner_area->y2 + 1; + blend_area.y2 = outer_area->y2; + _lv_blend_fill(clip_area, &blend_area, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode); + } + + if(left_side) { + blend_area.x1 = outer_area->x1; + blend_area.x2 = inner_area->x1 - 1; + blend_area.y1 = core_area.y1; + blend_area.y2 = core_area.y2; + _lv_blend_fill(clip_area, &blend_area, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode); + } + + if(right_side) { + blend_area.x1 = inner_area->x2 + 1; + blend_area.x2 = outer_area->x2; + blend_area.y1 = core_area.y1; + blend_area.y2 = core_area.y2; + _lv_blend_fill(clip_area, &blend_area, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode); + } + + /*Draw the corners*/ + lv_coord_t blend_w; + + /*Left and right corner together is they close to eachother*/ + if(!split_hor) { + /*Calculate the top corner and mirror it to the bottom*/ + blend_area.x1 = draw_area.x1; + blend_area.x2 = draw_area.x2; + lv_coord_t max_h = LV_MAX(rout, outer_area->y1 - inner_area->y1); + for(h = 0; h < max_h; h++) { + lv_coord_t top_y = outer_area->y1 + h; + lv_coord_t bottom_y = outer_area->y2 - h; + if(top_y < draw_area.y1 && bottom_y > draw_area.y2) continue; /*This line is clipped now*/ + + lv_memset_ff(mask_buf, draw_area_w); + mask_res = lv_draw_mask_apply(mask_buf, blend_area.x1, top_y, draw_area_w); + + if(top_y >= draw_area.y1) { + blend_area.y1 = top_y; + blend_area.y2 = top_y; + _lv_blend_fill(clip_area, &blend_area, color, mask_buf, mask_res, opa, blend_mode); + } + + if(bottom_y <= draw_area.y2) { + blend_area.y1 = bottom_y; + blend_area.y2 = bottom_y; + _lv_blend_fill(clip_area, &blend_area, color, mask_buf, mask_res, opa, blend_mode); + } + } + } + else { + /*Left corners*/ + blend_area.x1 = draw_area.x1; + blend_area.x2 = LV_MIN(draw_area.x2, core_area.x1 - 1); + blend_w = lv_area_get_width(&blend_area); + if(blend_w > 0) { + if(left_side || top_side) { + for(h = draw_area.y1; h < core_area.y1; h++) { + blend_area.y1 = h; + blend_area.y2 = h; + + lv_memset_ff(mask_buf, blend_w); + mask_res = lv_draw_mask_apply(mask_buf, blend_area.x1, h, blend_w); + _lv_blend_fill(clip_area, &blend_area, color, mask_buf, mask_res, opa, blend_mode); + } + } + + if(left_side || bottom_side) { + for(h = core_area.y2 + 1; h <= draw_area.y2; h++) { + blend_area.y1 = h; + blend_area.y2 = h; + + lv_memset_ff(mask_buf, blend_w); + mask_res = lv_draw_mask_apply(mask_buf, blend_area.x1, h, blend_w); + _lv_blend_fill(clip_area, &blend_area, color, mask_buf, mask_res, opa, blend_mode); + } + } + } + + /*Right corners*/ + blend_area.x1 = LV_MAX(draw_area.x1, core_area.x2 + 1); + blend_area.x2 = draw_area.x2; + blend_w = lv_area_get_width(&blend_area); + + if(blend_w > 0) { + if(right_side || top_side) { + for(h = draw_area.y1; h < core_area.y1; h++) { + blend_area.y1 = h; + blend_area.y2 = h; + + lv_memset_ff(mask_buf, blend_w); + mask_res = lv_draw_mask_apply(mask_buf, blend_area.x1, h, blend_w); + _lv_blend_fill(clip_area, &blend_area, color, mask_buf, mask_res, opa, blend_mode); + } + } + + if(right_side || bottom_side) { + for(h = core_area.y2 + 1; h <= draw_area.y2; h++) { + blend_area.y1 = h; + blend_area.y2 = h; + + lv_memset_ff(mask_buf, blend_w); + mask_res = lv_draw_mask_apply(mask_buf, blend_area.x1, h, blend_w); + _lv_blend_fill(clip_area, &blend_area, color, mask_buf, mask_res, opa, blend_mode); + } + } + } + } + + lv_draw_mask_free_param(&mask_rin_param); + lv_draw_mask_remove_id(mask_rin_id); + lv_draw_mask_free_param(&mask_rout_param); + lv_draw_mask_remove_id(mask_rout_id); + lv_mem_buf_release(mask_buf); + +#else /*LV_DRAW_COMPLEX*/ + LV_UNUSED(blend_mode); +#endif /*LV_DRAW_COMPLEX*/ +} + +static void draw_border_simple(const lv_area_t * clip, const lv_area_t * outer_area, const lv_area_t * inner_area, + lv_color_t color, lv_opa_t opa) +{ + bool top_side = outer_area->y1 <= inner_area->y1 ? true : false; + bool bottom_side = outer_area->y2 >= inner_area->y2 ? true : false; + bool left_side = outer_area->x1 <= inner_area->x1 ? true : false; + bool right_side = outer_area->x2 >= inner_area->x2 ? true : false; + + lv_area_t a; + /*Top*/ + a.x1 = outer_area->x1; + a.x2 = outer_area->x2; + a.y1 = outer_area->y1; + a.y2 = inner_area->y1 - 1; + if(top_side) { + _lv_blend_fill(clip, &a, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, LV_BLEND_MODE_NORMAL); + } + + /*Bottom*/ + a.y1 = inner_area->y2 + 1; + a.y2 = outer_area->y2; + if(bottom_side) { + _lv_blend_fill(clip, &a, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, LV_BLEND_MODE_NORMAL); + } + + /*Left*/ + a.x1 = outer_area->x1; + a.x2 = inner_area->x1 - 1; + a.y1 = (top_side) ? inner_area->y1 : outer_area->y1; + a.y2 = (bottom_side) ? inner_area->y2 : outer_area->y2; + if(left_side) { + _lv_blend_fill(clip, &a, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, LV_BLEND_MODE_NORMAL); + } + + /*Right*/ + a.x1 = inner_area->x2 + 1; + a.x2 = outer_area->x2; + if(right_side) { + _lv_blend_fill(clip, &a, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, LV_BLEND_MODE_NORMAL); + } + +} + +#endif diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_rect.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.h similarity index 90% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_rect.h rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.h index f4d05922b..f43a0eafb 100644 --- a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_rect.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.h @@ -37,7 +37,7 @@ typedef struct { uint8_t bg_main_color_stop; uint8_t bg_grad_color_stop; lv_opa_t bg_opa; - lv_grad_dir_t bg_grad_dir :3; + lv_grad_dir_t bg_grad_dir : 3; /*Background img*/ const void * bg_img_src; @@ -52,7 +52,7 @@ typedef struct { lv_coord_t border_width; lv_opa_t border_opa; uint8_t border_post : 1; /*There is a border it will be drawn later.*/ - lv_border_side_t border_side :5; + lv_border_side_t border_side : 5; /*Outline*/ lv_color_t outline_color; @@ -80,10 +80,10 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc); /** * Draw a rectangle * @param coords the coordinates of the rectangle - * @param mask the rectangle will be drawn only in this mask + * @param clip the rectangle will be drawn only in this area * @param dsc pointer to an initialized `lv_draw_rect_dsc_t` variable */ -void lv_draw_rect(const lv_area_t * coords, const lv_area_t * mask, const lv_draw_rect_dsc_t * dsc); +void lv_draw_rect(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc); /** * Draw a pixel diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_triangle.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_triangle.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_triangle.c rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw_triangle.c diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_triangle.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_triangle.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_draw_triangle.h rename to lib/libesp32_lvgl/lvgl/src/draw/lv_draw_triangle.h diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_img_buf.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.c similarity index 98% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_img_buf.c rename to lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.c index e01c77313..07ea03c52 100644 --- a/lib/libesp32_lvgl/LVGL8/src/draw/lv_img_buf.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.c @@ -367,7 +367,7 @@ void lv_img_buf_free(lv_img_dsc_t * dsc) { if(dsc != NULL) { if(dsc->data != NULL) - lv_mem_free((void*)dsc->data); + lv_mem_free((void *)dsc->data); lv_mem_free(dsc); } @@ -483,10 +483,10 @@ void _lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t return; } - res->x1 = (((-pivot->x) * zoom) >> 8) - 1; - res->y1 = (((-pivot->y) * zoom) >> 8) - 1; - res->x2 = (((w - pivot->x) * zoom) >> 8) + 2; - res->y2 = (((h - pivot->y) * zoom) >> 8) + 2; + res->x1 = (((int32_t)(-pivot->x) * zoom) >> 8) - 1; + res->y1 = (((int32_t)(-pivot->y) * zoom) >> 8) - 1; + res->x2 = (((int32_t)(w - pivot->x) * zoom) >> 8) + 2; + res->y2 = (((int32_t)(h - pivot->y) * zoom) >> 8) + 2; if(angle == 0) { res->x1 += pivot->x; @@ -710,7 +710,7 @@ bool _lv_img_buf_transform_anti_alias(lv_img_transform_dsc_t * dsc) lv_memcpy_small(&c01, &src_u8[dsc->tmp.pxi + dsc->tmp.px_size * xn], sizeof(lv_color_t)); lv_memcpy_small(&c10, &src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn], sizeof(lv_color_t)); lv_memcpy_small(&c11, &src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size * xn], - sizeof(lv_color_t)); + sizeof(lv_color_t)); if(dsc->tmp.has_alpha) { a10 = src_u8[dsc->tmp.pxi + dsc->tmp.px_size * xn + dsc->tmp.px_size - 1]; a01 = src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size - 1]; diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_img_buf.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_img_buf.h rename to lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.h diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_img_cache.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_cache.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_img_cache.c rename to lib/libesp32_lvgl/lvgl/src/draw/lv_img_cache.c diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_img_cache.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_cache.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_img_cache.h rename to lib/libesp32_lvgl/lvgl/src/draw/lv_img_cache.h diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_img_decoder.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.c similarity index 96% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_img_decoder.c rename to lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.c index cb42c8fe6..3678a5712 100644 --- a/lib/libesp32_lvgl/LVGL8/src/draw/lv_img_decoder.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.c @@ -82,7 +82,15 @@ void _lv_img_decoder_init(void) */ lv_res_t lv_img_decoder_get_info(const void * src, lv_img_header_t * header) { - lv_memset_00(header, sizeof(lv_img_header_t)); + lv_memset_00(header, sizeof(lv_img_header_t)); + + if(src == NULL) return LV_RES_INV; + + lv_img_src_t src_type = lv_img_src_get_type(src); + if(src_type == LV_IMG_SRC_VARIABLE) { + const lv_img_dsc_t * img_dsc = src; + if(img_dsc->data == NULL) return LV_RES_INV; + } lv_res_t res = LV_RES_INV; lv_img_decoder_t * d; @@ -100,8 +108,15 @@ lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, lv_co { lv_memset_00(dsc, sizeof(lv_img_decoder_dsc_t)); + if(src == NULL) return LV_RES_INV; + lv_img_src_t src_type = lv_img_src_get_type(src); + if(src_type == LV_IMG_SRC_VARIABLE) { + const lv_img_dsc_t * img_dsc = src; + if(img_dsc->data == NULL) return LV_RES_INV; + } + dsc->color = color; - dsc->src_type = lv_img_src_get_type(src); + dsc->src_type = src_type; dsc->frame_id = frame_id; if(dsc->src_type == LV_IMG_SRC_FILE) { @@ -144,7 +159,7 @@ lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, lv_co } if(dsc->src_type == LV_IMG_SRC_FILE) - lv_mem_free((void*)dsc->src); + lv_mem_free((void *)dsc->src); return res; } @@ -176,7 +191,7 @@ void lv_img_decoder_close(lv_img_decoder_dsc_t * dsc) if(dsc->decoder->close_cb) dsc->decoder->close_cb(dsc->decoder, dsc); if(dsc->src_type == LV_IMG_SRC_FILE) { - lv_mem_free((void*)dsc->src); + lv_mem_free((void *)dsc->src); dsc->src = NULL; } } @@ -257,7 +272,7 @@ void lv_img_decoder_set_close_cb(lv_img_decoder_t * decoder, lv_img_decoder_clos */ lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header) { - (void)decoder; /*Unused*/ + LV_UNUSED(decoder); /*Unused*/ lv_img_src_t src_type = lv_img_src_get_type(src); if(src_type == LV_IMG_SRC_VARIABLE) { @@ -420,7 +435,7 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder /*Free the potentially allocated memories*/ lv_img_decoder_built_in_close(decoder, dsc); - LV_LOG_WARN("Image decoder open: unknown color format") + LV_LOG_WARN("Image decoder open: unknown color format"); return LV_RES_INV; } } @@ -439,7 +454,7 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf) { - (void)decoder; /*Unused*/ + LV_UNUSED(decoder); /*Unused*/ lv_res_t res = LV_RES_INV; @@ -474,7 +489,7 @@ lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_de */ void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) { - (void)decoder; /*Unused*/ + LV_UNUSED(decoder); /*Unused*/ lv_img_decoder_built_in_data_t * user_data = dsc->user_data; if(user_data) { @@ -579,7 +594,7 @@ static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, l lv_img_decoder_built_in_data_t * user_data = dsc->user_data; uint8_t * fs_buf = lv_mem_buf_get(w); - if (fs_buf == NULL) return LV_RES_INV; + if(fs_buf == NULL) return LV_RES_INV; const uint8_t * data_tmp = NULL; if(dsc->src_type == LV_IMG_SRC_VARIABLE) { @@ -648,7 +663,7 @@ static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc, lv_img_decoder_built_in_data_t * user_data = dsc->user_data; uint8_t * fs_buf = lv_mem_buf_get(w); - if (fs_buf == NULL) return LV_RES_INV; + if(fs_buf == NULL) return LV_RES_INV; const uint8_t * data_tmp = NULL; if(dsc->src_type == LV_IMG_SRC_VARIABLE) { const lv_img_dsc_t * img_dsc = dsc->src; diff --git a/lib/libesp32_lvgl/LVGL8/src/draw/lv_img_decoder.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/draw/lv_img_decoder.h rename to lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.h diff --git a/lib/libesp32_lvgl/lvgl/src/extra/README.md b/lib/libesp32_lvgl/lvgl/src/extra/README.md new file mode 100644 index 000000000..bd564a74c --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/README.md @@ -0,0 +1,30 @@ +# Extra components + +This directory contains extra (optional) components to lvgl. +It's a good place for contributions as there are less strict expectations about the completeness and flexibility of the components here. + +In other words, if you have created a complex widget from other widgets, or modified an existing widget with special events, styles or animations, or have a new feature that could work as a plugin to lvgl feel free to the share it here. + +## How to contribute +- Create a [Pull request](https://docs.lvgl.io/8.0/CONTRIBUTING.html#pull-request) with your new content +- Please and follow the [Coding style](https://github.com/lvgl/lvgl/blob/master/docs/CODING_STYLE.md) of LVGL +- Add setter/getter functions in pair +- Update [lv_conf_template.h](https://github.com/lvgl/lvgl/blob/master/lv_conf_template.h) +- Add description in the [docs](https://github.com/lvgl/lvgl/tree/master/docs) +- Add [examples](https://github.com/lvgl/lvgl/tree/master/examples) +- Update the [changelog](https://github.com/lvgl/lvgl/tree/master/docs/CHANGELOG.md) +- Add yourself to the [Contributors](#contributors) section below. + +## Ideas +Here some ideas as inspiration feel free to contribute with ideas too. +- New [Calendar headers](https://github.com/lvgl/lvgl/tree/master/src/extra/widgets/calendar) +- Color picker with RGB and or HSV bars +- Ruler, horizontal or vertical with major and minor ticks and labels +- New [List items types](https://github.com/lvgl/lvgl/tree/master/src/extra/widgets/list) +- [Preloaders](https://www.google.com/search?q=preloader&sxsrf=ALeKk01ddA4YB0WEgLLN1bZNSm8YER7pkg:1623080551559&source=lnms&tbm=isch&sa=X&ved=2ahUKEwiwoN6d7oXxAhVuw4sKHVedBB4Q_AUoAXoECAEQAw&biw=952&bih=940) +- Drop-down list with a container to which an content can be added +- 9 patch button: Similar to [lv_imgbtn](https://docs.lvgl.io/8.0/widgets/extra/imgbtn.html) but 9 images for 4 corner, 4 sides and the center + +## Contributors +- lv_animimg: @ZhaoQiang-b45475 +- lv_span: @guoweilkd diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/extra.mk b/lib/libesp32_lvgl/lvgl/src/extra/extra.mk similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/extra/extra.mk rename to lib/libesp32_lvgl/lvgl/src/extra/extra.mk diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/layouts/flex/lv_flex.c b/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.c similarity index 83% rename from lib/libesp32_lvgl/LVGL8/src/extra/layouts/flex/lv_flex.c rename to lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.c index c618d16f1..7538ae4ae 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/layouts/flex/lv_flex.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.c @@ -21,10 +21,10 @@ typedef struct { lv_flex_align_t main_place; lv_flex_align_t cross_place; lv_flex_align_t track_place; - uint8_t row :1; - uint8_t wrap :1; - uint8_t rev :1; -}flex_t; + uint8_t row : 1; + uint8_t wrap : 1; + uint8_t rev : 1; +} flex_t; typedef struct { lv_obj_t * item; @@ -32,8 +32,8 @@ typedef struct { lv_coord_t max_size; lv_coord_t final_size; uint32_t grow_value; - uint32_t clamped :1; -}grow_dsc_t; + uint32_t clamped : 1; +} grow_dsc_t; typedef struct { lv_coord_t track_cross_size; @@ -42,8 +42,8 @@ typedef struct { uint32_t item_cnt; grow_dsc_t * grow_dsc; uint32_t grow_item_cnt; - uint32_t grow_dsc_calc :1; -}track_t; + uint32_t grow_dsc_calc : 1; +} track_t; /********************** @@ -54,9 +54,12 @@ typedef struct { * STATIC PROTOTYPES **********************/ static void flex_update(lv_obj_t * cont, void * user_data); -static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, lv_coord_t item_gap, lv_coord_t max_main_size, track_t * t); -static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, int32_t item_last_id, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t max_main_size, lv_coord_t item_gap, track_t * t); -static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t content_size, lv_coord_t item_cnt, lv_coord_t * start_pos, lv_coord_t * gap); +static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, lv_coord_t item_gap, + lv_coord_t max_main_size, track_t * t); +static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, int32_t item_last_id, lv_coord_t abs_x, + lv_coord_t abs_y, lv_coord_t max_main_size, lv_coord_t item_gap, track_t * t); +static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t content_size, lv_coord_t item_cnt, + lv_coord_t * start_pos, lv_coord_t * gap); static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, int32_t * item_id); /********************** @@ -102,7 +105,8 @@ void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow) lv_obj_set_style_layout(obj, LV_LAYOUT_FLEX, 0); } -void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place, lv_flex_align_t track_place) +void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place, + lv_flex_align_t track_place) { lv_obj_set_style_flex_main_place(obj, main_place, 0); lv_obj_set_style_flex_cross_place(obj, cross_place, 0); @@ -152,7 +156,7 @@ void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value) void lv_style_set_flex_grow(lv_style_t * style, uint8_t value) { lv_style_value_t v = { - .num = (int32_t)value + .num = (int32_t)value }; lv_style_set_prop(style, LV_STYLE_FLEX_GROW, v); } @@ -204,7 +208,7 @@ void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector static void flex_update(lv_obj_t * cont, void * user_data) { - LV_LOG_INFO("update %p container", cont); + LV_LOG_INFO("update %p container", (void *)cont); LV_UNUSED(user_data); flex_t f; @@ -217,12 +221,16 @@ static void flex_update(lv_obj_t * cont, void * user_data) f.track_place = lv_obj_get_style_flex_track_place(cont, LV_PART_MAIN); bool rtl = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false; - lv_coord_t track_gap = !f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont, LV_PART_MAIN); - lv_coord_t item_gap = f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont, LV_PART_MAIN); + lv_coord_t track_gap = !f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont, + LV_PART_MAIN); + lv_coord_t item_gap = f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont, + LV_PART_MAIN); lv_coord_t max_main_size = (f.row ? lv_obj_get_content_width(cont) : lv_obj_get_content_height(cont)); - lv_coord_t border_widt = lv_obj_get_style_border_width(cont, LV_PART_MAIN); - lv_coord_t abs_y = cont->coords.y1 + lv_obj_get_style_pad_top(cont, LV_PART_MAIN) + border_widt - lv_obj_get_scroll_y(cont); - lv_coord_t abs_x = cont->coords.x1 + lv_obj_get_style_pad_left(cont, LV_PART_MAIN) + border_widt - lv_obj_get_scroll_x(cont); + lv_coord_t border_width = lv_obj_get_style_border_width(cont, LV_PART_MAIN); + lv_coord_t abs_y = cont->coords.y1 + lv_obj_get_style_pad_top(cont, + LV_PART_MAIN) + border_width - lv_obj_get_scroll_y(cont); + lv_coord_t abs_x = cont->coords.x1 + lv_obj_get_style_pad_left(cont, + LV_PART_MAIN) + border_width - lv_obj_get_scroll_x(cont); lv_flex_align_t track_cross_place = f.track_place; lv_coord_t * cross_pos = (f.row ? &abs_y : &abs_x); @@ -232,8 +240,7 @@ static void flex_update(lv_obj_t * cont, void * user_data) /*Content sized objects should squeezed the gap between the children, therefore any alignment will look like `START`*/ if((f.row && h_set == LV_SIZE_CONTENT && cont->h_layout == 0) || - (!f.row && w_set == LV_SIZE_CONTENT && cont->w_layout == 0)) - { + (!f.row && w_set == LV_SIZE_CONTENT && cont->w_layout == 0)) { track_cross_place = LV_FLEX_ALIGN_START; } @@ -270,7 +277,7 @@ static void flex_update(lv_obj_t * cont, void * user_data) track_first_item = f.rev ? cont->spec_attr->child_cnt - 1 : 0; if(rtl && !f.row) { - *cross_pos += total_track_cross_size; + *cross_pos += total_track_cross_size; } while(track_first_item < (int32_t)cont->spec_attr->child_cnt && track_first_item >= 0) { @@ -288,7 +295,8 @@ static void flex_update(lv_obj_t * cont, void * user_data) t.grow_dsc = NULL; if(rtl && !f.row) { *cross_pos -= gap + track_gap; - } else { + } + else { *cross_pos += t.track_cross_size + gap + track_gap; } } @@ -306,7 +314,8 @@ static void flex_update(lv_obj_t * cont, void * user_data) /** * Find the last item of a track */ -static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, lv_coord_t max_main_size, lv_coord_t item_gap, track_t * t) +static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, lv_coord_t max_main_size, + lv_coord_t item_gap, track_t * t) { lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN); lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN); @@ -318,7 +327,6 @@ static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id lv_coord_t(*get_main_size)(const lv_obj_t *) = (f->row ? lv_obj_get_width : lv_obj_get_height); lv_coord_t(*get_cross_size)(const lv_obj_t *) = (!f->row ? lv_obj_get_width : lv_obj_get_height); - lv_coord_t grow_sum = 0; t->track_main_size = 0; t->track_fix_main_size = 0; t->grow_item_cnt = 0; @@ -335,7 +343,6 @@ static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id if(!lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) { uint8_t grow_value = lv_obj_get_style_flex_grow(item, LV_PART_MAIN); if(grow_value) { - grow_sum += grow_value; t->grow_item_cnt++; t->track_fix_main_size += item_gap; if(t->grow_dsc_calc) { @@ -348,13 +355,16 @@ static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id lv_mem_buf_release(t->grow_dsc); } new_dsc[t->grow_item_cnt - 1].item = item; - new_dsc[t->grow_item_cnt - 1].min_size = f->row ? lv_obj_get_style_min_width(item, LV_PART_MAIN) : lv_obj_get_style_min_height(item, LV_PART_MAIN); - new_dsc[t->grow_item_cnt - 1].max_size = f->row ? lv_obj_get_style_max_width(item, LV_PART_MAIN) : lv_obj_get_style_max_height(item, LV_PART_MAIN); + new_dsc[t->grow_item_cnt - 1].min_size = f->row ? lv_obj_get_style_min_width(item, + LV_PART_MAIN) : lv_obj_get_style_min_height(item, LV_PART_MAIN); + new_dsc[t->grow_item_cnt - 1].max_size = f->row ? lv_obj_get_style_max_width(item, + LV_PART_MAIN) : lv_obj_get_style_max_height(item, LV_PART_MAIN); new_dsc[t->grow_item_cnt - 1].grow_value = grow_value; new_dsc[t->grow_item_cnt - 1].clamped = 0; t->grow_dsc = new_dsc; } - } else { + } + else { lv_coord_t item_size = get_main_size(item); if(f->wrap && t->track_fix_main_size + item_size > max_main_size) break; t->track_fix_main_size += item_size + item_gap; @@ -392,7 +402,8 @@ static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id /** * Position the children in the same track */ -static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, int32_t item_last_id, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t max_main_size, lv_coord_t item_gap, track_t * t) +static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, int32_t item_last_id, lv_coord_t abs_x, + lv_coord_t abs_y, lv_coord_t max_main_size, lv_coord_t item_gap, track_t * t) { void (*area_set_main_size)(lv_area_t *, lv_coord_t) = (f->row ? lv_area_set_width : lv_area_set_height); lv_coord_t (*area_get_main_size)(const lv_area_t *) = (f->row ? lv_area_get_width : lv_area_get_height); @@ -408,7 +419,8 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i for(i = 0; i < t->grow_item_cnt; i++) { if(t->grow_dsc[i].clamped == 0) { grow_value_sum += t->grow_dsc[i].grow_value; - } else { + } + else { grow_max_size -= t->grow_dsc[i].final_size; } } @@ -470,23 +482,24 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i lv_event_send(lv_obj_get_parent(item), LV_EVENT_CHILD_CHANGED, item); lv_obj_invalidate(item); } - } else { + } + else { item->w_layout = 0; item->h_layout = 0; } lv_coord_t cross_pos = 0; switch(f->cross_place) { - case LV_FLEX_ALIGN_CENTER: - /*Round up the cross size to avoid rounding error when dividing by 2 - *The issue comes up e,g, with column direction with center cross direction if an element's width changes*/ - cross_pos = (((t->track_cross_size + 1) & (~1)) - area_get_cross_size(&item->coords)) / 2; - break; - case LV_FLEX_ALIGN_END: - cross_pos = t->track_cross_size - area_get_cross_size(&item->coords); - break; - default: - break; + case LV_FLEX_ALIGN_CENTER: + /*Round up the cross size to avoid rounding error when dividing by 2 + *The issue comes up e,g, with column direction with center cross direction if an element's width changes*/ + cross_pos = (((t->track_cross_size + 1) & (~1)) - area_get_cross_size(&item->coords)) / 2; + break; + case LV_FLEX_ALIGN_END: + cross_pos = t->track_cross_size - area_get_cross_size(&item->coords); + break; + default: + break; } if(f->row && rtl) main_pos -= area_get_main_size(&item->coords); @@ -525,7 +538,8 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i /** * Tell a start coordinate and gap for a placement type. */ -static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t content_size, lv_coord_t item_cnt, lv_coord_t * start_pos, lv_coord_t * gap) +static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t content_size, lv_coord_t item_cnt, + lv_coord_t * start_pos, lv_coord_t * gap) { if(item_cnt <= 1) { switch(place) { @@ -540,27 +554,27 @@ static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t } switch(place) { - case LV_FLEX_ALIGN_CENTER: - *gap = 0; - *start_pos += (max_size - content_size) / 2; - break; - case LV_FLEX_ALIGN_END: - *gap = 0; - *start_pos += max_size - content_size; - break; - case LV_FLEX_ALIGN_SPACE_BETWEEN: - *gap = (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt - 1); - break; - case LV_FLEX_ALIGN_SPACE_AROUND: - *gap += (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt); - *start_pos += *gap / 2; - break; - case LV_FLEX_ALIGN_SPACE_EVENLY: - *gap = (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt + 1); - *start_pos += *gap; - break; - default: - *gap = 0; + case LV_FLEX_ALIGN_CENTER: + *gap = 0; + *start_pos += (max_size - content_size) / 2; + break; + case LV_FLEX_ALIGN_END: + *gap = 0; + *start_pos += max_size - content_size; + break; + case LV_FLEX_ALIGN_SPACE_BETWEEN: + *gap = (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt - 1); + break; + case LV_FLEX_ALIGN_SPACE_AROUND: + *gap += (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt); + *start_pos += *gap / 2; + break; + case LV_FLEX_ALIGN_SPACE_EVENLY: + *gap = (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt + 1); + *start_pos += *gap; + break; + default: + *gap = 0; } } @@ -570,7 +584,8 @@ static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, int32_t * item_id) (*item_id)--; if(*item_id >= 0) return cont->spec_attr->children[*item_id]; else return NULL; - } else { + } + else { (*item_id)++; if((*item_id) < (int32_t)cont->spec_attr->child_cnt) return cont->spec_attr->children[*item_id]; else return NULL; diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/layouts/flex/lv_flex.h b/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.h similarity index 95% rename from lib/libesp32_lvgl/LVGL8/src/extra/layouts/flex/lv_flex.h rename to lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.h index 62d3e7f80..139fd4810 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/layouts/flex/lv_flex.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.h @@ -41,7 +41,7 @@ typedef enum { LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_SPACE_AROUND, LV_FLEX_ALIGN_SPACE_BETWEEN, -}lv_flex_align_t; +} lv_flex_align_t; typedef enum { LV_FLEX_FLOW_ROW = 0x00, @@ -52,7 +52,7 @@ typedef enum { LV_FLEX_FLOW_COLUMN_WRAP = LV_FLEX_FLOW_COLUMN | _LV_FLEX_WRAP, LV_FLEX_FLOW_COLUMN_REVERSE = LV_FLEX_FLOW_COLUMN | _LV_FLEX_REVERSE, LV_FLEX_FLOW_COLUMN_WRAP_REVERSE = LV_FLEX_FLOW_COLUMN | _LV_FLEX_WRAP | _LV_FLEX_REVERSE, -}lv_flex_flow_t; +} lv_flex_flow_t; /********************** * GLOBAL VARIABLES @@ -69,7 +69,7 @@ extern lv_style_prop_t LV_STYLE_FLEX_GROW; **********************/ /** - * Initialize a felx layout the default values + * Initialize a flex layout the default values * @param flex pointer to a flex layout descriptor */ void lv_flex_init(void); @@ -82,13 +82,14 @@ void lv_flex_init(void); void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow); /** - * Set how to place (where to align) the items an tracks + * Set how to place (where to align) the items and tracks * @param flex pointer: to a flex layout descriptor * @param main_place where to place the items on main axis (in their track). Any value of `lv_flex_align_t`. * @param cross_place where to place the item in their track on the cross axis. `LV_FLEX_ALIGN_START/END/CENTER` * @param track_place where to place the tracks in the cross direction. Any value of `lv_flex_align_t`. */ -void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place, lv_flex_align_t track_cross_place); +void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place, + lv_flex_align_t track_cross_place); /** * Sets the width or height (on main axis) to grow the object in order fill the free space diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/layouts/grid/lv_grid.c b/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.c similarity index 86% rename from lib/libesp32_lvgl/LVGL8/src/extra/layouts/grid/lv_grid.c rename to lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.c index 3cd7c689f..027f6af31 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/layouts/grid/lv_grid.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.c @@ -27,7 +27,7 @@ typedef struct { uint32_t col; uint32_t row; lv_point_t grid_abs; -}item_repos_hint_t; +} item_repos_hint_t; typedef struct { lv_coord_t * x; @@ -38,7 +38,7 @@ typedef struct { uint32_t row_num; lv_coord_t grid_w; lv_coord_t grid_h; -}_lv_grid_calc_t; +} _lv_grid_calc_t; /********************** @@ -54,19 +54,50 @@ static void calc_free(_lv_grid_calc_t * calc); static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c); static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c); static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * hint); -static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t align, lv_coord_t gap, uint32_t track_num, lv_coord_t * size_array, lv_coord_t * pos_array, bool reverse); +static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t align, lv_coord_t gap, uint32_t track_num, + lv_coord_t * size_array, lv_coord_t * pos_array, bool reverse); static uint32_t count_tracks(const lv_coord_t * templ); -static inline const lv_coord_t * get_col_dsc(lv_obj_t * obj) {return lv_obj_get_style_grid_column_dsc_array(obj, 0); } -static inline const lv_coord_t * get_row_dsc(lv_obj_t * obj) {return lv_obj_get_style_grid_row_dsc_array(obj, 0); } -static inline uint8_t get_col_pos(lv_obj_t * obj) {return lv_obj_get_style_grid_cell_column_pos(obj, 0); } -static inline uint8_t get_row_pos(lv_obj_t * obj) {return lv_obj_get_style_grid_cell_row_pos(obj, 0); } -static inline uint8_t get_col_span(lv_obj_t * obj) {return lv_obj_get_style_grid_cell_column_span(obj, 0); } -static inline uint8_t get_row_span(lv_obj_t * obj) {return lv_obj_get_style_grid_cell_row_span(obj, 0); } -static inline uint8_t get_cell_col_align(lv_obj_t * obj) {return lv_obj_get_style_grid_cell_x_align(obj, 0); } -static inline uint8_t get_cell_row_align(lv_obj_t * obj) {return lv_obj_get_style_grid_cell_y_align(obj, 0); } -static inline uint8_t get_grid_col_align(lv_obj_t * obj) {return lv_obj_get_style_grid_column_align(obj, 0); } -static inline uint8_t get_grid_row_align(lv_obj_t * obj) {return lv_obj_get_style_grid_row_align(obj, 0); } +static inline const lv_coord_t * get_col_dsc(lv_obj_t * obj) +{ + return lv_obj_get_style_grid_column_dsc_array(obj, 0); +} +static inline const lv_coord_t * get_row_dsc(lv_obj_t * obj) +{ + return lv_obj_get_style_grid_row_dsc_array(obj, 0); +} +static inline uint8_t get_col_pos(lv_obj_t * obj) +{ + return lv_obj_get_style_grid_cell_column_pos(obj, 0); +} +static inline uint8_t get_row_pos(lv_obj_t * obj) +{ + return lv_obj_get_style_grid_cell_row_pos(obj, 0); +} +static inline uint8_t get_col_span(lv_obj_t * obj) +{ + return lv_obj_get_style_grid_cell_column_span(obj, 0); +} +static inline uint8_t get_row_span(lv_obj_t * obj) +{ + return lv_obj_get_style_grid_cell_row_span(obj, 0); +} +static inline uint8_t get_cell_col_align(lv_obj_t * obj) +{ + return lv_obj_get_style_grid_cell_x_align(obj, 0); +} +static inline uint8_t get_cell_row_align(lv_obj_t * obj) +{ + return lv_obj_get_style_grid_cell_y_align(obj, 0); +} +static inline uint8_t get_grid_col_align(lv_obj_t * obj) +{ + return lv_obj_get_style_grid_column_align(obj, 0); +} +static inline uint8_t get_grid_row_align(lv_obj_t * obj) +{ + return lv_obj_get_style_grid_row_align(obj, 0); +} /********************** * GLOBAL VARIABLES @@ -128,7 +159,7 @@ void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid } void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t x_align, uint8_t col_pos, uint8_t col_span, - lv_grid_align_t y_align, uint8_t row_pos, uint8_t row_span) + lv_grid_align_t y_align, uint8_t row_pos, uint8_t row_span) { lv_obj_set_style_grid_cell_column_pos(obj, col_pos, 0); @@ -228,7 +259,7 @@ void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const lv_coord_t value[ lv_style_value_t v = { .ptr = (const void *)value }; - lv_obj_set_local_style_prop(obj,LV_STYLE_GRID_ROW_DSC_ARRAY, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_ROW_DSC_ARRAY, v, selector); } void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector) @@ -262,7 +293,7 @@ void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, lv_coord_t value, lv_ lv_style_value_t v = { .num = value }; - lv_obj_set_local_style_prop(obj,LV_STYLE_GRID_CELL_COLUMN_POS, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_POS, v, selector); } void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) @@ -270,7 +301,7 @@ void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, lv_coord_t value, lv lv_style_value_t v = { .num = value }; - lv_obj_set_local_style_prop(obj,LV_STYLE_GRID_CELL_COLUMN_SPAN, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_SPAN, v, selector); } void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) @@ -278,7 +309,7 @@ void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, lv_coord_t value, lv_sty lv_style_value_t v = { .num = value }; - lv_obj_set_local_style_prop(obj,LV_STYLE_GRID_CELL_ROW_POS, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_ROW_POS, v, selector); } void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) @@ -312,7 +343,7 @@ void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_coord_t value, lv_sty static void grid_update(lv_obj_t * cont, void * user_data) { - LV_LOG_INFO("update %p container", cont); + LV_LOG_INFO("update %p container", (void *)cont); LV_UNUSED(user_data); const lv_coord_t * col_templ = get_col_dsc(cont); @@ -376,11 +407,13 @@ static void calc(lv_obj_t * cont, _lv_grid_calc_t * calc_out) lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN); bool auto_w = (w_set == LV_SIZE_CONTENT && !cont->w_layout) ? true : false; lv_coord_t cont_w = lv_obj_get_content_width(cont); - calc_out->grid_w = grid_align(cont_w, auto_w, get_grid_col_align(cont), col_gap, calc_out->col_num, calc_out->w, calc_out->x, rev); + calc_out->grid_w = grid_align(cont_w, auto_w, get_grid_col_align(cont), col_gap, calc_out->col_num, calc_out->w, + calc_out->x, rev); bool auto_h = (h_set == LV_SIZE_CONTENT && !cont->h_layout) ? true : false; lv_coord_t cont_h = lv_obj_get_content_height(cont); - calc_out->grid_h = grid_align(cont_h, auto_h, get_grid_row_align(cont), row_gap, calc_out->row_num, calc_out->h, calc_out->y, false); + calc_out->grid_h = grid_align(cont_h, auto_h, get_grid_row_align(cont), row_gap, calc_out->row_num, calc_out->h, + calc_out->y, false); LV_ASSERT_MEM_INTEGRITY(); } @@ -437,7 +470,7 @@ static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c) if(IS_FR(x)) { col_fr_cnt += GET_FR(x); } - else if (IS_CONTENT(x)) { + else if(IS_CONTENT(x)) { grid_w += c->w[i]; } else { @@ -465,7 +498,7 @@ static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c) /*To avoid rounding errors set the last FR track to the remaining size */ if(last_fr_i >= 0) { - c->w[last_fr_i] = free_w - ((free_w * (col_fr_cnt - last_fr_x)) / col_fr_cnt); + c->w[last_fr_i] = free_w - ((free_w * (col_fr_cnt - last_fr_x)) / col_fr_cnt); } } @@ -505,9 +538,11 @@ static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c) lv_coord_t x = row_templ[i]; if(IS_FR(x)) { row_fr_cnt += GET_FR(x); - } else if (IS_CONTENT(x)) { + } + else if(IS_CONTENT(x)) { grid_h += c->h[i]; - } else { + } + else { c->h[i] = x; grid_h += x; } @@ -531,7 +566,7 @@ static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c) /*To avoid rounding errors set the last FR track to the remaining size */ if(last_fr_i >= 0) { - c->h[last_fr_i] = free_h - ((free_h * (row_fr_cnt - last_fr_x)) / row_fr_cnt); + c->h[last_fr_i] = free_h - ((free_h * (row_fr_cnt - last_fr_x)) / row_fr_cnt); } } @@ -666,14 +701,16 @@ static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * * @param pos_array write the positions of the tracks here * @return the total size of the grid */ -static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t align, lv_coord_t gap, uint32_t track_num, lv_coord_t * size_array, lv_coord_t * pos_array, bool reverse) +static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t align, lv_coord_t gap, uint32_t track_num, + lv_coord_t * size_array, lv_coord_t * pos_array, bool reverse) { lv_coord_t grid_size = 0; uint32_t i; if(auto_size) { pos_array[0] = 0; - } else { + } + else { /*With spaced alignment gap will be calculated from the remaining space*/ if(align == LV_GRID_ALIGN_SPACE_AROUND || align == LV_GRID_ALIGN_SPACE_BETWEEN || align == LV_GRID_ALIGN_SPACE_EVENLY) { gap = 0; @@ -688,27 +725,27 @@ static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t alig /*Calculate the position of the first item and set gap is necessary*/ switch(align) { - case LV_GRID_ALIGN_START: - pos_array[0] = 0; - break; - case LV_GRID_ALIGN_CENTER: - pos_array[0] = (cont_size - grid_size) / 2; - break; - case LV_GRID_ALIGN_END: - pos_array[0] = cont_size - grid_size; - break; - case LV_GRID_ALIGN_SPACE_BETWEEN: - pos_array[0] = 0; - gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num - 1); - break; - case LV_GRID_ALIGN_SPACE_AROUND: - gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num); - pos_array[0] = gap / 2; - break; - case LV_GRID_ALIGN_SPACE_EVENLY: - gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num + 1); - pos_array[0] = gap; - break; + case LV_GRID_ALIGN_START: + pos_array[0] = 0; + break; + case LV_GRID_ALIGN_CENTER: + pos_array[0] = (cont_size - grid_size) / 2; + break; + case LV_GRID_ALIGN_END: + pos_array[0] = cont_size - grid_size; + break; + case LV_GRID_ALIGN_SPACE_BETWEEN: + pos_array[0] = 0; + gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num - 1); + break; + case LV_GRID_ALIGN_SPACE_AROUND: + gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num); + pos_array[0] = gap / 2; + break; + case LV_GRID_ALIGN_SPACE_EVENLY: + gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num + 1); + pos_array[0] = gap; + break; } } @@ -734,7 +771,7 @@ static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t alig static uint32_t count_tracks(const lv_coord_t * templ) { uint32_t i; - for(i = 0; templ[i] != LV_COORD_MAX; i++); + for(i = 0; templ[i] != LV_GRID_TEMPLATE_LAST; i++); return i; } diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/layouts/grid/lv_grid.h b/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.h similarity index 96% rename from lib/libesp32_lvgl/LVGL8/src/extra/layouts/grid/lv_grid.h rename to lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.h index f2966d0d9..cd2510ec0 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/layouts/grid/lv_grid.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.h @@ -47,7 +47,7 @@ typedef enum { LV_GRID_ALIGN_SPACE_EVENLY, LV_GRID_ALIGN_SPACE_AROUND, LV_GRID_ALIGN_SPACE_BETWEEN, -}lv_grid_align_t; +} lv_grid_align_t; /********************** * GLOBAL VARIABLES @@ -78,15 +78,15 @@ void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid /** * Set the cell of an object. The object's parent needs to have grid layout, else nothing will happen * @param obj pointer to an object - * @param hor_place the vertical alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH` + * @param column_align the vertical alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH` * @param col_pos column ID * @param col_span number of columns to take (>= 1) - * @param ver_place the horizontal alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH` + * @param row_align the horizontal alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH` * @param row_pos row ID * @param row_span number of rows to take (>= 1) */ void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t column_align, uint8_t col_pos, uint8_t col_span, - lv_grid_align_t row_align, uint8_t row_pos, uint8_t row_span); + lv_grid_align_t row_align, uint8_t row_pos, uint8_t row_span); /** * Just a wrapper to `LV_GRID_FR` for bindings. diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/layouts/lv_layouts.h b/lib/libesp32_lvgl/lvgl/src/extra/layouts/lv_layouts.h similarity index 91% rename from lib/libesp32_lvgl/LVGL8/src/extra/layouts/lv_layouts.h rename to lib/libesp32_lvgl/lvgl/src/extra/layouts/lv_layouts.h index 0ad7b75b3..9c1e958d6 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/layouts/lv_layouts.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/layouts/lv_layouts.h @@ -32,7 +32,7 @@ extern "C" { * MACROS **********************/ #if LV_USE_LOG && LV_LOG_TRACE_LAYOUT -# define LV_TRACE_LAYOUT(...) LV_LOG_TRACE( __VA_ARGS__) +# define LV_TRACE_LAYOUT(...) LV_LOG_TRACE(__VA_ARGS__) #else # define LV_TRACE_LAYOUT(...) #endif diff --git a/lib/libesp32_lvgl/lv_lib_freetype/arial.ttf b/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/arial.ttf similarity index 100% rename from lib/libesp32_lvgl/lv_lib_freetype/arial.ttf rename to lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/arial.ttf diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.c new file mode 100644 index 000000000..96f68af21 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.c @@ -0,0 +1,486 @@ +/** + * @file lv_freetype.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_freetype.h" +#if LV_USE_FREETYPE + +#include "ft2build.h" +#include FT_FREETYPE_H +#include FT_GLYPH_H +#include FT_CACHE_H +#include FT_SIZES_H + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + char * name; +} lv_face_info_t; + +typedef struct { + lv_ll_t face_ll; +} lv_faces_control_t; + +typedef struct { +#if LV_FREETYPE_CACHE_SIZE >= 0 + void * face_id; +#else + FT_Size size; +#endif + lv_font_t * font; + uint16_t style; + uint16_t height; +} lv_font_fmt_ft_dsc_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +#if LV_FREETYPE_CACHE_SIZE >= 0 +static FT_Error font_face_requester(FTC_FaceID face_id, + FT_Library library_is, FT_Pointer req_data, FT_Face * aface); +static bool lv_ft_font_init_cache(lv_ft_info_t * info); +static void lv_ft_font_destroy_cache(lv_font_t * font); +static bool lv_ft_font_init_cache(lv_ft_info_t * info); +static void lv_ft_font_destroy_cache(lv_font_t * font); +#else +static FT_Face face_find_in_list(lv_ft_info_t * info); +static void face_add_to_list(FT_Face face); +static void face_remove_from_list(FT_Face face); +static void face_generic_finalizer(void * object); +static bool lv_ft_font_init_nocache(lv_ft_info_t * info); +static void lv_ft_font_destroy_nocache(lv_font_t * font); +#endif + +/********************** +* STATIC VARIABLES +**********************/ +static FT_Library library; + +#if LV_FREETYPE_CACHE_SIZE >= 0 + static FTC_Manager cache_manager; + static FTC_CMapCache cmap_cache; + static FTC_SBitCache sbit_cache; + static FTC_SBit sbit; +#else + static lv_faces_control_t face_control; +#endif + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +bool lv_freetype_init(uint16_t max_faces, uint16_t max_sizes, uint32_t max_bytes) +{ + FT_Error error = FT_Init_FreeType(&library); + if(error) { + LV_LOG_ERROR("init freeType error(%d)", error); + return false; + } + +#if LV_FREETYPE_CACHE_SIZE >= 0 + error = FTC_Manager_New(library, max_faces, max_sizes, + max_bytes, font_face_requester, NULL, &cache_manager); + if(error) { + FT_Done_FreeType(library); + LV_LOG_ERROR("Failed to open cache manager"); + return false; + } + + error = FTC_CMapCache_New(cache_manager, &cmap_cache); + if(error) { + LV_LOG_ERROR("Failed to open Cmap Cache"); + goto Fail; + } + + error = FTC_SBitCache_New(cache_manager, &sbit_cache); + if(error) { + LV_LOG_ERROR("Failed to open sbit cache"); + goto Fail; + } + + return true; +Fail: + FTC_Manager_Done(cache_manager); + FT_Done_FreeType(library); + return false; +#else + LV_UNUSED(max_faces); + LV_UNUSED(max_sizes); + LV_UNUSED(max_bytes); + _lv_ll_init(&face_control.face_ll, sizeof(FT_Face *)); + return true; +#endif/* LV_FREETYPE_CACHE_SIZE */ +} + +void lv_freetype_destroy(void) +{ +#if LV_FREETYPE_CACHE_SIZE >= 0 + FTC_Manager_Done(cache_manager); +#endif + FT_Done_FreeType(library); +} + +bool lv_ft_font_init(lv_ft_info_t * info) +{ +#if LV_FREETYPE_CACHE_SIZE >= 0 + return lv_ft_font_init_cache(info); +#else + return lv_ft_font_init_nocache(info); +#endif +} + +void lv_ft_font_destroy(lv_font_t * font) +{ +#if LV_FREETYPE_CACHE_SIZE >= 0 + lv_ft_font_destroy_cache(font); +#else + lv_ft_font_destroy_nocache(font); +#endif +} + +/********************** + * STATIC FUNCTIONS + **********************/ +#if LV_FREETYPE_CACHE_SIZE >= 0 + +static FT_Error font_face_requester(FTC_FaceID face_id, + FT_Library library_is, FT_Pointer req_data, FT_Face * aface) +{ + LV_UNUSED(library_is); + LV_UNUSED(req_data); + + lv_face_info_t * info = (lv_face_info_t *)face_id; + FT_Error error = FT_New_Face(library, info->name, 0, aface); + if(error) { + LV_LOG_ERROR("FT_New_Face error:%d\n", error); + return error; + } + return FT_Err_Ok; +} + +static bool get_glyph_dsc_cb_cache(const lv_font_t * font, + lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) +{ + LV_UNUSED(unicode_letter_next); + if(unicode_letter < 0x20) { + dsc_out->adv_w = 0; + dsc_out->box_h = 0; + dsc_out->box_w = 0; + dsc_out->ofs_x = 0; + dsc_out->ofs_y = 0; + dsc_out->bpp = 0; + return true; + } + + lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); + + FT_Face face; + FTC_ImageTypeRec desc_sbit_type; + FTC_FaceID face_id = (FTC_FaceID)dsc->face_id; + FTC_Manager_LookupFace(cache_manager, face_id, &face); + + desc_sbit_type.face_id = face_id; + desc_sbit_type.flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL; + desc_sbit_type.height = dsc->height; + desc_sbit_type.width = dsc->height; + FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap); + FT_UInt glyph_index = FTC_CMapCache_Lookup(cmap_cache, face_id, charmap_index, unicode_letter); + FT_Error error = FTC_SBitCache_Lookup(sbit_cache, &desc_sbit_type, glyph_index, &sbit, NULL); + if(error) { + LV_LOG_ERROR("SBitCache_Lookup error"); + } + + dsc_out->adv_w = sbit->xadvance; + dsc_out->box_h = sbit->height; /*Height of the bitmap in [px]*/ + dsc_out->box_w = sbit->width; /*Width of the bitmap in [px]*/ + dsc_out->ofs_x = sbit->left; /*X offset of the bitmap in [pf]*/ + dsc_out->ofs_y = sbit->top - sbit->height; /*Y offset of the bitmap measured from the as line*/ + dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ + + return true; +} + +static const uint8_t * get_glyph_bitmap_cb_cache(const lv_font_t * font, uint32_t unicode_letter) +{ + LV_UNUSED(font); + LV_UNUSED(unicode_letter); + return (const uint8_t *)sbit->buffer; +} + +static bool lv_ft_font_init_cache(lv_ft_info_t * info) +{ + lv_font_fmt_ft_dsc_t * dsc = lv_mem_alloc(sizeof(lv_font_fmt_ft_dsc_t)); + if(dsc == NULL) return false; + + dsc->font = lv_mem_alloc(sizeof(lv_font_t)); + if(dsc->font == NULL) { + lv_mem_free(dsc); + return false; + } + + lv_face_info_t * face_info = NULL; + face_info = lv_mem_alloc(sizeof(lv_face_info_t) + strlen(info->name) + 1); + if(face_info == NULL) { + goto Fail; + } + face_info->name = ((char *)face_info) + sizeof(lv_face_info_t); + strcpy(face_info->name, info->name); + + dsc->face_id = face_info; + dsc->height = info->weight; + dsc->style = info->style; + + /* use to get font info */ + FT_Size face_size; + struct FTC_ScalerRec_ scaler; + scaler.face_id = (FTC_FaceID)dsc->face_id; + scaler.width = info->weight; + scaler.height = info->weight; + scaler.pixel = 1; + FT_Error error = FTC_Manager_LookupSize(cache_manager, &scaler, &face_size); + if(error) { + lv_mem_free(face_info); + LV_LOG_ERROR("Failed to LookupSize"); + goto Fail; + } + + lv_font_t * font = dsc->font; + font->dsc = dsc; + font->get_glyph_dsc = get_glyph_dsc_cb_cache; + font->get_glyph_bitmap = get_glyph_bitmap_cb_cache; + font->subpx = LV_FONT_SUBPX_NONE; + font->line_height = (face_size->face->size->metrics.height >> 6); + font->base_line = -(face_size->face->size->metrics.descender >> 6); + + FT_Fixed scale = face_size->face->size->metrics.y_scale; + int8_t thickness = FT_MulFix(scale, face_size->face->underline_thickness) >> 6; + font->underline_position = FT_MulFix(scale, face_size->face->underline_position) >> 6; + font->underline_thickness = thickness < 1 ? 1 : thickness; + + /* return to user */ + info->font = font; + + return true; + +Fail: + lv_mem_free(dsc->font); + lv_mem_free(dsc); + return false; +} + +void lv_ft_font_destroy_cache(lv_font_t * font) +{ + if(font == NULL) { + return; + } + + lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); + if(dsc) { + lv_mem_free(dsc->face_id); + lv_mem_free(dsc->font); + lv_mem_free(dsc); + } +} + +#else/* LV_FREETYPE_CACHE_SIZE */ + +static FT_Face face_find_in_list(lv_ft_info_t * info) +{ + lv_face_info_t * face_info; + FT_Face * pface = _lv_ll_get_head(&face_control.face_ll); + while(pface) { + face_info = (lv_face_info_t *)(*pface)->generic.data; + if(strcmp(face_info->name, info->name) == 0) { + return *pface; + } + pface = _lv_ll_get_next(&face_control.face_ll, pface); + } + + return NULL; +} + +static void face_add_to_list(FT_Face face) +{ + FT_Face * pface; + pface = (FT_Face *)_lv_ll_ins_tail(&face_control.face_ll); + *pface = face; +} + +static void face_remove_from_list(FT_Face face) +{ + FT_Face * pface = _lv_ll_get_head(&face_control.face_ll); + while(pface) { + if(*pface == face) { + _lv_ll_remove(&face_control.face_ll, pface); + lv_mem_free(pface); + break; + } + pface = _lv_ll_get_next(&face_control.face_ll, pface); + } +} + +static void face_generic_finalizer(void * object) +{ + FT_Face face = (FT_Face)object; + face_remove_from_list(face); + if(face->generic.data) { + lv_face_info_t * face_info = (lv_face_info_t *)face->generic.data; + lv_mem_free(face_info); + } + LV_LOG_INFO("face finalizer(%p)\n", face); +} + +static bool get_glyph_dsc_cb_nocache(const lv_font_t * font, + lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) +{ + LV_UNUSED(unicode_letter_next); + if(unicode_letter < 0x20) { + dsc_out->adv_w = 0; + dsc_out->box_h = 0; + dsc_out->box_w = 0; + dsc_out->ofs_x = 0; + dsc_out->ofs_y = 0; + dsc_out->bpp = 0; + return true; + } + + FT_Error error; + lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); + FT_Face face = dsc->size->face; + + FT_UInt glyph_index = FT_Get_Char_Index(face, unicode_letter); + + if(face->size != dsc->size) { + FT_Activate_Size(dsc->size); + } + + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if(error) { + return false; + } + + error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); + if(error) { + return false; + } + + dsc_out->adv_w = (face->glyph->metrics.horiAdvance >> 6); + dsc_out->box_h = face->glyph->bitmap.rows; /*Height of the bitmap in [px]*/ + dsc_out->box_w = face->glyph->bitmap.width; /*Width of the bitmap in [px]*/ + dsc_out->ofs_x = face->glyph->bitmap_left; /*X offset of the bitmap in [pf]*/ + dsc_out->ofs_y = face->glyph->bitmap_top - + face->glyph->bitmap.rows; /*Y offset of the bitmap measured from the as line*/ + dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ + + return true; +} + +static const uint8_t * get_glyph_bitmap_cb_nocache(const lv_font_t * font, uint32_t unicode_letter) +{ + LV_UNUSED(unicode_letter); + lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); + FT_Face face = dsc->size->face; + return (const uint8_t *)(face->glyph->bitmap.buffer); +} + +static bool lv_ft_font_init_nocache(lv_ft_info_t * info) +{ + lv_font_fmt_ft_dsc_t * dsc = lv_mem_alloc(sizeof(lv_font_fmt_ft_dsc_t)); + if(dsc == NULL) return false; + + dsc->font = lv_mem_alloc(sizeof(lv_font_t)); + if(dsc->font == NULL) { + lv_mem_free(dsc); + return false; + } + + lv_face_info_t * face_info = NULL; + FT_Face face = face_find_in_list(info); + if(face == NULL) { + face_info = lv_mem_alloc(sizeof(lv_face_info_t) + strlen(info->name) + 1); + if(face_info == NULL) { + goto Fail; + } + FT_Error error = FT_New_Face(library, info->name, 0, &face); + if(error) { + lv_mem_free(face_info); + LV_LOG_WARN("create face error(%d)", error); + goto Fail; + } + + /* link face and face info */ + face_info->name = ((char *)face_info) + sizeof(lv_face_info_t); + strcpy(face_info->name, info->name); + face->generic.data = face_info; + face->generic.finalizer = face_generic_finalizer; + face_add_to_list(face); + } + else { + FT_Size size; + FT_Error error = FT_New_Size(face, &size); + if(error) { + goto Fail; + } + FT_Activate_Size(size); + FT_Reference_Face(face); + } + + FT_Set_Pixel_Sizes(face, 0, info->weight); + dsc->size = face->size; + dsc->height = info->weight; + dsc->style = info->style; + + lv_font_t * font = dsc->font; + font->dsc = dsc; + font->get_glyph_dsc = get_glyph_dsc_cb_nocache; + font->get_glyph_bitmap = get_glyph_bitmap_cb_nocache; + font->line_height = (face->size->metrics.height >> 6); + font->base_line = -(face->size->metrics.descender >> 6); + font->subpx = LV_FONT_SUBPX_NONE; + + FT_Fixed scale = face->size->metrics.y_scale; + int8_t thickness = FT_MulFix(scale, face->underline_thickness) >> 6; + font->underline_position = FT_MulFix(scale, face->underline_position) >> 6; + font->underline_thickness = thickness < 1 ? 1 : thickness; + + info->font = font; + return true; + +Fail: + lv_mem_free(dsc->font); + lv_mem_free(dsc); + return false; +} + +static void lv_ft_font_destroy_nocache(lv_font_t * font) +{ + if(font == NULL) { + return; + } + + lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); + if(dsc) { + FT_Face face = dsc->size->face; + FT_Done_Size(dsc->size); + FT_Done_Face(face); + lv_mem_free(dsc->font); + lv_mem_free(dsc); + } +} + +#endif/* LV_FREETYPE_CACHE_SIZE */ + +#endif /*LV_USE_FREETYPE*/ diff --git a/lib/libesp32_lvgl/lv_lib_freetype/lv_freetype.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.h similarity index 60% rename from lib/libesp32_lvgl/lv_lib_freetype/lv_freetype.h rename to lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.h index 1b419b99a..3f1fe7076 100644 --- a/lib/libesp32_lvgl/lv_lib_freetype/lv_freetype.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.h @@ -2,8 +2,8 @@ * @file lv_freetype.h * */ -#ifndef _LV_FONT_TTF_H -#define _LV_FONT_TTF_H +#ifndef LV_FREETYPE_H +#define LV_FREETYPE_H #ifdef __cplusplus extern "C" { @@ -12,37 +12,16 @@ extern "C" { /********************* * INCLUDES *********************/ -// #include "lvgl/lvgl.h" // TODO -#include "lvgl.h" -#include "ft2build.h" -#include FT_FREETYPE_H -#include FT_GLYPH_H -#include FT_CACHE_H -#include FT_SIZES_H +#include "../../../lvgl.h" +#if LV_USE_FREETYPE /********************* * DEFINES *********************/ -#ifndef LV_USE_FT_CACHE_MANAGER -#define LV_USE_FT_CACHE_MANAGER 0 -#endif - -#define LV_USE_FT_STACK_SIZE 24*1024 // FreeType consumes a large amount of stack /********************** * TYPEDEFS **********************/ -typedef struct { - uint16_t cnt; - char* name; -} lv_face_info_t; - -typedef struct { - uint16_t num; - uint16_t cnt; - lv_ll_t face_ll; -} lv_faces_control_t; - typedef enum { FT_FONT_STYLE_NORMAL = 0, FT_FONT_STYLE_ITALIC = 1 << 0, @@ -50,22 +29,12 @@ typedef enum { } LV_FT_FONT_STYLE; typedef struct { - const char* name; /* The name of the font file */ - lv_font_t* font; /* point to lvgl font */ + const char * name; /* The name of the font file */ + lv_font_t * font; /* point to lvgl font */ uint16_t weight; /* font size */ uint16_t style; /* font style */ } lv_ft_info_t; -typedef struct { - FT_Face face; - FT_Size size; - lv_font_t* font; - uint16_t style; - uint16_t weight; -} lv_font_fmt_freetype_dsc_t; - -typedef lv_font_fmt_freetype_dsc_t lv_font_fmt_ft_dsc_t; - /********************** * GLOBAL PROTOTYPES **********************/ @@ -78,7 +47,7 @@ typedef lv_font_fmt_freetype_dsc_t lv_font_fmt_ft_dsc_t; * Note that this value does not account for managed FT_Face and FT_Size objects. * @return true on success, otherwise false. */ -bool lv_freetype_init(FT_UInt max_faces, FT_UInt max_sizes, FT_ULong max_bytes); +bool lv_freetype_init(uint16_t max_faces, uint16_t max_sizes, uint32_t max_bytes); /** * Destroy freetype library @@ -91,20 +60,22 @@ void lv_freetype_destroy(void); * when success, lv_ft_info_t->font point to the font you created. * @return true on success, otherwise false. */ -bool lv_ft_font_init(lv_ft_info_t *info); +bool lv_ft_font_init(lv_ft_info_t * info); /** * Destroy a font that has been created. * @param font pointer to font. */ -void lv_ft_font_destroy(lv_font_t* font); +void lv_ft_font_destroy(lv_font_t * font); /********************** * MACROS **********************/ +#endif /*LV_USE_FREETYPE*/ + #ifdef __cplusplus } /* extern "C" */ #endif -#endif +#endif /* LV_FREETYPE_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_fatfs.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_fatfs.c new file mode 100644 index 000000000..157a778ed --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_fatfs.c @@ -0,0 +1,276 @@ +/** + * @file lv_fs_fatfs.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_FS_FATFS != '\0' +#include "ff.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void fs_init(void); + +static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode); +static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p); +static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br); +static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw); +static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); +static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); +static void * fs_dir_open(lv_fs_drv_t * drv, const char * path); +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn); +static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_fs_fatfs_init(void) +{ + /*---------------------------------------------------- + * Initialize your storage device and File System + * -------------------------------------------------*/ + fs_init(); + + /*--------------------------------------------------- + * Register the file system interface in LittlevGL + *--------------------------------------------------*/ + + /*Add a simple drive to open images*/ + static lv_fs_drv_t fs_drv; /*A driver descriptor*/ + lv_fs_drv_init(&fs_drv); + + /*Set up fields...*/ + fs_drv.letter = LV_USE_FS_FATFS; + fs_drv.open_cb = fs_open; + fs_drv.close_cb = fs_close; + fs_drv.read_cb = fs_read; + fs_drv.write_cb = fs_write; + fs_drv.seek_cb = fs_seek; + fs_drv.tell_cb = fs_tell; + + fs_drv.dir_close_cb = fs_dir_close; + fs_drv.dir_open_cb = fs_dir_open; + fs_drv.dir_read_cb = fs_dir_read; + + lv_fs_drv_register(&fs_drv); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/*Initialize your Storage device and File system.*/ +static void fs_init(void) +{ + /*Initialize the SD card and FatFS itself. + *Better to do it in your code to keep this library untouched for easy updating*/ +} + +/** + * Open a file + * @param drv pointer to a driver where this function belongs + * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) + * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR + * @return pointer to FIL struct or NULL in case of fail + */ +static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) +{ + LV_UNUSED(drv); + uint8_t flags = 0; + + if(mode == LV_FS_MODE_WR) flags = FA_WRITE | FA_OPEN_ALWAYS; + else if(mode == LV_FS_MODE_RD) flags = FA_READ; + else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) flags = FA_READ | FA_WRITE | FA_OPEN_ALWAYS; + + FIL * f = lv_mem_alloc(sizeof(FIL)); + if(f == NULL) return NULL; + + FRESULT res = f_open(f, path, flags); + if(res == FR_OK) { + return f; + } else { + lv_mem_free(f); + return NULL; + } +} + +/** + * Close an opened file + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FIL variable. (opened with fs_open) + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p) +{ + LV_UNUSED(drv); + f_close(file_p); + lv_mem_free(file_p); + return LV_FS_RES_OK; +} + +/** + * Read data from an opened file + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FIL variable. + * @param buf pointer to a memory block where to store the read data + * @param btr number of Bytes To Read + * @param br the real number of read bytes (Byte Read) + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br) +{ + LV_UNUSED(drv); + FRESULT res = f_read(file_p, buf, btr, (UINT *)br); + if(res == FR_OK) return LV_FS_RES_OK; + else return LV_FS_RES_UNKNOWN; +} + +/** + * Write into a file + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FIL variable + * @param buf pointer to a buffer with the bytes to write + * @param btr Bytes To Write + * @param br the number of real written bytes (Bytes Written). NULL if unused. + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) +{ + LV_UNUSED(drv); + FRESULT res = f_write(file_p, buf, btw, (UINT *)bw); + if(res == FR_OK) return LV_FS_RES_OK; + else return LV_FS_RES_UNKNOWN; +} + +/** + * Set the read write pointer. Also expand the file size if necessary. + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FIL variable. (opened with fs_open ) + * @param pos the new position of read write pointer + * @param whence only LV_SEEK_SET is supported + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence) +{ + LV_UNUSED(drv); + switch (whence) { + case LV_FS_SEEK_SET: + f_lseek(file_p, pos); + break; + case LV_FS_SEEK_CUR: + f_lseek(file_p, f_tell(file_p) + pos); + break; + case LV_FS_SEEK_END: + f_lseek(file_p, f_size(file_p) + pos); + break; + default: + break; + } + return LV_FS_RES_OK; +} + +/** + * Give the position of the read write pointer + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FIL variable. + * @param pos_p pointer to to store the result + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) +{ + LV_UNUSED(drv); + *pos_p = f_tell(file_p); + return LV_FS_RES_OK; +} + +/** + * Initialize a 'DIR' variable for directory reading + * @param drv pointer to a driver where this function belongs + * @param path path to a directory + * @return pointer to an initialized 'DIR' variable + */ +static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) +{ + LV_UNUSED(drv); + DIR * d = lv_mem_alloc(sizeof(DIR)); + if(d == NULL) return NULL; + + FRESULT res = f_opendir(d, path); + if(res != FR_OK) { + lv_mem_free(d); + d = NULL; + } + return d; +} + +/** + * Read the next filename from a directory. + * The name of the directories will begin with '/' + * @param drv pointer to a driver where this function belongs + * @param dir_p pointer to an initialized 'DIR' variable + * @param fn pointer to a buffer to store the filename + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) +{ + LV_UNUSED(drv); + FRESULT res; + FILINFO fno; + fn[0] = '\0'; + + do { + res = f_readdir(dir_p, &fno); + if(res != FR_OK) return LV_FS_RES_UNKNOWN; + + if(fno.fattrib & AM_DIR) { + fn[0] = '/'; + strcpy(&fn[1], fno.fname); + } + else strcpy(fn, fno.fname); + + } while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0); + + return LV_FS_RES_OK; +} + +/** + * Close the directory reading + * @param drv pointer to a driver where this function belongs + * @param dir_p pointer to an initialized 'DIR' variable + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p) +{ + LV_UNUSED(drv); + f_closedir(dir_p); + lv_mem_free(dir_p); + return LV_FS_RES_OK; +} + +#endif /*LV_USE_FS_FATFS*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_posix.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_posix.c new file mode 100644 index 000000000..85985bcb0 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_posix.c @@ -0,0 +1,313 @@ +/** + * @file lv_fs_posix.c + * + */ + + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_FS_POSIX != '\0' + +#include +#include +#ifndef WIN32 +#include +#include +#else +#include +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode); +static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p); +static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br); +static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw); +static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); +static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); +static void * fs_dir_open(lv_fs_drv_t * drv, const char * path); +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn); +static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Register a driver for the File system interface + */ +void lv_fs_posix_init(void) +{ + /*--------------------------------------------------- + * Register the file system interface in LittlevGL + *--------------------------------------------------*/ + + /*Add a simple drive to open images*/ + static lv_fs_drv_t fs_drv; /*A driver descriptor*/ + lv_fs_drv_init(&fs_drv); + + /*Set up fields...*/ + fs_drv.letter = LV_USE_FS_POSIX; + fs_drv.open_cb = fs_open; + fs_drv.close_cb = fs_close; + fs_drv.read_cb = fs_read; + fs_drv.write_cb = fs_write; + fs_drv.seek_cb = fs_seek; + fs_drv.tell_cb = fs_tell; + + fs_drv.dir_close_cb = fs_dir_close; + fs_drv.dir_open_cb = fs_dir_open; + fs_drv.dir_read_cb = fs_dir_read; + + lv_fs_drv_register(&fs_drv); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Open a file + * @param drv pointer to a driver where this function belongs + * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) + * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR + * @return a file handle or -1 in case of fail + */ +static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) +{ + LV_UNUSED(drv); + + uint32_t flags = 0; + if(mode == LV_FS_MODE_WR) flags = O_WRONLY; + else if(mode == LV_FS_MODE_RD) flags = O_RDONLY; + else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) flags = O_RDWR; + +#ifdef LV_FS_POSIX_PATH + /*Make the path relative to the current directory (the projects root folder)*/ + char buf[256]; + sprintf(buf, LV_FS_POSIX_PATH "%s", path); + + int f = open(buf, flags); +#else + int f = open(path, flags); +#endif + if(f < 0) return NULL; + + return (void *)(lv_uintptr_t)f; +} + +/** + * Close an opened file + * @param drv pointer to a driver where this function belongs + * @param file_p a file handle. (opened with fs_open) + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p) +{ + LV_UNUSED(drv); + close((lv_uintptr_t)file_p); + return LV_FS_RES_OK; +} + +/** + * Read data from an opened file + * @param drv pointer to a driver where this function belongs + * @param file_p a file handle variable. + * @param buf pointer to a memory block where to store the read data + * @param btr number of Bytes To Read + * @param br the real number of read bytes (Byte Read) + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br) +{ + LV_UNUSED(drv); + *br = read((lv_uintptr_t)file_p, buf, btr); + return (int32_t)*br < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK; +} + +/** + * Write into a file + * @param drv pointer to a driver where this function belongs + * @param file_p a file handle variable + * @param buf pointer to a buffer with the bytes to write + * @param btr Bytes To Write + * @param br the number of real written bytes (Bytes Written). NULL if unused. + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) +{ + LV_UNUSED(drv); + *bw = write((lv_uintptr_t)file_p, buf, btw); + return (int32_t)*bw < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK; +} + +/** + * Set the read write pointer. Also expand the file size if necessary. + * @param drv pointer to a driver where this function belongs + * @param file_p a file handle variable. (opened with fs_open ) + * @param pos the new position of read write pointer + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence) +{ + LV_UNUSED(drv); + lseek((lv_uintptr_t)file_p, pos, whence); + return LV_FS_RES_OK; +} + +/** + * Give the position of the read write pointer + * @param drv pointer to a driver where this function belongs + * @param file_p a file handle variable. + * @param pos_p pointer to to store the result + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) +{ + LV_UNUSED(drv); + *pos_p = lseek((lv_uintptr_t)file_p, 0, SEEK_CUR); + return LV_FS_RES_OK; +} + +#ifdef WIN32 +static char next_fn[256]; +#endif + +/** + * Initialize a 'fs_read_dir_t' variable for directory reading + * @param drv pointer to a driver where this function belongs + * @param path path to a directory + * @return pointer to an initialized 'DIR' or 'HANDLE' variable + */ +static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) +{ + LV_UNUSED(drv); + +#ifndef WIN32 +# ifdef LV_FS_POSIX_PATH + /*Make the path relative to the current directory (the projects root folder)*/ + char buf[256]; + sprintf(buf, LV_FS_POSIX_PATH "%s", path); + return opendir(buf); +# else + return opendir(path); +# endif +#else + HANDLE d = INVALID_HANDLE_VALUE; + WIN32_FIND_DATA fdata; + + /*Make the path relative to the current directory (the projects root folder)*/ + char buf[256]; +# ifdef LV_FS_POSIX_PATH + sprintf(buf, LV_FS_POSIX_PATH "%s\\*", path); +# else + sprintf(buf, "%s\\*", path); +# endif + + strcpy(next_fn, ""); + d = FindFirstFile(buf, &fdata); + do { + if (strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { + continue; + } else { + if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + sprintf(next_fn, "/%s", fdata.cFileName); + } else { + sprintf(next_fn, "%s", fdata.cFileName); + } + break; + } + } while(FindNextFileA(d, &fdata)); + + return d; +#endif +} + +/** + * Read the next filename from a directory. + * The name of the directories will begin with '/' + * @param drv pointer to a driver where this function belongs + * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable + * @param fn pointer to a buffer to store the filename + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) +{ + LV_UNUSED(drv); + +#ifndef WIN32 + struct dirent *entry; + do { + entry = readdir(dir_p); + if(entry) { + if(entry->d_type == DT_DIR) sprintf(fn, "/%s", entry->d_name); + else strcpy(fn, entry->d_name); + } else { + strcpy(fn, ""); + } + } while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0); +#else + strcpy(fn, next_fn); + + strcpy(next_fn, ""); + WIN32_FIND_DATA fdata; + + if(FindNextFile(dir_p, &fdata) == false) return LV_FS_RES_OK; + do { + if (strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { + continue; + } else { + if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + sprintf(next_fn, "/%s", fdata.cFileName); + } else { + sprintf(next_fn, "%s", fdata.cFileName); + } + break; + } + } while(FindNextFile(dir_p, &fdata)); + +#endif + return LV_FS_RES_OK; +} + +/** + * Close the directory reading + * @param drv pointer to a driver where this function belongs + * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p) +{ + LV_UNUSED(drv); +#ifndef WIN32 + closedir(dir_p); +#else + FindClose(dir_p); +#endif + return LV_FS_RES_OK; +} + +#endif /*LV_USE_FS_POSIX*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_stdio.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_stdio.c new file mode 100644 index 000000000..193741b20 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_stdio.c @@ -0,0 +1,310 @@ +/** + * @file lv_fs_stdio.c + * + */ + + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_FS_STDIO != '\0' + +#include +#ifndef WIN32 +#include +#include +#else +#include +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode); +static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p); +static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br); +static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw); +static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); +static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); +static void * fs_dir_open(lv_fs_drv_t * drv, const char * path); +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn); +static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Register a driver for the File system interface + */ +void lv_fs_stdio_init(void) +{ + /*--------------------------------------------------- + * Register the file system interface in LittlevGL + *--------------------------------------------------*/ + + /*Add a simple drive to open images*/ + static lv_fs_drv_t fs_drv; /*A driver descriptor*/ + lv_fs_drv_init(&fs_drv); + + /*Set up fields...*/ + fs_drv.letter = LV_USE_FS_STDIO; + fs_drv.open_cb = fs_open; + fs_drv.close_cb = fs_close; + fs_drv.read_cb = fs_read; + fs_drv.write_cb = fs_write; + fs_drv.seek_cb = fs_seek; + fs_drv.tell_cb = fs_tell; + + fs_drv.dir_close_cb = fs_dir_close; + fs_drv.dir_open_cb = fs_dir_open; + fs_drv.dir_read_cb = fs_dir_read; + + lv_fs_drv_register(&fs_drv); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Open a file + * @param drv pointer to a driver where this function belongs + * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) + * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR + * @return pointer to FIL struct or NULL in case of fail + */ +static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) +{ + LV_UNUSED(drv); + + const char * flags = ""; + + if(mode == LV_FS_MODE_WR) flags = "wb"; + else if(mode == LV_FS_MODE_RD) flags = "rb"; + else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) flags = "rb+"; + +#ifdef LV_FS_STDIO_PATH + /*Make the path relative to the current directory (the projects root folder)*/ + + char buf[256]; + sprintf(buf, LV_FS_STDIO_PATH "%s", path); + + return fopen(buf, flags); +#else + return fopen(path, flags); +#endif +} + +/** + * Close an opened file + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. (opened with fs_open) + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p) +{ + LV_UNUSED(drv); + fclose(file_p); + return LV_FS_RES_OK; +} + +/** + * Read data from an opened file + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. + * @param buf pointer to a memory block where to store the read data + * @param btr number of Bytes To Read + * @param br the real number of read bytes (Byte Read) + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br) +{ + LV_UNUSED(drv); + *br = fread(buf, 1, btr, file_p); + return (int32_t)*br < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK; +} + +/** + * Write into a file + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable + * @param buf pointer to a buffer with the bytes to write + * @param btr Bytes To Write + * @param br the number of real written bytes (Bytes Written). NULL if unused. + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) +{ + LV_UNUSED(drv); + *bw = fwrite(buf, 1, btw, file_p); + return (int32_t)*bw < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK; +} + +/** + * Set the read write pointer. Also expand the file size if necessary. + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. (opened with fs_open ) + * @param pos the new position of read write pointer + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence) +{ + LV_UNUSED(drv); + fseek(file_p, pos, whence); + return LV_FS_RES_OK; +} + +/** + * Give the position of the read write pointer + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. + * @param pos_p pointer to to store the result + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) +{ + LV_UNUSED(drv); + *pos_p = ftell(file_p); + return LV_FS_RES_OK; +} + +#ifdef WIN32 +static char next_fn[256]; +#endif + +/** + * Initialize a 'DIR' or 'HANDLE' variable for directory reading + * @param drv pointer to a driver where this function belongs + * @param path path to a directory + * @return pointer to an initialized 'DIR' or 'HANDLE' variable + */ +static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) +{ + LV_UNUSED(drv); +#ifndef WIN32 +# ifdef LV_FS_STDIO_PATH + /*Make the path relative to the current directory (the projects root folder)*/ + char buf[256]; + sprintf(buf, LV_FS_STDIO_PATH "%s", path); + return opendir(buf); +# else + return opendir(path); +# endif +#else + HANDLE d = INVALID_HANDLE_VALUE; + WIN32_FIND_DATA fdata; + + /*Make the path relative to the current directory (the projects root folder)*/ + char buf[256]; +# ifdef LV_FS_STDIO_PATH + sprintf(buf, LV_FS_STDIO_PATH "%s\\*", path); +# else + sprintf(buf, "%s\\*", path); +# endif + + strcpy(next_fn, ""); + d = FindFirstFile(buf, &fdata); + do { + if (strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { + continue; + } else { + if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + sprintf(next_fn, "/%s", fdata.cFileName); + } else { + sprintf(next_fn, "%s", fdata.cFileName); + } + break; + } + } while(FindNextFileA(d, &fdata)); + + return d; +#endif +} + +/** + * Read the next filename form a directory. + * The name of the directories will begin with '/' + * @param drv pointer to a driver where this function belongs + * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable + * @param fn pointer to a buffer to store the filename + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) +{ + LV_UNUSED(drv); + +#ifndef WIN32 + struct dirent *entry; + do { + entry = readdir(dir_p); + if(entry) { + if(entry->d_type == DT_DIR) sprintf(fn, "/%s", entry->d_name); + else strcpy(fn, entry->d_name); + } else { + strcpy(fn, ""); + } + } while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0); +#else + strcpy(fn, next_fn); + + strcpy(next_fn, ""); + WIN32_FIND_DATA fdata; + + if(FindNextFile(dir_p, &fdata) == false) return LV_FS_RES_OK; + do { + if (strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { + continue; + } else { + if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + sprintf(next_fn, "/%s", fdata.cFileName); + } else { + sprintf(next_fn, "%s", fdata.cFileName); + } + break; + } + } while(FindNextFile(dir_p, &fdata)); + +#endif + return LV_FS_RES_OK; +} + +/** + * Close the directory reading + * @param drv pointer to a driver where this function belongs + * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p) +{ + LV_UNUSED(drv); +#ifndef WIN32 + closedir(dir_p); +#else + FindClose(dir_p); +#endif + return LV_FS_RES_OK; +} + +#endif /*LV_USE_FS_STDIO*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_win32.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_win32.c new file mode 100644 index 000000000..72ef22a70 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_win32.c @@ -0,0 +1,451 @@ +/** + * @file lv_fs_win32.c + * + */ + + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_FS_WIN32 != '\0' + +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static bool is_dots_name(const char * name); +static lv_fs_res_t fs_error_from_win32(DWORD error); +static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode); +static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p); +static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br); +static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw); +static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); +static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); +static void * fs_dir_open(lv_fs_drv_t * drv, const char * path); +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn); +static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Register a driver for the File system interface + */ +void lv_fs_win32_init(void) +{ + /*--------------------------------------------------- + * Register the file system interface in LittlevGL + *--------------------------------------------------*/ + + /*Add a simple drive to open images*/ + static lv_fs_drv_t fs_drv; /*A driver descriptor*/ + lv_fs_drv_init(&fs_drv); + + /*Set up fields...*/ + fs_drv.letter = LV_USE_FS_WIN32; + fs_drv.open_cb = fs_open; + fs_drv.close_cb = fs_close; + fs_drv.read_cb = fs_read; + fs_drv.write_cb = fs_write; + fs_drv.seek_cb = fs_seek; + fs_drv.tell_cb = fs_tell; + + fs_drv.dir_close_cb = fs_dir_close; + fs_drv.dir_open_cb = fs_dir_open; + fs_drv.dir_read_cb = fs_dir_read; + + lv_fs_drv_register(&fs_drv); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Check the dots name + * @param name file or dir name + * @return true if the name is dots name + */ +static bool is_dots_name(const char * name) +{ + return name[0] == '.' && (!name[1] || (name[1] == '.' && !name[2])); +} + +/** + * Convert Win32 error code to error from lv_fs_res_t enum + * @param error Win32 error code + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_error_from_win32(DWORD error) +{ + lv_fs_res_t res; + + switch (error) { + case ERROR_SUCCESS: + res = LV_FS_RES_OK; + break; + case ERROR_BAD_UNIT: + case ERROR_NOT_READY: + case ERROR_CRC: + case ERROR_SEEK: + case ERROR_NOT_DOS_DISK: + case ERROR_WRITE_FAULT: + case ERROR_READ_FAULT: + case ERROR_GEN_FAILURE: + case ERROR_WRONG_DISK: + res = LV_FS_RES_HW_ERR; + break; + case ERROR_INVALID_HANDLE: + case ERROR_INVALID_TARGET_HANDLE: + res = LV_FS_RES_FS_ERR; + break; + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + case ERROR_INVALID_DRIVE: + case ERROR_NO_MORE_FILES: + case ERROR_SECTOR_NOT_FOUND: + case ERROR_BAD_NETPATH: + case ERROR_BAD_NET_NAME: + case ERROR_BAD_PATHNAME: + case ERROR_FILENAME_EXCED_RANGE: + res = LV_FS_RES_NOT_EX; + break; + case ERROR_DISK_FULL: + res = LV_FS_RES_FULL; + break; + case ERROR_SHARING_VIOLATION: + case ERROR_LOCK_VIOLATION: + case ERROR_DRIVE_LOCKED: + res = LV_FS_RES_LOCKED; + break; + case ERROR_ACCESS_DENIED: + case ERROR_CURRENT_DIRECTORY: + case ERROR_WRITE_PROTECT: + case ERROR_NETWORK_ACCESS_DENIED: + case ERROR_CANNOT_MAKE: + case ERROR_FAIL_I24: + case ERROR_SEEK_ON_DEVICE: + case ERROR_NOT_LOCKED: + case ERROR_LOCK_FAILED: + res = LV_FS_RES_DENIED; + break; + case ERROR_BUSY: + res = LV_FS_RES_BUSY; + break; + case ERROR_TIMEOUT: + res = LV_FS_RES_TOUT; + break; + case ERROR_NOT_SAME_DEVICE: + case ERROR_DIRECT_ACCESS_HANDLE: + res = LV_FS_RES_NOT_IMP; + break; + case ERROR_TOO_MANY_OPEN_FILES: + case ERROR_ARENA_TRASHED: + case ERROR_NOT_ENOUGH_MEMORY: + case ERROR_INVALID_BLOCK: + case ERROR_OUT_OF_PAPER: + case ERROR_SHARING_BUFFER_EXCEEDED: + case ERROR_NOT_ENOUGH_QUOTA: + res = LV_FS_RES_OUT_OF_MEM; + break; + case ERROR_INVALID_FUNCTION: + case ERROR_INVALID_ACCESS: + case ERROR_INVALID_DATA: + case ERROR_BAD_COMMAND: + case ERROR_BAD_LENGTH: + case ERROR_INVALID_PARAMETER: + case ERROR_NEGATIVE_SEEK: + res = LV_FS_RES_INV_PARAM; + break; + default: + res = LV_FS_RES_UNKNOWN; + break; + } + + return res; +} + +/** + * Open a file + * @param drv pointer to a driver where this function belongs + * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) + * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR + * @return pointer to FIL struct or NULL in case of fail + */ +static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) +{ + LV_UNUSED(drv); + + DWORD desired_access = 0; + + if (mode & LV_FS_MODE_RD) { + desired_access |= GENERIC_READ; + } + + if (mode & LV_FS_MODE_WR) { + desired_access |= GENERIC_WRITE; + } + +#ifdef LV_FS_WIN32_PATH + /*Make the path relative to the current directory (the projects root folder)*/ + + char buf[MAX_PATH]; + sprintf(buf, LV_FS_WIN32_PATH "%s", path); +#endif + + return (void*)CreateFileA( +#ifdef LV_FS_WIN32_PATH + buf, +#else + path, +#endif + desired_access, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); +} + +/** + * Close an opened file + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. (opened with fs_open) + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p) +{ + LV_UNUSED(drv); + return CloseHandle((HANDLE)file_p) + ? LV_FS_RES_OK + : fs_error_from_win32(GetLastError()); +} + +/** + * Read data from an opened file + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. + * @param buf pointer to a memory block where to store the read data + * @param btr number of Bytes To Read + * @param br the real number of read bytes (Byte Read) + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br) +{ + LV_UNUSED(drv); + return ReadFile((HANDLE)file_p, buf, btr, (LPDWORD)br, NULL) + ? LV_FS_RES_OK + : fs_error_from_win32(GetLastError()); +} + +/** + * Write into a file + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable + * @param buf pointer to a buffer with the bytes to write + * @param btr Bytes To Write + * @param br the number of real written bytes (Bytes Written). NULL if unused. + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) +{ + LV_UNUSED(drv); + return WriteFile((HANDLE)file_p, buf, btw, (LPDWORD)bw, NULL) + ? LV_FS_RES_OK + : fs_error_from_win32(GetLastError()); +} + +/** + * Set the read write pointer. Also expand the file size if necessary. + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. (opened with fs_open ) + * @param pos the new position of read write pointer + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence) +{ + LV_UNUSED(drv); + + DWORD move_method = (DWORD)-1; + if (whence == LV_FS_SEEK_SET) { + move_method = FILE_BEGIN; + } + else if(whence == LV_FS_SEEK_CUR) { + move_method = FILE_CURRENT; + } + else if(whence == LV_FS_SEEK_END) { + move_method = FILE_END; + } + + LARGE_INTEGER distance_to_move; + distance_to_move.QuadPart = pos; + return SetFilePointerEx((HANDLE)file_p, distance_to_move, NULL, move_method) + ? LV_FS_RES_OK + : fs_error_from_win32(GetLastError()); +} + +/** + * Give the position of the read write pointer + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. + * @param pos_p pointer to to store the result + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) +{ + LV_UNUSED(drv); + + if (!pos_p) { + return LV_FS_RES_INV_PARAM; + } + + LARGE_INTEGER file_pointer; + file_pointer.QuadPart = 0; + + LARGE_INTEGER distance_to_move; + distance_to_move.QuadPart = 0; + if (SetFilePointerEx( + (HANDLE)file_p, + distance_to_move, + &file_pointer, + FILE_CURRENT)) { + if (file_pointer.QuadPart > LONG_MAX) { + return LV_FS_RES_INV_PARAM; + } + else { + *pos_p = file_pointer.LowPart; + return LV_FS_RES_OK; + } + } + else { + return fs_error_from_win32(GetLastError()); + } +} + +static char next_fn[256]; +static lv_fs_res_t next_error = LV_FS_RES_OK; + +/** + * Initialize a 'DIR' or 'HANDLE' variable for directory reading + * @param drv pointer to a driver where this function belongs + * @param path path to a directory + * @return pointer to an initialized 'DIR' or 'HANDLE' variable + */ +static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) +{ + LV_UNUSED(drv); + + HANDLE d = INVALID_HANDLE_VALUE; + WIN32_FIND_DATAA fdata; + + /*Make the path relative to the current directory (the projects root folder)*/ + char buf[256]; +#ifdef LV_FS_WIN32_PATH + sprintf(buf, LV_FS_WIN32_PATH "%s\\*", path); +#else + sprintf(buf, "%s\\*", path); +#endif + + strcpy(next_fn, ""); + d = FindFirstFileA(buf, &fdata); + do { + if (is_dots_name(fdata.cFileName)) { + continue; + } + else { + if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + sprintf(next_fn, "/%s", fdata.cFileName); + } + else { + sprintf(next_fn, "%s", fdata.cFileName); + } + break; + } + + } while (FindNextFileA(d, &fdata)); + + next_error = fs_error_from_win32(GetLastError()); + return d; +} + +/** + * Read the next filename from a directory. + * The name of the directories will begin with '/' + * @param drv pointer to a driver where this function belongs + * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable + * @param fn pointer to a buffer to store the filename + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) +{ + LV_UNUSED(drv); + + strcpy(fn, next_fn); + lv_fs_res_t current_error = next_error; + next_error = LV_FS_RES_OK; + + strcpy(next_fn, ""); + WIN32_FIND_DATAA fdata; + + while (FindNextFileA(dir_p, &fdata)) { + if (is_dots_name(fdata.cFileName)) { + continue; + } + else { + if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + sprintf(next_fn, "/%s", fdata.cFileName); + } + else { + sprintf(next_fn, "%s", fdata.cFileName); + } + break; + } + } + + if (next_fn[0] == '\0') { + next_error = fs_error_from_win32(GetLastError()); + } + + return current_error; +} + +/** + * Close the directory reading + * @param drv pointer to a driver where this function belongs + * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p) +{ + LV_UNUSED(drv); + return FindClose((HANDLE)dir_p) + ? LV_FS_RES_OK + : fs_error_from_win32(GetLastError()); +} + +#endif /*LV_USE_FS_WIN32*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fsdrv.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fsdrv.h new file mode 100644 index 000000000..c7ca8df1b --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fsdrv.h @@ -0,0 +1,55 @@ +/** + * @file lv_fsdrv.h + * + */ + +#ifndef LV_FSDRV_H +#define LV_FSDRV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lv_conf_internal.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +#if LV_USE_FS_FATFS != '\0' + void lv_fs_fatfs_init(void); +#endif + +#if LV_USE_FS_STDIO != '\0' + void lv_fs_stdio_init(void); +#endif + +#if LV_USE_FS_POSIX != '\0' + void lv_fs_posix_init(void); +#endif + +#if LV_USE_FS_WIN32 != '\0' + void lv_fs_win32_init(void); +#endif + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_FSDRV_H*/ + diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/lv_libs.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/lv_libs.h new file mode 100644 index 000000000..eb2d03532 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/lv_libs.h @@ -0,0 +1,46 @@ +/** + * @file lv_libs.h + * + */ + +#ifndef LV_LIBS_H +#define LV_LIBS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +// TODO Tasmota +// #include "bmp/lv_bmp.h" +// #include "fsdrv/lv_fsdrv.h" +#include "png/lv_png.h" +// #include "gif/lv_gif.h" +// #include "qrcode/lv_qrcode.h" +// #include "sjpg/lv_sjpg.h" +#include "freetype/lv_freetype.h" +// #include "rlottie/lv_rlottie.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_LAYOUTS_H*/ diff --git a/lib/libesp32_lvgl/lv_lib_png/src/lodepng.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.c similarity index 99% rename from lib/libesp32_lvgl/lv_lib_png/src/lodepng.c rename to lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.c index 6c1facd2a..65139bc5b 100644 --- a/lib/libesp32_lvgl/lv_lib_png/src/lodepng.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.c @@ -29,10 +29,10 @@ Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for */ #include "lodepng.h" +#if LV_USE_PNG #ifdef LODEPNG_COMPILE_DISK #include /* LONG_MAX */ -#include /* file handling */ #endif /* LODEPNG_COMPILE_DISK */ #ifdef LODEPNG_COMPILE_ALLOCATORS @@ -75,7 +75,7 @@ static void* lodepng_malloc(size_t size) { #ifdef LODEPNG_MAX_ALLOC if(size > LODEPNG_MAX_ALLOC) return 0; #endif - return malloc(size); + return lv_mem_alloc(size); } /* NOTE: when realloc returns NULL, it leaves the original memory untouched */ @@ -83,11 +83,11 @@ static void* lodepng_realloc(void* ptr, size_t new_size) { #ifdef LODEPNG_MAX_ALLOC if(new_size > LODEPNG_MAX_ALLOC) return 0; #endif - return realloc(ptr, new_size); + return lv_mem_realloc(ptr, new_size); } static void lodepng_free(void* ptr) { - free(ptr); + lv_mem_free(ptr); } #else /*LODEPNG_COMPILE_ALLOCATORS*/ /* TODO: support giving additional void* payload to the custom allocators */ @@ -343,12 +343,11 @@ static void lodepng_set32bitInt(unsigned char* buffer, unsigned value) { /* returns negative value on error. This should be pure C compatible, so no fstat. */ static long lodepng_filesize(const char* filename) { -#if LV_PNG_USE_LV_FILESYSTEM lv_fs_file_t f; lv_fs_res_t res = lv_fs_open(&f, filename, LV_FS_MODE_RD); if(res != LV_FS_RES_OK) return -1; uint32_t size = 0; - if(lv_fs_seek(&f, 0, SEEK_END) != 0) { + if(lv_fs_seek(&f, 0, LV_FS_SEEK_END) != 0) { lv_fs_close(&f); return -1; } @@ -356,29 +355,10 @@ static long lodepng_filesize(const char* filename) { lv_fs_tell(&f, &size); lv_fs_close(&f); return size; -#else - FILE* file; - long size; - file = fopen(filename, "rb"); - if(!file) return -1; - - if(fseek(file, 0, SEEK_END) != 0) { - fclose(file); - return -1; - } - - size = ftell(file); - /* It may give LONG_MAX as directory size, this is invalid for us. */ - if(size == LONG_MAX) size = -1; - - fclose(file); - return size; -#endif } /* load file into buffer that already has the correct allocated size. Returns error code.*/ static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename) { -#if LV_PNG_USE_LV_FILESYSTEM lv_fs_file_t f; lv_fs_res_t res = lv_fs_open(&f, filename, LV_FS_MODE_RD); if(res != LV_FS_RES_OK) return 78; @@ -389,18 +369,6 @@ static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* if (br != size) return 78; lv_fs_close(&f); return 0; -#else - FILE* file; - size_t readsize; - file = fopen(filename, "rb"); - if(!file) return 78; - - readsize = fread(out, 1, size, file); - fclose(file); - - if(readsize != size) return 78; - return 0; -#endif } unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) { @@ -416,11 +384,13 @@ unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* fil /*write given buffer to the file, overwriting the file, it doesn't append to it.*/ unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename) { - FILE* file; - file = fopen(filename, "wb" ); - if(!file) return 79; - fwrite(buffer, 1, buffersize, file); - fclose(file); + lv_fs_file_t f; + lv_fs_res_t res = lv_fs_open(&f, filename, LV_FS_MODE_WR); + if(res != LV_FS_RES_OK) return 79; + + uint32_t bw; + res = lv_fs_write(&f, buffer, buffersize, &bw); + lv_fs_close(&f); return 0; } @@ -611,6 +581,7 @@ static unsigned readBits(LodePNGBitReader* reader, size_t nbits) { return result; } +#if 0 /*Disable because tests fail due to unused declaration*/ /* Public for testing only. steps and result must have numsteps values. */ static unsigned lode_png_test_bitreader(const unsigned char* data, size_t size, size_t numsteps, const size_t* steps, unsigned* result) { @@ -630,6 +601,8 @@ static unsigned lode_png_test_bitreader(const unsigned char* data, size_t size, } return 1; } +#endif + #endif /*LODEPNG_COMPILE_DECODER*/ static unsigned reverseBits(unsigned bits, unsigned num) { @@ -2337,7 +2310,7 @@ static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsign static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size, const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) { if(!settings->custom_zlib) return 87; /*no custom zlib function provided */ - (void)expected_size; + LV_UNUSED(expected_size); return settings->custom_zlib(out, outsize, in, insize, settings); } #endif /*LODEPNG_COMPILE_DECODER*/ @@ -2579,6 +2552,8 @@ unsigned char* lodepng_chunk_find(unsigned char* chunk, unsigned char* end, cons if(lodepng_chunk_type_equals(chunk, type)) return chunk; chunk = lodepng_chunk_next(chunk, end); } + + return 0; /*Shouldn't reach this*/ } const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]) { @@ -2587,6 +2562,8 @@ const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const if(lodepng_chunk_type_equals(chunk, type)) return chunk; chunk = lodepng_chunk_next_const(chunk, end); } + + return 0; /*Shouldn't reach this*/ } unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk) { @@ -6490,3 +6467,5 @@ unsigned encode(const std::string& filename, #endif /* LODEPNG_COMPILE_PNG */ } /* namespace lodepng */ #endif /*LODEPNG_COMPILE_CPP*/ + +#endif /*LV_USE_PNG*/ diff --git a/lib/libesp32_lvgl/lv_lib_png/src/lodepng.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.h similarity index 99% rename from lib/libesp32_lvgl/lv_lib_png/src/lodepng.h rename to lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.h index 75bffe245..dbfed72e5 100644 --- a/lib/libesp32_lvgl/lv_lib_png/src/lodepng.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.h @@ -28,18 +28,8 @@ freely, subject to the following restrictions: #include /*for size_t*/ -#ifndef LV_PNG_USE_LV_FILESYSTEM -#define LV_PNG_USE_LV_FILESYSTEM 0 -#endif - -#if LV_PNG_USE_LV_FILESYSTEM -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif -#endif /* LV_PNG_USE_LV_FILESYSTEM */ - +#include "../../../lvgl.h" +#if LV_USE_PNG extern const char* LODEPNG_VERSION_STRING; /* @@ -1095,6 +1085,8 @@ TODO: [X] provide alternatives for C library functions not present on some platforms (memcpy, ...) */ +#endif /*LV_USE_PNG*/ + #endif /*LODEPNG_H inclusion guard*/ /* diff --git a/lib/libesp32_lvgl/lv_lib_png/src/lv_png.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.c similarity index 85% rename from lib/libesp32_lvgl/lv_lib_png/src/lv_png.c rename to lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.c index 3f87a3b3b..5eb2ff71c 100644 --- a/lib/libesp32_lvgl/lv_lib_png/src/lv_png.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.c @@ -6,19 +6,12 @@ /********************* * INCLUDES *********************/ -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif +#include "../../../lvgl.h" +#if LV_USE_PNG #include "lv_png.h" #include "lodepng.h" #include -#if LV_MEM_CUSTOM != 0 - #include LV_MEM_CUSTOM_INCLUDE -#endif -#include /********************* * DEFINES @@ -84,7 +77,6 @@ static lv_res_t decoder_info(struct _lv_img_decoder_t * decoder, const void * sr * [24..27]: height */ uint32_t size[2]; -#if LV_PNG_USE_LV_FILESYSTEM lv_fs_file_t f; lv_fs_res_t res = lv_fs_open(&f, fn, LV_FS_MODE_RD); if(res != LV_FS_RES_OK) return LV_RES_INV; @@ -93,15 +85,6 @@ static lv_res_t decoder_info(struct _lv_img_decoder_t * decoder, const void * sr lv_fs_read(&f, &size, 8, &rn); if(rn != 8) return LV_RES_INV; lv_fs_close(&f); -#else - FILE* file; - file = fopen(fn, "rb" ); - if(!file) return LV_RES_INV; - fseek(file, 16, SEEK_SET); - size_t rn = fread(size, 1 , 8, file); - fclose(file); - if(rn != 8) return LV_RES_INV; -#endif /*Save the data in the header*/ header->always_zero = 0; header->cf = LV_IMG_CF_RAW_ALPHA; @@ -152,11 +135,7 @@ static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * error = lodepng_load_file(&png_data, &png_data_size, fn); /*Load the file*/ if(error) { -#ifdef LODEPNG_COMPILE_ERROR_TEXT - LV_LOG_ERROR("lv_png error %u: %s\n", error, lodepng_error_text(error)); -#else - LV_LOG_ERROR("lv_png error %u\n", error); -#endif + LV_LOG_WARN("error %u: %s\n", error, lodepng_error_text(error)); return LV_RES_INV; } @@ -166,13 +145,9 @@ static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * /*Decode the loaded image in ARGB8888 */ error = lodepng_decode32(&img_data, &png_width, &png_height, png_data, png_data_size); - LV_MEM_CUSTOM_FREE(png_data); /*Free the loaded file*/ + lv_mem_free(png_data); /*Free the loaded file*/ if(error) { -#ifdef LODEPNG_COMPILE_ERROR_TEXT - LV_LOG_ERROR("lv_png error %u: %s\n", error, lodepng_error_text(error)); -#else - LV_LOG_ERROR("lv_png error %u\n", error); -#endif + LV_LOG_WARN("error %u: %s\n", error, lodepng_error_text(error)); return LV_RES_INV; } @@ -210,8 +185,11 @@ static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * */ static void decoder_close(lv_img_decoder_t *decoder, lv_img_decoder_dsc_t *dsc) { - (void) decoder; /*Unused*/ - if(dsc->img_data) LV_MEM_CUSTOM_FREE((uint8_t *)dsc->img_data); + LV_UNUSED(decoder); /*Unused*/ + if (dsc->img_data) { + lv_mem_free((uint8_t *)dsc->img_data); + dsc->img_data = NULL; + } } /** @@ -243,15 +221,25 @@ static void convert_color_depth(uint8_t * img, uint32_t px_cnt) } #elif LV_COLOR_DEPTH == 8 lv_color32_t * img_argb = (lv_color32_t*)img; - lv_color_t c; - uint32_t i; - for(i = 0; i < px_cnt; i++) { - c = lv_color_make(img_argb[i].red, img_argb[i].green, img_argb[i].blue); - img[i*2 + 1] = img_argb[i].alpha; - img[i*2 + 0] = c.full - } + lv_color_t c; + uint32_t i; + for(i = 0; i < px_cnt; i++) { + c = lv_color_make(img_argb[i].ch.red, img_argb[i].ch.green, img_argb[i].ch.blue); + img[i*2 + 1] = img_argb[i].ch.alpha; + img[i*2 + 0] = c.full; + } +#elif LV_COLOR_DEPTH == 1 + lv_color32_t * img_argb = (lv_color32_t*)img; + uint8_t b; + uint32_t i; + for(i = 0; i < px_cnt; i++) { + b = img_argb[i].ch.red | img_argb[i].ch.green | img_argb[i].ch.blue; + img[i*2 + 1] = img_argb[i].ch.alpha; + img[i*2 + 0] = b > 128 ? 1 : 0; + } #endif } +#endif /*LV_USE_PNG*/ diff --git a/lib/libesp32_lvgl/lv_lib_png/src/lv_png.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.h similarity index 88% rename from lib/libesp32_lvgl/lv_lib_png/src/lv_png.h rename to lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.h index d47f77fad..1e9b02d65 100644 --- a/lib/libesp32_lvgl/lv_lib_png/src/lv_png.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.h @@ -13,6 +13,8 @@ extern "C" { /********************* * INCLUDES *********************/ +#include "../../../lv_conf_internal.h" +#if LV_USE_PNG /********************* * DEFINES @@ -35,6 +37,7 @@ void lv_png_init(void); * MACROS **********************/ +#endif /*LV_USE_PNG*/ #ifdef __cplusplus } /* extern "C" */ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.c b/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.c new file mode 100644 index 000000000..1f5765b8a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.c @@ -0,0 +1,82 @@ +/** + * @file lv_extra.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../lvgl.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_extra_init(void) +{ +#if LV_USE_FLEX + lv_flex_init(); +#endif + +#if LV_USE_GRID + lv_grid_init(); +#endif + +#if LV_USE_FS_FATFS != '\0' + lv_fs_fatfs_init(); +#endif + +#if LV_USE_FS_STDIO != '\0' + lv_fs_stdio_init(); +#endif + +#if LV_USE_FS_POSIX != '\0' + lv_fs_posix_init(); +#endif + +#if LV_USE_FS_WIN32 != '\0' + lv_fs_win32_init(); +#endif + +#if LV_USE_PNG + lv_png_init(); +#endif + +#if LV_USE_SJPG + lv_split_jpeg_init(); +#endif + +#if LV_USE_BMP + lv_bmp_init(); +#endif + +#if LV_USE_FREETYPE + /*Init freetype library + *Cache max 64 faces and 1 size*/ + lv_freetype_init(0, 0, LV_FREETYPE_CACHE_SIZE); +#endif +} + +/********************** + * STATIC FUNCTIONS + **********************/ diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/lv_extra.h b/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/extra/lv_extra.h rename to lib/libesp32_lvgl/lvgl/src/extra/lv_extra.h diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/lv_others.h b/lib/libesp32_lvgl/lvgl/src/extra/others/lv_others.h new file mode 100644 index 000000000..a95727146 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/lv_others.h @@ -0,0 +1,38 @@ +/** + * @file lv_others.h + * + */ + +#ifndef LV_OTHERS_H +#define LV_OTHERS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "snapshot/lv_snapshot.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_OTHERS_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.c b/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.c new file mode 100644 index 000000000..4575539c7 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.c @@ -0,0 +1,228 @@ +/** + * @file lv_snapshot.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_snapshot.h" +#if LV_USE_SNAPSHOT + +#include +#include "../../../core/lv_disp.h" +#include "../../../core/lv_refr.h" +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** Get the buffer needed for object snapshot image. + * + * @param obj The object to generate snapshot. + * @param cf color format for generated image. + * + * @return the buffer size needed in bytes + */ +uint32_t lv_snapshot_buf_size_needed(lv_obj_t * obj, lv_img_cf_t cf) +{ + switch(cf) { + case LV_IMG_CF_TRUE_COLOR_ALPHA: + case LV_IMG_CF_ALPHA_1BIT: + case LV_IMG_CF_ALPHA_2BIT: + case LV_IMG_CF_ALPHA_4BIT: + case LV_IMG_CF_ALPHA_8BIT: + break; + default: + return 0; + } + + lv_obj_update_layout(obj); + + /*Width and height determine snapshot image size.*/ + lv_coord_t w = lv_obj_get_width(obj); + lv_coord_t h = lv_obj_get_height(obj); + lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj); + w += ext_size * 2; + h += ext_size * 2; + + uint8_t px_size = lv_img_cf_get_px_size(cf); + return w * h * ((px_size + 7) >> 3); +} + +/** Take snapshot for object with its children, save image info to provided buffer. + * + * @param obj The object to generate snapshot. + * @param cf color format for generated image. + * @param dsc image descriptor to store the image result. + * @param buf the buffer to store image data. + * @param buff_size provided buffer size in bytes. + * + * @return LV_RES_OK on success, LV_RES_INV on error. + */ +lv_res_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_img_cf_t cf, lv_img_dsc_t * dsc, void * buf, uint32_t buff_size) +{ + LV_ASSERT(dsc); + LV_ASSERT(buf); + + switch(cf) { + case LV_IMG_CF_TRUE_COLOR_ALPHA: + case LV_IMG_CF_ALPHA_1BIT: + case LV_IMG_CF_ALPHA_2BIT: + case LV_IMG_CF_ALPHA_4BIT: + case LV_IMG_CF_ALPHA_8BIT: + break; + default: + return LV_RES_INV; + } + + if(lv_snapshot_buf_size_needed(obj, cf) > buff_size) + return LV_RES_INV; + + /*Width and height determine snapshot image size.*/ + lv_coord_t w = lv_obj_get_width(obj); + lv_coord_t h = lv_obj_get_height(obj); + lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj); + w += ext_size * 2; + h += ext_size * 2; + + /*Backup obj original info.*/ + lv_obj_t * parent_old = lv_obj_get_parent(obj); + lv_area_t coords_bkp; + lv_area_copy(&coords_bkp, &obj->coords); + + lv_memset(buf, 0x00, buff_size); + lv_memset_00(dsc, sizeof(lv_img_dsc_t)); + + /*We are safe to use stack for below variables since disp will be + * unregistered when function returns. */ + lv_disp_t * disp; + lv_disp_drv_t driver; + lv_disp_draw_buf_t draw_buf; + + lv_disp_draw_buf_init(&draw_buf, buf, NULL, w * h); + + lv_disp_drv_init(&driver); + driver.draw_buf = &draw_buf; + driver.hor_res = w; + driver.ver_res = h; + lv_disp_drv_use_generic_set_px_cb(&driver, cf); + + disp = lv_disp_drv_register(&driver); + if(disp == NULL) { + return LV_RES_INV; + } + + /*Make background transparent */ + lv_disp_set_bg_opa(disp, LV_OPA_TRANSP); + + /*Move obj to newly created disp and refresh it. */ + lv_obj_t * screen = lv_disp_get_scr_act(disp); + lv_obj_remove_style_all(screen); + lv_obj_allocate_spec_attr(screen); + screen->spec_attr->child_cnt = 1; + screen->spec_attr->children = &obj; + + obj->parent = screen; + + disp->inv_p = 0; + + obj->coords.x2 = w - ext_size - 1; + obj->coords.x1 = ext_size; + obj->coords.y2 = h - ext_size - 1; + obj->coords.y1 = ext_size; + + lv_obj_invalidate(obj); + + /*Don't call lv_refr_now to avoid animation disruption */ + _lv_disp_refr_timer(disp->refr_timer); + + /*Restore obj original parameters and clean up*/ + obj->parent = parent_old; + screen->spec_attr->child_cnt = 0; + screen->spec_attr->children = NULL; + + lv_disp_remove(disp); + + lv_area_copy(&obj->coords, &coords_bkp); + + dsc->data = buf; + dsc->header.w = lv_area_get_width(&draw_buf.area); + dsc->header.h = lv_area_get_height(&draw_buf.area); + dsc->header.cf = cf; + return LV_RES_OK; +} + +/** Take snapshot for object with its children, alloc the memory needed. + * + * @param obj The object to generate snapshot. + * @param cf color format for generated image. + * + * @return a pointer to a image descriptor, or NULL if failed. + */ +lv_img_dsc_t * lv_snapshot_take(lv_obj_t * obj, lv_img_cf_t cf) +{ + uint32_t buff_size = lv_snapshot_buf_size_needed(obj, cf); + + void * buf = lv_mem_alloc(buff_size); + if(buf == NULL) { + return NULL; + } + + lv_img_dsc_t * dsc = lv_mem_alloc(sizeof(lv_img_dsc_t)); + if(dsc == NULL) { + lv_mem_free(buf); + return NULL; + } + + if(lv_snapshot_take_to_buf(obj, cf, dsc, buf, buff_size) == LV_RES_INV) { + lv_mem_free(buf); + lv_mem_free(dsc); + return NULL; + } + + return dsc; +} + +/** Free the snapshot image returned by @ref lv_snapshot_take + * + * It will firstly free the data image takes, then the image descriptor. + * + * @param dsc The image descriptor generated by lv_snapshot_take. + * + */ +void lv_snapshot_free(lv_img_dsc_t * dsc) +{ + if(!dsc) + return; + + if(dsc->data) + lv_mem_free((void *)dsc->data); + + lv_mem_free(dsc); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_SNAPSHOT*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.h b/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.h new file mode 100644 index 000000000..b84973317 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.h @@ -0,0 +1,84 @@ +/** + * @file lv_snapshot.h + * + */ + +#ifndef LV_SNAPSHOT_H +#define LV_SNAPSHOT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include + +#include "../../../lv_conf_internal.h" +#include "../../../core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +#if LV_USE_SNAPSHOT +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** Take snapshot for object with its children. + * + * @param obj The object to generate snapshot. + * @param cf color format for generated image. + * + * @return a pointer to a image descriptor, or NULL if failed. + */ +lv_img_dsc_t * lv_snapshot_take(lv_obj_t * obj, lv_img_cf_t cf); + +/** Free the snapshot image returned by @ref lv_snapshot_take + * + * It will firstly free the data image takes, then the image descriptor. + * + * @param dsc The image descriptor generated by lv_snapshot_take. + * + */ +void lv_snapshot_free(lv_img_dsc_t * dsc); + +/** Get the buffer needed for object snapshot image. + * + * @param obj The object to generate snapshot. + * @param cf color format for generated image. + * + * @return the buffer size needed in bytes + */ +uint32_t lv_snapshot_buf_size_needed(lv_obj_t * obj, lv_img_cf_t cf); + +/** Take snapshot for object with its children, save image info to provided buffer. + * + * @param obj The object to generate snapshot. + * @param cf color format for generated image. + * @param dsc image descriptor to store the image result. + * @param buff the buffer to store image data. + * @param buff_size provided buffer size in bytes. + * + * @return LV_RES_OK on success, LV_RES_INV on error. + */ +lv_res_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_img_cf_t cf, lv_img_dsc_t * dsc, void * buf, uint32_t buff_size); + + +/********************** + * MACROS + **********************/ +#endif /*LV_USE_SNAPSHOT*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/themes/basic/lv_theme_basic.c b/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.c similarity index 98% rename from lib/libesp32_lvgl/LVGL8/src/extra/themes/basic/lv_theme_basic.c rename to lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.c index 9231e79a0..fd5bc2d02 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/themes/basic/lv_theme_basic.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.c @@ -201,12 +201,12 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_WIN /*Header*/ - if(lv_obj_get_child_id(obj) == 0 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { + if(lv_obj_get_index(obj) == 0 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { lv_obj_add_style(obj, &styles->light, 0); return; } /*Content*/ - else if(lv_obj_get_child_id(obj) == 1 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { + else if(lv_obj_get_index(obj) == 1 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { lv_obj_add_style(obj, &styles->light, 0); lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); return; @@ -406,8 +406,8 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_LED else if(lv_obj_check_type(obj, &lv_led_class)) { - lv_obj_add_style(obj, &styles->light, 0); - } + lv_obj_add_style(obj, &styles->light, 0); + } #endif } diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/themes/basic/lv_theme_basic.h b/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/extra/themes/basic/lv_theme_basic.h rename to lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.h diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/themes/default/lv_theme_default.c b/lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.c similarity index 88% rename from lib/libesp32_lvgl/LVGL8/src/extra/themes/default/lv_theme_default.c rename to lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.c index 977ad1ff1..479dba47f 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/themes/default/lv_theme_default.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.c @@ -1,5 +1,5 @@ /** - * @file lv_theme_defau.c + * @file lv_theme_default.c * */ @@ -29,7 +29,7 @@ #define DARK_COLOR_TEXT lv_palette_lighten(LV_PALETTE_GREY, 5) #define DARK_COLOR_GREY lv_color_hex(0x2f3237) -#define TRANSITION_TIME LV_THEME_DEFAULT_TRANSITON_TIME +#define TRANSITION_TIME LV_THEME_DEFAULT_TRANSITION_TIME #define BORDER_WIDTH lv_disp_dpx(theme.disp, 2) #define OUTLINE_WIDTH lv_disp_dpx(theme.disp, 3) @@ -74,6 +74,7 @@ typedef struct { lv_style_t transition_delayed; lv_style_t transition_normal; lv_style_t anim; + lv_style_t anim_fast; /*Parts*/ lv_style_t knob; @@ -117,7 +118,7 @@ typedef struct { #endif #if LV_USE_CALENDAR - lv_style_t calendar_bg, calendar_day; + lv_style_t calendar_btnm_bg, calendar_btnm_day, calendar_header; #endif #if LV_USE_COLORWHEEL @@ -125,7 +126,7 @@ typedef struct { #endif #if LV_USE_MSGBOX - lv_style_t msgbox_bg, msgbox_btn_bg; + lv_style_t msgbox_bg, msgbox_btn_bg, msgbox_backdrop_bg; #endif #if LV_USE_KEYBOARD @@ -146,14 +147,14 @@ typedef struct { typedef struct { lv_theme_t base; - uint8_t light :1; -}my_theme_t; + uint8_t light : 1; +} my_theme_t; typedef enum { DISP_SMALL = 3, DISP_MEDIUM = 2, DISP_LARGE = 1, -}disp_size_t; +} disp_size_t; /********************** * STATIC PROTOTYPES @@ -199,12 +200,12 @@ static lv_color_t grey_filter_cb(const lv_color_filter_dsc_t * f, lv_color_t col static void style_init(void) { static const lv_style_prop_t trans_props[] = { - LV_STYLE_BG_OPA, LV_STYLE_BG_COLOR, - LV_STYLE_TRANSFORM_WIDTH, LV_STYLE_TRANSFORM_HEIGHT, - LV_STYLE_TRANSLATE_Y, LV_STYLE_TRANSLATE_X, - LV_STYLE_TRANSFORM_ZOOM, LV_STYLE_TRANSFORM_ANGLE, - LV_STYLE_COLOR_FILTER_OPA, LV_STYLE_COLOR_FILTER_DSC, - 0 + LV_STYLE_BG_OPA, LV_STYLE_BG_COLOR, + LV_STYLE_TRANSFORM_WIDTH, LV_STYLE_TRANSFORM_HEIGHT, + LV_STYLE_TRANSLATE_Y, LV_STYLE_TRANSLATE_X, + LV_STYLE_TRANSFORM_ZOOM, LV_STYLE_TRANSFORM_ANGLE, + LV_STYLE_COLOR_FILTER_OPA, LV_STYLE_COLOR_FILTER_DSC, + 0 }; color_scr = theme.flags & MODE_DARK ? DARK_COLOR_SCR : LIGHT_COLOR_SCR; @@ -225,7 +226,8 @@ static void style_init(void) lv_style_set_transition(&styles->transition_normal, &trans_normal); /*Go back to default state with delay*/ style_init_reset(&styles->scrollbar); - lv_style_set_bg_color(&styles->scrollbar, (theme.flags & MODE_DARK) ? lv_palette_darken(LV_PALETTE_GREY, 2) : lv_palette_main(LV_PALETTE_GREY)); + lv_style_set_bg_color(&styles->scrollbar, (theme.flags & MODE_DARK) ? lv_palette_darken(LV_PALETTE_GREY, + 2) : lv_palette_main(LV_PALETTE_GREY)); lv_style_set_radius(&styles->scrollbar, LV_RADIUS_CIRCLE); lv_style_set_pad_right(&styles->scrollbar, lv_disp_dpx(theme.disp, 7)); lv_style_set_pad_top(&styles->scrollbar, lv_disp_dpx(theme.disp, 7)); @@ -269,13 +271,15 @@ static void style_init(void) lv_style_set_outline_opa(&styles->outline_secondary, LV_OPA_50); style_init_reset(&styles->btn); - lv_style_set_radius(&styles->btn, (disp_size == DISP_LARGE ? lv_disp_dpx(theme.disp, 16) : disp_size == DISP_MEDIUM ? lv_disp_dpx(theme.disp, 12) : lv_disp_dpx(theme.disp, 8))); + lv_style_set_radius(&styles->btn, (disp_size == DISP_LARGE ? lv_disp_dpx(theme.disp, + 16) : disp_size == DISP_MEDIUM ? lv_disp_dpx(theme.disp, 12) : lv_disp_dpx(theme.disp, 8))); lv_style_set_bg_opa(&styles->btn, LV_OPA_COVER); lv_style_set_bg_color(&styles->btn, color_grey); if(!(theme.flags & MODE_DARK)) { - lv_style_set_shadow_color(&styles->btn, lv_palette_lighten(LV_PALETTE_GREY, 3)); - lv_style_set_shadow_width(&styles->btn, 1); - lv_style_set_shadow_ofs_y(&styles->btn, lv_disp_dpx(theme.disp, 4)); + lv_style_set_shadow_color(&styles->btn, lv_palette_main(LV_PALETTE_GREY)); + lv_style_set_shadow_width(&styles->btn, LV_DPX(3)); + lv_style_set_shadow_opa(&styles->btn, LV_OPA_50); + lv_style_set_shadow_ofs_y(&styles->btn, lv_disp_dpx(theme.disp, LV_DPX(4))); } lv_style_set_text_color(&styles->btn, color_text); lv_style_set_pad_hor(&styles->btn, PAD_DEF); @@ -299,6 +303,7 @@ static void style_init(void) style_init_reset(&styles->clip_corner); lv_style_set_clip_corner(&styles->clip_corner, true); + lv_style_set_border_post(&styles->clip_corner, true); style_init_reset(&styles->pad_normal); lv_style_set_pad_all(&styles->pad_normal, PAD_DEF); @@ -380,6 +385,9 @@ static void style_init(void) style_init_reset(&styles->anim); lv_style_set_anim_time(&styles->anim, 200); + style_init_reset(&styles->anim_fast); + lv_style_set_anim_time(&styles->anim_fast, 120); + #if LV_USE_ARC style_init_reset(&styles->arc_indic); lv_style_set_arc_color(&styles->arc_indic, color_grey); @@ -434,7 +442,7 @@ static void style_init(void) lv_style_set_pad_column(&styles->chart_series, lv_disp_dpx(theme.disp, 2)); style_init_reset(&styles->chart_indic); - lv_style_set_radius(&styles->chart_indic,LV_RADIUS_CIRCLE); + lv_style_set_radius(&styles->chart_indic, LV_RADIUS_CIRCLE); lv_style_set_size(&styles->chart_indic, lv_disp_dpx(theme.disp, 8)); lv_style_set_bg_color(&styles->chart_indic, theme.color_primary); lv_style_set_bg_opa(&styles->chart_indic, LV_OPA_COVER); @@ -464,32 +472,38 @@ static void style_init(void) style_init_reset(&styles->table_cell); lv_style_set_border_width(&styles->table_cell, lv_disp_dpx(theme.disp, 1)); lv_style_set_border_color(&styles->table_cell, color_grey); - lv_style_set_border_side(&styles->table_cell, LV_BORDER_SIDE_TOP | LV_BORDER_SIDE_BOTTOM ); + lv_style_set_border_side(&styles->table_cell, LV_BORDER_SIDE_TOP | LV_BORDER_SIDE_BOTTOM); #endif #if LV_USE_TEXTAREA style_init_reset(&styles->ta_cursor); lv_style_set_border_color(&styles->ta_cursor, color_text); lv_style_set_border_width(&styles->ta_cursor, lv_disp_dpx(theme.disp, 2)); - lv_style_set_pad_left(&styles->ta_cursor, lv_disp_dpx(theme.disp, 1)); + lv_style_set_pad_left(&styles->ta_cursor, - lv_disp_dpx(theme.disp, 1)); lv_style_set_border_side(&styles->ta_cursor, LV_BORDER_SIDE_LEFT); lv_style_set_anim_time(&styles->ta_cursor, 400); style_init_reset(&styles->ta_placeholder); - lv_style_set_text_color(&styles->ta_placeholder, (theme.flags & MODE_DARK) ? lv_palette_darken(LV_PALETTE_GREY, 2) : lv_palette_lighten(LV_PALETTE_GREY, 1)); + lv_style_set_text_color(&styles->ta_placeholder, (theme.flags & MODE_DARK) ? lv_palette_darken(LV_PALETTE_GREY, + 2) : lv_palette_lighten(LV_PALETTE_GREY, 1)); #endif #if LV_USE_CALENDAR - style_init_reset(&styles->calendar_bg); - lv_style_set_pad_all(&styles->calendar_bg, PAD_SMALL); - lv_style_set_pad_gap(&styles->calendar_bg, PAD_SMALL / 2); - lv_style_set_radius(&styles->calendar_bg, 0); + style_init_reset(&styles->calendar_btnm_bg); + lv_style_set_pad_all(&styles->calendar_btnm_bg, PAD_SMALL); + lv_style_set_pad_gap(&styles->calendar_btnm_bg, PAD_SMALL / 2); - style_init_reset(&styles->calendar_day); - lv_style_set_border_width(&styles->calendar_day, lv_disp_dpx(theme.disp, 1)); - lv_style_set_border_color(&styles->calendar_day, color_grey); - lv_style_set_bg_color(&styles->calendar_day, color_card); - lv_style_set_bg_opa(&styles->calendar_day, LV_OPA_20); + style_init_reset(&styles->calendar_btnm_day); + lv_style_set_border_width(&styles->calendar_btnm_day, lv_disp_dpx(theme.disp, 1)); + lv_style_set_border_color(&styles->calendar_btnm_day, color_grey); + lv_style_set_bg_color(&styles->calendar_btnm_day, color_card); + lv_style_set_bg_opa(&styles->calendar_btnm_day, LV_OPA_20); + + style_init_reset(&styles->calendar_header); + lv_style_set_pad_hor(&styles->calendar_header, PAD_SMALL); + lv_style_set_pad_top(&styles->calendar_header, PAD_SMALL); + lv_style_set_pad_bottom(&styles->calendar_header, PAD_TINY); + lv_style_set_pad_gap(&styles->calendar_header, PAD_SMALL); #endif #if LV_USE_COLORWHEEL @@ -504,6 +518,10 @@ static void style_init(void) style_init_reset(&styles->msgbox_bg); lv_style_set_max_width(&styles->msgbox_bg, lv_pct(100)); + + style_init_reset(&styles->msgbox_backdrop_bg); + lv_style_set_bg_color(&styles->msgbox_backdrop_bg, lv_palette_main(LV_PALETTE_GREY)); + lv_style_set_bg_opa(&styles->msgbox_backdrop_bg, LV_OPA_50); #endif #if LV_USE_KEYBOARD style_init_reset(&styles->keyboard_btn_bg); @@ -556,7 +574,8 @@ static void style_init(void) * GLOBAL FUNCTIONS **********************/ -lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font) +lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, + const lv_font_t * font) { /*This trick is required only to avoid the garbage collection of @@ -589,6 +608,13 @@ lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, l return (lv_theme_t *)&theme; } +lv_theme_t * lv_theme_default_get(void) +{ + if(!inited) return NULL; + + return (lv_theme_t *)&theme; +} + bool lv_theme_default_is_inited(void) { return inited; @@ -624,13 +650,13 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_WIN /*Header*/ - if(lv_obj_get_child_id(obj) == 0 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { + if(lv_obj_get_index(obj) == 0 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { lv_obj_add_style(obj, &styles->bg_color_grey, 0); lv_obj_add_style(obj, &styles->pad_tiny, 0); return; } /*Content*/ - else if(lv_obj_get_child_id(obj) == 1 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { + else if(lv_obj_get_index(obj) == 1 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { lv_obj_add_style(obj, &styles->scr, 0); lv_obj_add_style(obj, &styles->pad_normal, 0); lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); @@ -638,11 +664,20 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) return; } #endif + + +#if LV_USE_CALENDAR + else if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_calendar_class)) { + /*No style*/ + return; + } +#endif + lv_obj_add_style(obj, &styles->card, 0); lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); } - #if LV_USE_BTN +#if LV_USE_BTN else if(lv_obj_check_type(obj, &lv_btn_class)) { lv_obj_add_style(obj, &styles->btn, 0); lv_obj_add_style(obj, &styles->bg_color_primary, 0); @@ -693,6 +728,20 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) return; } #endif + +#if LV_USE_CALENDAR + if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_calendar_class)) { + lv_obj_add_style(obj, &styles->calendar_btnm_bg, 0); + lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); + lv_obj_add_style(obj, &styles->calendar_btnm_day, LV_PART_ITEMS); + lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); + lv_obj_add_style(obj, &styles->disabled, LV_PART_ITEMS | LV_STATE_DISABLED); + lv_obj_add_style(obj, &styles->outline_primary, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &styles->outline_secondary, LV_PART_ITEMS | LV_STATE_EDITED); + return; + } +#endif lv_obj_add_style(obj, &styles->card, 0); lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); @@ -772,6 +821,7 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) else if(lv_obj_check_type(obj, &lv_switch_class)) { lv_obj_add_style(obj, &styles->bg_color_grey, 0); lv_obj_add_style(obj, &styles->circle, 0); + lv_obj_add_style(obj, &styles->anim_fast, 0); lv_obj_add_style(obj, &styles->disabled, LV_STATE_DISABLED); lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); lv_obj_add_style(obj, &styles->bg_color_primary, LV_PART_INDICATOR | LV_STATE_CHECKED); @@ -781,6 +831,9 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) lv_obj_add_style(obj, &styles->bg_color_white, LV_PART_KNOB); lv_obj_add_style(obj, &styles->switch_knob, LV_PART_KNOB); lv_obj_add_style(obj, &styles->disabled, LV_PART_KNOB | LV_STATE_DISABLED); + + lv_obj_add_style(obj, &styles->transition_normal, LV_PART_INDICATOR | LV_STATE_CHECKED); + lv_obj_add_style(obj, &styles->transition_normal, LV_PART_INDICATOR); } #endif @@ -876,26 +929,19 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_CALENDAR else if(lv_obj_check_type(obj, &lv_calendar_class)) { lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->calendar_bg, 0); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); - lv_obj_add_style(obj, &styles->calendar_day, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->disabled, LV_PART_ITEMS | LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->outline_primary, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_PART_ITEMS | LV_STATE_EDITED); + lv_obj_add_style(obj, &styles->pad_zero, 0); } #endif #if LV_USE_CALENDAR_HEADER_ARROW else if(lv_obj_check_type(obj, &lv_calendar_header_arrow_class)) { - lv_obj_add_style(obj, &styles->card, 0); + lv_obj_add_style(obj, &styles->calendar_header, 0); } #endif #if LV_USE_CALENDAR_HEADER_DROPDOWN else if(lv_obj_check_type(obj, &lv_calendar_header_dropdown_class)) { - lv_obj_add_style(obj, &styles->card, 0); + lv_obj_add_style(obj, &styles->calendar_header, 0); } #endif @@ -943,6 +989,9 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) lv_obj_add_style(obj, &styles->msgbox_bg, 0); return; } + else if(lv_obj_check_type(obj, &lv_msgbox_backdrop_class)) { + lv_obj_add_style(obj, &styles->msgbox_backdrop_bg, 0); + } #endif #if LV_USE_SPINBOX else if(lv_obj_check_type(obj, &lv_spinbox_class)) { @@ -966,10 +1015,15 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #endif #if LV_USE_TABVIEW - if(lv_obj_check_type(obj, &lv_tabview_class)) { + else if(lv_obj_check_type(obj, &lv_tabview_class)) { lv_obj_add_style(obj, &styles->scr, 0); lv_obj_add_style(obj, &styles->pad_zero, 0); - return; + } +#endif + +#if LV_USE_WIN + else if(lv_obj_check_type(obj, &lv_win_class)) { + lv_obj_add_style(obj, &styles->clip_corner, 0); } #endif @@ -984,8 +1038,8 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_LED else if(lv_obj_check_type(obj, &lv_led_class)) { - lv_obj_add_style(obj, &styles->led, 0); - } + lv_obj_add_style(obj, &styles->led, 0); + } #endif } diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/themes/default/lv_theme_default.h b/lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.h similarity index 71% rename from lib/libesp32_lvgl/LVGL8/src/extra/themes/default/lv_theme_default.h rename to lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.h index ef8502622..5b1fd9186 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/themes/default/lv_theme_default.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.h @@ -36,9 +36,19 @@ extern "C" { * @param font pointer to a font to use. * @return a pointer to reference this theme later */ -lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font); +lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, + const lv_font_t * font); +/** + * Get default theme + * @return a pointer to default theme, or NULL if this is not initialized + */ +lv_theme_t * lv_theme_default_get(void); +/** + * Check if default theme is initialized + * @return true if default theme is initialized, false otherwise + */ bool lv_theme_default_is_inited(void); /********************** diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/themes/lv_themes.h b/lib/libesp32_lvgl/lvgl/src/extra/themes/lv_themes.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/extra/themes/lv_themes.h rename to lib/libesp32_lvgl/lvgl/src/extra/themes/lv_themes.h diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/themes/mono/lv_theme_mono.c b/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.c similarity index 97% rename from lib/libesp32_lvgl/LVGL8/src/extra/themes/mono/lv_theme_mono.c rename to lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.c index 7abb0a4b3..637564274 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/themes/mono/lv_theme_mono.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.c @@ -78,7 +78,7 @@ static void style_init(bool dark_bg, const lv_font_t * font) { style_init_reset(&styles->scrollbar); lv_style_set_bg_opa(&styles->scrollbar, LV_OPA_COVER); - lv_style_set_bg_color(&styles->scrollbar,COLOR_FG); + lv_style_set_bg_color(&styles->scrollbar, COLOR_FG); lv_style_set_width(&styles->scrollbar, PAD_DEF); style_init_reset(&styles->scr); @@ -219,13 +219,13 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_WIN /*Header*/ - if(lv_obj_get_child_id(obj) == 0 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { + if(lv_obj_get_index(obj) == 0 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { lv_obj_add_style(obj, &styles->card, 0); lv_obj_add_style(obj, &styles->no_radius, 0); return; } /*Content*/ - else if(lv_obj_get_child_id(obj) == 1 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { + else if(lv_obj_get_index(obj) == 1 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { lv_obj_add_style(obj, &styles->card, 0); lv_obj_add_style(obj, &styles->no_radius, 0); lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); @@ -279,7 +279,7 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) lv_obj_add_style(obj, &styles->inv, LV_PART_ITEMS | LV_STATE_CHECKED); lv_obj_add_style(obj, &styles->disabled, LV_PART_ITEMS | LV_STATE_DISABLED); lv_obj_add_style(obj, &styles->underline, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->large_border, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &styles->large_border, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); } #endif @@ -476,8 +476,8 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_LED else if(lv_obj_check_type(obj, &lv_led_class)) { - lv_obj_add_style(obj, &styles->card, 0); - } + lv_obj_add_style(obj, &styles->card, 0); + } #endif } diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/themes/mono/lv_theme_mono.h b/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/extra/themes/mono/lv_theme_mono.h rename to lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.h diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/animimg/lv_animimg.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/animimg/lv_animimg.c similarity index 91% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/animimg/lv_animimg.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/animimg/lv_animimg.c index 7d7cdfe65..135a8a4ba 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/animimg/lv_animimg.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/animimg/lv_animimg.c @@ -27,6 +27,8 @@ *********************/ #define LV_OBJX_NAME "lv_animimg" +#define MY_CLASS &lv_animimg_class + /********************** * TYPEDEFS **********************/ @@ -56,7 +58,7 @@ const lv_obj_class_t lv_animimg_class = { lv_obj_t * lv_animimg_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(&lv_animimg_class, parent); lv_obj_class_init_obj(obj); return obj; @@ -64,14 +66,16 @@ lv_obj_t * lv_animimg_create(lv_obj_t * parent) void lv_animimg_set_src(lv_obj_t * obj, lv_img_dsc_t * dsc[], uint8_t num) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_animimg_t * animimg = (lv_animimg_t *)obj; animimg->dsc = dsc; animimg->pic_count = num; - lv_anim_set_values(&animimg->anim, 0 , num); + lv_anim_set_values(&animimg->anim, 0, num); } void lv_animimg_start(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_animimg_t * animimg = (lv_animimg_t *)obj; lv_anim_start(&animimg->anim); } @@ -82,6 +86,7 @@ void lv_animimg_start(lv_obj_t * obj) void lv_animimg_set_duration(lv_obj_t * obj, uint32_t duration) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_animimg_t * animimg = (lv_animimg_t *)obj; lv_anim_set_time(&animimg->anim, duration); lv_anim_set_playback_delay(&animimg->anim, duration); @@ -89,6 +94,7 @@ void lv_animimg_set_duration(lv_obj_t * obj, uint32_t duration) void lv_animimg_set_repeat_count(lv_obj_t * obj, uint16_t count) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_animimg_t * animimg = (lv_animimg_t *)obj; lv_anim_set_repeat_count(&animimg->anim, count); } @@ -115,7 +121,7 @@ static void lv_animimg_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob lv_anim_set_var(&animimg->anim, obj); lv_anim_set_time(&animimg->anim, 30); lv_anim_set_exec_cb(&animimg->anim, (lv_anim_exec_xcb_t)index_change); - lv_anim_set_values(&animimg->anim, 0 , 1); + lv_anim_set_values(&animimg->anim, 0, 1); lv_anim_set_repeat_count(&animimg->anim, LV_ANIM_REPEAT_INFINITE); } diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/animimg/lv_animimg.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/animimg/lv_animimg.h similarity index 94% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/animimg/lv_animimg.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/animimg/lv_animimg.h index 28d10896a..a61da3539 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/animimg/lv_animimg.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/animimg/lv_animimg.h @@ -19,7 +19,7 @@ extern "C" { /*Testing of dependencies*/ #if LV_USE_IMG == 0 -#error "lv_animing: lv_img is required. Enable it in lv_conf.h (LV_USE_IMG 1)" +#error "lv_animimg: lv_img is required. Enable it in lv_conf.h (LV_USE_IMG 1)" #endif /********************* @@ -37,8 +37,8 @@ typedef struct { lv_img_t img; lv_anim_t anim; /*picture sequence */ - lv_img_dsc_t **dsc; - int8_t pic_count; + lv_img_dsc_t ** dsc; + int8_t pic_count; } lv_animimg_t; diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.c similarity index 76% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.c index 52012acb1..3ba73ea30 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.c @@ -10,12 +10,16 @@ #include "../../../lvgl.h" #if LV_USE_CALENDAR +#include "../../../misc/lv_assert.h" + /********************* * DEFINES *********************/ #define LV_CALENDAR_CTRL_TODAY LV_BTNMATRIX_CTRL_CUSTOM_1 #define LV_CALENDAR_CTRL_HIGHLIGHT LV_BTNMATRIX_CTRL_CUSTOM_2 +#define MY_CLASS &lv_calendar_class + /********************** * TYPEDEFS **********************/ @@ -37,13 +41,12 @@ static void highlight_update(lv_obj_t * calendar); const lv_obj_class_t lv_calendar_class = { .constructor_cb = lv_calendar_constructor, .width_def = (LV_DPI_DEF * 3) / 2, - .height_def =(LV_DPI_DEF * 3) / 2, + .height_def = (LV_DPI_DEF * 3) / 2, .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, .instance_size = sizeof(lv_calendar_t), - .base_class = &lv_btnmatrix_class + .base_class = &lv_obj_class }; - static const char * day_names_def[7] = LV_CALENDAR_DEFAULT_DAY_NAMES; /********************** @@ -56,7 +59,7 @@ static const char * day_names_def[7] = LV_CALENDAR_DEFAULT_DAY_NAMES; lv_obj_t * lv_calendar_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(&lv_calendar_class, parent); lv_obj_class_init_obj(obj); return obj; @@ -68,16 +71,21 @@ lv_obj_t * lv_calendar_create(lv_obj_t * parent) void lv_calendar_set_day_names(lv_obj_t * obj, const char * day_names[]) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_calendar_t * calendar = (lv_calendar_t *)obj; + uint32_t i; for(i = 0; i < 7; i++) { calendar->map[i] = day_names[i]; } + lv_obj_invalidate(obj); } void lv_calendar_set_today_date(lv_obj_t * obj, uint32_t year, uint32_t month, uint32_t day) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_calendar_t * calendar = (lv_calendar_t *)obj; + calendar->today.year = year; calendar->today.month = month; calendar->today.day = day; @@ -89,7 +97,9 @@ void lv_calendar_set_highlighted_dates(lv_obj_t * obj, lv_calendar_date_t highli { LV_ASSERT_NULL(highlighted); + LV_ASSERT_OBJ(obj, MY_CLASS); lv_calendar_t * calendar = (lv_calendar_t *)obj; + calendar->highlighted_dates = highlighted; calendar->highlighted_dates_num = date_num; @@ -98,7 +108,9 @@ void lv_calendar_set_highlighted_dates(lv_obj_t * obj, lv_calendar_date_t highli void lv_calendar_set_showed_date(lv_obj_t * obj, uint32_t year, uint32_t month) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_calendar_t * calendar = (lv_calendar_t *)obj; + calendar->showed_date.year = year; calendar->showed_date.month = month; calendar->showed_date.day = 1; @@ -111,9 +123,9 @@ void lv_calendar_set_showed_date(lv_obj_t * obj, uint32_t year, uint32_t month) uint8_t i; /*Remove the disabled state but revert it for day names*/ - lv_btnmatrix_clear_btn_ctrl_all(obj, LV_BTNMATRIX_CTRL_DISABLED); + lv_btnmatrix_clear_btn_ctrl_all(calendar->btnm, LV_BTNMATRIX_CTRL_DISABLED); for(i = 0; i < 7; i++) { - lv_btnmatrix_set_btn_ctrl(obj, i, LV_BTNMATRIX_CTRL_DISABLED); + lv_btnmatrix_set_btn_ctrl(calendar->btnm, i, LV_BTNMATRIX_CTRL_DISABLED); } uint8_t act_mo_len = get_month_length(d.year, d.month); @@ -126,65 +138,82 @@ void lv_calendar_set_showed_date(lv_obj_t * obj, uint32_t year, uint32_t month) uint8_t prev_mo_len = get_month_length(d.year, d.month - 1); for(i = 0, c = prev_mo_len - day_first + 1; i < day_first; i++, c++) { lv_snprintf(calendar->nums[i], sizeof(calendar->nums[0]), "%d", c); - lv_btnmatrix_set_btn_ctrl(obj, i + 7, LV_BTNMATRIX_CTRL_DISABLED); + lv_btnmatrix_set_btn_ctrl(calendar->btnm, i + 7, LV_BTNMATRIX_CTRL_DISABLED); } for(i = day_first + act_mo_len, c = 1; i < 6 * 7; i++, c++) { lv_snprintf(calendar->nums[i], sizeof(calendar->nums[0]), "%d", c); - lv_btnmatrix_set_btn_ctrl(obj, i + 7, LV_BTNMATRIX_CTRL_DISABLED); + lv_btnmatrix_set_btn_ctrl(calendar->btnm, i + 7, LV_BTNMATRIX_CTRL_DISABLED); } highlight_update(obj); + + /*Reset the focused button if the days changes*/ + if(lv_btnmatrix_get_selected_btn(calendar->btnm) != LV_BTNMATRIX_BTN_NONE) { + lv_btnmatrix_set_selected_btn(calendar->btnm, day_first + 7); + } + lv_obj_invalidate(obj); + + /* The children of the calendar are probably headers. + * Notify them to let the headers updated to the new date*/ + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); + if(child == calendar->btnm) continue; + lv_event_send(child, LV_EVENT_VALUE_CHANGED, obj); + } } /*===================== * Getter functions *====================*/ -/** - * Get the today's date - * @param calendar pointer to a calendar object - * @return return pointer to an `lv_calendar_date_t` variable containing the date of today. - */ +lv_obj_t * lv_calendar_get_btnmatrix(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + const lv_calendar_t * calendar = (lv_calendar_t *)obj; + return calendar->btnm; +} + const lv_calendar_date_t * lv_calendar_get_today_date(const lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); const lv_calendar_t * calendar = (lv_calendar_t *)obj; + return &calendar->today; } -/** - * Get the currently showed - * @param calendar pointer to a calendar object - * @return pointer to an `lv_calendar_date_t` variable containing the date is being shown. - */ const lv_calendar_date_t * lv_calendar_get_showed_date(const lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); const lv_calendar_t * calendar = (lv_calendar_t *)obj; + return &calendar->showed_date; } -/** - * Get the the highlighted dates - * @param calendar pointer to a calendar object - * @return pointer to an `lv_calendar_date_t` array containing the dates. - */ lv_calendar_date_t * lv_calendar_get_highlighted_dates(const lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_calendar_t * calendar = (lv_calendar_t *)obj; + return calendar->highlighted_dates; } uint16_t lv_calendar_get_highlighted_dates_num(const lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_calendar_t * calendar = (lv_calendar_t *)obj; + return calendar->highlighted_dates_num; } lv_res_t lv_calendar_get_pressed_date(const lv_obj_t * obj, lv_calendar_date_t * date) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_calendar_t * calendar = (lv_calendar_t *)obj; - uint16_t d = lv_btnmatrix_get_selected_btn(obj); + + uint16_t d = lv_btnmatrix_get_selected_btn(calendar->btnm); if(d == LV_BTNMATRIX_BTN_NONE) { date->year = 0; date->month = 0; @@ -192,7 +221,7 @@ lv_res_t lv_calendar_get_pressed_date(const lv_obj_t * obj, lv_calendar_date_t * return LV_RES_INV; } - const char * txt = lv_btnmatrix_get_btn_text(obj, lv_btnmatrix_get_selected_btn(obj)); + const char * txt = lv_btnmatrix_get_btn_text(calendar->btnm, lv_btnmatrix_get_selected_btn(calendar->btnm)); if(txt[1] == 0) date->day = txt[0] - '0'; else date->day = (txt[0] - '0') * 10 + (txt[1] - '0'); @@ -232,9 +261,11 @@ static void lv_calendar_constructor(const lv_obj_class_t * class_p, lv_obj_t * o /*Every 8th string is "\n"*/ if(i != 0 && (i + 1) % 8 == 0) { calendar->map[i] = "\n"; - } else if(i < 8){ + } + else if(i < 8) { calendar->map[i] = day_names_def[i]; - } else { + } + else { calendar->nums[j][0] = 'x'; calendar->map[i] = calendar->nums[j]; j++; @@ -242,14 +273,19 @@ static void lv_calendar_constructor(const lv_obj_class_t * class_p, lv_obj_t * o } calendar->map[8 * 7 - 1] = ""; - lv_btnmatrix_set_map(obj, calendar->map); - lv_btnmatrix_set_btn_ctrl_all(obj, LV_BTNMATRIX_CTRL_CLICK_TRIG | LV_BTNMATRIX_CTRL_NO_REPEAT); + calendar->btnm = lv_btnmatrix_create(obj); + lv_btnmatrix_set_map(calendar->btnm, calendar->map); + lv_btnmatrix_set_btn_ctrl_all(calendar->btnm, LV_BTNMATRIX_CTRL_CLICK_TRIG | LV_BTNMATRIX_CTRL_NO_REPEAT); + lv_obj_add_event_cb(calendar->btnm, draw_part_begin_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL); + lv_obj_set_width(calendar->btnm, lv_pct(100)); + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_grow(calendar->btnm, 1); lv_calendar_set_showed_date(obj, calendar->showed_date.year, calendar->showed_date.month); lv_calendar_set_today_date(obj, calendar->today.year, calendar->today.month, calendar->today.day); - lv_obj_add_event_cb(obj, draw_part_begin_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL); + lv_obj_add_flag(calendar->btnm, LV_OBJ_FLAG_EVENT_BUBBLE); } static void draw_part_begin_event_cb(lv_event_t * e) @@ -285,9 +321,6 @@ static void draw_part_begin_event_cb(lv_event_t * e) } } - - - /** * Get the number of days in a month * @param year a year @@ -339,7 +372,7 @@ static uint8_t get_day_of_week(uint32_t year, uint32_t month, uint32_t day) uint32_t day_of_week = (day + (31 * (month - 2 + 12 * a) / 12) + b + (b / 4) - (b / 100) + (b / 400)) % 7; #endif - return day_of_week; + return day_of_week ; } static void highlight_update(lv_obj_t * obj) @@ -348,19 +381,20 @@ static void highlight_update(lv_obj_t * obj) uint16_t i; /*Clear all kind of selection*/ - lv_btnmatrix_clear_btn_ctrl_all(obj, LV_CALENDAR_CTRL_TODAY | LV_CALENDAR_CTRL_HIGHLIGHT); + lv_btnmatrix_clear_btn_ctrl_all(calendar->btnm, LV_CALENDAR_CTRL_TODAY | LV_CALENDAR_CTRL_HIGHLIGHT); + uint8_t day_first = get_day_of_week(calendar->showed_date.year, calendar->showed_date.month, 1); if(calendar->highlighted_dates) { for(i = 0; i < calendar->highlighted_dates_num; i++) { - if(calendar->highlighted_dates[i].year == calendar->today.year && calendar->highlighted_dates[i].month == calendar->showed_date.month) { - lv_btnmatrix_set_btn_ctrl(obj, calendar->highlighted_dates[i].day + 7, LV_CALENDAR_CTRL_HIGHLIGHT); + if(calendar->highlighted_dates[i].year == calendar->showed_date.year && + calendar->highlighted_dates[i].month == calendar->showed_date.month) { + lv_btnmatrix_set_btn_ctrl(calendar->btnm, calendar->highlighted_dates[i].day - 1 + day_first + 7, LV_CALENDAR_CTRL_HIGHLIGHT); } } } if(calendar->showed_date.year == calendar->today.year && calendar->showed_date.month == calendar->today.month) { - uint8_t day_first = get_day_of_week(calendar->today.year, calendar->today.month, 0); - lv_btnmatrix_set_btn_ctrl(obj, calendar->today.day + day_first + 7, LV_CALENDAR_CTRL_TODAY); + lv_btnmatrix_set_btn_ctrl(calendar->btnm, calendar->today.day - 1 + day_first + 7, LV_CALENDAR_CTRL_TODAY); } } diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.h similarity index 91% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.h index 1fe0c4654..a91ce4b22 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.h @@ -36,11 +36,13 @@ typedef struct { /*Data of calendar*/ typedef struct { - lv_btnmatrix_t btnm; + lv_obj_t obj; + lv_obj_t * btnm; /*New data for this type*/ lv_calendar_date_t today; /*Date of today*/ lv_calendar_date_t showed_date; /*Currently visible month (day is ignored)*/ - lv_calendar_date_t * highlighted_dates; /*Apply different style on these days (pointer to an array defined by the user)*/ + lv_calendar_date_t * + highlighted_dates; /*Apply different style on these days (pointer to an array defined by the user)*/ uint16_t highlighted_dates_num; /*Number of elements in `highlighted_days`*/ const char * map[8 * 7]; char nums [7 * 6][4]; @@ -101,6 +103,14 @@ void lv_calendar_set_day_names(lv_obj_t * obj, const char ** day_names); * Getter functions *====================*/ +/** + * Get the button matrix object of the calendar. + * It shows the dates and day names. + * @param obj pointer to a calendar object + * @return pointer to a the button matrix + */ +lv_obj_t * lv_calendar_get_btnmatrix(const lv_obj_t * obj); + /** * Get the today's date * @param calendar pointer to a calendar object diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar_header_arrow.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.c similarity index 68% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar_header_arrow.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.c index c38e09e89..fecb1392e 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar_header_arrow.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.c @@ -27,18 +27,19 @@ **********************/ static void my_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void month_event_cb(lv_event_t * e); +static void value_changed_event_cb(lv_event_t * e); /********************** * STATIC VARIABLES **********************/ const lv_obj_class_t lv_calendar_header_arrow_class = { - .base_class = &lv_obj_class, - .constructor_cb = my_constructor + .base_class = &lv_obj_class, + .constructor_cb = my_constructor, + .width_def = LV_PCT(100), + .height_def = LV_DPI_DEF / 3 }; static const char * month_names_def[12] = LV_CALENDAR_DEFAULT_MONTH_NAMES; -static lv_obj_t * calendar_param; -static lv_coord_t btn_size_param; /********************** * MACROS @@ -48,10 +49,8 @@ static lv_coord_t btn_size_param; * GLOBAL FUNCTIONS **********************/ -lv_obj_t * lv_calendar_header_arrow_create(lv_obj_t * parent, lv_obj_t * calendar, lv_coord_t btn_size) +lv_obj_t * lv_calendar_header_arrow_create(lv_obj_t * parent) { - calendar_param = calendar; - btn_size_param = btn_size; lv_obj_t * obj = lv_obj_class_create_obj(&lv_calendar_header_arrow_class, parent); lv_obj_class_init_obj(obj); return obj; @@ -67,41 +66,36 @@ static void my_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) LV_UNUSED(class_p); - /*Use the same paddings as the calendar_param*/ - lv_obj_set_style_pad_left(obj, lv_obj_get_style_pad_left(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_right(obj, lv_obj_get_style_pad_right(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_top(obj, lv_obj_get_style_pad_top(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_bottom(obj, lv_obj_get_style_pad_bottom(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_column(obj, lv_obj_get_style_pad_column(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_radius(obj, lv_obj_get_style_radius(calendar_param, LV_PART_MAIN), 0); + lv_obj_move_to_index(obj, 0); - const lv_calendar_date_t * cur_date = lv_calendar_get_showed_date(calendar_param); - - lv_obj_update_layout(calendar_param); - lv_coord_t w = lv_obj_get_width(calendar_param); - lv_obj_set_size(obj, w, LV_SIZE_CONTENT); lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(obj, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START); lv_obj_t * mo_prev = lv_btn_create(obj); lv_obj_set_style_bg_img_src(mo_prev, LV_SYMBOL_LEFT, 0); - lv_obj_set_size(mo_prev, btn_size_param, btn_size_param); - lv_obj_add_event_cb(mo_prev, month_event_cb, LV_EVENT_CLICKED, calendar_param); + lv_obj_set_height(mo_prev, lv_pct(100)); + lv_obj_update_layout(mo_prev); + lv_coord_t btn_size = lv_obj_get_height(mo_prev); + lv_obj_set_width(mo_prev, btn_size); + + lv_obj_add_event_cb(mo_prev, month_event_cb, LV_EVENT_CLICKED, NULL); lv_obj_clear_flag(mo_prev, LV_OBJ_FLAG_CLICK_FOCUSABLE); lv_obj_t * label = lv_label_create(obj); lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_flex_grow(label, 1); - lv_label_set_text_fmt(label, "%d %s", cur_date->year, month_names_def[cur_date->month - 1]); lv_obj_t * mo_next = lv_btn_create(obj); lv_obj_set_style_bg_img_src(mo_next, LV_SYMBOL_RIGHT, 0); - lv_obj_set_size(mo_next, btn_size_param, btn_size_param); - lv_obj_add_event_cb(mo_next, month_event_cb, LV_EVENT_CLICKED, calendar_param); + lv_obj_set_size(mo_next, btn_size, btn_size); + + lv_obj_add_event_cb(mo_next, month_event_cb, LV_EVENT_CLICKED, NULL); lv_obj_clear_flag(mo_next, LV_OBJ_FLAG_CLICK_FOCUSABLE); - lv_obj_align_to(obj, calendar_param, LV_ALIGN_OUT_TOP_MID, 0, 0); + lv_obj_add_event_cb(obj, value_changed_event_cb, LV_EVENT_VALUE_CHANGED, NULL); + /*Refresh the drop downs*/ + lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); } static void month_event_cb(lv_event_t * e) @@ -109,7 +103,7 @@ static void month_event_cb(lv_event_t * e) lv_obj_t * btn = lv_event_get_target(e); lv_obj_t * header = lv_obj_get_parent(btn); - lv_obj_t * calendar = lv_event_get_user_data(e); + lv_obj_t * calendar = lv_obj_get_parent(header); const lv_calendar_date_t * d; d = lv_calendar_get_showed_date(calendar); @@ -120,14 +114,17 @@ static void month_event_cb(lv_event_t * e) if(newd.month == 1) { newd.month = 12; newd.year --; - } else { + } + else { newd.month --; } - } else { + } + else { if(newd.month == 12) { newd.month = 1; newd.year ++; - } else { + } + else { newd.month ++; } } @@ -138,5 +135,15 @@ static void month_event_cb(lv_event_t * e) lv_label_set_text_fmt(label, "%d %s", newd.year, month_names_def[newd.month - 1]); } +static void value_changed_event_cb(lv_event_t * e) +{ + lv_obj_t * header = lv_event_get_target(e); + lv_obj_t * calendar = lv_obj_get_parent(header); + + const lv_calendar_date_t * cur_date = lv_calendar_get_showed_date(calendar); + lv_obj_t * label = lv_obj_get_child(header, 1); + lv_label_set_text_fmt(label, "%d %s", cur_date->year, month_names_def[cur_date->month - 1]); +} + #endif /*LV_USE_CALENDAR_HEADER_ARROW*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar_header_arrow.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.h similarity index 74% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar_header_arrow.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.h index b4e3b52e3..f33ef7dc8 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar_header_arrow.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.h @@ -30,11 +30,11 @@ extern const lv_obj_class_t lv_calendar_header_arrow_class; **********************/ /** - * Create a calendar objects - * @param par pointer to an object, it will be the parent of the new calendar - * @return pointer to the created calendar + * Create a calendar header with drop-drowns to select the year and month + * @param parent pointer to a calendar object. + * @return the created header */ -lv_obj_t * lv_calendar_header_arrow_create(lv_obj_t * parent, lv_obj_t * calendar, lv_coord_t btn_size); +lv_obj_t * lv_calendar_header_arrow_create(lv_obj_t * parent); /********************** * MACROS diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar_header_dropdown.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.c similarity index 58% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar_header_dropdown.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.c index 18af0d94a..5e8f90d4a 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar_header_dropdown.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.c @@ -27,28 +27,29 @@ static void my_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void year_event_cb(lv_event_t * e); static void month_event_cb(lv_event_t * e); +static void value_changed_event_cb(lv_event_t * e); /********************** * STATIC VARIABLES **********************/ const lv_obj_class_t lv_calendar_header_dropdown_class = { - .base_class = &lv_obj_class, - .constructor_cb = my_constructor - }; + .base_class = &lv_obj_class, + .width_def = LV_PCT(100), + .height_def = LV_SIZE_CONTENT, + .constructor_cb = my_constructor +}; static const char * month_list = "01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12"; static const char * year_list = { - "2023\n2022\n2021\n" - "2020\n2019\n2018\n2017\n2016\n2015\n2014\n2013\n2012\n2011\n2010\n2009\n2008\n2007\n2006\n2005\n2004\n2003\n2002\n2001\n" - "2000\n1999\n1998\n1997\n1996\n1995\n1994\n1993\n1992\n1991\n1990\n1989\n1988\n1987\n1986\n1985\n1984\n1983\n1982\n1981\n" - "1980\n1979\n1978\n1977\n1976\n1975\n1974\n1973\n1972\n1971\n1970\n1969\n1968\n1967\n1966\n1965\n1964\n1963\n1962\n1961\n" - "1960\n1959\n1958\n1957\n1956\n1955\n1954\n1953\n1952\n1951\n1950\n1949\n1948\n1947\n1946\n1945\n1944\n1943\n1942\n1941\n" - "1940\n1939\n1938\n1937\n1936\n1935\n1934\n1933\n1932\n1931\n1930\n1929\n1928\n1927\n1926\n1925\n1924\n1923\n1922\n1921\n" - "1920\n1919\n1918\n1917\n1916\n1915\n1914\n1913\n1912\n1911\n1910\n1909\n1908\n1907\n1906\n1905\n1904\n1903\n1902\n1901" + "2023\n2022\n2021\n" + "2020\n2019\n2018\n2017\n2016\n2015\n2014\n2013\n2012\n2011\n2010\n2009\n2008\n2007\n2006\n2005\n2004\n2003\n2002\n2001\n" + "2000\n1999\n1998\n1997\n1996\n1995\n1994\n1993\n1992\n1991\n1990\n1989\n1988\n1987\n1986\n1985\n1984\n1983\n1982\n1981\n" + "1980\n1979\n1978\n1977\n1976\n1975\n1974\n1973\n1972\n1971\n1970\n1969\n1968\n1967\n1966\n1965\n1964\n1963\n1962\n1961\n" + "1960\n1959\n1958\n1957\n1956\n1955\n1954\n1953\n1952\n1951\n1950\n1949\n1948\n1947\n1946\n1945\n1944\n1943\n1942\n1941\n" + "1940\n1939\n1938\n1937\n1936\n1935\n1934\n1933\n1932\n1931\n1930\n1929\n1928\n1927\n1926\n1925\n1924\n1923\n1922\n1921\n" + "1920\n1919\n1918\n1917\n1916\n1915\n1914\n1913\n1912\n1911\n1910\n1909\n1908\n1907\n1906\n1905\n1904\n1903\n1902\n1901" }; -static lv_obj_t * calendar_param; - /********************** * MACROS **********************/ @@ -57,9 +58,8 @@ static lv_obj_t * calendar_param; * GLOBAL FUNCTIONS **********************/ -lv_obj_t * lv_calendar_header_dropdown_create(lv_obj_t * parent, lv_obj_t * calendar) +lv_obj_t * lv_calendar_header_dropdown_create(lv_obj_t * parent) { - calendar_param = calendar; lv_obj_t * obj = lv_obj_class_create_obj(&lv_calendar_header_dropdown_class, parent); lv_obj_class_init_obj(obj); @@ -76,36 +76,23 @@ static void my_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) LV_UNUSED(class_p); - /*Use the same paddings as the calendar_param*/ - lv_obj_set_style_pad_left(obj,lv_obj_get_style_pad_left(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_right(obj,lv_obj_get_style_pad_right(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_top(obj,lv_obj_get_style_pad_top(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_bottom(obj,lv_obj_get_style_pad_bottom(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_column(obj,lv_obj_get_style_pad_column(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_radius(obj,lv_obj_get_style_radius(calendar_param, LV_PART_MAIN), 0); - - const lv_calendar_date_t * cur_date = lv_calendar_get_showed_date(calendar_param); - - lv_obj_update_layout(calendar_param); - lv_coord_t w = lv_obj_get_width(calendar_param); - lv_obj_set_size(obj, w, LV_SIZE_CONTENT); + lv_obj_t * calendar = lv_obj_get_parent(obj); + lv_obj_move_to_index(obj, 0); lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW); - lv_obj_set_flex_align(obj, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START); lv_obj_t * year_dd = lv_dropdown_create(obj); lv_dropdown_set_options(year_dd, year_list); - lv_dropdown_set_selected(year_dd, 2023 - cur_date->year); - lv_obj_add_event_cb(year_dd, year_event_cb, LV_EVENT_VALUE_CHANGED, calendar_param); + lv_obj_add_event_cb(year_dd, year_event_cb, LV_EVENT_VALUE_CHANGED, calendar); lv_obj_set_flex_grow(year_dd, 1); lv_obj_t * month_dd = lv_dropdown_create(obj); lv_dropdown_set_options(month_dd, month_list); - lv_dropdown_set_selected(month_dd, cur_date->month - 1); - lv_obj_add_event_cb(month_dd, month_event_cb, LV_EVENT_VALUE_CHANGED, calendar_param); + lv_obj_add_event_cb(month_dd, month_event_cb, LV_EVENT_VALUE_CHANGED, calendar); lv_obj_set_flex_grow(month_dd, 1); - lv_obj_align_to(obj, calendar_param, LV_ALIGN_OUT_TOP_MID, 0, 0); - + lv_obj_add_event_cb(obj, value_changed_event_cb, LV_EVENT_VALUE_CHANGED, NULL); + /*Refresh the drop downs*/ + lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); } static void month_event_cb(lv_event_t * e) @@ -122,6 +109,7 @@ static void month_event_cb(lv_event_t * e) lv_calendar_set_showed_date(calendar, newd.year, newd.month); } + static void year_event_cb(lv_event_t * e) { lv_obj_t * dropdown = lv_event_get_target(e); @@ -137,5 +125,18 @@ static void year_event_cb(lv_event_t * e) lv_calendar_set_showed_date(calendar, newd.year, newd.month); } +static void value_changed_event_cb(lv_event_t * e) +{ + lv_obj_t * header = lv_event_get_target(e); + lv_obj_t * calendar = lv_obj_get_parent(header); + const lv_calendar_date_t * cur_date = lv_calendar_get_showed_date(calendar); + + lv_obj_t * year_dd = lv_obj_get_child(header, 0); + lv_dropdown_set_selected(year_dd, 2023 - cur_date->year); + + lv_obj_t * month_dd = lv_obj_get_child(header, 1); + lv_dropdown_set_selected(month_dd, cur_date->month - 1); +} + #endif /*LV_USE_CALENDAR_HEADER_ARROW*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar_header_dropdown.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.h similarity index 76% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar_header_dropdown.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.h index 8d6333d9d..7ce924e94 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/calendar/lv_calendar_header_dropdown.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.h @@ -30,11 +30,11 @@ extern const lv_obj_class_t lv_calendar_header_dropdown_class; **********************/ /** - * Create a calendar objects - * @param par pointer to an object, it will be the parent of the new calendar - * @return pointer to the created calendar + * Create a calendar header with drop-drowns to select the year and month + * @param parent pointer to a calendar object. + * @return the created header */ -lv_obj_t * lv_calendar_header_dropdown_create(lv_obj_t * parent, lv_obj_t * calendar); +lv_obj_t * lv_calendar_header_dropdown_create(lv_obj_t * parent); /********************** * MACROS diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/chart/lv_chart.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.c similarity index 76% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/chart/lv_chart.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.c index 6face3dba..12c05b338 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/chart/lv_chart.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.c @@ -9,6 +9,8 @@ #include "lv_chart.h" #if LV_USE_CHART != 0 +#include "../../../misc/lv_assert.h" + /********************* * DEFINES *********************/ @@ -17,6 +19,7 @@ #define LV_CHART_HDIV_DEF 3 #define LV_CHART_VDIV_DEF 5 #define LV_CHART_POINT_CNT_DEF 10 +#define LV_CHART_LABEL_MAX_TEXT_LENGTH 16 /********************** * TYPEDEFS @@ -29,7 +32,7 @@ static void lv_chart_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) static void lv_chart_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void lv_chart_event(const lv_obj_class_t * class_p, lv_event_t * e); -static void draw_div_lines(lv_obj_t * obj , const lv_area_t * mask); +static void draw_div_lines(lv_obj_t * obj, const lv_area_t * mask); static void draw_series_line(lv_obj_t * obj, const lv_area_t * clip_area); static void draw_series_bar(lv_obj_t * obj, const lv_area_t * clip_area); static void draw_series_scatter(lv_obj_t * obj, const lv_area_t * clip_area); @@ -63,7 +66,7 @@ const lv_obj_class_t lv_chart_class = { lv_obj_t * lv_chart_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -130,25 +133,25 @@ void lv_chart_set_range(lv_obj_t * obj, lv_chart_axis_t axis, lv_coord_t min, lv lv_chart_t * chart = (lv_chart_t *)obj; switch(axis) { - case LV_CHART_AXIS_PRIMARY_Y: - chart->ymin[0] = min; - chart->ymax[0] = max; - break; - case LV_CHART_AXIS_SECONDARY_Y: - chart->ymin[1] = min; - chart->ymax[1] = max; - break; - case LV_CHART_AXIS_PRIMARY_X: - chart->xmin[0] = min; - chart->xmax[0] = max; - break; - case LV_CHART_AXIS_SECONDARY_X: - chart->xmin[1] = min; - chart->xmax[1] = max; - break; - default: - LV_LOG_WARN("Invalid axis: %d", axis); - return; + case LV_CHART_AXIS_PRIMARY_Y: + chart->ymin[0] = min; + chart->ymax[0] = max; + break; + case LV_CHART_AXIS_SECONDARY_Y: + chart->ymin[1] = min; + chart->ymax[1] = max; + break; + case LV_CHART_AXIS_PRIMARY_X: + chart->xmin[0] = min; + chart->xmax[0] = max; + break; + case LV_CHART_AXIS_SECONDARY_X: + chart->xmin[1] = min; + chart->xmax[1] = max; + break; + default: + LV_LOG_WARN("Invalid axis: %d", axis); + return; } lv_chart_refresh(obj); @@ -188,6 +191,8 @@ void lv_chart_set_zoom_x(lv_obj_t * obj, uint16_t zoom_x) chart->zoom_x = zoom_x; lv_obj_refresh_self_size(obj); + /*Be the chart doesn't remain scrolled out*/ + lv_obj_readjust_scroll(obj, LV_ANIM_OFF); lv_obj_invalidate(obj); } @@ -200,6 +205,8 @@ void lv_chart_set_zoom_y(lv_obj_t * obj, uint16_t zoom_y) chart->zoom_y = zoom_y; lv_obj_refresh_self_size(obj); + /*Be the chart doesn't remain scrolled out*/ + lv_obj_readjust_scroll(obj, LV_ANIM_OFF); lv_obj_invalidate(obj); } @@ -219,7 +226,8 @@ uint16_t lv_chart_get_zoom_y(const lv_obj_t * obj) return chart->zoom_y; } -void lv_chart_set_axis_tick(lv_obj_t * obj, lv_chart_axis_t axis, lv_coord_t major_len, lv_coord_t minor_len, lv_coord_t major_cnt, lv_coord_t minor_cnt, bool label_en, lv_coord_t draw_size) +void lv_chart_set_axis_tick(lv_obj_t * obj, lv_chart_axis_t axis, lv_coord_t major_len, lv_coord_t minor_len, + lv_coord_t major_cnt, lv_coord_t minor_cnt, bool label_en, lv_coord_t draw_size) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -263,6 +271,7 @@ void lv_chart_get_point_pos_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint1 { LV_ASSERT_NULL(obj); LV_ASSERT_NULL(ser); + LV_ASSERT_OBJ(obj, MY_CLASS); lv_chart_t * chart = (lv_chart_t *)obj; if(id >= chart->point_cnt) { @@ -272,8 +281,8 @@ void lv_chart_get_point_pos_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint1 return; } - lv_coord_t w = (lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - lv_coord_t h = (lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; + lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; + lv_coord_t h = ((int32_t)lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; if(chart->type == LV_CHART_TYPE_LINE) { p_out->x = (w * id) / (chart->point_cnt - 1); @@ -283,8 +292,10 @@ void lv_chart_get_point_pos_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint1 } else if(chart->type == LV_CHART_TYPE_BAR) { uint32_t ser_cnt = _lv_ll_get_len(&chart->series_ll); - int32_t ser_gap = (lv_obj_get_style_pad_column(obj, LV_PART_ITEMS) * chart->zoom_x) >> 8; /*Gap between the column on the ~same X*/ - int32_t block_gap = (lv_obj_get_style_pad_column(obj, LV_PART_MAIN) * chart->zoom_x) >> 8; /*Gap between the column on ~adjacent X*/ + int32_t ser_gap = ((int32_t)lv_obj_get_style_pad_column(obj, + LV_PART_ITEMS) * chart->zoom_x) >> 8; /*Gap between the column on the ~same X*/ + int32_t block_gap = ((int32_t)lv_obj_get_style_pad_column(obj, + LV_PART_MAIN) * chart->zoom_x) >> 8; /*Gap between the column on ~adjacent X*/ lv_coord_t block_w = (w - ((chart->point_cnt - 1) * block_gap)) / chart->point_cnt; lv_coord_t col_w = block_w / ser_cnt; @@ -303,11 +314,12 @@ void lv_chart_get_point_pos_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint1 p_out->x += lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; p_out->x -= lv_obj_get_scroll_left(obj); - p_out->y = (int32_t)((int32_t)ser->y_points[id] - chart->ymin[ser->y_axis_sec]) * h; - p_out->y = p_out->y / (chart->ymax[ser->y_axis_sec] - chart->ymin[ser->y_axis_sec]); - p_out->y = h - p_out->y; + int32_t temp_y = 0; + temp_y = (int32_t)((int32_t)ser->y_points[id] - chart->ymin[ser->y_axis_sec]) * h; + temp_y = temp_y / (chart->ymax[ser->y_axis_sec] - chart->ymin[ser->y_axis_sec]); + p_out->y = h - temp_y; p_out->y += lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; - + p_out->y -= lv_obj_get_scroll_top(obj); } void lv_chart_refresh(lv_obj_t * obj) @@ -323,7 +335,7 @@ void lv_chart_refresh(lv_obj_t * obj) lv_chart_series_t * lv_chart_add_series(lv_obj_t * obj, lv_color_t color, lv_chart_axis_t axis) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); LV_ASSERT_OBJ(obj, MY_CLASS); @@ -560,7 +572,8 @@ void lv_chart_set_value_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t ser->y_points[id] = value; } -void lv_chart_set_value_by_id2(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_coord_t x_value, lv_coord_t y_value) +void lv_chart_set_value_by_id2(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_coord_t x_value, + lv_coord_t y_value) { LV_ASSERT_OBJ(obj, MY_CLASS); LV_ASSERT_NULL(ser); @@ -702,18 +715,24 @@ static void lv_chart_event(const lv_obj_class_t * class_p, lv_event_t * e) chart->pressed_point_id = id; lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); } - } else if(code == LV_EVENT_RELEASED) { + } + else if(code == LV_EVENT_RELEASED) { invalidate_point(obj, chart->pressed_point_id); chart->pressed_point_id = LV_CHART_POINT_NONE; - } else if(code == LV_EVENT_SIZE_CHANGED) { + } + else if(code == LV_EVENT_SIZE_CHANGED) { lv_obj_refresh_self_size(obj); - } else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - lv_event_set_ext_draw_size(e, LV_MAX4(chart->tick[0].draw_size, chart->tick[1].draw_size, chart->tick[2].draw_size, chart->tick[3].draw_size)); - } else if(code == LV_EVENT_GET_SELF_SIZE) { + } + else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { + lv_event_set_ext_draw_size(e, LV_MAX4(chart->tick[0].draw_size, chart->tick[1].draw_size, chart->tick[2].draw_size, + chart->tick[3].draw_size)); + } + else if(code == LV_EVENT_GET_SELF_SIZE) { lv_point_t * p = lv_event_get_param(e); - p->x = (lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - p->y = (lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; - } else if(code == LV_EVENT_DRAW_MAIN) { + p->x = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; + p->y = ((int32_t)lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; + } + else if(code == LV_EVENT_DRAW_MAIN) { const lv_area_t * clip_area = lv_event_get_param(e); draw_div_lines(obj, clip_area); draw_axes(obj, clip_area); @@ -744,17 +763,23 @@ static void draw_div_lines(lv_obj_t * obj, const lv_area_t * clip_area) lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; - lv_coord_t w = (lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - lv_coord_t h = (lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; + lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; + lv_coord_t h = ((int32_t)lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; lv_draw_line_dsc_t line_dsc; lv_draw_line_dsc_init(&line_dsc); lv_obj_init_draw_line_dsc(obj, LV_PART_MAIN, &line_dsc); - lv_obj_draw_part_dsc_t obj_draw_dsc; - lv_obj_draw_dsc_init(&obj_draw_dsc, clip_area); - obj_draw_dsc.line_dsc = &line_dsc; - obj_draw_dsc.part = LV_PART_MAIN; + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + part_draw_dsc.part = LV_PART_MAIN; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_CHART_DRAW_PART_DIV_LINE_INIT; + part_draw_dsc.line_dsc = &line_dsc; + part_draw_dsc.id = 0xFFFFFFFF; + part_draw_dsc.p1 = NULL; + part_draw_dsc.p2 = NULL; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_opa_t border_opa = lv_obj_get_style_border_opa(obj, LV_PART_MAIN); lv_coord_t border_w = lv_obj_get_style_border_width(obj, LV_PART_MAIN); @@ -775,17 +800,19 @@ static void draw_div_lines(lv_obj_t * obj, const lv_area_t * clip_area) } for(i = i_start; i < i_end; i++) { - p1.y = (int32_t)((int32_t)(h - line_dsc.width) * i) / (chart->hdiv_cnt - 1); + p1.y = (int32_t)((int32_t)h * i) / (chart->hdiv_cnt - 1); p1.y += y_ofs; p2.y = p1.y; - obj_draw_dsc.p1 = &p1; - obj_draw_dsc.p2 = &p2; - obj_draw_dsc.id = i; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_CHART_DRAW_PART_DIV_LINE_HOR; + part_draw_dsc.p1 = &p1; + part_draw_dsc.p2 = &p2; + part_draw_dsc.id = i; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &obj_draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_line(&p1, &p2, &series_mask, &line_dsc); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &obj_draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } } @@ -801,19 +828,27 @@ static void draw_div_lines(lv_obj_t * obj, const lv_area_t * clip_area) } for(i = i_start; i < i_end; i++) { - p1.x = (int32_t)((int32_t)(w - line_dsc.width) * i) / (chart->vdiv_cnt - 1); + p1.x = (int32_t)((int32_t)w * i) / (chart->vdiv_cnt - 1); p1.x += x_ofs; p2.x = p1.x; - obj_draw_dsc.p1 = &p1; - obj_draw_dsc.p2 = &p2; - obj_draw_dsc.id = i; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_CHART_DRAW_PART_DIV_LINE_VER; + part_draw_dsc.p1 = &p1; + part_draw_dsc.p2 = &p2; + part_draw_dsc.id = i; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &obj_draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_line(&p1, &p2, &series_mask, &line_dsc); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &obj_draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } } + + part_draw_dsc.id = 0xFFFFFFFF; + part_draw_dsc.p1 = NULL; + part_draw_dsc.p2 = NULL; + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); + } static void draw_series_line(lv_obj_t * obj, const lv_area_t * clip_area) @@ -822,6 +857,7 @@ static void draw_series_line(lv_obj_t * obj, const lv_area_t * clip_area) if(_lv_area_intersect(&com_area, &obj->coords, clip_area) == false) return; lv_chart_t * chart = (lv_chart_t *)obj; + if(chart->point_cnt < 2) return; uint16_t i; lv_point_t p1; @@ -829,8 +865,8 @@ static void draw_series_line(lv_obj_t * obj, const lv_area_t * clip_area) lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; - lv_coord_t w = (lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - lv_coord_t h = (lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; + lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; + lv_coord_t h = ((int32_t)lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; lv_coord_t x_ofs = obj->coords.x1 + pad_left - lv_obj_get_scroll_left(obj); lv_coord_t y_ofs = obj->coords.y1 + pad_top - lv_obj_get_scroll_top(obj); lv_chart_series_t * ser; @@ -859,7 +895,7 @@ static void draw_series_line(lv_obj_t * obj, const lv_area_t * clip_area) /*Go through all data lines*/ _LV_LL_READ_BACK(&chart->series_ll, ser) { - if (ser->hidden) continue; + if(ser->hidden) continue; line_dsc_default.color = ser->color; point_dsc_default.bg_color = ser->color; @@ -874,12 +910,14 @@ static void draw_series_line(lv_obj_t * obj, const lv_area_t * clip_area) y_tmp = y_tmp / (chart->ymax[ser->y_axis_sec] - chart->ymin[ser->y_axis_sec]); p2.y = h - y_tmp + y_ofs; - lv_obj_draw_part_dsc_t dsc; - lv_obj_draw_dsc_init(&dsc, clip_area); - dsc.part = LV_PART_ITEMS; - dsc.line_dsc = &line_dsc_default; - dsc.rect_dsc = &point_dsc_default; - dsc.sub_part_ptr = ser; + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_CHART_DRAW_PART_LINE_AND_POINT; + part_draw_dsc.part = LV_PART_ITEMS; + part_draw_dsc.line_dsc = &line_dsc_default; + part_draw_dsc.rect_dsc = &point_dsc_default; + part_draw_dsc.sub_part_ptr = ser; lv_coord_t y_min = p2.y; lv_coord_t y_max = p2.y; @@ -906,7 +944,7 @@ static void draw_series_line(lv_obj_t * obj, const lv_area_t * clip_area) if(i != 0) { if(crowded_mode) { if(ser->y_points[p_prev] != LV_CHART_POINT_NONE && ser->y_points[p_act] != LV_CHART_POINT_NONE) { - /*Draw only one vertical line between the min an max y values on the same x value*/ + /*Draw only one vertical line between the min and max y-values on the same x-value*/ y_max = LV_MAX(y_max, p2.y); y_min = LV_MIN(y_min, p2.y); if(p1.x != p2.x) { @@ -922,30 +960,31 @@ static void draw_series_line(lv_obj_t * obj, const lv_area_t * clip_area) y_max = y_cur; } } - } else { + } + else { lv_area_t point_area; point_area.x1 = p1.x - point_w; point_area.x2 = p1.x + point_w; point_area.y1 = p1.y - point_h; point_area.y2 = p1.y + point_h; - dsc.id = i - 1; - dsc.p1 = ser->y_points[p_prev] != LV_CHART_POINT_NONE ? &p1 : NULL; - dsc.p2 = ser->y_points[p_act] != LV_CHART_POINT_NONE ? &p2 : NULL; - dsc.draw_area = &point_area; - dsc.value = ser->y_points[p_prev]; + part_draw_dsc.id = i - 1; + part_draw_dsc.p1 = ser->y_points[p_prev] != LV_CHART_POINT_NONE ? &p1 : NULL; + part_draw_dsc.p2 = ser->y_points[p_act] != LV_CHART_POINT_NONE ? &p2 : NULL; + part_draw_dsc.draw_area = &point_area; + part_draw_dsc.value = ser->y_points[p_prev]; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); if(ser->y_points[p_prev] != LV_CHART_POINT_NONE && ser->y_points[p_act] != LV_CHART_POINT_NONE) { lv_draw_line(&p1, &p2, &series_mask, &line_dsc_default); } - if(point_w && point_h && ser->y_points[p_act] != LV_CHART_POINT_NONE) { + if(point_w && point_h && ser->y_points[p_prev] != LV_CHART_POINT_NONE) { lv_draw_rect(&point_area, &series_mask, &point_dsc_default); } - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } } @@ -962,14 +1001,14 @@ static void draw_series_line(lv_obj_t * obj, const lv_area_t * clip_area) point_area.y1 = p2.y - point_h; point_area.y2 = p2.y + point_h; - dsc.id = i - 1; - dsc.p1 = NULL; - dsc.p2 = NULL; - dsc.draw_area = &point_area; - dsc.value = ser->y_points[p_act]; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &dsc); + part_draw_dsc.id = i - 1; + part_draw_dsc.p1 = NULL; + part_draw_dsc.p2 = NULL; + part_draw_dsc.draw_area = &point_area; + part_draw_dsc.value = ser->y_points[p_act]; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_rect(&point_area, &series_mask, &point_dsc_default); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } } } @@ -989,8 +1028,8 @@ static void draw_series_scatter(lv_obj_t * obj, const lv_area_t * clip_area) lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t w = (lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - lv_coord_t h = (lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; + lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; + lv_coord_t h = ((int32_t)lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; lv_coord_t x_ofs = obj->coords.x1 + pad_left + border_width - lv_obj_get_scroll_left(obj); lv_coord_t y_ofs = obj->coords.y1 + pad_top + border_width - lv_obj_get_scroll_top(obj); lv_chart_series_t * ser; @@ -1016,7 +1055,7 @@ static void draw_series_scatter(lv_obj_t * obj, const lv_area_t * clip_area) /*Go through all data lines*/ _LV_LL_READ_BACK(&chart->series_ll, ser) { - if (ser->hidden) continue; + if(ser->hidden) continue; line_dsc_default.color = ser->color; point_dsc_default.bg_color = ser->color; @@ -1034,17 +1073,20 @@ static void draw_series_scatter(lv_obj_t * obj, const lv_area_t * clip_area) p2.y = lv_map(ser->y_points[p_act], chart->ymin[ser->y_axis_sec], chart->ymax[ser->y_axis_sec], 0, h); p2.y = h - p2.y; p2.y += y_ofs; - } else { + } + else { p2.x = LV_COORD_MIN; p2.y = LV_COORD_MIN; } - lv_obj_draw_part_dsc_t dsc; - lv_obj_draw_dsc_init(&dsc, clip_area); - dsc.part = LV_PART_ITEMS; - dsc.line_dsc = &line_dsc_default; - dsc.rect_dsc = &point_dsc_default; - dsc.sub_part_ptr = ser; + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + part_draw_dsc.part = LV_PART_ITEMS; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_CHART_DRAW_PART_LINE_AND_POINT; + part_draw_dsc.line_dsc = &line_dsc_default; + part_draw_dsc.rect_dsc = &point_dsc_default; + part_draw_dsc.sub_part_ptr = ser; for(i = 0; i < chart->point_cnt; i++) { p1.x = p2.x; @@ -1058,7 +1100,8 @@ static void draw_series_scatter(lv_obj_t * obj, const lv_area_t * clip_area) p2.x = lv_map(ser->x_points[p_act], chart->xmin[ser->x_axis_sec], chart->xmax[ser->x_axis_sec], 0, w); p2.x += x_ofs; - } else { + } + else { p_prev = p_act; continue; } @@ -1071,13 +1114,13 @@ static void draw_series_scatter(lv_obj_t * obj, const lv_area_t * clip_area) point_area.y1 = p1.y - point_h; point_area.y2 = p1.y + point_h; - dsc.id = i - 1; - dsc.p1 = ser->y_points[p_prev] != LV_CHART_POINT_NONE ? &p1 : NULL; - dsc.p2 = ser->y_points[p_act] != LV_CHART_POINT_NONE ? &p2 : NULL; - dsc.draw_area = &point_area; - dsc.value = ser->y_points[p_prev]; + part_draw_dsc.id = i - 1; + part_draw_dsc.p1 = ser->y_points[p_prev] != LV_CHART_POINT_NONE ? &p1 : NULL; + part_draw_dsc.p2 = ser->y_points[p_act] != LV_CHART_POINT_NONE ? &p2 : NULL; + part_draw_dsc.draw_area = &point_area; + part_draw_dsc.value = ser->y_points[p_prev]; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); if(ser->y_points[p_prev] != LV_CHART_POINT_NONE && ser->y_points[p_act] != LV_CHART_POINT_NONE) { lv_draw_line(&p1, &p2, &series_mask, &line_dsc_default); @@ -1086,7 +1129,7 @@ static void draw_series_scatter(lv_obj_t * obj, const lv_area_t * clip_area) } } - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } p_prev = p_act; } @@ -1101,14 +1144,14 @@ static void draw_series_scatter(lv_obj_t * obj, const lv_area_t * clip_area) point_area.y1 = p2.y - point_h; point_area.y2 = p2.y + point_h; - dsc.id = i - 1; - dsc.p1 = NULL; - dsc.p2 = NULL; - dsc.draw_area = &point_area; - dsc.value = ser->y_points[p_act]; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &dsc); + part_draw_dsc.id = i - 1; + part_draw_dsc.p1 = NULL; + part_draw_dsc.p2 = NULL; + part_draw_dsc.draw_area = &point_area; + part_draw_dsc.value = ser->y_points[p_act]; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_rect(&point_area, &series_mask, &point_dsc_default); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } } } @@ -1125,15 +1168,17 @@ static void draw_series_bar(lv_obj_t * obj, const lv_area_t * clip_area) lv_area_t col_a; lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t w = (lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - lv_coord_t h = (lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; + lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; + lv_coord_t h = ((int32_t)lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; int32_t y_tmp; lv_chart_series_t * ser; uint32_t ser_cnt = _lv_ll_get_len(&chart->series_ll); - int32_t block_gap = (lv_obj_get_style_pad_column(obj, LV_PART_MAIN) * chart->zoom_x) >> 8; /*Gap between the column on ~adjacent X*/ + int32_t block_gap = ((int32_t)lv_obj_get_style_pad_column(obj, + LV_PART_MAIN) * chart->zoom_x) >> 8; /*Gap between the column on ~adjacent X*/ lv_coord_t block_w = (w - ((chart->point_cnt - 1) * block_gap)) / chart->point_cnt; lv_coord_t col_w = block_w / ser_cnt; - int32_t ser_gap = (lv_obj_get_style_pad_column(obj, LV_PART_ITEMS) * chart->zoom_x) >> 8; /*Gap between the column on the ~same X*/ + int32_t ser_gap = ((int32_t)lv_obj_get_style_pad_column(obj, + LV_PART_ITEMS) * chart->zoom_x) >> 8; /*Gap between the column on the ~same X*/ lv_coord_t x_ofs = pad_left - lv_obj_get_scroll_left(obj); lv_coord_t y_ofs = pad_top - lv_obj_get_scroll_top(obj); @@ -1150,19 +1195,21 @@ static void draw_series_bar(lv_obj_t * obj, const lv_area_t * clip_area) bool mask_ret = _lv_area_intersect(&series_mask, &obj->coords, clip_area); if(mask_ret == false) return; - lv_obj_draw_part_dsc_t dsc; - lv_obj_draw_dsc_init(&dsc, &series_mask); - dsc.part = LV_PART_ITEMS; + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, &series_mask); + part_draw_dsc.part = LV_PART_ITEMS; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_CHART_DRAW_PART_BAR; /*Go through all points*/ for(i = 0; i < chart->point_cnt; i++) { lv_coord_t x_act = (int32_t)((int32_t)(w + block_gap) * i) / (chart->point_cnt) + obj->coords.x1 + x_ofs; - dsc.id = i; + part_draw_dsc.id = i; /*Draw the current point of all data line*/ _LV_LL_READ_BACK(&chart->series_ll, ser) { - if (ser->hidden) continue; + if(ser->hidden) continue; lv_coord_t start_point = chart->update_mode == LV_CHART_UPDATE_MODE_SHIFT ? ser->start_point : 0; col_a.x1 = x_act; @@ -1180,13 +1227,13 @@ static void draw_series_bar(lv_obj_t * obj, const lv_area_t * clip_area) col_a.y1 = h - y_tmp + obj->coords.y1 + y_ofs; if(ser->y_points[p_act] != LV_CHART_POINT_NONE) { - dsc.draw_area = &col_a; - dsc.rect_dsc = &col_dsc; - dsc.sub_part_ptr = ser; - dsc.value = ser->y_points[p_act]; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &dsc); + part_draw_dsc.draw_area = &col_a; + part_draw_dsc.rect_dsc = &col_dsc; + part_draw_dsc.sub_part_ptr = ser; + part_draw_dsc.value = ser->y_points[p_act]; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_rect(&col_a, &series_mask, &col_dsc); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } } } @@ -1218,11 +1265,13 @@ static void draw_cursors(lv_obj_t * obj, const lv_area_t * clip_area) lv_coord_t point_w = lv_obj_get_style_width(obj, LV_PART_CURSOR) / 2; lv_coord_t point_h = lv_obj_get_style_width(obj, LV_PART_CURSOR) / 2; - lv_obj_draw_part_dsc_t dsc; - lv_obj_draw_dsc_init(&dsc, clip_area); - dsc.line_dsc = &line_dsc_tmp; - dsc.rect_dsc = &point_dsc_tmp; - dsc.part = LV_PART_CURSOR; + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + part_draw_dsc.line_dsc = &line_dsc_tmp; + part_draw_dsc.rect_dsc = &point_dsc_tmp; + part_draw_dsc.part = LV_PART_CURSOR; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_CHART_DRAW_PART_CURSOR; lv_area_t clip_area2; _lv_area_intersect(&clip_area2, clip_area, &obj->coords); @@ -1234,15 +1283,16 @@ static void draw_cursors(lv_obj_t * obj, const lv_area_t * clip_area) line_dsc_tmp.color = cursor->color; point_dsc_tmp.bg_color = cursor->color; - dsc.p1 = &p1; - dsc.p2 = &p2; + part_draw_dsc.p1 = &p1; + part_draw_dsc.p2 = &p2; lv_coord_t cx; lv_coord_t cy; if(cursor->pos_set) { cx = cursor->pos.x; cy = cursor->pos.y; - } else { + } + else { if(cursor->point_id == LV_CHART_POINT_NONE) continue; lv_point_t p; lv_chart_get_point_pos_by_id(obj, cursor->ser, cursor->point_id, &p); @@ -1253,15 +1303,29 @@ static void draw_cursors(lv_obj_t * obj, const lv_area_t * clip_area) cx += obj->coords.x1; cy += obj->coords.y1; + lv_area_t point_area; + if(point_w && point_h) { + point_area.x1 = cx - point_w; + point_area.x2 = cx + point_w; + point_area.y1 = cy - point_h; + point_area.y2 = cy + point_h; + + part_draw_dsc.draw_area = &point_area; + } + else { + part_draw_dsc.draw_area = NULL; + } + if(cursor->dir & LV_DIR_HOR) { p1.x = cursor->dir & LV_DIR_LEFT ? obj->coords.x1 : cx; p1.y = cy; p2.x = cursor->dir & LV_DIR_RIGHT ? obj->coords.x2 : cx; p2.y = p1.y; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_line(&p1, &p2, &clip_area2, &line_dsc_tmp); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &dsc); + lv_draw_rect(&point_area, &clip_area2, &point_dsc_tmp); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } if(cursor->dir & LV_DIR_VER) { @@ -1270,27 +1334,12 @@ static void draw_cursors(lv_obj_t * obj, const lv_area_t * clip_area) p2.x = p1.x; p2.y = cursor->dir & LV_DIR_BOTTOM ? obj->coords.y2 : cy; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_line(&p1, &p2, &clip_area2, &line_dsc_tmp); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &dsc); - } - - if(point_w && point_h) { - lv_area_t point_area; - - point_area.x1 = cx - point_w; - point_area.x2 = cx + point_w; - point_area.y1 = cy - point_h; - point_area.y2 = cy + point_h; - - dsc.draw_area = &point_area; - dsc.p1 = NULL; - dsc.p2 = NULL; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &dsc); lv_draw_rect(&point_area, &clip_area2, &point_dsc_tmp); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } + } } @@ -1312,7 +1361,7 @@ static void draw_y_ticks(lv_obj_t * obj, const lv_area_t * clip_area, lv_chart_a lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t h = (lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; + lv_coord_t h = ((int32_t)lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; lv_coord_t y_ofs = obj->coords.y1 + pad_top + border_width - lv_obj_get_scroll_top(obj); lv_coord_t label_gap; @@ -1320,7 +1369,8 @@ static void draw_y_ticks(lv_obj_t * obj, const lv_area_t * clip_area, lv_chart_a if(axis == LV_CHART_AXIS_PRIMARY_Y) { label_gap = lv_obj_get_style_pad_left(obj, LV_PART_TICKS); x_ofs = obj->coords.x1; - } else { + } + else { label_gap = lv_obj_get_style_pad_right(obj, LV_PART_TICKS); x_ofs = obj->coords.x2; } @@ -1341,12 +1391,14 @@ static void draw_y_ticks(lv_obj_t * obj, const lv_area_t * clip_area, lv_chart_a lv_draw_label_dsc_init(&label_dsc); lv_obj_init_draw_label_dsc(obj, LV_PART_TICKS, &label_dsc); - lv_obj_draw_part_dsc_t dsc; - lv_obj_draw_dsc_init(&dsc, clip_area); - dsc.id = axis; - dsc.part = LV_PART_TICKS; - dsc.line_dsc = &line_dsc; - dsc.label_dsc = &label_dsc; + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_CHART_DRAW_PART_TICK_LABEL; + part_draw_dsc.id = axis; + part_draw_dsc.part = LV_PART_TICKS; + part_draw_dsc.line_dsc = &line_dsc; + part_draw_dsc.label_dsc = &label_dsc; uint32_t total_tick_num = (t->major_cnt - 1) * (t->minor_cnt); for(i = 0; i <= total_tick_num; i++) { @@ -1367,22 +1419,25 @@ static void draw_y_ticks(lv_obj_t * obj, const lv_area_t * clip_area, lv_chart_a if(major) p2.x = p1.x - major_len; /*major tick*/ else p2.x = p1.x - minor_len; /*minor tick*/ - if(p1.y + line_dsc.width / 2 >= obj->coords.y1 && - p2.y - line_dsc.width / 2 <= obj->coords.y2) - { - lv_draw_line(&p1, &p2, clip_area, &line_dsc); - } + part_draw_dsc.p1 = &p1; + part_draw_dsc.p2 = &p2; + + int32_t tick_value = lv_map(total_tick_num - i, 0, total_tick_num, chart->ymin[sec_axis], chart->ymax[sec_axis]); + part_draw_dsc.value = tick_value; /*add text only to major tick*/ - if(major && t->label_en) { - int32_t tick_value = lv_map(total_tick_num - i, 0, total_tick_num, chart->ymin[sec_axis], chart->ymax[sec_axis]); - lv_snprintf(dsc.text, sizeof(dsc.text), "%d", tick_value); - dsc.value = tick_value; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &dsc); + if(major && t->label_en) { + char buf[LV_CHART_LABEL_MAX_TEXT_LENGTH]; + lv_snprintf(buf, sizeof(buf), "%" LV_PRId32, tick_value); + part_draw_dsc.label_dsc = &label_dsc; + part_draw_dsc.text = buf; + part_draw_dsc.text_length = LV_CHART_LABEL_MAX_TEXT_LENGTH; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); /*reserve appropriate area*/ lv_point_t size; - lv_txt_get_size(&size, dsc.text, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + lv_txt_get_size(&size, part_draw_dsc.text, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, LV_COORD_MAX, + LV_TEXT_FLAG_NONE); /*set the area at some distance of the major tick len left of the tick*/ lv_area_t a; @@ -1399,12 +1454,23 @@ static void draw_y_ticks(lv_obj_t * obj, const lv_area_t * clip_area, lv_chart_a } if(a.y2 >= obj->coords.y1 && - a.y1 <= obj->coords.y2) - { - lv_draw_label(&a, clip_area, &label_dsc, dsc.text, NULL); + a.y1 <= obj->coords.y2) { + lv_draw_label(&a, clip_area, &label_dsc, part_draw_dsc.text, NULL); } - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &dsc); } + else { + part_draw_dsc.label_dsc = NULL; + part_draw_dsc.text = NULL; + part_draw_dsc.text_length = 0; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); + } + + if(p1.y + line_dsc.width / 2 >= obj->coords.y1 && + p2.y - line_dsc.width / 2 <= obj->coords.y2) { + lv_draw_line(&p1, &p2, clip_area, &line_dsc); + } + + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } } @@ -1421,7 +1487,7 @@ static void draw_x_ticks(lv_obj_t * obj, const lv_area_t * clip_area, lv_chart_a lv_point_t p2; lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t w = (lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; + lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; lv_draw_label_dsc_t label_dsc; @@ -1434,7 +1500,8 @@ static void draw_x_ticks(lv_obj_t * obj, const lv_area_t * clip_area, lv_chart_a if(axis == LV_CHART_AXIS_PRIMARY_X) { label_gap = t->label_en ? lv_obj_get_style_pad_bottom(obj, LV_PART_TICKS) : 0; y_ofs = obj->coords.y2; - } else { + } + else { label_gap = t->label_en ? lv_obj_get_style_pad_top(obj, LV_PART_TICKS) : 0; y_ofs = obj->coords.y1; } @@ -1450,18 +1517,21 @@ static void draw_x_ticks(lv_obj_t * obj, const lv_area_t * clip_area, lv_chart_a line_dsc.dash_gap = 0; line_dsc.dash_width = 0; - lv_obj_draw_part_dsc_t dsc; - lv_obj_draw_dsc_init(&dsc, clip_area); - dsc.id = LV_CHART_AXIS_PRIMARY_X; - dsc.part = LV_PART_TICKS; - dsc.label_dsc = &label_dsc; - dsc.line_dsc = &line_dsc; + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_CHART_DRAW_PART_TICK_LABEL; + part_draw_dsc.id = LV_CHART_AXIS_PRIMARY_X; + part_draw_dsc.part = LV_PART_TICKS; + part_draw_dsc.label_dsc = &label_dsc; + part_draw_dsc.line_dsc = &line_dsc; uint8_t sec_axis = axis == LV_CHART_AXIS_PRIMARY_X ? 0 : 1; /*The columns ticks should be aligned to the center of blocks*/ if(chart->type == LV_CHART_TYPE_BAR) { - int32_t block_gap = (lv_obj_get_style_pad_column(obj, LV_PART_MAIN) * chart->zoom_x) >> 8; /*Gap between the columns on ~adjacent X*/ + int32_t block_gap = ((int32_t)lv_obj_get_style_pad_column(obj, + LV_PART_MAIN) * chart->zoom_x) >> 8; /*Gap between the columns on ~adjacent X*/ lv_coord_t block_w = (w + block_gap) / (chart->point_cnt); x_ofs += (block_w - block_gap) / 2; w -= block_w - block_gap; @@ -1479,49 +1549,65 @@ static void draw_x_ticks(lv_obj_t * obj, const lv_area_t * clip_area, lv_chart_a if(sec_axis) p2.y = p1.y - (major ? t->major_len : t->minor_len); else p2.y = p1.y + (major ? t->major_len : t->minor_len); - if(p1.x + line_dsc.width / 2 >= obj->coords.x1 && - p2.x - line_dsc.width / 2 <= obj->coords.x2) - { - lv_draw_line(&p1, &p2, clip_area, &line_dsc); - } + part_draw_dsc.p1 = &p1; + part_draw_dsc.p2 = &p2; /*add text only to major tick*/ - if(!major || !t->label_en) continue; - int32_t tick_value; if(chart->type == LV_CHART_TYPE_SCATTER) { tick_value = lv_map(i, 0, total_tick_num, chart->xmin[sec_axis], chart->xmax[sec_axis]); - } else { - tick_value = i / t->minor_cnt; - } - - lv_snprintf(dsc.text, sizeof(dsc.text), "%d", tick_value); - dsc.value = tick_value; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &dsc); - - /*reserve appropriate area*/ - lv_point_t size; - lv_txt_get_size(&size, dsc.text, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, LV_COORD_MAX, LV_TEXT_FLAG_NONE); - - /*set the area at some distance of the major tick len under of the tick*/ - lv_area_t a; - a.x1 = (p2.x - size.x / 2); - a.x2 = (p2.x + size.x / 2); - if(sec_axis) { - a.y2 = p2.y - label_gap; - a.y1 = a.y2 - size.y; } else { - a.y1 = p2.y + label_gap; - a.y2 = a.y1 + size.y; + tick_value = i / t->minor_cnt; + } + part_draw_dsc.value = tick_value; + + if(major && t->label_en) { + char buf[LV_CHART_LABEL_MAX_TEXT_LENGTH]; + lv_snprintf(buf, sizeof(buf), "%" LV_PRId32, tick_value); + part_draw_dsc.label_dsc = &label_dsc; + part_draw_dsc.text = buf; + part_draw_dsc.text_length = LV_CHART_LABEL_MAX_TEXT_LENGTH; + + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); + + /*reserve appropriate area*/ + lv_point_t size; + lv_txt_get_size(&size, part_draw_dsc.text, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, LV_COORD_MAX, + LV_TEXT_FLAG_NONE); + + /*set the area at some distance of the major tick len under of the tick*/ + lv_area_t a; + a.x1 = (p2.x - size.x / 2); + a.x2 = (p2.x + size.x / 2); + if(sec_axis) { + a.y2 = p2.y - label_gap; + a.y1 = a.y2 - size.y; + } + else { + a.y1 = p2.y + label_gap; + a.y2 = a.y1 + size.y; + } + + if(a.x2 >= obj->coords.x1 && + a.x1 <= obj->coords.x2) { + lv_draw_label(&a, clip_area, &label_dsc, part_draw_dsc.text, NULL); + } + } + else { + part_draw_dsc.label_dsc = NULL; + part_draw_dsc.text = NULL; + part_draw_dsc.text_length = 0; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); } - if(a.x2 >= obj->coords.x1 && - a.x1 <= obj->coords.x2) - { - lv_draw_label(&a, clip_area, &label_dsc, dsc.text, NULL); + + if(p1.x + line_dsc.width / 2 >= obj->coords.x1 && + p2.x - line_dsc.width / 2 <= obj->coords.x2) { + lv_draw_line(&p1, &p2, clip_area, &line_dsc); } - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &dsc); + + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } } @@ -1542,9 +1628,9 @@ static void draw_axes(lv_obj_t * obj, const lv_area_t * mask) static uint32_t get_index_from_x(lv_obj_t * obj, lv_coord_t x) { lv_chart_t * chart = (lv_chart_t *)obj; - lv_coord_t w = (lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; + lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - x-= pad_left; + x -= pad_left; if(x < 0) return 0; if(x > w) return chart->point_cnt - 1; @@ -1559,7 +1645,7 @@ static void invalidate_point(lv_obj_t * obj, uint16_t i) lv_chart_t * chart = (lv_chart_t *)obj; if(i >= chart->point_cnt) return; - lv_coord_t w = (lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; + lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; lv_coord_t scroll_left = lv_obj_get_scroll_left(obj); /*In shift mode the whole chart changes so the whole object*/ @@ -1594,7 +1680,8 @@ static void invalidate_point(lv_obj_t * obj, uint16_t i) } else if(chart->type == LV_CHART_TYPE_BAR) { lv_area_t col_a; - int32_t block_gap = (lv_obj_get_style_pad_column(obj, LV_PART_MAIN) * chart->zoom_x) >> 8; /*Gap between the column on ~adjacent X*/ + int32_t block_gap = ((int32_t)lv_obj_get_style_pad_column(obj, + LV_PART_MAIN) * chart->zoom_x) >> 8; /*Gap between the column on ~adjacent X*/ lv_coord_t block_w = (w + block_gap) / chart->point_cnt; lv_coord_t x_act; @@ -1620,7 +1707,7 @@ static void new_points_alloc(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t c { if((*a) == NULL) return; - lv_chart_t * chart = (lv_chart_t*) obj; + lv_chart_t * chart = (lv_chart_t *) obj; uint32_t point_cnt_old = chart->point_cnt; uint32_t i; @@ -1632,7 +1719,7 @@ static void new_points_alloc(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t c if(cnt >= point_cnt_old) { for(i = 0; i < point_cnt_old; i++) { new_points[i] = - (*a)[(i + ser->start_point) % point_cnt_old]; /*Copy old contents to new array*/ + (*a)[(i + ser->start_point) % point_cnt_old]; /*Copy old contents to new array*/ } for(i = point_cnt_old; i < cnt; i++) { new_points[i] = LV_CHART_POINT_NONE; /*Fill up the rest with default value*/ @@ -1641,7 +1728,7 @@ static void new_points_alloc(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t c else { for(i = 0; i < cnt; i++) { new_points[i] = - (*a)[(i + ser->start_point) % point_cnt_old]; /*Copy old contents to new array*/ + (*a)[(i + ser->start_point) % point_cnt_old]; /*Copy old contents to new array*/ } } @@ -1664,13 +1751,18 @@ static void new_points_alloc(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t c lv_chart_tick_dsc_t * get_tick_gsc(lv_obj_t * obj, lv_chart_axis_t axis) { - lv_chart_t * chart = (lv_chart_t*) obj; + lv_chart_t * chart = (lv_chart_t *) obj; switch(axis) { - case LV_CHART_AXIS_PRIMARY_Y: return &chart->tick[0]; - case LV_CHART_AXIS_PRIMARY_X: return &chart->tick[1]; - case LV_CHART_AXIS_SECONDARY_Y: return &chart->tick[2]; - case LV_CHART_AXIS_SECONDARY_X: return &chart->tick[3]; - default: return NULL; + case LV_CHART_AXIS_PRIMARY_Y: + return &chart->tick[0]; + case LV_CHART_AXIS_PRIMARY_X: + return &chart->tick[1]; + case LV_CHART_AXIS_SECONDARY_Y: + return &chart->tick[2]; + case LV_CHART_AXIS_SECONDARY_X: + return &chart->tick[3]; + default: + return NULL; } } diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/chart/lv_chart.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.h similarity index 90% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/chart/lv_chart.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.h index 03b85e7d9..364c58d2d 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/chart/lv_chart.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.h @@ -82,17 +82,17 @@ typedef struct { lv_color_t color; lv_chart_series_t * ser; lv_dir_t dir; - uint8_t pos_set:1; /*1: pos is set; 0: point_id is set*/ + uint8_t pos_set: 1; /*1: pos is set; 0: point_id is set*/ } lv_chart_cursor_t; typedef struct { lv_coord_t major_len; lv_coord_t minor_len; lv_coord_t draw_size; - uint32_t minor_cnt :15; - uint32_t major_cnt :15; - uint32_t label_en :1; -}lv_chart_tick_dsc_t; + uint32_t minor_cnt : 15; + uint32_t major_cnt : 15; + uint32_t label_en : 1; +} lv_chart_tick_dsc_t; typedef struct { @@ -110,12 +110,26 @@ typedef struct { uint16_t point_cnt; /**< Point number in a data line*/ uint16_t zoom_x; uint16_t zoom_y; - lv_chart_type_t type :3; /**< Line or column chart*/ + lv_chart_type_t type : 3; /**< Line or column chart*/ lv_chart_update_mode_t update_mode : 1; -}lv_chart_t; +} lv_chart_t; extern const lv_obj_class_t lv_chart_class; +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_chart_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_CHART_DRAW_PART_DIV_LINE_INIT, /**< Used before/after drawn the div lines*/ + LV_CHART_DRAW_PART_DIV_LINE_HOR, /**< Used for each horizontal division lines*/ + LV_CHART_DRAW_PART_DIV_LINE_VER, /**< Used for each vertical division lines*/ + LV_CHART_DRAW_PART_LINE_AND_POINT, /**< Used on line and scatter charts for lines and points*/ + LV_CHART_DRAW_PART_BAR, /**< Used on bar charts for the rectangles*/ + LV_CHART_DRAW_PART_CURSOR, /**< Used on cursor lines and points*/ + LV_CHART_DRAW_PART_TICK_LABEL, /**< Used on tick lines and labels*/ +} lv_chart_draw_part_type_t; + /********************** * GLOBAL PROTOTYPES **********************/ @@ -204,7 +218,8 @@ uint16_t lv_chart_get_zoom_y(const lv_obj_t * obj); * @param draw_size extra size required to draw the tick and labels * (start with 20 px and increase if the ticks/labels are clipped) */ -void lv_chart_set_axis_tick(lv_obj_t * obj, lv_chart_axis_t axis, lv_coord_t major_len, lv_coord_t minor_len, lv_coord_t major_cnt, lv_coord_t minor_cnt, bool label_en, lv_coord_t draw_size); +void lv_chart_set_axis_tick(lv_obj_t * obj, lv_chart_axis_t axis, lv_coord_t major_len, lv_coord_t minor_len, + lv_coord_t major_cnt, lv_coord_t minor_cnt, bool label_en, lv_coord_t draw_size); /** * Get the type of a chart @@ -292,7 +307,7 @@ void lv_chart_set_x_start_point(lv_obj_t * obj, lv_chart_series_t * ser, uint16_ * Get the next series. * @param chart pointer to a chart * @param ser the previous series or NULL to get the first - * @return the next series or NULL if thre is no more. + * @return the next series or NULL if there is no more. */ lv_chart_series_t * lv_chart_get_series_next(const lv_obj_t * chart, const lv_chart_series_t * ser); @@ -326,7 +341,8 @@ void lv_chart_set_cursor_pos(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_po * @param ser pointer to a series * @param point_id the point's index or `LV_CHART_POINT_NONE` to not assign to any points. */ -void lv_chart_set_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_chart_series_t * ser, uint16_t point_id); +void lv_chart_set_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_chart_series_t * ser, + uint16_t point_id); /** * Get the coordinate of the cursor with respect to the paddings @@ -344,7 +360,7 @@ lv_point_t lv_chart_get_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * curso * Initialize all data points of a series with a value * @param obj pointer to chart object * @param ser pointer to a data series on 'chart' - * @param value the new value for all points. `LV_CHART_POINT_DEF` can be used to hide the points. + * @param value the new value for all points. `LV_CHART_POINT_NONE` can be used to hide the points. */ void lv_chart_set_all_value(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t value); @@ -383,7 +399,8 @@ void lv_chart_set_value_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t * @param x_value the new X value of the next data * @param y_value the new Y value of the next data */ -void lv_chart_set_value_by_id2(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_coord_t x_value, lv_coord_t y_value); +void lv_chart_set_value_by_id2(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_coord_t x_value, + lv_coord_t y_value); /** * Set an external array for the y data points to use for the chart diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/colorwheel/lv_colorwheel.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.c similarity index 91% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/colorwheel/lv_colorwheel.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.c index 4d2853745..633ede7d1 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/colorwheel/lv_colorwheel.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.c @@ -10,6 +10,8 @@ #include "lv_colorwheel.h" #if LV_USE_COLORWHEEL +#include "../../../misc/lv_assert.h" + /********************* * DEFINES *********************/ @@ -50,12 +52,12 @@ static uint16_t get_angle(lv_obj_t * obj); * STATIC VARIABLES **********************/ const lv_obj_class_t lv_colorwheel_class = {.instance_size = sizeof(lv_colorwheel_t), .base_class = &lv_obj_class, - .constructor_cb = lv_colorwheel_constructor, - .event_cb = lv_colorwheel_event, - .width_def = LV_DPI_DEF * 2, - .height_def = LV_DPI_DEF * 2, - .editable = LV_OBJ_CLASS_EDITABLE_TRUE, -}; + .constructor_cb = lv_colorwheel_constructor, + .event_cb = lv_colorwheel_event, + .width_def = LV_DPI_DEF * 2, + .height_def = LV_DPI_DEF * 2, + .editable = LV_OBJ_CLASS_EDITABLE_TRUE, + }; static bool create_knob_recolor; @@ -74,7 +76,7 @@ static bool create_knob_recolor; */ lv_obj_t * lv_colorwheel_create(lv_obj_t * parent, bool knob_recolor) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); create_knob_recolor = knob_recolor; lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); @@ -98,6 +100,7 @@ bool lv_colorwheel_set_hsv(lv_obj_t * obj, lv_color_hsv_t hsv) if(hsv.s > 100) hsv.s = 100; if(hsv.v > 100) hsv.v = 100; + LV_ASSERT_OBJ(obj, MY_CLASS); lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; if(colorwheel->hsv.h == hsv.h && colorwheel->hsv.s == hsv.s && colorwheel->hsv.v == hsv.v) return false; @@ -132,6 +135,7 @@ bool lv_colorwheel_set_rgb(lv_obj_t * obj, lv_color_t color) */ void lv_colorwheel_set_mode(lv_obj_t * obj, lv_colorwheel_mode_t mode) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; colorwheel->mode = mode; @@ -146,6 +150,7 @@ void lv_colorwheel_set_mode(lv_obj_t * obj, lv_colorwheel_mode_t mode) */ void lv_colorwheel_set_mode_fixed(lv_obj_t * obj, bool fixed) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; colorwheel->mode_fixed = fixed; @@ -163,6 +168,7 @@ void lv_colorwheel_set_mode_fixed(lv_obj_t * obj, bool fixed) */ lv_color_hsv_t lv_colorwheel_get_hsv(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; return colorwheel->hsv; @@ -175,6 +181,7 @@ lv_color_hsv_t lv_colorwheel_get_hsv(lv_obj_t * obj) */ lv_color_t lv_colorwheel_get_rgb(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; return lv_color_hsv_to_rgb(colorwheel->hsv.h, colorwheel->hsv.s, colorwheel->hsv.v); @@ -187,6 +194,7 @@ lv_color_t lv_colorwheel_get_rgb(lv_obj_t * obj) */ lv_colorwheel_mode_t lv_colorwheel_get_color_mode(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; return colorwheel->mode; @@ -199,6 +207,7 @@ lv_colorwheel_mode_t lv_colorwheel_get_color_mode(lv_obj_t * obj) */ bool lv_colorwheel_get_color_mode_fixed(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; return colorwheel->mode_fixed; @@ -287,6 +296,8 @@ static void draw_disc_grad(lv_event_t * e) } #if LV_DRAW_COMPLEX + lv_draw_mask_free_param(&mask_out_param); + lv_draw_mask_free_param(&mask_in_param); lv_draw_mask_remove_id(mask_out_id); lv_draw_mask_remove_id(mask_in_id); #endif @@ -588,7 +599,7 @@ static lv_res_t double_click_reset(lv_obj_t * obj) #define SWAPPTR(A, B) do { uint8_t * t = A; A = B; B = t; } while(0) #define HSV_PTR_SWAP(sextant,r,g,b) if((sextant) & 2) { SWAPPTR((r), (b)); } if((sextant) & 4) { SWAPPTR((g), (b)); } if(!((sextant) & 6)) { \ - if(!((sextant) & 1)) { SWAPPTR((r), (g)); } } else { if((sextant) & 1) { SWAPPTR((r), (g)); } } + if(!((sextant) & 1)) { SWAPPTR((r), (g)); } } else { if((sextant) & 1) { SWAPPTR((r), (g)); } } /** * Based on the idea from https://www.vagrearg.org/content/hsvrgb @@ -602,10 +613,13 @@ static lv_res_t double_click_reset(lv_obj_t * obj) * We replace division by 255 by a division by 256, a.k.a a shift right by 8 bits. * This is wrong, but since this is only used to compute the pixels on the screen and not the final color, it's ok. */ -static void fast_hsv2rgb(uint16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t *g , uint8_t *b); -static void fast_hsv2rgb(uint16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t *g , uint8_t *b) +static void fast_hsv2rgb(uint16_t h, uint8_t s, uint8_t v, uint8_t * r, uint8_t * g, uint8_t * b); +static void fast_hsv2rgb(uint16_t h, uint8_t s, uint8_t v, uint8_t * r, uint8_t * g, uint8_t * b) { - if (!s) { *r = *g = *b = v; return; } + if(!s) { + *r = *g = *b = v; + return; + } uint8_t sextant = h >> 8; HSV_PTR_SWAP(sextant, r, g, b); /*Swap pointers so the conversion code is the same*/ @@ -621,7 +635,8 @@ static void fast_hsv2rgb(uint16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t * if(!(sextant & 1)) { /*Up slope*/ ww = !h_frac ? ((uint16_t)s << 8) : (s * (uint8_t)(-h_frac)); /*Skip multiply if not required*/ - } else { + } + else { /*Down slope*/ ww = s * h_frac; } @@ -633,7 +648,7 @@ static void fast_hsv2rgb(uint16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t * static lv_color_t angle_to_mode_color_fast(lv_obj_t * obj, uint16_t angle) { - lv_colorwheel_t * ext = (lv_colorwheel_t*)obj; + lv_colorwheel_t * ext = (lv_colorwheel_t *)obj; uint8_t r = 0, g = 0, b = 0; static uint16_t h = 0; static uint8_t s = 0, v = 0, m = 255; @@ -642,25 +657,29 @@ static lv_color_t angle_to_mode_color_fast(lv_obj_t * obj, uint16_t angle) default: case LV_COLORWHEEL_MODE_HUE: /*Don't recompute costly scaling if it does not change*/ - if (m != ext->mode) { - s = (uint8_t)(((uint16_t)ext->hsv.s * 51) / 20); v = (uint8_t)(((uint16_t)ext->hsv.v * 51) / 20); - m = ext->mode; + if(m != ext->mode) { + s = (uint8_t)(((uint16_t)ext->hsv.s * 51) / 20); + v = (uint8_t)(((uint16_t)ext->hsv.v * 51) / 20); + m = ext->mode; } - fast_hsv2rgb(angle * 6, s, v, &r, &g, &b); /*A smart compiler will replace x * 6 by (x << 2) + (x << 1) if it's more efficient*/ + fast_hsv2rgb(angle * 6, s, v, &r, &g, + &b); /*A smart compiler will replace x * 6 by (x << 2) + (x << 1) if it's more efficient*/ break; case LV_COLORWHEEL_MODE_SATURATION: /*Don't recompute costly scaling if it does not change*/ - if (m != ext->mode) { - h = (uint16_t)(((uint32_t)ext->hsv.h * 6 * 256) / 360); v = (uint8_t)(((uint16_t)ext->hsv.v * 51) / 20); - m = ext->mode; + if(m != ext->mode) { + h = (uint16_t)(((uint32_t)ext->hsv.h * 6 * 256) / 360); + v = (uint8_t)(((uint16_t)ext->hsv.v * 51) / 20); + m = ext->mode; } fast_hsv2rgb(h, angle, v, &r, &g, &b); break; case LV_COLORWHEEL_MODE_VALUE: /*Don't recompute costly scaling if it does not change*/ - if (m != ext->mode) { - h = (uint16_t)(((uint32_t)ext->hsv.h * 6 * 256) / 360); s = (uint8_t)(((uint16_t)ext->hsv.s * 51) / 20); - m = ext->mode; + if(m != ext->mode) { + h = (uint16_t)(((uint32_t)ext->hsv.h * 6 * 256) / 360); + s = (uint8_t)(((uint16_t)ext->hsv.s * 51) / 20); + m = ext->mode; } fast_hsv2rgb(h, s, angle, &r, &g, &b); break; diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/colorwheel/lv_colorwheel.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/colorwheel/lv_colorwheel.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.h diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/imgbtn/lv_imgbtn.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.c similarity index 88% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/imgbtn/lv_imgbtn.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.c index eaabade2b..964801f7c 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/imgbtn/lv_imgbtn.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.c @@ -34,10 +34,10 @@ lv_imgbtn_state_t get_state(const lv_obj_t * imgbtn); * STATIC VARIABLES **********************/ const lv_obj_class_t lv_imgbtn_class = { - .base_class = &lv_obj_class, - .instance_size = sizeof(lv_imgbtn_t), - .constructor_cb = lv_imgbtn_constructor, - .event_cb = lv_imgbtn_event, + .base_class = &lv_obj_class, + .instance_size = sizeof(lv_imgbtn_t), + .constructor_cb = lv_imgbtn_constructor, + .event_cb = lv_imgbtn_event, }; /********************** @@ -55,7 +55,7 @@ const lv_obj_class_t lv_imgbtn_class = { */ lv_obj_t * lv_imgbtn_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -77,7 +77,7 @@ lv_obj_t * lv_imgbtn_create(lv_obj_t * parent) * to a file) */ void lv_imgbtn_set_src(lv_obj_t * obj, lv_imgbtn_state_t state, const void * src_left, const void * src_mid, - const void * src_right) + const void * src_right) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -90,6 +90,23 @@ void lv_imgbtn_set_src(lv_obj_t * obj, lv_imgbtn_state_t state, const void * src refr_img(obj); } +void lv_imgbtn_set_state(lv_obj_t * obj, lv_imgbtn_state_t state) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_state_t obj_state = LV_STATE_DEFAULT; + if(state == LV_IMGBTN_STATE_PRESSED || state == LV_IMGBTN_STATE_CHECKED_PRESSED) obj_state |= LV_STATE_PRESSED; + if(state == LV_IMGBTN_STATE_DISABLED || state == LV_IMGBTN_STATE_CHECKED_DISABLED) obj_state |= LV_STATE_DISABLED; + if(state == LV_IMGBTN_STATE_CHECKED_DISABLED || state == LV_IMGBTN_STATE_CHECKED_PRESSED || state == LV_IMGBTN_STATE_CHECKED_RELEASED) { + obj_state |= LV_STATE_CHECKED; + } + + lv_obj_clear_state(obj, LV_STATE_CHECKED | LV_STATE_PRESSED | LV_STATE_DISABLED); + lv_obj_add_state(obj, obj_state); + + refr_img(obj); +} + /*===================== * Getter functions *====================*/ @@ -146,13 +163,13 @@ const void * lv_imgbtn_get_src_right(lv_obj_t * obj, lv_imgbtn_state_t state) static void lv_imgbtn_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { LV_UNUSED(class_p); - lv_imgbtn_t * imgbtn = (lv_imgbtn_t *)obj; - /*Initialize the allocated 'ext'*/ - lv_memset_00((void *)imgbtn->img_src_mid, sizeof(imgbtn->img_src_mid)); - lv_memset_00(imgbtn->img_src_left, sizeof(imgbtn->img_src_left)); - lv_memset_00(imgbtn->img_src_right, sizeof(imgbtn->img_src_right)); + lv_imgbtn_t * imgbtn = (lv_imgbtn_t *)obj; + /*Initialize the allocated 'ext'*/ + lv_memset_00((void *)imgbtn->img_src_mid, sizeof(imgbtn->img_src_mid)); + lv_memset_00(imgbtn->img_src_left, sizeof(imgbtn->img_src_left)); + lv_memset_00(imgbtn->img_src_right, sizeof(imgbtn->img_src_right)); - imgbtn->act_cf = LV_IMG_CF_UNKNOWN; + imgbtn->act_cf = LV_IMG_CF_UNKNOWN; } @@ -181,8 +198,7 @@ static void lv_imgbtn_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_imgbtn_state_t state = suggest_state(obj, get_state(obj)); if(imgbtn->img_src_left[state] == NULL && imgbtn->img_src_mid[state] != NULL && - imgbtn->img_src_right[state] == NULL) - { + imgbtn->img_src_right[state] == NULL) { lv_img_header_t header; lv_img_decoder_get_info(imgbtn->img_src_mid[state], &header); p->x = LV_MAX(p->x, header.w); @@ -260,8 +276,7 @@ static void draw_main(lv_event_t * e) coords_part.x2 = coords_part.x1 + header.w - 1; coords_part.y2 = coords_part.y1 + header.h - 1; - for(i = 0; i < clip_center_area.x2 + header.w - 1; i += header.w) { - + for(i = coords_part.x1; i < (lv_coord_t)(clip_center_area.x2 + header.w - 1); i += header.w) { lv_draw_img(&coords_part, &clip_center_area, src, &img_dsc); coords_part.x1 = coords_part.x2 + 1; coords_part.x2 += header.w; diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/imgbtn/lv_imgbtn.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h similarity index 91% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/imgbtn/lv_imgbtn.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h index 20eee9ce2..b8e2c8a2a 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/imgbtn/lv_imgbtn.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h @@ -28,7 +28,7 @@ typedef enum { LV_IMGBTN_STATE_CHECKED_PRESSED, LV_IMGBTN_STATE_CHECKED_DISABLED, _LV_IMGBTN_STATE_NUM, -}lv_imgbtn_state_t; +} lv_imgbtn_state_t; /********************** * TYPEDEFS @@ -75,9 +75,16 @@ lv_obj_t * lv_imgbtn_create(lv_obj_t * parent); * to a file) */ void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_imgbtn_state_t state, const void * src_left, const void * src_mid, - const void * src_right); + const void * src_right); +/** + * Use this function instead of `lv_obj_add/clear_state` to set a state manually + * @param imgbtn pointer to an image button object + * @param state the new state + */ +void lv_imgbtn_set_state(lv_obj_t * imgbtn, lv_imgbtn_state_t state); + /*===================== * Getter functions *====================*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/keyboard/lv_keyboard.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.c similarity index 68% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/keyboard/lv_keyboard.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.c index 45434f8fd..09cb0c875 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/keyboard/lv_keyboard.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.c @@ -11,10 +11,15 @@ #if LV_USE_KEYBOARD #include "../../../widgets/lv_textarea.h" +#include "../../../misc/lv_assert.h" + +#include /********************* * DEFINES *********************/ +#define MY_CLASS &lv_keyboard_class +#define LV_KB_BTN(width) LV_BTNMATRIX_CTRL_POPOVER | width /********************** * TYPEDEFS @@ -27,6 +32,8 @@ static void lv_keyboard_constructor(const lv_obj_class_t * class_p, lv_obj_t * o static void lv_keyboard_update_map(lv_obj_t * obj); +static void lv_keyboard_update_ctrl_map(lv_obj_t * obj); + /********************** * STATIC VARIABLES **********************/ @@ -46,9 +53,9 @@ static const char * const default_kb_map_lc[] = {"1#", "q", "w", "e", "r", "t", }; static const lv_btnmatrix_ctrl_t default_kb_ctrl_lc_map[] = { - LV_KEYBOARD_CTRL_BTN_FLAGS | 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, LV_BTNMATRIX_CTRL_CHECKED | 7, - LV_KEYBOARD_CTRL_BTN_FLAGS | 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, LV_BTNMATRIX_CTRL_CHECKED | 7, - LV_BTNMATRIX_CTRL_CHECKED | 1, LV_BTNMATRIX_CTRL_CHECKED | 1, 1, 1, 1, 1, 1, 1, 1, LV_BTNMATRIX_CTRL_CHECKED | 1, LV_BTNMATRIX_CTRL_CHECKED | 1, LV_BTNMATRIX_CTRL_CHECKED | 1, + LV_KEYBOARD_CTRL_BTN_FLAGS | 5, LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_BTNMATRIX_CTRL_CHECKED | 7, + LV_KEYBOARD_CTRL_BTN_FLAGS | 6, LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_BTNMATRIX_CTRL_CHECKED | 7, + LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_BTNMATRIX_CTRL_CHECKED | 2, 6, LV_BTNMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2 }; @@ -59,9 +66,9 @@ static const char * const default_kb_map_uc[] = {"1#", "Q", "W", "E", "R", "T", }; static const lv_btnmatrix_ctrl_t default_kb_ctrl_uc_map[] = { - LV_KEYBOARD_CTRL_BTN_FLAGS | 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, LV_BTNMATRIX_CTRL_CHECKED | 7, - LV_KEYBOARD_CTRL_BTN_FLAGS | 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, LV_BTNMATRIX_CTRL_CHECKED | 7, - LV_BTNMATRIX_CTRL_CHECKED | 1, LV_BTNMATRIX_CTRL_CHECKED | 1, 1, 1, 1, 1, 1, 1, 1, LV_BTNMATRIX_CTRL_CHECKED | 1, LV_BTNMATRIX_CTRL_CHECKED | 1, LV_BTNMATRIX_CTRL_CHECKED | 1, + LV_KEYBOARD_CTRL_BTN_FLAGS | 5, LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_BTNMATRIX_CTRL_CHECKED | 7, + LV_KEYBOARD_CTRL_BTN_FLAGS | 6, LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_BTNMATRIX_CTRL_CHECKED | 7, + LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_BTNMATRIX_CTRL_CHECKED | 2, 6, LV_BTNMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2 }; @@ -72,9 +79,9 @@ static const char * const default_kb_map_spec[] = {"1", "2", "3", "4", "5", "6", }; static const lv_btnmatrix_ctrl_t default_kb_ctrl_spec_map[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, LV_BTNMATRIX_CTRL_CHECKED | 2, - LV_KEYBOARD_CTRL_BTN_FLAGS | 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | 2, + LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), + LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_BTNMATRIX_CTRL_CHECKED | 2, 6, LV_BTNMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2 }; @@ -91,18 +98,26 @@ static const lv_btnmatrix_ctrl_t default_kb_ctrl_num_map[] = { 1, 1, 1, 1, 1 }; -static const char * * kb_map[5] = { +static const char * * kb_map[9] = { (const char * *)default_kb_map_lc, (const char * *)default_kb_map_uc, (const char * *)default_kb_map_spec, (const char * *)default_kb_map_num, + (const char * *)default_kb_map_lc, + (const char * *)default_kb_map_lc, + (const char * *)default_kb_map_lc, + (const char * *)default_kb_map_lc, (const char * *)NULL, }; -static const lv_btnmatrix_ctrl_t * kb_ctrl[5] = { +static const lv_btnmatrix_ctrl_t * kb_ctrl[9] = { default_kb_ctrl_lc_map, default_kb_ctrl_uc_map, default_kb_ctrl_spec_map, default_kb_ctrl_num_map, + default_kb_ctrl_lc_map, + default_kb_ctrl_lc_map, + default_kb_ctrl_lc_map, + default_kb_ctrl_lc_map, NULL, }; @@ -121,7 +136,7 @@ static const lv_btnmatrix_ctrl_t * kb_ctrl[5] = { */ lv_obj_t * lv_keyboard_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(&lv_keyboard_class, parent); lv_obj_class_init_obj(obj); return obj; @@ -142,6 +157,7 @@ void lv_keyboard_set_textarea(lv_obj_t * obj, lv_obj_t * ta) LV_ASSERT_OBJ(ta, &lv_textarea_class); } + LV_ASSERT_OBJ(obj, MY_CLASS); lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; /*Hide the cursor of the old Text area if cursor management is enabled*/ @@ -164,12 +180,29 @@ void lv_keyboard_set_textarea(lv_obj_t * obj, lv_obj_t * ta) */ void lv_keyboard_set_mode(lv_obj_t * obj, lv_keyboard_mode_t mode) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; if(keyboard->mode == mode) return; keyboard->mode = mode; - lv_btnmatrix_set_map(obj, kb_map[mode]); - lv_btnmatrix_set_ctrl_map(obj, kb_ctrl[mode]); + lv_keyboard_update_map(obj); +} + +/** + * Show the button title in a popover when pressed. + * @param kb pointer to a Keyboard object + * @param en whether "popovers" mode is enabled + */ +void lv_keyboard_set_popovers(lv_obj_t * obj, bool en) +{ + lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; + + if (keyboard->popovers == en) { + return; + } + + keyboard->popovers = en; + lv_keyboard_update_ctrl_map(obj); } /** @@ -179,7 +212,8 @@ void lv_keyboard_set_mode(lv_obj_t * obj, lv_keyboard_mode_t mode) * @param map pointer to a string array to describe the map. * See 'lv_btnmatrix_set_map()' for more info. */ -void lv_keyboard_set_map(lv_obj_t * obj, lv_keyboard_mode_t mode, const char * map[], const lv_btnmatrix_ctrl_t ctrl_map[]) +void lv_keyboard_set_map(lv_obj_t * obj, lv_keyboard_mode_t mode, const char * map[], + const lv_btnmatrix_ctrl_t ctrl_map[]) { kb_map[mode] = map; kb_ctrl[mode] = ctrl_map; @@ -197,6 +231,7 @@ void lv_keyboard_set_map(lv_obj_t * obj, lv_keyboard_mode_t mode, const char * m */ lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; return keyboard->ta; } @@ -208,25 +243,38 @@ lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * obj) */ lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; return keyboard->mode; } +/** + * Tell whether "popovers" mode is enabled or not. + * @param kb pointer to a Keyboard object + * @return true: "popovers" mode is enabled; false: disabled + */ +bool lv_btnmatrix_get_popovers(const lv_obj_t * obj) +{ + lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; + return keyboard->popovers; +} + /*===================== * Other functions *====================*/ /** * Default keyboard event to add characters to the Text area and change the map. - * If a custom `event_cb` is added to the keyboard this function be called from it to handle the + * If a custom `event_cb` is added to the keyboard this function can be called from it to handle the * button clicks - * @param kb pointer to a keyboard + * @param kb pointer to a keyboard * @param event the triggering event */ void lv_keyboard_def_event_cb(lv_event_t * e) { lv_obj_t * obj = lv_event_get_target(e); + LV_ASSERT_OBJ(obj, MY_CLASS); lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; uint16_t btn_id = lv_btnmatrix_get_selected_btn(obj); if(btn_id == LV_BTNMATRIX_BTN_NONE) return; @@ -282,13 +330,17 @@ void lv_keyboard_def_event_cb(lv_event_t * e) lv_res_t res = lv_event_send(keyboard->ta, LV_EVENT_READY, NULL); if(res != LV_RES_OK) return; } - } else if(strcmp(txt, LV_SYMBOL_LEFT) == 0) { + } + else if(strcmp(txt, LV_SYMBOL_LEFT) == 0) { lv_textarea_cursor_left(keyboard->ta); - } else if(strcmp(txt, LV_SYMBOL_RIGHT) == 0) { + } + else if(strcmp(txt, LV_SYMBOL_RIGHT) == 0) { lv_textarea_cursor_right(keyboard->ta); - } else if(strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) { + } + else if(strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) { lv_textarea_del_char(keyboard->ta); - } else if(strcmp(txt, "+/-") == 0) { + } + else if(strcmp(txt, "+/-") == 0) { uint16_t cur = lv_textarea_get_cursor_pos(keyboard->ta); const char * ta_txt = lv_textarea_get_text(keyboard->ta); if(ta_txt[0] == '-') { @@ -326,24 +378,52 @@ static void lv_keyboard_constructor(const lv_obj_class_t * class_p, lv_obj_t * o lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; keyboard->ta = NULL; keyboard->mode = LV_KEYBOARD_MODE_TEXT_LOWER; + keyboard->popovers = 0; lv_obj_align(obj, LV_ALIGN_BOTTOM_MID, 0, 0); lv_obj_add_event_cb(obj, lv_keyboard_def_event_cb, LV_EVENT_VALUE_CHANGED, NULL); lv_obj_set_style_base_dir(obj, LV_BASE_DIR_LTR, 0); - lv_btnmatrix_set_map(obj, kb_map[keyboard->mode]); - lv_btnmatrix_set_ctrl_map(obj, kb_ctrl[keyboard->mode]); + lv_keyboard_update_map(obj); } /** - * Update the key map for the current mode - * @param kb pointer to a keyboard object + * Update the key and control map for the current mode + * @param obj pointer to a keyboard object */ static void lv_keyboard_update_map(lv_obj_t * obj) { lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; lv_btnmatrix_set_map(obj, kb_map[keyboard->mode]); - lv_btnmatrix_set_ctrl_map(obj, kb_ctrl[keyboard->mode]); + lv_keyboard_update_ctrl_map(obj); +} + +/** + * Update the control map for the current mode + * @param obj pointer to a keyboard object + */ +static void lv_keyboard_update_ctrl_map(lv_obj_t * obj) +{ + lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; + + if (keyboard->popovers) { + /*Apply the current control map (already includes LV_BTNMATRIX_CTRL_POPOVER flags)*/ + lv_btnmatrix_set_ctrl_map(obj, kb_ctrl[keyboard->mode]); + } else { + /*Make a copy of the current control map*/ + lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; + lv_btnmatrix_ctrl_t * ctrl_map = lv_mem_alloc(btnm->btn_cnt * sizeof(lv_btnmatrix_ctrl_t)); + lv_memcpy(ctrl_map, kb_ctrl[keyboard->mode], sizeof(lv_btnmatrix_ctrl_t) * btnm->btn_cnt); + + /*Remove all LV_BTNMATRIX_CTRL_POPOVER flags*/ + for(uint16_t i = 0; i < btnm->btn_cnt; i++) { + ctrl_map[i] &= (~LV_BTNMATRIX_CTRL_POPOVER); + } + + /*Apply new control map and clean up*/ + lv_btnmatrix_set_ctrl_map(obj, ctrl_map); + lv_mem_free(ctrl_map); + } } #endif /*LV_USE_KEYBOARD*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/keyboard/lv_keyboard.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.h similarity index 82% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/keyboard/lv_keyboard.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.h index 2aa2f3d11..4b867c282 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/keyboard/lv_keyboard.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.h @@ -41,6 +41,10 @@ enum { LV_KEYBOARD_MODE_TEXT_UPPER, LV_KEYBOARD_MODE_SPECIAL, LV_KEYBOARD_MODE_NUMBER, + LV_KEYBOARD_MODE_USER_1, + LV_KEYBOARD_MODE_USER_2, + LV_KEYBOARD_MODE_USER_3, + LV_KEYBOARD_MODE_USER_4, }; typedef uint8_t lv_keyboard_mode_t; @@ -49,6 +53,7 @@ typedef struct { lv_btnmatrix_t btnm; lv_obj_t * ta; /*Pointer to the assigned text area*/ lv_keyboard_mode_t mode; /*Key map type*/ + uint8_t popovers : 1; /*Show button titles in popovers on press*/ } lv_keyboard_t; extern const lv_obj_class_t lv_keyboard_class; @@ -82,6 +87,13 @@ 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); +/** + * Show the button title in a popover when pressed. + * @param kb pointer to a Keyboard object + * @param en whether "popovers" mode is enabled + */ +void lv_keyboard_set_popovers(lv_obj_t * kb, bool en); + /** * Set a new map for the keyboard * @param kb pointer to a Keyboard object @@ -89,7 +101,8 @@ void lv_keyboard_set_mode(lv_obj_t * kb, lv_keyboard_mode_t mode); * @param map pointer to a string array to describe the map. * See 'lv_btnmatrix_set_map()' for more info. */ -void lv_keyboard_set_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const char * map[], const lv_btnmatrix_ctrl_t ctrl_map[]); +void lv_keyboard_set_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const char * map[], + const lv_btnmatrix_ctrl_t ctrl_map[]); /*===================== * Getter functions @@ -109,6 +122,13 @@ 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); +/** + * Tell whether "popovers" mode is enabled or not. + * @param kb pointer to a Keyboard object + * @return true: "popovers" mode is enabled; false: disabled + */ +bool lv_btnmatrix_get_popovers(const lv_obj_t * obj); + /** * Get the current map of a keyboard * @param kb pointer to a keyboard object @@ -125,9 +145,9 @@ static inline const char ** lv_keyboard_get_map_array(const lv_obj_t * kb) /** * Default keyboard event to add characters to the Text area and change the map. - * If a custom `event_cb` is added to the keyboard this function be called from it to handle the + * If a custom `event_cb` is added to the keyboard this function can be called from it to handle the * button clicks - * @param kb pointer to a keyboard + * @param kb pointer to a keyboard * @param event the triggering event */ void lv_keyboard_def_event_cb(lv_event_t * e); diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/led/lv_led.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/led/lv_led.c similarity index 81% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/led/lv_led.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/led/lv_led.c index 297912b50..443d325ef 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/led/lv_led.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/led/lv_led.c @@ -9,19 +9,13 @@ #include "lv_led.h" #if LV_USE_LED +#include "../../../misc/lv_assert.h" + /********************* * DEFINES *********************/ #define MY_CLASS &lv_led_class -#ifndef LV_LED_BRIGHT_MIN -# define LV_LED_BRIGHT_MIN 80 -#endif - -#ifndef LV_LED_BRIGHT_MAX -# define LV_LED_BRIGHT_MAX 255 -#endif - /********************** * TYPEDEFS **********************/ @@ -36,12 +30,12 @@ static void lv_led_event(const lv_obj_class_t * class_p, lv_event_t * e); * STATIC VARIABLES **********************/ const lv_obj_class_t lv_led_class = { - .base_class = &lv_obj_class, - .constructor_cb = lv_led_constructor, - .width_def = LV_DPI_DEF / 5, - .height_def = LV_DPI_DEF / 5, - .event_cb = lv_led_event, - .instance_size = sizeof(lv_led_t), + .base_class = &lv_obj_class, + .constructor_cb = lv_led_constructor, + .width_def = LV_DPI_DEF / 5, + .height_def = LV_DPI_DEF / 5, + .event_cb = lv_led_event, + .instance_size = sizeof(lv_led_t), }; /********************** @@ -59,7 +53,7 @@ const lv_obj_class_t lv_led_class = { */ lv_obj_t * lv_led_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -76,6 +70,8 @@ lv_obj_t * lv_led_create(lv_obj_t * parent) */ void lv_led_set_color(lv_obj_t * obj, lv_color_t color) { + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_led_t * led = (lv_led_t *)obj; led->color = color; lv_obj_invalidate(obj); @@ -88,13 +84,12 @@ void lv_led_set_color(lv_obj_t * obj, lv_color_t color) */ void lv_led_set_brightness(lv_obj_t * obj, uint8_t bright) { + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_led_t * led = (lv_led_t *)obj; if(led->bright == bright) return; - if(bright <= LV_LED_BRIGHT_MIN) bright = LV_LED_BRIGHT_MIN; - if(bright >= LV_LED_BRIGHT_MAX) bright = LV_LED_BRIGHT_MAX; - - led->bright = bright; + led->bright = LV_CLAMP(LV_LED_BRIGHT_MIN, bright, LV_LED_BRIGHT_MAX); /*Invalidate the object there fore it will be redrawn*/ lv_obj_invalidate(obj); @@ -142,6 +137,8 @@ void lv_led_toggle(lv_obj_t * obj) */ uint8_t lv_led_get_brightness(const lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_led_t * led = (lv_led_t *)obj; return led->bright; } @@ -165,10 +162,12 @@ static void lv_led_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_res_t res; /* Call the ancestor's event handler */ - res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; - lv_event_code_t code = lv_event_get_code(e); + if(code != LV_EVENT_DRAW_MAIN && code != LV_EVENT_DRAW_MAIN_END) { + res = lv_obj_event_base(MY_CLASS, e); + if(res != LV_RES_OK) return; + } + lv_obj_t * obj = lv_event_get_target(e); if(code == LV_EVENT_DRAW_MAIN) { /*Make darker colors in a temporary style according to the brightness*/ @@ -195,12 +194,23 @@ static void lv_led_event(const lv_obj_class_t * class_p, lv_event_t * e) /*Set the current shadow width according to brightness proportionally between LV_LED_BRIGHT_OFF * and LV_LED_BRIGHT_ON*/ rect_dsc.shadow_width = ((led->bright - LV_LED_BRIGHT_MIN) * rect_dsc.shadow_width) / - (LV_LED_BRIGHT_MAX - LV_LED_BRIGHT_MIN); + (LV_LED_BRIGHT_MAX - LV_LED_BRIGHT_MIN); rect_dsc.shadow_spread = ((led->bright - LV_LED_BRIGHT_MIN) * rect_dsc.shadow_spread) / - (LV_LED_BRIGHT_MAX - LV_LED_BRIGHT_MIN); + (LV_LED_BRIGHT_MAX - LV_LED_BRIGHT_MIN); const lv_area_t * clip_area = lv_event_get_param(e); + + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + part_draw_dsc.draw_area = &obj->coords; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_LED_DRAW_PART_RECTANGLE; + part_draw_dsc.rect_dsc = &rect_dsc; + part_draw_dsc.part = LV_PART_MAIN; + + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_rect(&obj->coords, clip_area, &rect_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } } diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/led/lv_led.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/led/lv_led.h similarity index 80% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/led/lv_led.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/led/lv_led.h index 7c9b350cb..0bc4aaa71 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/led/lv_led.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/led/lv_led.h @@ -21,6 +21,15 @@ extern "C" { /********************* * DEFINES *********************/ +/** Brightness when the LED if OFF */ +#ifndef LV_LED_BRIGHT_MIN +# define LV_LED_BRIGHT_MIN 80 +#endif + +/** Brightness when the LED if ON */ +#ifndef LV_LED_BRIGHT_MAX +# define LV_LED_BRIGHT_MAX 255 +#endif /********************** * TYPEDEFS @@ -35,6 +44,14 @@ typedef struct { extern const lv_obj_class_t lv_led_class; +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_led_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_LED_DRAW_PART_RECTANGLE, /**< The main rectangle*/ +} lv_led_draw_part_type_t; + /********************** * GLOBAL PROTOTYPES **********************/ diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/list/lv_list.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.c similarity index 97% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/list/lv_list.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.c index 07d62689d..798fb708a 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/list/lv_list.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.c @@ -55,7 +55,7 @@ const lv_obj_class_t lv_list_text_class = { lv_obj_t * lv_list_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(&lv_list_class, parent); lv_obj_class_init_obj(obj); lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN); @@ -64,7 +64,7 @@ lv_obj_t * lv_list_create(lv_obj_t * parent) lv_obj_t * lv_list_add_text(lv_obj_t * list, const char * txt) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(&lv_list_text_class, list); lv_obj_class_init_obj(obj); lv_label_set_text(obj, txt); @@ -75,7 +75,7 @@ lv_obj_t * lv_list_add_text(lv_obj_t * list, const char * txt) lv_obj_t * lv_list_add_btn(lv_obj_t * list, const char * icon, const char * txt) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(&lv_list_btn_class, list); lv_obj_class_init_obj(obj); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/list/lv_list.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/list/lv_list.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.h diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/lv_widgets.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/lv_widgets.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/lv_widgets.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/lv_widgets.h diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/meter/lv_meter.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.c similarity index 82% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/meter/lv_meter.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.c index ff175404a..0932ecec7 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/meter/lv_meter.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.c @@ -9,6 +9,8 @@ #include "lv_meter.h" #if LV_USE_METER != 0 +#include "../../../misc/lv_assert.h" + /********************* * DEFINES *********************/ @@ -51,7 +53,7 @@ const lv_obj_class_t lv_meter_class = { lv_obj_t * lv_meter_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -63,6 +65,7 @@ lv_obj_t * lv_meter_create(lv_obj_t * parent) lv_meter_scale_t * lv_meter_add_scale(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_meter_t * meter = (lv_meter_t *)obj; lv_meter_scale_t * scale = _lv_ll_ins_head(&meter->scale_ll); @@ -81,7 +84,8 @@ lv_meter_scale_t * lv_meter_add_scale(lv_obj_t * obj) return scale; } -void lv_meter_set_scale_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t cnt, uint16_t width, uint16_t len, lv_color_t color) +void lv_meter_set_scale_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t cnt, uint16_t width, uint16_t len, + lv_color_t color) { scale->tick_cnt = cnt; scale->tick_width = width; @@ -90,7 +94,8 @@ void lv_meter_set_scale_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t lv_obj_invalidate(obj); } -void lv_meter_set_scale_major_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t nth, uint16_t width, uint16_t len, lv_color_t color, int16_t label_gap) +void lv_meter_set_scale_major_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t nth, uint16_t width, + uint16_t len, lv_color_t color, int16_t label_gap) { scale->tick_major_nth = nth; scale->tick_major_width = width; @@ -100,7 +105,8 @@ void lv_meter_set_scale_major_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, ui lv_obj_invalidate(obj); } -void lv_meter_set_scale_range(lv_obj_t * obj, lv_meter_scale_t * scale, int32_t min, int32_t max, uint32_t angle_range, uint32_t rotation) +void lv_meter_set_scale_range(lv_obj_t * obj, lv_meter_scale_t * scale, int32_t min, int32_t max, uint32_t angle_range, + uint32_t rotation) { scale->min = min; scale->max = max; @@ -113,8 +119,10 @@ void lv_meter_set_scale_range(lv_obj_t * obj, lv_meter_scale_t * scale, int32_t * Add indicator *====================*/ -lv_meter_indicator_t * lv_meter_add_needle_line(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, lv_color_t color, int16_t r_mod) +lv_meter_indicator_t * lv_meter_add_needle_line(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, + lv_color_t color, int16_t r_mod) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_meter_t * meter = (lv_meter_t *)obj; lv_meter_indicator_t * indic = _lv_ll_ins_head(&meter->indicator_ll); LV_ASSERT_MALLOC(indic); @@ -131,8 +139,10 @@ lv_meter_indicator_t * lv_meter_add_needle_line(lv_obj_t * obj, lv_meter_scale_t return indic; } -lv_meter_indicator_t * lv_meter_add_needle_img(lv_obj_t * obj, lv_meter_scale_t * scale, const void * src, lv_coord_t pivot_x, lv_coord_t pivot_y) +lv_meter_indicator_t * lv_meter_add_needle_img(lv_obj_t * obj, lv_meter_scale_t * scale, const void * src, + lv_coord_t pivot_x, lv_coord_t pivot_y) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_meter_t * meter = (lv_meter_t *)obj; lv_meter_indicator_t * indic = _lv_ll_ins_head(&meter->indicator_ll); LV_ASSERT_MALLOC(indic); @@ -149,8 +159,10 @@ lv_meter_indicator_t * lv_meter_add_needle_img(lv_obj_t * obj, lv_meter_scale_t return indic; } -lv_meter_indicator_t * lv_meter_add_arc(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, lv_color_t color, int16_t r_mod) +lv_meter_indicator_t * lv_meter_add_arc(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, lv_color_t color, + int16_t r_mod) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_meter_t * meter = (lv_meter_t *)obj; lv_meter_indicator_t * indic = _lv_ll_ins_head(&meter->indicator_ll); LV_ASSERT_MALLOC(indic); @@ -167,8 +179,10 @@ lv_meter_indicator_t * lv_meter_add_arc(lv_obj_t * obj, lv_meter_scale_t * scale return indic; } -lv_meter_indicator_t * lv_meter_add_scale_lines(lv_obj_t * obj, lv_meter_scale_t * scale, lv_color_t color_start, lv_color_t color_end, bool local, int16_t width_mod) +lv_meter_indicator_t * lv_meter_add_scale_lines(lv_obj_t * obj, lv_meter_scale_t * scale, lv_color_t color_start, + lv_color_t color_end, bool local, int16_t width_mod) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_meter_t * meter = (lv_meter_t *)obj; lv_meter_indicator_t * indic = _lv_ll_ins_head(&meter->indicator_ll); LV_ASSERT_MALLOC(indic); @@ -205,7 +219,8 @@ void lv_meter_set_indicator_value(lv_obj_t * obj, lv_meter_indicator_t * indic, inv_line(obj, indic, old_start); inv_line(obj, indic, old_end); inv_line(obj, indic, value); - } else { + } + else { lv_obj_invalidate(obj); } } @@ -264,6 +279,7 @@ static void lv_meter_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) static void lv_meter_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { LV_UNUSED(class_p); + LV_ASSERT_OBJ(obj, MY_CLASS); lv_meter_t * meter = (lv_meter_t *)obj; _lv_ll_clear(&meter->indicator_ll); _lv_ll_clear(&meter->scale_ll); @@ -322,6 +338,14 @@ static void draw_arcs(lv_obj_t * obj, const lv_area_t * clip_area, const lv_area lv_opa_t opa_main = lv_obj_get_style_opa(obj, LV_PART_MAIN); lv_meter_indicator_t * indic; + + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + part_draw_dsc.arc_dsc = &arc_dsc; + part_draw_dsc.part = LV_PART_INDICATOR; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_METER_DRAW_PART_ARC; + _LV_LL_READ_BACK(&meter->indicator_ll, indic) { if(indic->type != LV_METER_INDICATOR_TYPE_ARC) continue; @@ -331,9 +355,18 @@ static void draw_arcs(lv_obj_t * obj, const lv_area_t * clip_area, const lv_area lv_meter_scale_t * scale = indic->scale; - int32_t start_angle = lv_map(indic->start_value, scale->min, scale->max, scale->rotation, scale->rotation + scale->angle_range); - int32_t end_angle = lv_map(indic->end_value, scale->min, scale->max, scale->rotation, scale->rotation + scale->angle_range); - lv_draw_arc(scale_center.x, scale_center.y, r_out + indic->type_data.arc.r_mod, start_angle, end_angle, clip_area, &arc_dsc); + int32_t start_angle = lv_map(indic->start_value, scale->min, scale->max, scale->rotation, + scale->rotation + scale->angle_range); + int32_t end_angle = lv_map(indic->end_value, scale->min, scale->max, scale->rotation, + scale->rotation + scale->angle_range); + + part_draw_dsc.radius = r_out + indic->type_data.arc.r_mod; + part_draw_dsc.sub_part_ptr = indic; + part_draw_dsc.p1 = &scale_center; + + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); + lv_draw_arc(scale_center.x, scale_center.y, part_draw_dsc.radius, start_angle, end_angle, clip_area, &arc_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } } @@ -359,22 +392,24 @@ static void draw_ticks_and_labels(lv_obj_t * obj, const lv_area_t * clip_area, c lv_meter_scale_t * scale; - lv_obj_draw_part_dsc_t dsc; - lv_obj_draw_dsc_init(&dsc, clip_area); - -#if LV_DRAW_COMPLEX lv_draw_mask_radius_param_t inner_minor_mask; lv_draw_mask_radius_param_t inner_major_mask; lv_draw_mask_radius_param_t outer_mask; -#endif + + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.part = LV_PART_TICKS; + part_draw_dsc.type = LV_METER_DRAW_PART_TICK; + part_draw_dsc.line_dsc = &line_dsc; _LV_LL_READ_BACK(&meter->scale_ll, scale) { + part_draw_dsc.sub_part_ptr = scale; lv_coord_t r_out = r_edge + scale->r_mod; lv_coord_t r_in_minor = r_out - scale->tick_length; lv_coord_t r_in_major = r_out - scale->tick_major_length; -#if LV_DRAW_COMPLEX lv_area_t area_inner_minor; area_inner_minor.x1 = p_center.x - r_in_minor; area_inner_minor.y1 = p_center.y - r_in_minor; @@ -397,8 +432,7 @@ static void draw_ticks_and_labels(lv_obj_t * obj, const lv_area_t * clip_area, c lv_draw_mask_radius_init(&outer_mask, &area_outer, LV_RADIUS_CIRCLE, false); int16_t outer_mask_id = lv_draw_mask_add(&outer_mask, NULL); - int16_t inner_act_mask_id = -1; /*Will be added later*/ -#endif + int16_t inner_act_mask_id = LV_MASK_ID_INV; /*Will be added later*/ uint32_t minor_cnt = scale->tick_major_nth ? scale->tick_major_nth - 1 : 0xFFFF; for(i = 0; i < scale->tick_cnt; i++) { @@ -409,11 +443,8 @@ static void draw_ticks_and_labels(lv_obj_t * obj, const lv_area_t * clip_area, c major = true; } -#if LV_DRAW_COMPLEX - inner_act_mask_id = lv_draw_mask_add(major ? &inner_major_mask : &inner_minor_mask, NULL); -#endif - int32_t value_of_line = lv_map(i, 0, scale->tick_cnt - 1, scale->min, scale->max); + part_draw_dsc.value = value_of_line; lv_color_t line_color = major ? scale->tick_major_color : scale->tick_color; lv_color_t line_color_ori = line_color; @@ -429,11 +460,13 @@ static void draw_ticks_and_labels(lv_obj_t * obj, const lv_area_t * clip_area, c if(indic->type_data.scale_lines.color_start.full == indic->type_data.scale_lines.color_end.full) { line_color = indic->type_data.scale_lines.color_start; - } else { + } + else { lv_opa_t ratio; if(indic->type_data.scale_lines.local_grad) { ratio = lv_map(value_of_line, indic->start_value, indic->end_value, LV_OPA_TRANSP, LV_OPA_COVER); - } else { + } + else { ratio = lv_map(value_of_line, scale->min, scale->max, LV_OPA_TRANSP, LV_OPA_COVER); } line_color = lv_color_mix(indic->type_data.scale_lines.color_end, indic->type_data.scale_lines.color_start, ratio); @@ -457,40 +490,22 @@ static void draw_ticks_and_labels(lv_obj_t * obj, const lv_area_t * clip_area, c int32_t cos_high = lv_trigo_cos(angle_high + scale->rotation); int32_t cos_mid = (cos_low * (256 - angle_rem) + cos_high * angle_rem) >> 8; - line_dsc.color = line_color; line_dsc.width = line_width; -#if LV_DRAW_COMPLEX /*Use the interpolated angle to get the outer x and y coordinates. *Draw a little bit longer lines to be sure the mask will clip them correctly*/ lv_point_t p_outer; p_outer.x = (int32_t)(((int32_t)cos_mid * (r_out + line_width) + 127) >> (LV_TRIGO_SHIFT)) + p_center.x; p_outer.y = (int32_t)(((int32_t)sin_mid * (r_out + line_width) + 127) >> (LV_TRIGO_SHIFT)) + p_center.y; - lv_draw_line(&p_outer, &p_center, clip_area, &line_dsc); -#else - /*Use the interpolated angle to get the outer and inner x and y coordinates.*/ - lv_point_t p_outer; - p_outer.x = (int32_t)(((int32_t)cos_mid * (r_out) + 127) >> (LV_TRIGO_SHIFT)) + p_center.x; - p_outer.y = (int32_t)(((int32_t)sin_mid * (r_out) + 127) >> (LV_TRIGO_SHIFT)) + p_center.y; - lv_point_t p_inner; - lv_coord_t r_in = major ? r_in_major : r_in_minor; - p_inner.x = (int32_t)(((int32_t)cos_mid * (r_in) + 127) >> (LV_TRIGO_SHIFT)) + p_center.x; - p_inner.y = (int32_t)(((int32_t)sin_mid * (r_in) + 127) >> (LV_TRIGO_SHIFT)) + p_center.y; - lv_draw_line(&p_outer, &p_inner, clip_area, &line_dsc); -#endif - line_dsc.color = line_color_ori; - line_dsc.width = line_width_ori; - -#if LV_DRAW_COMPLEX - lv_draw_mask_remove_id(inner_act_mask_id); -#endif + part_draw_dsc.p1 = &p_outer; + part_draw_dsc.p1 = &p_center; + part_draw_dsc.id = i; + part_draw_dsc.label_dsc = &label_dsc; /*Draw the text*/ if(major) { -#if LV_DRAW_COMPLEX lv_draw_mask_remove_id(outer_mask_id); -#endif uint32_t r_text = r_in_major - scale->label_gap; lv_point_t p; p.x = (int32_t)((int32_t)((int32_t)cos_mid * r_text + 127) >> LV_TRIGO_SHIFT) + p_center.x; @@ -499,15 +514,17 @@ static void draw_ticks_and_labels(lv_obj_t * obj, const lv_area_t * clip_area, c lv_draw_label_dsc_t label_dsc_tmp; lv_memcpy(&label_dsc_tmp, &label_dsc, sizeof(label_dsc_tmp)); - dsc.id = i / scale->tick_major_nth; - dsc.value = value_of_line; - dsc.label_dsc = &label_dsc_tmp; - lv_snprintf(dsc.text, sizeof(dsc.text), "%d", value_of_line); - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &dsc); + part_draw_dsc.label_dsc = &label_dsc_tmp; + char buf[16]; + + lv_snprintf(buf, sizeof(buf), "%" LV_PRId32, value_of_line); + part_draw_dsc.text = buf; + + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_point_t label_size; - lv_txt_get_size(&label_size, dsc.text, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, - LV_COORD_MAX, LV_TEXT_FLAG_NONE); + lv_txt_get_size(&label_size, part_draw_dsc.text, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, + LV_COORD_MAX, LV_TEXT_FLAG_NONE); lv_area_t label_cord; label_cord.x1 = p.x - label_size.x / 2; @@ -515,18 +532,29 @@ static void draw_ticks_and_labels(lv_obj_t * obj, const lv_area_t * clip_area, c label_cord.x2 = label_cord.x1 + label_size.x; label_cord.y2 = label_cord.y1 + label_size.y; - lv_draw_label(&label_cord, clip_area, &label_dsc, dsc.text, NULL); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &dsc); + lv_draw_label(&label_cord, clip_area, &label_dsc, part_draw_dsc.text, NULL); -#if LV_DRAW_COMPLEX outer_mask_id = lv_draw_mask_add(&outer_mask, NULL); -#endif + } + else { + part_draw_dsc.label_dsc = NULL; + part_draw_dsc.text = NULL; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); } + inner_act_mask_id = lv_draw_mask_add(major ? &inner_major_mask : &inner_minor_mask, NULL); + lv_draw_line(&p_outer, &p_center, clip_area, &line_dsc); + lv_draw_mask_remove_id(inner_act_mask_id); + lv_event_send(obj, LV_EVENT_DRAW_MAIN_END, &part_draw_dsc); + + line_dsc.color = line_color_ori; + line_dsc.width = line_width_ori; + } -#if LV_DRAW_COMPLEX + lv_draw_mask_free_param(&inner_minor_mask); + lv_draw_mask_free_param(&inner_major_mask); + lv_draw_mask_free_param(&outer_mask); lv_draw_mask_remove_id(outer_mask_id); -#endif } } @@ -542,17 +570,23 @@ static void draw_needles(lv_obj_t * obj, const lv_area_t * clip_area, const lv_a lv_draw_line_dsc_t line_dsc; lv_draw_line_dsc_init(&line_dsc); - lv_obj_init_draw_line_dsc(obj, LV_PART_INDICATOR, &line_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_ITEMS, &line_dsc); lv_draw_img_dsc_t img_dsc; lv_draw_img_dsc_init(&img_dsc); - lv_obj_init_draw_img_dsc(obj, LV_PART_INDICATOR, &img_dsc); - img_dsc.antialias = 1; + lv_obj_init_draw_img_dsc(obj, LV_PART_ITEMS, &img_dsc); lv_opa_t opa_main = lv_obj_get_style_opa(obj, LV_PART_MAIN); + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.p1 = &scale_center; + lv_meter_indicator_t * indic; _LV_LL_READ_BACK(&meter->indicator_ll, indic) { lv_meter_scale_t * scale = indic->scale; + part_draw_dsc.sub_part_ptr = indic; + if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_LINE) { int32_t angle = lv_map(indic->end_value, scale->min, scale->max, scale->rotation, scale->rotation + scale->angle_range); lv_coord_t r_out = r_edge + scale->r_mod + indic->type_data.needle_line.r_mod; @@ -562,7 +596,14 @@ static void draw_needles(lv_obj_t * obj, const lv_area_t * clip_area, const lv_a line_dsc.color = indic->type_data.needle_line.color; line_dsc.width = indic->type_data.needle_line.width; line_dsc.opa = indic->opa > LV_OPA_MAX ? opa_main : (opa_main * indic->opa) >> 8; + + part_draw_dsc.id = LV_METER_DRAW_PART_NEEDLE_LINE; + part_draw_dsc.line_dsc = &line_dsc; + part_draw_dsc.p2 = &p_end; + + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_line(&scale_center, &p_end, clip_area, &line_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG) { if(indic->type_data.needle_img.src == NULL) continue; @@ -582,7 +623,12 @@ static void draw_needles(lv_obj_t * obj, const lv_area_t * clip_area, const lv_a angle = angle * 10; if(angle > 3600) angle -= 3600; img_dsc.angle = angle; + + part_draw_dsc.img_dsc = &img_dsc; + + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_img(&a, clip_area, indic->type_data.needle_img.src, &img_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } } } @@ -605,8 +651,10 @@ static void inv_arc(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t old_va int32_t start_angle = lv_map(old_value, scale->min, scale->max, scale->rotation, scale->angle_range + scale->rotation); int32_t end_angle = lv_map(new_value, scale->min, scale->max, scale->rotation, scale->angle_range + scale->rotation); + lv_area_t a; - lv_draw_arc_get_area(scale_center.x, scale_center.y, r_out, LV_MIN(start_angle, end_angle), LV_MAX(start_angle, end_angle), indic->type_data.arc.width, rounded, &a); + lv_draw_arc_get_area(scale_center.x, scale_center.y, r_out, LV_MIN(start_angle, end_angle), LV_MAX(start_angle, + end_angle), indic->type_data.arc.width, rounded, &a); lv_obj_invalidate_area(obj, &a); } @@ -656,6 +704,6 @@ static void inv_line(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value a.y2 += scale_center.y + 2; lv_obj_invalidate_area(obj, &a); - } + } } #endif diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/meter/lv_meter.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.h similarity index 81% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/meter/lv_meter.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.h index ccf9a1624..3626fbad1 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/meter/lv_meter.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.h @@ -17,6 +17,11 @@ extern "C" { #if LV_USE_METER != 0 +/*Testing of dependencies*/ +#if LV_DRAW_COMPLEX == 0 +#error "lv_meter: Complex drawing is required. Enable it in lv_conf.h (LV_DRAW_COMPLEX 1)" +#endif + /********************* * DEFINES *********************/ @@ -44,7 +49,7 @@ typedef struct { int16_t r_mod; uint16_t angle_range; int16_t rotation; -}lv_meter_scale_t; +} lv_meter_scale_t; enum { LV_METER_INDICATOR_TYPE_NEEDLE_IMG, @@ -64,26 +69,26 @@ typedef struct { struct { const void * src; lv_point_t pivot; - }needle_img; + } needle_img; struct { uint16_t width; int16_t r_mod; lv_color_t color; - }needle_line; + } needle_line; struct { uint16_t width; const void * src; lv_color_t color; int16_t r_mod; - }arc; + } arc; struct { int16_t width_mod; lv_color_t color_start; lv_color_t color_end; - uint8_t local_grad :1; - }scale_lines; + uint8_t local_grad : 1; + } scale_lines; } type_data; -}lv_meter_indicator_t; +} lv_meter_indicator_t; /*Data of line meter*/ typedef struct { @@ -94,6 +99,17 @@ typedef struct { extern const lv_obj_class_t lv_meter_class; +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_meter_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_METER_DRAW_PART_ARC, /**< The arc indicator*/ + LV_METER_DRAW_PART_NEEDLE_LINE, /**< The needle lines*/ + LV_METER_DRAW_PART_NEEDLE_IMG, /**< The needle images*/ + LV_METER_DRAW_PART_TICK, /**< The tick lines and labels*/ +} lv_meter_draw_part_type_t; + /********************** * GLOBAL PROTOTYPES **********************/ @@ -126,7 +142,8 @@ lv_meter_scale_t * lv_meter_add_scale(lv_obj_t * obj); * @param len length of tick lines * @param color color of tick lines */ -void lv_meter_set_scale_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t cnt, uint16_t width, uint16_t len, lv_color_t color); +void lv_meter_set_scale_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t cnt, uint16_t width, uint16_t len, + lv_color_t color); /** * Make some "normal" ticks major ticks and set their attributes. @@ -139,7 +156,8 @@ void lv_meter_set_scale_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t * @param color color of the major ticks * @param label_gap gap between the major ticks and the labels */ -void lv_meter_set_scale_major_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t nth, uint16_t width, uint16_t len, lv_color_t color, int16_t label_gap); +void lv_meter_set_scale_major_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t nth, uint16_t width, + uint16_t len, lv_color_t color, int16_t label_gap); /** * Set the value and angular range of a scale. @@ -150,7 +168,8 @@ void lv_meter_set_scale_major_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, ui * @param angle_range the angular range of the scale * @param rotation the angular offset from the 3 o'clock position (clock-wise) */ -void lv_meter_set_scale_range(lv_obj_t * obj, lv_meter_scale_t * scale, int32_t min, int32_t max, uint32_t angle_range, uint32_t rotation); +void lv_meter_set_scale_range(lv_obj_t * obj, lv_meter_scale_t * scale, int32_t min, int32_t max, uint32_t angle_range, + uint32_t rotation); /*===================== * Add indicator @@ -165,7 +184,8 @@ void lv_meter_set_scale_range(lv_obj_t * obj, lv_meter_scale_t * scale, int32_t * @param r_mod the radius modifier (added to the scale's radius) to get the lines length * @return the new indicator */ -lv_meter_indicator_t * lv_meter_add_needle_line(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, lv_color_t color, int16_t r_mod); +lv_meter_indicator_t * lv_meter_add_needle_line(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, + lv_color_t color, int16_t r_mod); /** * Add a needle image indicator the scale @@ -177,7 +197,8 @@ lv_meter_indicator_t * lv_meter_add_needle_line(lv_obj_t * obj, lv_meter_scale_t * @return the new indicator * @note the needle image should point to the right, like -O-----> */ -lv_meter_indicator_t * lv_meter_add_needle_img(lv_obj_t * obj, lv_meter_scale_t * scale, const void * src, lv_coord_t pivot_x, lv_coord_t pivot_y); +lv_meter_indicator_t * lv_meter_add_needle_img(lv_obj_t * obj, lv_meter_scale_t * scale, const void * src, + lv_coord_t pivot_x, lv_coord_t pivot_y); /** * Add an arc indicator the scale @@ -188,7 +209,8 @@ lv_meter_indicator_t * lv_meter_add_needle_img(lv_obj_t * obj, lv_meter_scale_t * @param r_mod the radius modifier (added to the scale's radius) to get the outer radius of the arc * @return the new indicator */ -lv_meter_indicator_t * lv_meter_add_arc(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, lv_color_t color, int16_t r_mod); +lv_meter_indicator_t * lv_meter_add_arc(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, lv_color_t color, + int16_t r_mod); /** @@ -201,7 +223,8 @@ lv_meter_indicator_t * lv_meter_add_arc(lv_obj_t * obj, lv_meter_scale_t * scale * @param width_mod add this the affected tick's width * @return the new indicator */ -lv_meter_indicator_t * lv_meter_add_scale_lines(lv_obj_t * obj, lv_meter_scale_t * scale, lv_color_t color_start, lv_color_t color_end, bool local, int16_t width_mod); +lv_meter_indicator_t * lv_meter_add_scale_lines(lv_obj_t * obj, lv_meter_scale_t * scale, lv_color_t color_start, + lv_color_t color_end, bool local, int16_t width_mod); /*===================== * Set indicator value diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.c new file mode 100644 index 000000000..d8a6817e2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.c @@ -0,0 +1,209 @@ +/** + * @file lv_msgbox.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_msgbox.h" +#if LV_USE_MSGBOX + +#include "../../../misc/lv_assert.h" + +/********************* + * DEFINES + *********************/ +#define LV_MSGBOX_FLAG_AUTO_PARENT LV_OBJ_FLAG_WIDGET_1 /*Mark that the parent was automatically created*/ +#define MY_CLASS &lv_msgbox_class + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void msgbox_close_click_event_cb(lv_event_t * e); + +/********************** + * STATIC VARIABLES + **********************/ +const lv_obj_class_t lv_msgbox_class = { + .base_class = &lv_obj_class, + .width_def = LV_DPI_DEF * 2, + .height_def = LV_SIZE_CONTENT, + .instance_size = sizeof(lv_msgbox_t) +}; + +const lv_obj_class_t lv_msgbox_content_class = { + .base_class = &lv_obj_class, + .width_def = LV_PCT(100), + .height_def = LV_SIZE_CONTENT, + .instance_size = sizeof(lv_obj_t) +}; + +const lv_obj_class_t lv_msgbox_backdrop_class = { + .base_class = &lv_obj_class, + .width_def = LV_PCT(100), + .height_def = LV_PCT(100), + .instance_size = sizeof(lv_obj_t) +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_msgbox_create(lv_obj_t * parent, const char * title, const char * txt, const char * btn_txts[], + bool add_close_btn) +{ + LV_LOG_INFO("begin"); + bool auto_parent = false; + if(parent == NULL) { + auto_parent = true; + parent = lv_obj_class_create_obj(&lv_msgbox_backdrop_class, lv_layer_top()); + LV_ASSERT_MALLOC(parent); + lv_obj_class_init_obj(parent); + lv_obj_clear_flag(parent, LV_OBJ_FLAG_IGNORE_LAYOUT); + lv_obj_set_size(parent, LV_PCT(100), LV_PCT(100)); + } + + lv_obj_t * obj = lv_obj_class_create_obj(&lv_msgbox_class, parent); + LV_ASSERT_MALLOC(obj); + lv_obj_class_init_obj(obj); + if(obj == NULL) return NULL; + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + + if(auto_parent) lv_obj_add_flag(obj, LV_MSGBOX_FLAG_AUTO_PARENT); + + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW_WRAP); + + bool has_title = title && strlen(title) > 0; + + /*When a close button is required, we need the empty label as spacer to push the button to the right*/ + if (add_close_btn || has_title) { + mbox->title = lv_label_create(obj); + lv_label_set_text(mbox->title, has_title ? title : ""); + lv_label_set_long_mode(mbox->title, LV_LABEL_LONG_SCROLL_CIRCULAR); + if(add_close_btn) lv_obj_set_flex_grow(mbox->title, 1); + else lv_obj_set_width(mbox->title, LV_PCT(100)); + } + + if(add_close_btn) { + mbox->close_btn = lv_btn_create(obj); + lv_obj_set_ext_click_area(mbox->close_btn, LV_DPX(10)); + lv_obj_add_event_cb(mbox->close_btn, msgbox_close_click_event_cb, LV_EVENT_CLICKED, NULL); + lv_obj_t * label = lv_label_create(mbox->close_btn); + lv_label_set_text(label, LV_SYMBOL_CLOSE); + const lv_font_t * font = lv_obj_get_style_text_font(mbox->close_btn, LV_PART_MAIN); + lv_coord_t close_btn_size = lv_font_get_line_height(font) + LV_DPX(10); + lv_obj_set_size(mbox->close_btn, close_btn_size, close_btn_size); + lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); + } + + mbox->content = lv_obj_class_create_obj(&lv_msgbox_content_class, obj); + + bool has_txt = txt && strlen(txt) > 0; + if (has_txt) { + mbox->text = lv_label_create(mbox->content); + lv_label_set_text(mbox->text, txt); + lv_label_set_long_mode(mbox->text, LV_LABEL_LONG_WRAP); + lv_obj_set_width(mbox->text, lv_pct(100)); + } + + if(btn_txts) { + mbox->btns = lv_btnmatrix_create(obj); + lv_btnmatrix_set_map(mbox->btns, btn_txts); + lv_btnmatrix_set_btn_ctrl_all(mbox->btns, LV_BTNMATRIX_CTRL_CLICK_TRIG | LV_BTNMATRIX_CTRL_NO_REPEAT); + + uint32_t btn_cnt = 0; + while(btn_txts[btn_cnt] && btn_txts[btn_cnt][0] != '\0') { + btn_cnt++; + } + + const lv_font_t * font = lv_obj_get_style_text_font(mbox->btns, LV_PART_ITEMS); + lv_coord_t btn_h = lv_font_get_line_height(font) + LV_DPI_DEF / 10; + lv_obj_set_size(mbox->btns, btn_cnt * (2 * LV_DPI_DEF / 3), btn_h); + lv_obj_set_style_max_width(mbox->btns, lv_pct(100), 0); + lv_obj_add_flag(mbox->btns, LV_OBJ_FLAG_EVENT_BUBBLE); /*To see the event directly on the message box*/ + } + + return obj; +} + + +lv_obj_t * lv_msgbox_get_title(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + return mbox->title; +} + +lv_obj_t * lv_msgbox_get_close_btn(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + return mbox->close_btn; +} + +lv_obj_t * lv_msgbox_get_text(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + return mbox->text; +} + +lv_obj_t * lv_msgbox_get_content(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + return mbox->content; +} + +lv_obj_t * lv_msgbox_get_btns(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + return mbox->btns; +} + +uint16_t lv_msgbox_get_active_btn(lv_obj_t * mbox) +{ + lv_obj_t * btnm = lv_msgbox_get_btns(mbox); + return lv_btnmatrix_get_selected_btn(btnm); +} + +const char * lv_msgbox_get_active_btn_text(lv_obj_t * mbox) +{ + lv_obj_t * btnm = lv_msgbox_get_btns(mbox); + return lv_btnmatrix_get_btn_text(btnm, lv_btnmatrix_get_selected_btn(btnm)); +} + +void lv_msgbox_close(lv_obj_t * mbox) +{ + if(lv_obj_has_flag(mbox, LV_MSGBOX_FLAG_AUTO_PARENT)) lv_obj_del(lv_obj_get_parent(mbox)); + else lv_obj_del(mbox); +} + +void lv_msgbox_close_async(lv_obj_t * dialog) +{ + if(lv_obj_has_flag(dialog, LV_MSGBOX_FLAG_AUTO_PARENT)) lv_obj_del_async(lv_obj_get_parent(dialog)); + else lv_obj_del_async(dialog); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void msgbox_close_click_event_cb(lv_event_t * e) +{ + lv_obj_t * btn = lv_event_get_target(e); + lv_obj_t * mbox = lv_obj_get_parent(btn); + lv_msgbox_close(mbox); +} + +#endif /*LV_USE_MSGBOX*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/msgbox/lv_msgbox.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.h similarity index 62% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/msgbox/lv_msgbox.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.h index 6a54f85fa..2eaf0d399 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/msgbox/lv_msgbox.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.h @@ -33,14 +33,26 @@ extern "C" { /********************** * TYPEDEFS **********************/ + +typedef struct { + lv_obj_t obj; + lv_obj_t * title; + lv_obj_t * close_btn; + lv_obj_t * content; + lv_obj_t * text; + lv_obj_t * btns; +} lv_msgbox_t; + extern const lv_obj_class_t lv_msgbox_class; +extern const lv_obj_class_t lv_msgbox_content_class; +extern const lv_obj_class_t lv_msgbox_backdrop_class; /********************** * GLOBAL PROTOTYPES **********************/ /** - * Create a message box objects + * Create a message box object * @param parent pointer to parent or NULL to create a full screen modal message box * @param title the title of the message box * @param txt the text of the message box @@ -48,20 +60,32 @@ extern const lv_obj_class_t lv_msgbox_class; * @param add_close_btn true: add a close button * @return pointer to the message box object */ -lv_obj_t * lv_msgbox_create(lv_obj_t * parent, const char * title, const char * txt, const char * btn_txts[], bool add_close_btn); +lv_obj_t * lv_msgbox_create(lv_obj_t * parent, const char * title, const char * txt, const char * btn_txts[], + bool add_close_btn); -lv_obj_t * lv_msgbox_get_title(lv_obj_t * mbox); +lv_obj_t * lv_msgbox_get_title(lv_obj_t * obj); -lv_obj_t * lv_msgbox_get_close_btn(lv_obj_t * mbox); +lv_obj_t * lv_msgbox_get_close_btn(lv_obj_t * obj); -lv_obj_t * lv_msgbox_get_text(lv_obj_t * mbox); +lv_obj_t * lv_msgbox_get_text(lv_obj_t * obj); -lv_obj_t * lv_msgbox_get_btns(lv_obj_t * mbox); +lv_obj_t * lv_msgbox_get_content(lv_obj_t * obj); + +lv_obj_t * lv_msgbox_get_btns(lv_obj_t * obj); + +/** + * Get the index of the selected button + * @param mbox message box object + * @return index of the button (LV_BTNMATRIX_BTN_NONE: if unset) + */ +uint16_t lv_msgbox_get_active_btn(lv_obj_t * mbox); const char * lv_msgbox_get_active_btn_text(lv_obj_t * mbox); void lv_msgbox_close(lv_obj_t * mbox); +void lv_msgbox_close_async(lv_obj_t * mbox); + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/span/lv_span.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.c similarity index 81% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/span/lv_span.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.c index d9e4a6426..4e2f9f7bc 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/span/lv_span.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.c @@ -10,6 +10,8 @@ #if LV_USE_SPAN != 0 +#include "../../../misc/lv_assert.h" + /********************* * DEFINES *********************/ @@ -45,7 +47,6 @@ static void refresh_self_size(lv_obj_t * obj); static const lv_font_t * lv_span_get_style_text_font(lv_obj_t * par, lv_span_t * span); static lv_coord_t lv_span_get_style_text_letter_space(lv_obj_t * par, lv_span_t * span); static lv_color_t lv_span_get_style_text_color(lv_obj_t * par, lv_span_t * span); -static lv_color_t lv_span_get_style_text_color(lv_obj_t * par, lv_span_t * span); static lv_opa_t lv_span_get_style_text_opa(lv_obj_t * par, lv_span_t * span); static lv_opa_t lv_span_get_style_text_blend_mode(lv_obj_t * par, lv_span_t * span); static int32_t lv_span_get_style_text_decor(lv_obj_t * par, lv_span_t * span); @@ -57,9 +58,10 @@ static bool lv_txt_get_snippet(const char * txt, const lv_font_t * font, lv_coor uint32_t * end_ofs); static void lv_snippet_clear(void); -static uint16_t lv_get_snippet_cnt(); +static uint16_t lv_get_snippet_cnt(void); static void lv_snippet_push(lv_snippet_t * item); static lv_snippet_t * lv_get_snippet(uint16_t index); +static lv_coord_t convert_indent_pct(lv_obj_t * spans, lv_coord_t width); /********************** * STATIC VARIABLES @@ -107,6 +109,7 @@ lv_span_t * lv_spangroup_new_span(lv_obj_t * obj) return NULL; } + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; lv_span_t * span = _lv_ll_ins_tail(&spans->child_ll); LV_ASSERT_MALLOC(span); @@ -132,6 +135,7 @@ void lv_spangroup_del_span(lv_obj_t * obj, lv_span_t * span) return; } + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; lv_span_t * cur_span; _LV_LL_READ(&spans->child_ll, cur_span) { @@ -214,6 +218,7 @@ void lv_spangroup_set_align(lv_obj_t * obj, lv_text_align_t align) */ void lv_spangroup_set_overflow(lv_obj_t * obj, lv_span_overflow_t overflow) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; if(spans->overflow == overflow) return; @@ -224,10 +229,12 @@ void lv_spangroup_set_overflow(lv_obj_t * obj, lv_span_overflow_t overflow) /** * Set the indent of the spangroup. * @param obj pointer to a spangroup object. - * @param indent The first line indentation + * @param indent The first line indentation, support percent + * for LV_SPAN_MODE_FIXED and LV_SPAN_MODE_BREAK mode. */ void lv_spangroup_set_indent(lv_obj_t * obj, lv_coord_t indent) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; if(spans->indent == indent) return; @@ -243,9 +250,8 @@ void lv_spangroup_set_indent(lv_obj_t * obj, lv_coord_t indent) */ void lv_spangroup_set_mode(lv_obj_t * obj, lv_span_mode_t mode) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; - if(spans->mode == mode) return; - spans->mode = mode; lv_spangroup_refr_mode(obj); } @@ -254,6 +260,73 @@ void lv_spangroup_set_mode(lv_obj_t * obj, lv_span_mode_t mode) * Getter functions *====================*/ +/** + * Get a spangroup child by its index. + * + * @param obj The spangroup object + * @param id the index of the child. + * 0: the oldest (firstly created) child + * 1: the second oldest + * child count-1: the youngest + * -1: the youngest + * -2: the second youngest + * @return The child span at index `id`, or NULL if the ID does not exist + */ +lv_span_t * lv_spangroup_get_child(const lv_obj_t * obj, int32_t id) +{ + if(obj == NULL) { + return NULL; + } + + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_spangroup_t * spans = (lv_spangroup_t *)obj; + lv_ll_t * linked_list = &spans->child_ll; + + bool traverse_forwards = (id >= 0); + int32_t cur_idx = 0; + lv_ll_node_t * cur_node = linked_list->head; + + /*If using a negative index, start from the tail and use cur -1 to indicate the end*/ + if(!traverse_forwards) { + cur_idx = -1; + cur_node = linked_list->tail; + } + + while(cur_node != NULL) { + if(cur_idx == id) { + return (lv_span_t *) cur_node; + } + if(traverse_forwards) { + cur_node = (lv_ll_node_t *) _lv_ll_get_next(linked_list, cur_node); + cur_idx++; + } + else { + cur_node = (lv_ll_node_t *) _lv_ll_get_prev(linked_list, cur_node); + cur_idx--; + } + } + + return NULL; +} + +/** + * + * @param obj The spangroup object to get the child count of. + * @return The span count of the spangroup. + */ +uint32_t lv_spangroup_get_child_cnt(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + if(obj == NULL) { + return 0; + } + + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_spangroup_t * spans = (lv_spangroup_t *)obj; + return _lv_ll_get_len(&(spans->child_ll)); +} + /** * get the align of the spangroup. * @param obj pointer to a spangroup object. @@ -271,6 +344,7 @@ lv_text_align_t lv_spangroup_get_align(lv_obj_t * obj) */ lv_span_overflow_t lv_spangroup_get_overflow(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; return spans->overflow; } @@ -282,6 +356,7 @@ lv_span_overflow_t lv_spangroup_get_overflow(lv_obj_t * obj) */ lv_coord_t lv_spangroup_get_indent(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; return spans->indent; } @@ -293,6 +368,7 @@ lv_coord_t lv_spangroup_get_indent(lv_obj_t * obj) */ lv_span_mode_t lv_spangroup_get_mode(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; return spans->mode; } @@ -303,6 +379,7 @@ lv_span_mode_t lv_spangroup_get_mode(lv_obj_t * obj) */ void lv_spangroup_refr_mode(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; if(spans->mode == LV_SPAN_MODE_EXPAND) { @@ -340,6 +417,7 @@ void lv_spangroup_refr_mode(lv_obj_t * obj) */ lv_coord_t lv_spangroup_get_max_line_h(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; lv_coord_t max_line_h = 0; @@ -361,21 +439,23 @@ lv_coord_t lv_spangroup_get_max_line_h(lv_obj_t * obj) */ lv_coord_t lv_spangroup_get_expand_width(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; if(_lv_ll_get_head(&spans->child_ll) == NULL) { return 0; } - lv_coord_t width = 0; + lv_coord_t width = LV_COORD_IS_PCT(spans->indent) ? 0 : spans->indent; lv_span_t * cur_span; + lv_coord_t letter_space = 0; _LV_LL_READ(&spans->child_ll, cur_span) { const lv_font_t * font = lv_span_get_style_text_font(obj, cur_span); - lv_coord_t letter_space = lv_span_get_style_text_letter_space(obj, cur_span); + letter_space = lv_span_get_style_text_letter_space(obj, cur_span); uint32_t j = 0; const char * cur_txt = cur_span->txt; span_text_check(&cur_txt); - while(cur_txt[j] != 0) { + while(cur_txt[j] != '\0') { uint32_t letter = _lv_txt_encoded_next(cur_txt, &j); uint32_t letter_next = _lv_txt_encoded_next(&cur_txt[j], NULL); int32_t letter_w = lv_font_get_glyph_width(font, letter, letter_next); @@ -383,7 +463,7 @@ lv_coord_t lv_spangroup_get_expand_width(lv_obj_t * obj) } } - return width; + return width - letter_space; } /** @@ -392,6 +472,7 @@ lv_coord_t lv_spangroup_get_expand_width(lv_obj_t * obj) */ lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; if(_lv_ll_get_head(&spans->child_ll) == NULL || width <= 0) { return 0; @@ -401,12 +482,13 @@ lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width) lv_text_flag_t txt_flag = LV_TEXT_FLAG_NONE; lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); lv_coord_t max_width = width; - lv_coord_t max_w = max_width - spans->indent; /* first line need minus indent */ + lv_coord_t indent = convert_indent_pct(obj, max_width); + lv_coord_t max_w = max_width - indent; /* first line need minus indent */ /* coords of draw span-txt */ lv_point_t txt_pos; txt_pos.y = 0; - txt_pos.x = 0 + spans->indent; /* first line need add indent */ + txt_pos.x = 0 + indent; /* first line need add indent */ lv_span_t * cur_span = _lv_ll_get_head(&spans->child_ll); const char * cur_txt = cur_span->txt; @@ -429,6 +511,8 @@ lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width) cur_txt = cur_span->txt; span_text_check(&cur_txt); cur_txt_ofs = 0; + /* maybe also cur_txt[cur_txt_ofs] == '\0' */ + continue; } /* init span info to snippet. */ @@ -475,6 +559,7 @@ lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width) txt_pos.y += max_line_h; max_w = max_width; } + txt_pos.y -= line_space; return txt_pos.y; } @@ -587,6 +672,12 @@ static bool lv_txt_get_snippet(const char * txt, const lv_font_t * font, lv_coord_t letter_space, lv_coord_t max_width, lv_text_flag_t flag, lv_coord_t * use_width, uint32_t * end_ofs) { + if(txt == NULL || txt[0] == '\0') { + *end_ofs = 0; + *use_width = 0; + return false; + } + uint32_t ofs = _lv_txt_get_next_line(txt, font, letter_space, max_width, flag); lv_coord_t width = lv_txt_get_width(txt, ofs, font, letter_space, flag); *end_ofs = ofs; @@ -611,7 +702,7 @@ static void lv_snippet_push(lv_snippet_t * item) } } -static uint16_t lv_get_snippet_cnt() +static uint16_t lv_get_snippet_cnt(void) { return snippet_stack.index; } @@ -694,13 +785,11 @@ static lv_blend_mode_t lv_span_get_style_text_blend_mode(lv_obj_t * par, lv_span static int32_t lv_span_get_style_text_decor(lv_obj_t * par, lv_span_t * span) { - LV_UNUSED(par); - int32_t decor; lv_style_value_t value; lv_res_t res = lv_style_get_prop(&span->style, LV_STYLE_TEXT_DECOR, &value); if(res != LV_RES_OK) { - decor = LV_TEXT_DECOR_NONE; + decor = (lv_text_decor_t)lv_obj_get_style_text_decor(par, LV_PART_MAIN);; } else { decor = (int32_t)value.num; @@ -716,6 +805,23 @@ static inline void span_text_check(const char ** text) } } +static lv_coord_t convert_indent_pct(lv_obj_t * obj, lv_coord_t width) +{ + lv_spangroup_t * spans = (lv_spangroup_t *)obj; + + lv_coord_t indent = spans->indent; + if(LV_COORD_IS_PCT(spans->indent)) { + if(spans->mode == LV_SPAN_MODE_EXPAND) { + indent = 0; + } + else { + indent = (width * LV_COORD_GET_PCT(spans->indent)) / 100; + } + } + + return indent; +} + /** * draw span group * @param spans obj handle @@ -740,12 +846,14 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area lv_text_flag_t txt_flag = LV_TEXT_FLAG_NONE; lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN);; lv_coord_t max_width = lv_area_get_width(coords); - lv_coord_t max_w = max_width - spans->indent; /* first line need minus indent */ + lv_coord_t indent = convert_indent_pct(obj, max_width); + lv_coord_t max_w = max_width - indent; /* first line need minus indent */ + lv_opa_t obj_opa = lv_obj_get_style_opa(obj, LV_PART_MAIN); /* coords of draw span-txt */ lv_point_t txt_pos; txt_pos.y = coords->y1; - txt_pos.x = coords->x1 + spans->indent; /* first line need add indent */ + txt_pos.x = coords->x1 + indent; /* first line need add indent */ lv_span_t * cur_span = _lv_ll_get_head(&spans->child_ll); const char * cur_txt = cur_span->txt; @@ -754,8 +862,11 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area lv_snippet_t snippet; /* use to save cur_span info and push it to stack */ memset(&snippet, 0, sizeof(snippet)); + bool is_first_line = true; /* the loop control how many lines need to draw */ while(cur_span) { + bool is_end_line = false; + bool ellipsis_valid = false; lv_coord_t max_line_h = 0; /* the max height of span-font when a line have a lot of span */ lv_snippet_clear(); @@ -768,6 +879,8 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area cur_txt = cur_span->txt; span_text_check(&cur_txt); cur_txt_ofs = 0; + /* maybe also cur_txt[cur_txt_ofs] == '\0' */ + continue; } /* init span info to snippet. */ @@ -779,8 +892,10 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area } if(spans->overflow == LV_SPAN_OVERFLOW_ELLIPSIS) { - /* span txt overflow, don't push */ + /* curretn line span txt overflow, don't push */ if(txt_pos.y + snippet.line_h - line_space > coords->y2 + 1) { + ellipsis_valid = true; + is_end_line = true; break; } } @@ -791,13 +906,32 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area bool isfill = lv_txt_get_snippet(&cur_txt[cur_txt_ofs], snippet.font, snippet.letter_space, max_w, txt_flag, &use_width, &next_ofs); - /* break word deal width */ - if(isfill && next_ofs > 0 && lv_get_snippet_cnt() > 0) { - uint32_t letter = (uint32_t)cur_txt[cur_txt_ofs + next_ofs - 1]; - if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_txt_is_break_char(letter))) { - letter = (uint32_t)cur_txt[cur_txt_ofs + next_ofs]; - if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_txt_is_break_char(letter))) { - break; + if(isfill) { + lv_coord_t next_line_h = snippet.line_h; + if(cur_txt[cur_txt_ofs + next_ofs] == '\0') { + next_line_h = 0; + lv_span_t * next_span = _lv_ll_get_next(&spans->child_ll, cur_span); + if(next_span) { /* have the next line */ + next_line_h = lv_font_get_line_height(lv_span_get_style_text_font(obj, next_span)) + line_space; + } + } + lv_coord_t cur_line_h = max_line_h < snippet.line_h ? snippet.line_h : max_line_h; + if(txt_pos.y + cur_line_h + next_line_h - line_space > coords->y2 + 1) { /* for overflow if is end line. */ + if(cur_txt[cur_txt_ofs + next_ofs] != '\0') { + next_ofs = strlen(&cur_txt[cur_txt_ofs]); + use_width = lv_txt_get_width(&cur_txt[cur_txt_ofs], next_ofs, snippet.font, snippet.letter_space, txt_flag); + ellipsis_valid = spans->overflow == LV_SPAN_OVERFLOW_ELLIPSIS ? true : false; + is_end_line = true; + } + } + else if(next_ofs > 0 && lv_get_snippet_cnt() > 0) { + /* break word deal width */ + uint32_t letter = (uint32_t)cur_txt[cur_txt_ofs + next_ofs - 1]; + if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_txt_is_break_char(letter))) { + letter = (uint32_t)cur_txt[cur_txt_ofs + next_ofs]; + if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_txt_is_break_char(letter))) { + break; + } } } } @@ -811,10 +945,10 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area } lv_snippet_push(&snippet); - if(isfill) { + max_w = max_w - use_width - snippet.letter_space; + if(isfill || max_w <= 0) { break; } - max_w -= use_width; } /* start current line deal width */ @@ -829,38 +963,19 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area goto Next_line_init; } - /* overflow deal width */ - bool ellipsis_valid = false; - if(spans->overflow == LV_SPAN_OVERFLOW_ELLIPSIS) { - lv_coord_t next_line_h = snippet.line_h; - if(cur_txt[cur_txt_ofs] == '\0') { /* current span deal with ok, need get next line first line height */ - next_line_h = 0; - if(cur_span) { - lv_span_t * next_span = _lv_ll_get_next(&spans->child_ll, cur_span); - if(next_span) { /* have the next line */ - next_line_h = lv_font_get_line_height(lv_span_get_style_text_font(obj, next_span)) + line_space; - } - } - } - if(txt_pos.y + max_line_h + next_line_h > coords->y2 + 1) { - ellipsis_valid = true; - } - } - /* align deal with */ lv_text_align_t align = lv_obj_get_style_text_align(obj, LV_PART_MAIN); if(align != LV_TEXT_ALIGN_LEFT) { lv_coord_t align_ofs = 0; - lv_coord_t txts_w = 0; + lv_coord_t txts_w = is_first_line ? indent : 0; for(int i = 0; i < item_cnt; i++) { lv_snippet_t * pinfo = lv_get_snippet(i); - txts_w += pinfo->txt_w; + txts_w = txts_w + pinfo->txt_w + pinfo->letter_space; } + txts_w -= lv_get_snippet(item_cnt - 1)->letter_space; + align_ofs = max_width > txts_w ? max_width - txts_w : 0; if(align == LV_TEXT_ALIGN_CENTER) { - align_ofs = (max_width - txts_w) / 2; - } - else if(align == LV_TEXT_ALIGN_RIGHT) { - align_ofs = max_width - txts_w; + align_ofs = align_ofs >> 1; } txt_pos.x += align_ofs; } @@ -877,6 +992,9 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area pos.y = txt_pos.y + max_line_h - pinfo->line_h; lv_color_t letter_color = lv_span_get_style_text_color(obj, pinfo->span); lv_opa_t letter_opa = lv_span_get_style_text_opa(obj, pinfo->span); + if(obj_opa < LV_OPA_MAX) { + letter_opa = (uint16_t)((uint16_t)letter_opa * obj_opa) >> 8; + } lv_blend_mode_t blend_mode = lv_span_get_style_text_blend_mode(obj, pinfo->span); uint32_t txt_bytes = pinfo->bytes; @@ -884,7 +1002,6 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area uint16_t dot_letter_w = 0; uint16_t dot_width = 0; if(ellipsis_valid) { - txt_bytes = strlen(bidi_txt); dot_letter_w = lv_font_get_glyph_width(pinfo->font, '.', '.'); dot_width = dot_letter_w * 3; } @@ -913,6 +1030,9 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area lv_draw_letter(&pos, &clipped_area, pinfo->font, '.', letter_color, letter_opa, blend_mode); pos.x = pos.x + dot_letter_w + pinfo->letter_space; } + if(pos.x <= ellipsis_width) { + pos.x = ellipsis_width + 1; + } break; } else { @@ -944,7 +1064,7 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area lv_point_t p1; lv_point_t p2; p1.x = txt_pos.x; - p1.y = pos.y + (pinfo->line_h / 2) + line_dsc.width / 2; + p1.y = pos.y + ((pinfo->line_h - line_space) >> 1) + (line_dsc.width >> 1); p2.x = pos.x; p2.y = p1.y; lv_draw_line(&p1, &p2, mask, &line_dsc); @@ -954,7 +1074,7 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area lv_point_t p1; lv_point_t p2; p1.x = txt_pos.x; - p1.y = pos.y + pinfo->line_h + line_dsc.width / 2; + p1.y = pos.y + pinfo->line_h - line_space - pinfo->font->base_line - pinfo->font->underline_position; p2.x = pos.x; p2.y = p1.y; lv_draw_line(&p1, &p2, &clipped_area, &line_dsc); @@ -965,9 +1085,10 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area Next_line_init: /* next line init */ + is_first_line = false; txt_pos.x = coords->x1; txt_pos.y += max_line_h; - if(txt_pos.y > clipped_area.y2 + 1) { + if(is_end_line || txt_pos.y > clipped_area.y2 + 1) { return; } max_w = max_width; diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/span/lv_span.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.h similarity index 88% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/span/lv_span.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.h index 4f7613de3..c130465ea 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/span/lv_span.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.h @@ -137,6 +137,27 @@ void lv_spangroup_set_mode(lv_obj_t * obj, lv_span_mode_t mode); * Getter functions *====================*/ +/** + * Get a spangroup child by its index. + * + * @param obj The spangroup object + * @param id the index of the child. + * 0: the oldest (firstly created) child + * 1: the second oldest + * child count-1: the youngest + * -1: the youngest + * -2: the second youngest + * @return The child span at index `id`, or NULL if the ID does not exist + */ +lv_span_t * lv_spangroup_get_child(const lv_obj_t * obj, int32_t id); + +/** + * + * @param obj The spangroup object to get the child count of. + * @return The span count of the spangroup. + */ +uint32_t lv_spangroup_get_child_cnt(const lv_obj_t * obj); + /** * get the align of the spangroup. * @param obj pointer to a spangroup object. diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/spinbox/lv_spinbox.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.c similarity index 82% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/spinbox/lv_spinbox.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.c index 66bfdd0e6..97d00404e 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/spinbox/lv_spinbox.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.c @@ -9,6 +9,8 @@ #include "lv_spinbox.h" #if LV_USE_SPINBOX +#include "../../../misc/lv_assert.h" + /********************* * DEFINES *********************/ @@ -46,7 +48,7 @@ const lv_obj_class_t lv_spinbox_class = { lv_obj_t * lv_spinbox_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -63,6 +65,7 @@ lv_obj_t * lv_spinbox_create(lv_obj_t * parent) */ void lv_spinbox_set_value(lv_obj_t * obj, int32_t i) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; if(i > spinbox->range_max) i = spinbox->range_max; @@ -80,6 +83,7 @@ void lv_spinbox_set_value(lv_obj_t * obj, int32_t i) */ void lv_spinbox_set_rollover(lv_obj_t * obj, bool b) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; spinbox->rollover = b; @@ -94,6 +98,7 @@ void lv_spinbox_set_rollover(lv_obj_t * obj, bool b) */ void lv_spinbox_set_digit_format(lv_obj_t * obj, uint8_t digit_count, uint8_t separator_position) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; if(digit_count > LV_SPINBOX_MAX_DIGIT_COUNT) digit_count = LV_SPINBOX_MAX_DIGIT_COUNT; @@ -120,6 +125,7 @@ void lv_spinbox_set_digit_format(lv_obj_t * obj, uint8_t digit_count, uint8_t se */ void lv_spinbox_set_step(lv_obj_t * obj, uint32_t step) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; spinbox->step = step; @@ -134,6 +140,7 @@ void lv_spinbox_set_step(lv_obj_t * obj, uint32_t step) */ void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; spinbox->range_max = range_max; @@ -145,6 +152,37 @@ void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max) lv_spinbox_updatevalue(obj); } +/** + * Set cursor position to a specific digit for edition + * @param spinbox pointer to spinbox + * @param pos selected position in spinbox + */ +void lv_spinbox_set_pos(lv_obj_t * obj, uint8_t pos) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; + int32_t step_limit; + step_limit = LV_MAX(spinbox->range_max, (spinbox->range_min < 0 ? (-spinbox->range_min) : spinbox->range_min)); + int32_t new_step = spinbox->step * lv_pow(10, pos); + if(pos <= 0) spinbox->step = 1; + else if(new_step <= step_limit) spinbox->step = new_step; + + lv_spinbox_updatevalue(obj); +} + +/** + * Set direction of digit step when clicking an encoder button while in editing mode + * @param spinbox pointer to spinbox + * @param direction the direction (LV_DIR_RIGHT or LV_DIR_LEFT) + */ +void lv_spinbox_set_digit_step_direction(lv_obj_t *obj, lv_dir_t direction) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; + spinbox->digit_step_dir = direction; + + lv_spinbox_updatevalue(obj); +} /*===================== * Getter functions *====================*/ @@ -156,6 +194,7 @@ void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max) */ int32_t lv_spinbox_get_value(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; return spinbox->value; @@ -167,6 +206,7 @@ int32_t lv_spinbox_get_value(lv_obj_t * obj) */ int32_t lv_spinbox_get_step(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; return spinbox->step; @@ -182,6 +222,7 @@ int32_t lv_spinbox_get_step(lv_obj_t * obj) */ void lv_spinbox_step_next(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; int32_t new_step = spinbox->step / 10; @@ -199,6 +240,7 @@ void lv_spinbox_step_next(lv_obj_t * obj) */ void lv_spinbox_step_prev(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; int32_t step_limit; step_limit = LV_MAX(spinbox->range_max, (spinbox->range_min < 0 ? (-spinbox->range_min) : spinbox->range_min)); @@ -214,6 +256,7 @@ void lv_spinbox_step_prev(lv_obj_t * obj) */ bool lv_spinbox_get_rollover(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; return spinbox->rollover; @@ -225,6 +268,7 @@ bool lv_spinbox_get_rollover(lv_obj_t * obj) */ void lv_spinbox_increment(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; if(spinbox->value + spinbox->step <= spinbox->range_max) { @@ -250,6 +294,7 @@ void lv_spinbox_increment(lv_obj_t * obj) */ void lv_spinbox_decrement(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; if(spinbox->value - spinbox->step >= spinbox->range_min) { @@ -287,6 +332,7 @@ static void lv_spinbox_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob spinbox->range_max = 99999; spinbox->range_min = -99999; spinbox->rollover = false; + spinbox->digit_step_dir = LV_DIR_RIGHT; lv_textarea_set_one_line(obj, true); lv_textarea_set_cursor_click_pos(obj, true); @@ -314,19 +360,27 @@ static void lv_spinbox_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_indev_t * indev = lv_indev_get_act(); if(lv_indev_get_type(indev) == LV_INDEV_TYPE_ENCODER) { if(lv_group_get_editing(lv_obj_get_group(obj))) { - if(spinbox->step > 1) { - lv_spinbox_step_next(obj); - } - else { - /*Restart from the MSB*/ - spinbox->step = 1; - uint32_t i; - for(i = 0; i < spinbox->digit_count; i++) { - int32_t new_step = spinbox->step * 10; - if(new_step >= spinbox->range_max) break; - spinbox->step = new_step; + if (spinbox->digit_count > 1) { + if (spinbox->digit_step_dir == LV_DIR_RIGHT) { + if(spinbox->step > 1) { + lv_spinbox_step_next(obj); + } + else { + /*Restart from the MSB*/ + spinbox->step = lv_pow(10, spinbox->digit_count - 2); + lv_spinbox_step_prev(obj); + } + } + else { + if(spinbox->step < lv_pow(10, spinbox->digit_count - 1)) { + lv_spinbox_step_prev(obj); + } + else { + /*Restart from the LSB*/ + spinbox->step = 10; + lv_spinbox_step_next(obj); + } } - lv_spinbox_step_prev(obj); } } } @@ -409,7 +463,7 @@ static void lv_spinbox_updatevalue(lv_obj_t * obj) int32_t i; char digits[LV_SPINBOX_MAX_DIGIT_COUNT + 4]; /*Convert the numbers to string (the sign is already handled so always covert positive number)*/ - lv_snprintf(digits, sizeof(digits), "%d", LV_ABS(spinbox->value)); + lv_snprintf(digits, sizeof(digits), "%" LV_PRId32, LV_ABS(spinbox->value)); /*Add leading zeros*/ int lz_cnt = spinbox->digit_count - (int)strlen(digits); diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/spinbox/lv_spinbox.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.h similarity index 86% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/spinbox/lv_spinbox.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.h index 92000a042..71856c917 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/spinbox/lv_spinbox.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.h @@ -42,6 +42,7 @@ typedef struct { uint16_t digit_count : 4; uint16_t dec_point_pos : 4; /*if 0, there is no separator and the number is an integer*/ uint16_t rollover : 1; // Set to true for rollover functionality + uint16_t digit_step_dir : 2; // the direction the digit will step on encoder button press when editing } lv_spinbox_t; extern const lv_obj_class_t lv_spinbox_class; @@ -99,6 +100,20 @@ void lv_spinbox_set_step(lv_obj_t * obj, uint32_t step); */ void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max); +/** + * Set cursor position to a specific digit for edition + * @param spinbox pointer to spinbox + * @param pos selected position in spinbox + */ +void lv_spinbox_set_pos(lv_obj_t * obj, uint8_t pos); + +/** + * Set direction of digit step when clicking an encoder button while in editing mode + * @param spinbox pointer to spinbox + * @param direction the direction (LV_DIR_RIGHT or LV_DIR_LEFT) + */ +void lv_spinbox_set_digit_step_direction(lv_obj_t * obj, lv_dir_t direction); + /*===================== * Getter functions *====================*/ @@ -107,7 +122,7 @@ void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max); * Get spinbox rollover function status * @param spinbox pointer to spinbox */ -bool lv_spinbox_get_rollover(lv_obj_t * obj); +bool lv_spinbox_get_rollover(lv_obj_t *obj); /** * Get the spinbox numeral value (user has to convert to float according to its digit format) diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/spinner/lv_spinner.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinner/lv_spinner.c similarity index 96% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/spinner/lv_spinner.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/spinner/lv_spinner.c index 98bbca49e..65b6b046a 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/spinner/lv_spinner.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinner/lv_spinner.c @@ -28,8 +28,8 @@ static void arc_anim_end_angle(void * obj, int32_t v); * STATIC VARIABLES **********************/ const lv_obj_class_t lv_spinner_class = { - .base_class = &lv_arc_class, - .constructor_cb = lv_spinner_constructor + .base_class = &lv_arc_class, + .constructor_cb = lv_spinner_constructor }; static uint32_t time_param; diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/spinner/lv_spinner.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinner/lv_spinner.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/spinner/lv_spinner.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/spinner/lv_spinner.h diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/tabview/lv_tabview.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.c similarity index 83% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/tabview/lv_tabview.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.c index 1fff72625..8ccd143e1 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/tabview/lv_tabview.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.c @@ -9,9 +9,12 @@ #include "lv_tabview.h" #if LV_USE_TABVIEW +#include "../../../misc/lv_assert.h" + /********************* * DEFINES *********************/ +#define MY_CLASS &lv_tabview_class /********************** * TYPEDEFS @@ -30,13 +33,14 @@ static void cont_scroll_end_event_cb(lv_event_t * e); * STATIC VARIABLES **********************/ const lv_obj_class_t lv_tabview_class = { - .constructor_cb = lv_tabview_constructor, - .destructor_cb = lv_tabview_destructor, - .event_cb = lv_tabview_event, - .width_def = LV_PCT(100), - .height_def = LV_PCT(100), - .base_class = &lv_obj_class, - .instance_size = sizeof(lv_tabview_t)}; + .constructor_cb = lv_tabview_constructor, + .destructor_cb = lv_tabview_destructor, + .event_cb = lv_tabview_event, + .width_def = LV_PCT(100), + .height_def = LV_PCT(100), + .base_class = &lv_obj_class, + .instance_size = sizeof(lv_tabview_t) +}; static lv_dir_t tabpos_create; static lv_coord_t tabsize_create; @@ -51,7 +55,7 @@ static lv_coord_t tabsize_create; lv_obj_t * lv_tabview_create(lv_obj_t * parent, lv_dir_t tab_pos, lv_coord_t tab_size) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); tabpos_create = tab_pos; tabsize_create = tab_size; @@ -62,6 +66,7 @@ lv_obj_t * lv_tabview_create(lv_obj_t * parent, lv_dir_t tab_pos, lv_coord_t tab lv_obj_t * lv_tabview_add_tab(lv_obj_t * obj, const char * name) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_tabview_t * tabview = (lv_tabview_t *)obj; lv_obj_t * cont = lv_tabview_get_content(obj); @@ -91,7 +96,8 @@ lv_obj_t * lv_tabview_add_tab(lv_obj_t * obj, const char * name) new_map[0] = lv_mem_alloc(strlen(name) + 1); strcpy((char *)new_map[0], name); new_map[1] = ""; - } else { + } + else { new_map[tab_id * 2 - 3] = "\n"; new_map[tab_id * 2 - 2] = lv_mem_alloc(strlen(name) + 1); new_map[tab_id * 2 - 1] = ""; @@ -102,7 +108,8 @@ lv_obj_t * lv_tabview_add_tab(lv_obj_t * obj, const char * name) lv_btnmatrix_set_map(btns, (const char **)new_map); lv_mem_free(old_map); - lv_btnmatrix_set_btn_ctrl_all(btns, LV_BTNMATRIX_CTRL_CHECKABLE | LV_BTNMATRIX_CTRL_CLICK_TRIG | LV_BTNMATRIX_CTRL_NO_REPEAT); + lv_btnmatrix_set_btn_ctrl_all(btns, LV_BTNMATRIX_CTRL_CHECKABLE | LV_BTNMATRIX_CTRL_CLICK_TRIG | + LV_BTNMATRIX_CTRL_NO_REPEAT); tabview->tab_cnt++; if(tabview->tab_cnt == 1) { @@ -116,6 +123,7 @@ lv_obj_t * lv_tabview_add_tab(lv_obj_t * obj, const char * name) void lv_tabview_set_act(lv_obj_t * obj, uint32_t id, lv_anim_enable_t anim_en) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_tabview_t * tabview = (lv_tabview_t *)obj; if(id >= tabview->tab_cnt) { @@ -131,7 +139,8 @@ void lv_tabview_set_act(lv_obj_t * obj, uint32_t id, lv_anim_enable_t anim_en) lv_coord_t w = lv_obj_get_content_width(cont); if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) { lv_obj_scroll_to_x(cont, id * (gap + w), anim_en); - } else { + } + else { int32_t id_rtl = -(int32_t)id; lv_obj_scroll_to_x(cont, (gap + w) * id_rtl, anim_en); } @@ -143,6 +152,7 @@ void lv_tabview_set_act(lv_obj_t * obj, uint32_t id, lv_anim_enable_t anim_en) uint16_t lv_tabview_get_tab_act(lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_tabview_t * tabview = (lv_tabview_t *)obj; return tabview->tab_cur; } @@ -169,18 +179,18 @@ static void lv_tabview_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob tabview->tab_pos = tabpos_create; switch(tabview->tab_pos) { - case LV_DIR_TOP: - lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN); - break; - case LV_DIR_BOTTOM: - lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN_REVERSE); - break; - case LV_DIR_LEFT: - lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW); - break; - case LV_DIR_RIGHT: - lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW_REVERSE); - break; + case LV_DIR_TOP: + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN); + break; + case LV_DIR_BOTTOM: + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN_REVERSE); + break; + case LV_DIR_LEFT: + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW); + break; + case LV_DIR_RIGHT: + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW_REVERSE); + break; } lv_obj_set_size(obj, LV_PCT(100), LV_PCT(100)); @@ -202,19 +212,19 @@ static void lv_tabview_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob lv_obj_set_scrollbar_mode(cont, LV_SCROLLBAR_MODE_OFF); switch(tabview->tab_pos) { - case LV_DIR_TOP: - case LV_DIR_BOTTOM: - lv_obj_set_size(btnm, LV_PCT(100), tabsize_create); - lv_obj_set_width(cont, LV_PCT(100)); - lv_obj_set_flex_grow(cont, 1); - break; - case LV_DIR_LEFT: - case LV_DIR_RIGHT: - lv_obj_set_size(btnm, tabsize_create, LV_PCT(100)); - lv_obj_set_height(cont, LV_PCT(100)); - lv_obj_set_flex_grow(cont, 1); - break; - } + case LV_DIR_TOP: + case LV_DIR_BOTTOM: + lv_obj_set_size(btnm, LV_PCT(100), tabsize_create); + lv_obj_set_width(cont, LV_PCT(100)); + lv_obj_set_flex_grow(cont, 1); + break; + case LV_DIR_LEFT: + case LV_DIR_RIGHT: + lv_obj_set_size(btnm, tabsize_create, LV_PCT(100)); + lv_obj_set_height(cont, LV_PCT(100)); + lv_obj_set_flex_grow(cont, 1); + break; + } lv_group_t * g = lv_group_get_default(); if(g) lv_group_add_obj(g, btnm); @@ -289,8 +299,8 @@ static void cont_scroll_end_event_cb(lv_event_t * e) lv_coord_t w = lv_obj_get_content_width(cont); lv_coord_t t; - if(lv_obj_get_style_base_dir(tv, LV_PART_MAIN) == LV_BASE_DIR_RTL) t = -(p.x - w/ 2) / w; - else t = (p.x + w/ 2) / w; + if(lv_obj_get_style_base_dir(tv, LV_PART_MAIN) == LV_BASE_DIR_RTL) t = -(p.x - w / 2) / w; + else t = (p.x + w / 2) / w; if(t < 0) t = 0; bool new_tab = false; diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/tabview/lv_tabview.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.h similarity index 97% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/tabview/lv_tabview.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.h index 4cfc4971b..a01c6b9ba 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/tabview/lv_tabview.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.h @@ -25,14 +25,13 @@ extern "C" { * TYPEDEFS **********************/ -typedef struct -{ +typedef struct { lv_obj_t obj; char ** map; uint16_t tab_cnt; uint16_t tab_cur; lv_dir_t tab_pos; -}lv_tabview_t; +} lv_tabview_t; extern const lv_obj_class_t lv_tabview_class; diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/tileview/lv_tileview.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.c similarity index 88% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/tileview/lv_tileview.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.c index 1bbe110ac..8f8f3c4d2 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/tileview/lv_tileview.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.c @@ -29,12 +29,14 @@ static void tileview_event_cb(lv_event_t * e); **********************/ const lv_obj_class_t lv_tileview_class = {.constructor_cb = lv_tileview_constructor, - .base_class = &lv_obj_class, - .instance_size = sizeof(lv_tileview_t)}; + .base_class = &lv_obj_class, + .instance_size = sizeof(lv_tileview_t) + }; const lv_obj_class_t lv_tileview_tile_class = {.constructor_cb = lv_tileview_tile_constructor, - .base_class = &lv_obj_class, - .instance_size = sizeof(lv_tileview_tile_t)}; + .base_class = &lv_obj_class, + .instance_size = sizeof(lv_tileview_tile_t) + }; static lv_dir_t create_dir; static uint32_t create_col_id; @@ -50,7 +52,7 @@ static uint32_t create_row_id; lv_obj_t * lv_tileview_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(&lv_tileview_class, parent); lv_obj_class_init_obj(obj); return obj; @@ -62,7 +64,7 @@ lv_obj_t * lv_tileview_create(lv_obj_t * parent) lv_obj_t * lv_tileview_add_tile(lv_obj_t * tv, uint8_t col_id, uint8_t row_id, lv_dir_t dir) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); create_dir = dir; create_col_id = col_id; create_row_id = row_id; @@ -104,7 +106,7 @@ void lv_obj_set_tile_id(lv_obj_t * tv, uint32_t col_id, uint32_t row_id, lv_anim } } - LV_LOG_WARN("No tile found with at (%d,%d) index", col_id, row_id); + LV_LOG_WARN("No tile found with at (%d,%d) index", (int)col_id, (int)row_id); } lv_obj_t * lv_tileview_get_tile_act(lv_obj_t * obj) @@ -135,7 +137,8 @@ static void lv_tileview_tile_constructor(const lv_obj_class_t * class_p, lv_obj_ lv_obj_t * parent = lv_obj_get_parent(obj); lv_obj_set_size(obj, LV_PCT(100), LV_PCT(100)); lv_obj_update_layout(obj); /*Be sure the size is correct*/ - lv_obj_set_pos(obj, create_col_id * lv_obj_get_content_width(parent), create_row_id * lv_obj_get_content_height(parent)); + lv_obj_set_pos(obj, create_col_id * lv_obj_get_content_width(parent), + create_row_id * lv_obj_get_content_height(parent)); lv_tileview_tile_t * tile = (lv_tileview_tile_t *)obj; tile->dir = create_dir; diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/tileview/lv_tileview.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.h similarity index 97% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/tileview/lv_tileview.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.h index 79f1acd46..172338196 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/tileview/lv_tileview.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.h @@ -27,12 +27,12 @@ extern "C" { typedef struct { lv_obj_t obj; lv_obj_t * tile_act; -}lv_tileview_t; +} lv_tileview_t; typedef struct { lv_obj_t obj; lv_dir_t dir; -}lv_tileview_tile_t; +} lv_tileview_tile_t; extern const lv_obj_class_t lv_tileview_class; extern const lv_obj_class_t lv_tileview_tile_class; diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/win/lv_win.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/win/lv_win.c similarity index 92% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/win/lv_win.c rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/win/lv_win.c index eb9eb8eb6..92c3b8baa 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/win/lv_win.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/win/lv_win.c @@ -27,11 +27,11 @@ static void lv_win_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); * STATIC VARIABLES **********************/ const lv_obj_class_t lv_win_class = { - .constructor_cb = lv_win_constructor, - .width_def = LV_PCT(100), - .height_def = LV_PCT(100), - .base_class = &lv_obj_class, - .instance_size = sizeof(lv_win_t) + .constructor_cb = lv_win_constructor, + .width_def = LV_PCT(100), + .height_def = LV_PCT(100), + .base_class = &lv_obj_class, + .instance_size = sizeof(lv_win_t) }; static lv_coord_t create_header_height; /********************** @@ -44,7 +44,7 @@ static lv_coord_t create_header_height; lv_obj_t * lv_win_create(lv_obj_t * parent, lv_coord_t header_height) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); create_header_height = header_height; lv_obj_t * obj = lv_obj_class_create_obj(&lv_win_class, parent); diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/win/lv_win.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/win/lv_win.h similarity index 98% rename from lib/libesp32_lvgl/LVGL8/src/extra/widgets/win/lv_win.h rename to lib/libesp32_lvgl/lvgl/src/extra/widgets/win/lv_win.h index 524596339..4342b3104 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/widgets/win/lv_win.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/win/lv_win.h @@ -24,7 +24,7 @@ extern "C" { **********************/ typedef struct { lv_obj_t obj; -}lv_win_t; +} lv_win_t; extern const lv_obj_class_t lv_win_class; diff --git a/lib/libesp32_lvgl/LVGL8/src/font/korean.ttf b/lib/libesp32_lvgl/lvgl/src/font/korean.ttf similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/korean.ttf rename to lib/libesp32_lvgl/lvgl/src/font/korean.ttf diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font.c similarity index 94% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font.c index 5af902c57..cf3d374f4 100644 --- a/lib/libesp32_lvgl/LVGL8/src/font/lv_font.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font.c @@ -10,6 +10,7 @@ #include "lv_font.h" #include "../misc/lv_utils.h" #include "../misc/lv_log.h" +#include "../misc/lv_assert.h" /********************* * DEFINES @@ -47,6 +48,7 @@ */ const uint8_t * lv_font_get_glyph_bitmap(const lv_font_t * font_p, uint32_t letter) { + LV_ASSERT_NULL(font_p); return font_p->get_glyph_bitmap(font_p, letter); } @@ -61,6 +63,7 @@ const uint8_t * lv_font_get_glyph_bitmap(const lv_font_t * font_p, uint32_t lett bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_out, uint32_t letter, uint32_t letter_next) { + LV_ASSERT_NULL(font_p); return font_p->get_glyph_dsc(font_p, dsc_out, letter, letter_next); } @@ -73,6 +76,7 @@ bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_o */ uint16_t lv_font_get_glyph_width(const lv_font_t * font, uint32_t letter, uint32_t letter_next) { + LV_ASSERT_NULL(font); lv_font_glyph_dsc_t g; bool ret; ret = lv_font_get_glyph_dsc(font, &g, letter, letter_next); diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font.h b/lib/libesp32_lvgl/lvgl/src/font/lv_font.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font.h rename to lib/libesp32_lvgl/lvgl/src/font/lv_font.h diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font.mk b/lib/libesp32_lvgl/lvgl/src/font/lv_font.mk similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font.mk rename to lib/libesp32_lvgl/lvgl/src/font/lv_font.mk diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_dejavu_16_persian_hebrew.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_dejavu_16_persian_hebrew.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_dejavu_16_persian_hebrew.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_dejavu_16_persian_hebrew.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_fmt_txt.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.c similarity index 99% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_fmt_txt.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.c index d83235b22..991b23e6d 100644 --- a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_fmt_txt.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.c @@ -128,7 +128,7 @@ const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t unic (uint8_t)fdsc->bpp, prefilter); return LV_GC_ROOT(_lv_font_decompr_buf); #else /*!LV_USE_FONT_COMPRESSED*/ -// LV_LOG_WARN("Compressed fonts is used but LV_USE_FONT_COMPRESSED is not enabled in lv_conf.h") + LV_LOG_WARN("Compressed fonts is used but LV_USE_FONT_COMPRESSED is not enabled in lv_conf.h"); return NULL; #endif } diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_fmt_txt.h b/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_fmt_txt.h rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.h diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_loader.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_loader.c similarity index 99% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_loader.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_loader.c index 54e53c607..f7c061bbe 100644 --- a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_loader.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_loader.c @@ -457,6 +457,10 @@ static int32_t load_glyph(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, if(res != LV_FS_RES_OK) { return -1; } + + /*The last fragment should be on the MSB but read_bits() will place it to the LSB*/ + glyph_bmp[cur_bmp_size + bmp_size - 1] = glyph_bmp[cur_bmp_size + bmp_size - 1] << (nbits % 8); + } cur_bmp_size += bmp_size; diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_loader.h b/lib/libesp32_lvgl/lvgl/src/font/lv_font_loader.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_loader.h rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_loader.h diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_10.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_10.c similarity index 99% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_10.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_10.c index b6a806d5a..54f9f98e7 100644 --- a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_10.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_10.c @@ -5,13 +5,13 @@ ******************************************************************************/ #ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" + #include "lvgl.h" #else -#include "../../lvgl.h" + #include "../../lvgl.h" #endif #ifndef LV_FONT_MONTSERRAT_10 -#define LV_FONT_MONTSERRAT_10 1 + #define LV_FONT_MONTSERRAT_10 1 #endif #if LV_FONT_MONTSERRAT_10 @@ -1155,8 +1155,7 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ +static const lv_font_fmt_txt_cmap_t cmaps[] = { { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY @@ -1173,8 +1172,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = /*Map glyph_ids to kern left classes*/ -static const uint8_t kern_left_class_mapping[] = -{ +static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, 2, 6, 7, 8, 9, 10, 9, 10, 11, 12, 0, 13, 14, 15, 16, 17, @@ -1198,8 +1196,7 @@ static const uint8_t kern_left_class_mapping[] = }; /*Map glyph_ids to kern right classes*/ -static const uint8_t kern_right_class_mapping[] = -{ +static const uint8_t kern_right_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, 2, 6, 7, 8, 9, 10, 9, 10, 11, 12, 13, 14, 15, 16, 17, 12, @@ -1223,8 +1220,7 @@ static const uint8_t kern_right_class_mapping[] = }; /*Kern values between classes*/ -static const int8_t kern_class_values[] = -{ +static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, @@ -1603,8 +1599,7 @@ static const int8_t kern_class_values[] = /*Collect the kern class' data in one place*/ -static const lv_font_fmt_txt_kern_classes_t kern_classes = -{ +static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, .left_class_mapping = kern_left_class_mapping, .right_class_mapping = kern_right_class_mapping, diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_12.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_12.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_12.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_12.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_12_subpx.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_12_subpx.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_12_subpx.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_12_subpx.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_14.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_14.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_14.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_14.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_16.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_16.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_16.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_16.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_18.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_18.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_18.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_18.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_20.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_20.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_20.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_20.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_22.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_22.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_22.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_22.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_24.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_24.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_24.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_24.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_26.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_26.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_26.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_26.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_28.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_28.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_28.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_28.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_28_compressed.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_28_compressed.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_28_compressed.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_28_compressed.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_30.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_30.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_30.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_30.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_32.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_32.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_32.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_32.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_34.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_34.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_34.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_34.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_36.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_36.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_36.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_36.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_38.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_38.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_38.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_38.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_40.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_40.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_40.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_40.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_42.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_42.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_42.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_42.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_44.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_44.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_44.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_44.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_46.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_46.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_46.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_46.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_48.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_48.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_48.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_48.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_8.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_8.c similarity index 99% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_8.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_8.c index 8cd303f69..9d8b154b6 100644 --- a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_montserrat_8.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_8.c @@ -5,13 +5,13 @@ ******************************************************************************/ #ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" + #include "lvgl.h" #else -#include "../../lvgl.h" + #include "../../lvgl.h" #endif #ifndef LV_FONT_MONTSERRAT_8 -#define LV_FONT_MONTSERRAT_8 1 + #define LV_FONT_MONTSERRAT_8 1 #endif #if LV_FONT_MONTSERRAT_8 @@ -941,8 +941,7 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ +static const lv_font_fmt_txt_cmap_t cmaps[] = { { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY @@ -959,8 +958,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = /*Map glyph_ids to kern left classes*/ -static const uint8_t kern_left_class_mapping[] = -{ +static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, 2, 6, 7, 8, 9, 10, 9, 10, 11, 12, 0, 13, 14, 15, 16, 17, @@ -984,8 +982,7 @@ static const uint8_t kern_left_class_mapping[] = }; /*Map glyph_ids to kern right classes*/ -static const uint8_t kern_right_class_mapping[] = -{ +static const uint8_t kern_right_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, 2, 6, 7, 8, 9, 10, 9, 10, 11, 12, 13, 14, 15, 16, 17, 12, @@ -1009,8 +1006,7 @@ static const uint8_t kern_right_class_mapping[] = }; /*Kern values between classes*/ -static const int8_t kern_class_values[] = -{ +static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, @@ -1389,8 +1385,7 @@ static const int8_t kern_class_values[] = /*Collect the kern class' data in one place*/ -static const lv_font_fmt_txt_kern_classes_t kern_classes = -{ +static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, .left_class_mapping = kern_left_class_mapping, .right_class_mapping = kern_right_class_mapping, diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_simsun_16_cjk.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_simsun_16_cjk.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_simsun_16_cjk.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_simsun_16_cjk.c diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_unscii_16.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_unscii_16.c similarity index 99% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_unscii_16.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_unscii_16.c index 451cd1ea3..104bc2bce 100644 --- a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_unscii_16.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_unscii_16.c @@ -5,13 +5,13 @@ ******************************************************************************/ #ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" + #include "lvgl.h" #else -#include "../../lvgl.h" + #include "../../lvgl.h" #endif #ifndef LV_FONT_UNSCII_16 -#define LV_FONT_UNSCII_16 1 + #define LV_FONT_UNSCII_16 1 #endif #if LV_FONT_UNSCII_16 @@ -587,8 +587,7 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ +static const lv_font_fmt_txt_cmap_t cmaps[] = { { .range_start = 32, .range_length = 96, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_unscii_8.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_unscii_8.c similarity index 99% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_font_unscii_8.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_font_unscii_8.c index 49ea8394a..e67c5166d 100644 --- a/lib/libesp32_lvgl/LVGL8/src/font/lv_font_unscii_8.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_unscii_8.c @@ -5,13 +5,13 @@ ******************************************************************************/ #ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" + #include "lvgl.h" #else -#include "../../lvgl.h" + #include "../../lvgl.h" #endif #ifndef LV_FONT_UNSCII_8 -#define LV_FONT_UNSCII_8 1 + #define LV_FONT_UNSCII_8 1 #endif #if LV_FONT_UNSCII_8 @@ -423,8 +423,7 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ +static const lv_font_fmt_txt_cmap_t cmaps[] = { { .range_start = 32, .range_length = 96, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/lib/libesp32_lvgl/LVGL8/src/font/lv_symbol_def.h b/lib/libesp32_lvgl/lvgl/src/font/lv_symbol_def.h similarity index 99% rename from lib/libesp32_lvgl/LVGL8/src/font/lv_symbol_def.h rename to lib/libesp32_lvgl/lvgl/src/font/lv_symbol_def.h index 0e619e74b..75fd80b58 100644 --- a/lib/libesp32_lvgl/LVGL8/src/font/lv_symbol_def.h +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_symbol_def.h @@ -1,6 +1,5 @@ #ifndef LV_SYMBOL_DEF_H #define LV_SYMBOL_DEF_H -/*clang-format off*/ #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu.mk b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu.mk similarity index 76% rename from lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu.mk rename to lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu.mk index d909b0335..e162d79f6 100644 --- a/lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu.mk +++ b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu.mk @@ -2,8 +2,11 @@ CSRCS += lv_gpu_nxp_pxp.c CSRCS += lv_gpu_nxp_pxp_osa.c CSRCS += lv_gpu_nxp_vglite.c CSRCS += lv_gpu_stm32_dma2d.c +CSRCS += lv_gpu_sdl.c DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/gpu VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/gpu CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/gpu" + +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/gpu/sdl/lv_gpu_sdl.mk \ No newline at end of file diff --git a/lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_nxp_pxp.c b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_nxp_pxp.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_nxp_pxp.c rename to lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_nxp_pxp.c diff --git a/lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_nxp_pxp.h b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_nxp_pxp.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_nxp_pxp.h rename to lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_nxp_pxp.h diff --git a/lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_nxp_pxp_osa.c b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_nxp_pxp_osa.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_nxp_pxp_osa.c rename to lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_nxp_pxp_osa.c diff --git a/lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_nxp_pxp_osa.h b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_nxp_pxp_osa.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_nxp_pxp_osa.h rename to lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_nxp_pxp_osa.h diff --git a/lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_nxp_vglite.c b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_nxp_vglite.c similarity index 94% rename from lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_nxp_vglite.c rename to lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_nxp_vglite.c index 6021300e7..8e6ee193d 100644 --- a/lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_nxp_vglite.c +++ b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_nxp_vglite.c @@ -79,9 +79,9 @@ defined(CPU_MIMXRT595SFFOC) || defined(CPU_MIMXRT595SFFOC_cm33)) && \ ((LV_HOR_RES_MAX > RT595_BLIT_WRKRND_THR) || (LV_VER_RES_MAX > RT595_BLIT_WRKRND_THR)) && \ RT595_BLIT_WRKRND_ENABLED - #define _BLIT_SPLIT_ENABLED 1 +#define _BLIT_SPLIT_ENABLED 1 #else - #define _BLIT_SPLIT_ENABLED 0 +#define _BLIT_SPLIT_ENABLED 0 #endif /* BLIT split threshold - BLITs with width or height higher than this value will be done @@ -153,7 +153,8 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv lv_color32_t col32 = {.full = lv_color_to32(color)}; /*Convert color to RGBA8888*/ lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - if(_init_vg_buf(&rt, (uint32_t) dest_width, (uint32_t) dest_height, (uint32_t) dest_width * sizeof(lv_color_t), (const lv_color_t *) dest_buf, false) != LV_RES_OK) { + if(_init_vg_buf(&rt, (uint32_t) dest_width, (uint32_t) dest_height, (uint32_t) dest_width * sizeof(lv_color_t), + (const lv_color_t *) dest_buf, false) != LV_RES_OK) { #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("init_vg_buf reported error. Fill failed."); #endif @@ -171,17 +172,17 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv } err = vg_lite_clear(&rt, &rect, col32.full); - if (err != VG_LITE_SUCCESS) { - #if LV_GPU_NXP_VG_LITE_LOG_ERRORS + if(err != VG_LITE_SUCCESS) { +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("vg_lite_clear reported error. Fill failed."); - #endif +#endif return LV_RES_INV; } err = vg_lite_finish(); - if (err != VG_LITE_SUCCESS) { - #if LV_GPU_NXP_VG_LITE_LOG_ERRORS + if(err != VG_LITE_SUCCESS) { +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("vg_lite_finish reported error. Fill failed."); - #endif +#endif return LV_RES_INV; } } @@ -199,7 +200,8 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv }; err = vg_lite_init_path(&path, VG_LITE_S16, VG_LITE_LOW, sizeof(path_data), path_data, - (vg_lite_float_t) fill_area->x1, (vg_lite_float_t) fill_area->y1, ((vg_lite_float_t) fill_area->x2) + 1.0f, ((vg_lite_float_t) fill_area->y2) + 1.0f); + (vg_lite_float_t) fill_area->x1, (vg_lite_float_t) fill_area->y1, ((vg_lite_float_t) fill_area->x2) + 1.0f, + ((vg_lite_float_t) fill_area->y2) + 1.0f); if(err != VG_LITE_SUCCESS) { #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("vg_lite_init_path() failed."); @@ -449,8 +451,8 @@ static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * b lv_disp_t * disp = _lv_refr_get_disp_refreshing(); if(blit == NULL) { - /*Wrong parameter*/ - return LV_RES_INV; + /*Wrong parameter*/ + return LV_RES_INV; } if(blit->opa < (lv_opa_t) LV_OPA_MIN) { @@ -458,14 +460,16 @@ static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * b } /*Wrap src/dst buffer into VG-Lite buffer*/ - if(_init_vg_buf(&src_vgbuf, (uint32_t) blit->src_width, (uint32_t) blit->src_height, (uint32_t) blit->src_stride, blit->src, true) != LV_RES_OK) { + if(_init_vg_buf(&src_vgbuf, (uint32_t) blit->src_width, (uint32_t) blit->src_height, (uint32_t) blit->src_stride, + blit->src, true) != LV_RES_OK) { #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("init_vg_buf reported error. BLIT failed."); #endif return LV_RES_INV; } - if(_init_vg_buf(&dst_vgbuf, (uint32_t) blit->dst_width, (uint32_t) blit->dst_height, (uint32_t) blit->dst_stride, blit->dst, false) != LV_RES_OK) { + if(_init_vg_buf(&dst_vgbuf, (uint32_t) blit->dst_width, (uint32_t) blit->dst_height, (uint32_t) blit->dst_stride, + blit->dst, false) != LV_RES_OK) { #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("init_vg_buf reported error. BLIT failed."); #endif @@ -543,9 +547,11 @@ static lv_res_t _init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t he return LV_RES_INV; } - if(source && (stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t))) != 0x0U) { /*Test for stride alignment*/ + if(source && + (stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t))) != 0x0U) { /*Test for stride alignment*/ #if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("Buffer stride (%d px) not aligned to %d bytes.", stride, LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t)); + LV_LOG_ERROR("Buffer stride (%d px) not aligned to %d bytes.", stride, + LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t)); #endif return LV_RES_INV; } @@ -559,8 +565,8 @@ static lv_res_t _init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t he dst->height = (int32_t) height; dst->stride = (int32_t) stride; - void *r_ptr = memset(&dst->yuv, 0, sizeof(dst->yuv)); - if (r_ptr == NULL) { + void * r_ptr = memset(&dst->yuv, 0, sizeof(dst->yuv)); + if(r_ptr == NULL) { return LV_RES_INV; } @@ -642,16 +648,20 @@ static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * bl } /* No alignment requirement for destination pixel buffer when using mode VG_LITE_LINEAR */ - if((blit->src_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != 0x0) { /* Test for stride alignment */ + if((blit->src_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != + 0x0) { /* Test for stride alignment */ #if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("source buffer stride (%d px) not aligned to %d px.", blit->src_stride, LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); + LV_LOG_ERROR("source buffer stride (%d px) not aligned to %d px.", blit->src_stride, + LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); #endif return LV_RES_INV; } - if((blit->dst_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != 0x0) { /* Test for stride alignment */ + if((blit->dst_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != + 0x0) { /* Test for stride alignment */ #if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("destination buffer stride (%d px) not aligned to %d px.", blit->dst_stride, LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); + LV_LOG_ERROR("destination buffer stride (%d px) not aligned to %d px.", blit->dst_stride, + LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); #endif return LV_RES_INV; } @@ -675,7 +685,7 @@ static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * bl static void _align_x(lv_area_t * area, lv_color_t ** buf) { - int alignedAreaStartPx = area->x1 - (area->x1 % (LV_ATTRIBUTE_MEM_ALIGN_SIZE * 8 / LV_COLOR_DEPTH) ); + int alignedAreaStartPx = area->x1 - (area->x1 % (LV_ATTRIBUTE_MEM_ALIGN_SIZE * 8 / LV_COLOR_DEPTH)); CHECK(alignedAreaStartPx < 0, "Should never happen."); area->x1 -= alignedAreaStartPx; @@ -696,9 +706,11 @@ static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx) /* find how many lines of pixels will respect memory alignment requirement */ if(stridePx % LV_ATTRIBUTE_MEM_ALIGN_SIZE == 0) { alignedAreaStartPy = area->y1; - } else { + } + else { LineToAlignMem = LV_ATTRIBUTE_MEM_ALIGN_SIZE / (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); - CHECK(LV_ATTRIBUTE_MEM_ALIGN_SIZE % (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) != 0, "Complex case: need gcd function."); + CHECK(LV_ATTRIBUTE_MEM_ALIGN_SIZE % (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) != 0, + "Complex case: need gcd function."); alignedAreaStartPy = area->y1 - (area->y1 % LineToAlignMem); CHECK(alignedAreaStartPy < 0, "Should never happen."); } diff --git a/lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_nxp_vglite.h b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_nxp_vglite.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_nxp_vglite.h rename to lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_nxp_vglite.h diff --git a/lib/libesp32_lvgl/LVGL8/src/extra/lv_extra.c b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_sdl.c similarity index 58% rename from lib/libesp32_lvgl/LVGL8/src/extra/lv_extra.c rename to lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_sdl.c index 1de4df29f..2b46d87c9 100644 --- a/lib/libesp32_lvgl/LVGL8/src/extra/lv_extra.c +++ b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_sdl.c @@ -1,12 +1,20 @@ /** - * @file lv_extra.c + * @file lv_gpu_sdl.c * */ /********************* * INCLUDES *********************/ -#include "../lvgl.h" + + +#include "../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include "lv_gpu_sdl.h" +#include "sdl/lv_gpu_sdl_utils.h" +#include "sdl/lv_gpu_sdl_texture_cache.h" /********************* * DEFINES @@ -32,17 +40,20 @@ * GLOBAL FUNCTIONS **********************/ -void lv_extra_init(void) +void lv_gpu_sdl_init() { -#if LV_USE_FLEX - lv_flex_init(); -#endif - -#if LV_USE_GRID - lv_grid_init(); -#endif + _lv_gpu_sdl_utils_init(); + _lv_gpu_sdl_texture_cache_init(); } +void lv_gpu_sdl_deinit() +{ + _lv_gpu_sdl_texture_cache_deinit(); + _lv_gpu_sdl_utils_deinit(); +} /********************** * STATIC FUNCTIONS **********************/ + + +#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_sdl.h b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_sdl.h new file mode 100644 index 000000000..d5c22b3fc --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_sdl.h @@ -0,0 +1,73 @@ +/** + * @file lv_gpu_sdl.h + * + */ + +#ifndef LV_GPU_SDL_H +#define LV_GPU_SDL_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#if LV_USE_EXTERNAL_RENDERER == 0 +#error "SDL GPU requires LV_USE_EXTERNAL_RENDERER 1. Enable it in lv_conf.h" +#endif + +#include LV_GPU_SDL_INCLUDE_PATH + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_gpu_sdl_init(); + +/** + * @brief Free caches + * + */ +void lv_gpu_sdl_deinit(); + +/*====================== + * Add/remove functions + *=====================*/ + +/*===================== + * Setter functions + *====================*/ + +/*===================== + * Getter functions + *====================*/ + +/*===================== + * Other functions + *====================*/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GPU_SDL*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GPU_SDL_H*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_stm32_dma2d.c b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_stm32_dma2d.c similarity index 99% rename from lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_stm32_dma2d.c rename to lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_stm32_dma2d.c index e988589dc..9653e4121 100644 --- a/lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_stm32_dma2d.c +++ b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_stm32_dma2d.c @@ -76,6 +76,7 @@ void lv_gpu_stm32_dma2d_init(void) /*Delay after setting peripheral clock*/ volatile uint32_t temp = RCC->AHB1ENR; + LV_UNUSED(temp); /*set output colour mode*/ DMA2D->OPFCCR = LV_DMA2D_COLOR_FORMAT; @@ -112,7 +113,7 @@ void lv_gpu_stm32_dma2d_fill(lv_color_t * buf, lv_coord_t buf_w, lv_color_t colo * @param buf a buffer which should be filled using a mask * @param buf_w width of the buffer in pixels * @param color fill color - * @param mask 0..255 values describing the opacity of the corresponding pixel. It's width is `fill_w` + * @param mask 0..255 values describing the opacity of the corresponding pixel. Its width is `fill_w` * @param opa overall opacity. 255 in `mask` should mean this opacity. * @param fill_w width to fill in pixels (<= buf_w) * @param fill_h height to fill in pixels diff --git a/lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_stm32_dma2d.h b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_stm32_dma2d.h similarity index 98% rename from lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_stm32_dma2d.h rename to lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_stm32_dma2d.h index 82e66646d..014093cec 100644 --- a/lib/libesp32_lvgl/LVGL8/src/gpu/lv_gpu_stm32_dma2d.h +++ b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_stm32_dma2d.h @@ -57,7 +57,7 @@ void lv_gpu_stm32_dma2d_fill(lv_color_t * buf, lv_coord_t buf_w, lv_color_t colo * @param buf a buffer which should be filled using a mask * @param buf_w width of the buffer in pixels * @param color fill color - * @param mask 0..255 values describing the opacity of the corresponding pixel. It's width is `fill_w` + * @param mask 0..255 values describing the opacity of the corresponding pixel. Its width is `fill_w` * @param opa overall opacity. 255 in `mask` should mean this opacity. * @param fill_w width to fill in pixels (<= buf_w) * @param fill_h height to fill in pixels diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/README.md b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/README.md new file mode 100644 index 000000000..289fc04e4 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/README.md @@ -0,0 +1,28 @@ +# SDL_Renderer Based Drawing Functions + +In LVGL, drawing was performed by CPU. To improve drawing performance on platforms with GPU, +we should perform drawing operations on GPU if possible. + +This implementation has moved most bitmap blending and drawing procedures to utilize SDL_Renderer, +which takes advantages of hardware acceleration APIs like DirectX or OpenGL. + +This implementation can be also considered as a reference implementation, for contributors wants to +develop accelerated drawing functions with other APIs such as OpenGL/OpenGL ES. + +## Caveats +`lv_draw_arc`, `lv_draw_line` is not enabled, due to incomplete implementation. So lines and arcs will +have significant impact to drawing performances. + +Performance of this implementation still has room to improve. Or we should use more powerful APIs +such as OpenGL. + +## Notices for files + +### `lv_gpu_sdl_stack_blur.c` + +Contains modified code from [android-stackblur](https://github.com/kikoso/android-stackblur) project. +Apache License 2.0 + +### `lv_gpu_sdl_lru.c`/`lv_gpu_sdl_lru.h` + +Contains modified code from [C-LRU-Cache](https://github.com/willcannings/C-LRU-Cache) project. No license defined. \ No newline at end of file diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl.mk b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl.mk new file mode 100644 index 000000000..f258c8ba6 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl.mk @@ -0,0 +1,16 @@ +CSRCS += lv_gpu_sdl_draw_arc.c +CSRCS += lv_gpu_sdl_draw_blend.c +CSRCS += lv_gpu_sdl_draw_img.c +CSRCS += lv_gpu_sdl_draw_label.c +CSRCS += lv_gpu_sdl_draw_line.c +CSRCS += lv_gpu_sdl_draw_rect.c +CSRCS += lv_gpu_sdl_lru.c +CSRCS += lv_gpu_sdl_mask.c +CSRCS += lv_gpu_sdl_stack_blur.c +CSRCS += lv_gpu_sdl_texture_cache.c +CSRCS += lv_gpu_sdl_utils.c + +DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/gpu/sdl +VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/gpu/sdl + +CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/gpu/sdl" diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_arc.c b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_arc.c new file mode 100644 index 000000000..21bf9d8fa --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_arc.c @@ -0,0 +1,163 @@ +/** + * @file lv_gpu_sdl_draw_arc.c + * + * This implementation does not functioning properly so it's not enabled + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include "../../hal/lv_hal_disp.h" +#include "../../core/lv_refr.h" +#include "../../draw/lv_draw_arc.h" +#include "lv_gpu_sdl_utils.h" +#include "lv_gpu_sdl_lru.h" +#include "lv_gpu_sdl_texture_cache.h" +#include "lv_gpu_sdl_mask.h" + +#ifndef M_PI + #include +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_gpu_cache_key_magic_t magic; + uint16_t radius; + uint16_t angle; + lv_coord_t width; + uint8_t rounded; +} lv_draw_arc_key_t; + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_arc2(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uint16_t start_angle, uint16_t end_angle, + const lv_area_t * clip_area, const lv_draw_arc_dsc_t * dsc) +{ + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + lv_disp_drv_t * driver = disp->driver; + SDL_Renderer * renderer = (SDL_Renderer *) driver->user_data; + + lv_area_t area_out; + area_out.x1 = center_x - radius; + area_out.y1 = center_y - radius; + area_out.x2 = center_x + radius - 1; /*-1 because the center already belongs to the left/bottom part*/ + area_out.y2 = center_y + radius - 1; + + lv_area_t area_in; + lv_area_copy(&area_in, &area_out); + area_in.x1 += dsc->width; + area_in.y1 += dsc->width; + area_in.x2 -= dsc->width; + area_in.y2 -= dsc->width; + + /*Increase 1 px each side to texture, to have better rotation result*/ + lv_area_t texture_area_out; + lv_area_copy(&texture_area_out, &area_out); + lv_area_increase(&texture_area_out, 1, 1); + + SDL_Rect area_out_rect, clip_rect; + lv_area_to_sdl_rect(&texture_area_out, &area_out_rect); + lv_area_to_sdl_rect(clip_area, &clip_rect); + + lv_draw_arc_key_t key = { + .magic = LV_GPU_CACHE_KEY_MAGIC_ARC, + .radius = radius, + .angle = ((end_angle - start_angle) % 360 + 360) % 360, + .width = dsc->width, + .rounded = dsc->rounded, + }; + // SDL_Texture *texture = lv_gpu_draw_cache_get(&key, sizeof(key)); + SDL_Texture * texture = NULL; + if(texture == NULL) { + /*Create inner the mask*/ + lv_draw_mask_radius_param_t mask_in_param; + lv_draw_mask_radius_init(&mask_in_param, &area_in, LV_RADIUS_CIRCLE, true); + int16_t mask_in_id = lv_draw_mask_add(&mask_in_param, NULL); + + lv_draw_mask_radius_param_t mask_out_param; + lv_draw_mask_radius_init(&mask_out_param, &area_out, LV_RADIUS_CIRCLE, false); + int16_t mask_out_id = lv_draw_mask_add(&mask_out_param, NULL); + + SDL_Surface * ark_mask; + if(key.angle < 360) { + while(start_angle >= 360) start_angle -= 360; + while(end_angle >= 360) end_angle -= 360; + lv_draw_mask_angle_param_t mask_angle_param; + lv_draw_mask_angle_init(&mask_angle_param, center_x, center_y, 0, key.angle); + int16_t mask_angle_id = lv_draw_mask_add(&mask_angle_param, NULL); + ark_mask = lv_sdl_apply_mask_surface(&texture_area_out, NULL, 0); + lv_draw_mask_remove_id(mask_angle_id); + } + else { + ark_mask = lv_sdl_apply_mask_surface(&texture_area_out, NULL, 0); + } + lv_draw_mask_remove_id(mask_out_id); + lv_draw_mask_remove_id(mask_in_id); + + if(dsc->rounded) { + SDL_Renderer * mask_renderer = SDL_CreateSoftwareRenderer(ark_mask); + lv_area_t cap_area = {.x1 = 0, .y1 = 0}; + lv_area_set_width(&cap_area, dsc->width); + lv_area_set_height(&cap_area, dsc->width); + + lv_draw_mask_radius_param_t mask_rout_param; + lv_draw_mask_radius_init(&mask_rout_param, &cap_area, LV_RADIUS_CIRCLE, false); + int16_t mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); + SDL_Texture * round_texture = lv_sdl_gen_mask_texture(mask_renderer, &cap_area, &mask_rout_id, 1); + lv_draw_mask_remove_id(mask_rout_id); + + SDL_SetTextureBlendMode(round_texture, SDL_BLENDMODE_BLEND); + float mid_point = radius - key.width / 2.0f; + SDL_Rect cap_dst; + cap_dst.w = lv_area_get_width(&cap_area); + cap_dst.h = lv_area_get_height(&cap_area); + cap_dst.x = mid_point + lv_sdl_round(SDL_cos(0) * mid_point); + cap_dst.y = mid_point + lv_sdl_round(SDL_sin(0) * mid_point); + SDL_RenderCopy(mask_renderer, round_texture, NULL, &cap_dst); + cap_dst.x = mid_point + lv_sdl_round(SDL_cos(key.angle * M_PI / 180.0f) * mid_point); + cap_dst.y = mid_point + lv_sdl_round(SDL_sin(key.angle * M_PI / 180.0f) * mid_point); + SDL_RenderCopy(mask_renderer, round_texture, NULL, &cap_dst); + SDL_DestroyTexture(round_texture); + SDL_DestroyRenderer(mask_renderer); + } + texture = SDL_CreateTextureFromSurface(renderer, ark_mask); + SDL_FreeSurface(ark_mask); + + SDL_assert(texture); + // lv_gpu_draw_cache_put(&key, sizeof(key), texture); + } + + SDL_Color arc_color; + lv_color_to_sdl_color(&dsc->color, &arc_color); + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + SDL_SetTextureAlphaMod(texture, dsc->opa); + SDL_SetTextureColorMod(texture, arc_color.r, arc_color.g, arc_color.b); + SDL_RenderSetClipRect(renderer, &clip_rect); + SDL_RenderCopyEx(renderer, texture, NULL, &area_out_rect, start_angle, NULL, SDL_FLIP_NONE); + SDL_DestroyTexture(texture); +} + +#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_blend.c b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_blend.c new file mode 100644 index 000000000..f45ae118e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_blend.c @@ -0,0 +1,102 @@ +/** + * @file lv_gpu_sdl_draw_blend.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include "../../draw/lv_draw_blend.h" +#include "../../core/lv_refr.h" +#include "lv_gpu_sdl_texture_cache.h" +#include "lv_gpu_sdl_utils.h" +#include "lv_gpu_sdl_mask.h" + +#include LV_GPU_SDL_INCLUDE_PATH + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void _lv_blend_fill(const lv_area_t * clip_area, const lv_area_t * fill_area, lv_color_t color, + lv_opa_t * mask, lv_draw_mask_res_t mask_res, lv_opa_t opa, lv_blend_mode_t mode) +{ + /*Do not draw transparent things*/ + if(opa < LV_OPA_MIN) return; + if(mask_res == LV_DRAW_MASK_RES_TRANSP) return; + + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Renderer * renderer = (SDL_Renderer *) disp->driver->user_data; + + /*Get clipped fill area which is the real draw area. + *It is always the same or inside `fill_area`*/ + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, clip_area, fill_area)) return; + + SDL_Rect draw_area_rect; + lv_area_to_sdl_rect(&draw_area, &draw_area_rect); + if(mask) { + SDL_Surface * mask_surface = lv_sdl_create_mask_surface(mask, lv_area_get_width(&draw_area), + lv_area_get_height(&draw_area), + lv_area_get_width(&draw_area)); + SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, mask_surface); + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + SDL_SetTextureAlphaMod(texture, opa); + SDL_SetTextureColorMod(texture, color.ch.red, color.ch.green, color.ch.blue); + SDL_RenderSetClipRect(renderer, &draw_area_rect); + SDL_RenderCopy(renderer, texture, NULL, &draw_area_rect); + SDL_DestroyTexture(texture); + SDL_FreeSurface(mask_surface); + } + else { + SDL_SetRenderDrawColor(renderer, color.ch.red, color.ch.green, color.ch.blue, opa); + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); + SDL_RenderSetClipRect(renderer, &draw_area_rect); + SDL_RenderFillRect(renderer, &draw_area_rect); + } +} + +void _lv_blend_map(const lv_area_t * clip_area, const lv_area_t * map_area, + const lv_color_t * map_buf, lv_opa_t * mask, lv_draw_mask_res_t mask_res, lv_opa_t opa, + lv_blend_mode_t mode) +{ + LV_UNUSED(clip_area); + LV_UNUSED(map_area); + LV_UNUSED(map_buf); + LV_UNUSED(mask); + LV_UNUSED(mask_res); + LV_UNUSED(opa); + LV_UNUSED(mode); + +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_img.c b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_img.c new file mode 100644 index 000000000..d777b42d1 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_img.c @@ -0,0 +1,171 @@ +/** + * @file lv_gpu_sdl_draw_img.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include "../../core/lv_refr.h" +#include "lv_gpu_sdl_utils.h" +#include "lv_gpu_sdl_lru.h" +#include "lv_gpu_sdl_texture_cache.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + + +/********************** + * STATIC PROTOTYPES + **********************/ + +static SDL_Texture * upload_img_texture(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc); + +static SDL_Texture * upload_img_texture_fallback(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * src, + const lv_draw_img_dsc_t * draw_dsc) +{ + if(draw_dsc->opa <= LV_OPA_MIN) return; + + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Renderer * renderer = (SDL_Renderer *) disp->driver->user_data; + + size_t key_size; + lv_gpu_sdl_cache_key_head_img_t * key = lv_gpu_sdl_img_cache_key_create(src, draw_dsc->frame_id, &key_size); + bool texture_found = false; + SDL_Texture * texture = lv_gpu_draw_cache_get(key, key_size, &texture_found); + if(!texture_found) { + _lv_img_cache_entry_t * cdsc = _lv_img_cache_open(src, draw_dsc->recolor, draw_dsc->frame_id); + lv_gpu_sdl_cache_flag_t tex_flags = 0; + if(cdsc) { + lv_img_decoder_dsc_t * dsc = &cdsc->dec_dsc; + if(dsc->user_data && SDL_memcmp(dsc->user_data, LV_GPU_SDL_DEC_DSC_TEXTURE_HEAD, 8) == 0) { + texture = ((lv_gpu_sdl_dec_dsc_userdata_t *) dsc->user_data)->texture; + tex_flags |= LV_GPU_SDL_CACHE_FLAG_MANAGED; + } + else { + texture = upload_img_texture(renderer, dsc); + } +#if LV_IMG_CACHE_DEF_SIZE == 0 + lv_img_decoder_close(dsc); +#endif + } + if(texture && cdsc) { + lv_img_header_t * header = SDL_malloc(sizeof(lv_img_header_t)); + SDL_memcpy(header, &cdsc->dec_dsc.header, sizeof(lv_img_header_t)); + lv_gpu_draw_cache_put_advanced(key, key_size, texture, header, SDL_free, tex_flags); + } + else { + lv_gpu_draw_cache_put(key, key_size, NULL); + } + } + SDL_free(key); + if(!texture) { + return; + } + + SDL_Rect mask_rect, coords_rect; + lv_area_to_sdl_rect(mask, &mask_rect); + lv_area_to_sdl_rect(coords, &coords_rect); + lv_area_zoom_to_sdl_rect(coords, &coords_rect, draw_dsc->zoom, &draw_dsc->pivot); + + SDL_Point pivot = {.x = draw_dsc->pivot.x, .y = draw_dsc->pivot.y}; + SDL_SetTextureAlphaMod(texture, draw_dsc->opa); + SDL_SetTextureColorMod(texture, 0xFF, 0xFF, 0xFF); + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + SDL_RenderSetClipRect(renderer, &mask_rect); + + SDL_Color recolor; + lv_color_to_sdl_color(&draw_dsc->recolor, &recolor); + /*Draw original image if not fully recolored*/ + /*TODO: what if the image is translucent as well?*/ + if(draw_dsc->recolor_opa < LV_OPA_MAX) { + SDL_RenderCopyEx(renderer, texture, NULL, &coords_rect, draw_dsc->angle, &pivot, SDL_FLIP_NONE); + } + + SDL_SetTextureColorMod(texture, recolor.r, recolor.g, recolor.b); + if(draw_dsc->recolor_opa >= LV_OPA_MAX) { + /*Draw fully colored image*/ + SDL_SetTextureAlphaMod(texture, draw_dsc->opa); + SDL_RenderCopyEx(renderer, texture, NULL, &coords_rect, draw_dsc->angle, &pivot, SDL_FLIP_NONE); + } + else if(draw_dsc->recolor_opa >= LV_OPA_MIN) { + SDL_SetTextureAlphaMod(texture, draw_dsc->recolor_opa); + SDL_RenderCopyEx(renderer, texture, NULL, &coords_rect, draw_dsc->angle, &pivot, SDL_FLIP_NONE); + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static SDL_Texture * upload_img_texture(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc) +{ + if(!dsc->img_data) { + return upload_img_texture_fallback(renderer, dsc); + } + bool chroma_keyed = dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED; + uint32_t h = dsc->header.h; + uint32_t w = dsc->header.w; + void * data = (void *) dsc->img_data; + Uint32 rmask = 0x00FF0000; + Uint32 gmask = 0x0000FF00; + Uint32 bmask = 0x000000FF; + Uint32 amask = 0xFF000000; + if(chroma_keyed) { + amask = 0x00; + } + SDL_Surface * surface = SDL_CreateRGBSurfaceFrom(data, w, h, LV_COLOR_DEPTH, w * LV_COLOR_DEPTH / 8, + rmask, gmask, bmask, amask); + SDL_SetColorKey(surface, chroma_keyed, lv_color_to32(LV_COLOR_CHROMA_KEY)); + SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface); + SDL_FreeSurface(surface); + return texture; +} + +static SDL_Texture * upload_img_texture_fallback(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc) +{ + lv_coord_t h = dsc->header.h; + lv_coord_t w = dsc->header.w; + uint8_t * data = lv_mem_buf_get(w * h * sizeof(lv_color_t)); + for(lv_coord_t y = 0; y < h; y++) { + lv_img_decoder_read_line(dsc, 0, y, w, &data[y * w * sizeof(lv_color_t)]); + } + Uint32 rmask = 0x00FF0000; + Uint32 gmask = 0x0000FF00; + Uint32 bmask = 0x000000FF; + Uint32 amask = 0xFF000000; + SDL_Surface * surface = SDL_CreateRGBSurfaceFrom(data, w, h, LV_COLOR_DEPTH, w * LV_COLOR_DEPTH / 8, + rmask, gmask, bmask, amask); + SDL_SetColorKey(surface, SDL_TRUE, lv_color_to32(LV_COLOR_CHROMA_KEY)); + SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface); + SDL_FreeSurface(surface); + lv_mem_buf_release(data); + return texture; +} + + +#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_label.c b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_label.c new file mode 100644 index 000000000..e87773e53 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_label.c @@ -0,0 +1,332 @@ +/** + * @file lv_gpu_sdl_draw_label.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include "../../draw/lv_draw_label.h" +#include "../../font/lv_font_fmt_txt.h" +#include "../../core/lv_refr.h" +#include "../../misc/lv_utils.h" + +#include LV_GPU_SDL_INCLUDE_PATH + +#include "lv_gpu_sdl_utils.h" +#include "lv_gpu_sdl_texture_cache.h" +#include "lv_gpu_sdl_mask.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct lv_sdl_font_atlas_t { + SDL_Rect * pos; +} lv_sdl_font_atlas_t; + +typedef struct { + lv_gpu_cache_key_magic_t magic; + const lv_font_t * font_p; + uint32_t cmap_index; +} lv_font_key_t; + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void draw_letter_masked(SDL_Renderer * renderer, SDL_Texture * atlas, SDL_Rect * src, SDL_Rect * dst, + SDL_Rect * clip, lv_color_t color, lv_opa_t opa); + +static void font_atlas_free(lv_sdl_font_atlas_t * atlas); + +static SDL_Texture * font_atlas_bake(SDL_Renderer * renderer, const lv_font_t * font_p, uint32_t cmap_idx, + lv_sdl_font_atlas_t * atlas); + +static int32_t unicode_list_compare(const void * ref, const void * element); + +static bool font_cmap_find_index(const lv_font_fmt_txt_dsc_t * dsc, uint32_t letter, uint32_t * cmap_index, + uint32_t * char_index); + +static lv_font_key_t font_key_create(const lv_font_t * font_p, uint32_t cmap_index); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * clip_area, + const lv_font_t * font_p, uint32_t letter, lv_color_t color, lv_opa_t opa, + lv_blend_mode_t blend_mode) +{ + if(opa < LV_OPA_MIN) return; + if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; + + if(font_p == NULL) { + LV_LOG_WARN("lv_draw_letter: font is NULL"); + return; + } + + lv_font_glyph_dsc_t g; + bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0'); + if(g_ret == false) { + /*Add warning if the dsc is not found + *but do not print warning for non printable ASCII chars (e.g. '\n')*/ + if(letter >= 0x20 && + letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/ + letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/ + LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%X", letter); + } + return; + } + + /*Don't draw anything if the character is empty. E.g. space*/ + if((g.box_h == 0) || (g.box_w == 0)) return; + + int32_t pos_x = pos_p->x + g.ofs_x; + int32_t pos_y = pos_p->y + (font_p->line_height - font_p->base_line) - g.box_h - g.ofs_y; + + /*If the letter is completely out of mask don't draw it*/ + if(pos_x + g.box_w < clip_area->x1 || + pos_x > clip_area->x2 || + pos_y + g.box_h < clip_area->y1 || + pos_y > clip_area->y2) { + return; + } + lv_area_t dst = {pos_x, pos_y, pos_x + g.box_w - 1, pos_y + g.box_h - 1}; + uint32_t atlas_index; + uint32_t cmap_index; + if(!font_cmap_find_index(font_p->dsc, letter, &cmap_index, &atlas_index)) { + return; + } + lv_font_key_t key = font_key_create(font_p, cmap_index); + lv_sdl_font_atlas_t * atlas = NULL; + bool found = false; + SDL_Texture * texture = lv_gpu_draw_cache_get_with_userdata(&key, sizeof(key), &found, (void **) &atlas); + + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Renderer * renderer = (SDL_Renderer *) disp->driver->user_data; + + if(!found) { + atlas = SDL_malloc(sizeof(lv_sdl_font_atlas_t)); + texture = font_atlas_bake(renderer, font_p, cmap_index, atlas); + lv_gpu_draw_cache_put_advanced(&key, sizeof(key), texture, atlas, (lv_lru_free_t *) font_atlas_free, 0); + } + if(texture == NULL) return; + SDL_Rect dstrect = {.x = pos_x, .y = pos_y, .w = g.box_w, .h = g.box_h}; + + SDL_Rect clip_area_rect; + lv_area_to_sdl_rect(clip_area, &clip_area_rect); + + if(lv_draw_mask_is_any(&dst)) { + draw_letter_masked(renderer, texture, &atlas->pos[atlas_index], &dstrect, &clip_area_rect, color, opa); + return; + } + + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + SDL_SetTextureAlphaMod(texture, opa); + SDL_SetTextureColorMod(texture, color.ch.red, color.ch.green, color.ch.blue); + SDL_RenderSetClipRect(renderer, &clip_area_rect); + SDL_RenderCopy(renderer, texture, &atlas->pos[atlas_index], &dstrect); +} + + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void draw_letter_masked(SDL_Renderer * renderer, SDL_Texture * atlas, SDL_Rect * src, SDL_Rect * dst, + SDL_Rect * clip, lv_color_t color, lv_opa_t opa) +{ + SDL_Texture * screen = SDL_GetRenderTarget(renderer); + + lv_area_t mask_area = {.x1 = dst->x, .x2 = dst->x + dst->w - 1, .y1 = dst->y, .y2 = dst->y + dst->h - 1}; + SDL_Texture * content = lv_gpu_temp_texture_obtain(renderer, dst->w, dst->h); + SDL_SetTextureBlendMode(content, SDL_BLENDMODE_NONE); + SDL_SetRenderTarget(renderer, content); + SDL_RenderSetClipRect(renderer, NULL); + + /* Replace texture with clip mask */ + SDL_Rect mask_rect = {.w = dst->w, .h = dst->h, .x = 0, .y = 0}; + SDL_Texture * mask = lv_sdl_gen_mask_texture(renderer, &mask_area, NULL, 0); + SDL_SetTextureBlendMode(mask, SDL_BLENDMODE_NONE); + SDL_RenderCopy(renderer, mask, NULL, &mask_rect); + + /* Multiply with font atlas */ + SDL_SetTextureAlphaMod(atlas, 0xFF); + SDL_SetTextureColorMod(atlas, 0xFF, 0xFF, 0xFF); +#if SDL_VERSION_ATLEAST(2, 0, 6) + SDL_BlendMode mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ZERO, + SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_ZERO, + SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDOPERATION_ADD); + SDL_SetTextureBlendMode(atlas, mode); +#else + SDL_SetTextureBlendMode(atlas, SDL_BLENDMODE_BLEND); +#endif + SDL_RenderCopy(renderer, atlas, src, &mask_rect); + + /* Draw composited part on screen */ + SDL_SetTextureBlendMode(content, SDL_BLENDMODE_BLEND); + SDL_SetTextureAlphaMod(content, opa); + SDL_SetTextureColorMod(content, color.ch.red, color.ch.green, color.ch.blue); + + SDL_SetRenderTarget(renderer, screen); + SDL_RenderSetClipRect(renderer, clip); + SDL_RenderCopy(renderer, content, &mask_rect, dst); + SDL_DestroyTexture(mask); +} + +SDL_Texture * font_atlas_bake(SDL_Renderer * renderer, const lv_font_t * font_p, uint32_t cmap_idx, + lv_sdl_font_atlas_t * atlas) +{ + /* Clear atlas struct */ + SDL_memset(atlas, 0, sizeof(lv_sdl_font_atlas_t)); + const lv_font_fmt_txt_dsc_t * dsc = (lv_font_fmt_txt_dsc_t *) font_p->dsc; + if(dsc->bitmap_format != LV_FONT_FMT_TXT_PLAIN) { + /* we don't support compressed font at this moment */ + return NULL; + } + const lv_font_fmt_txt_cmap_t * cmap = &dsc->cmaps[cmap_idx]; + int glyph_count = cmap->type == LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY ? cmap->range_length : cmap->list_length; + int atlas_size = 0; + while(atlas_size * atlas_size < glyph_count) { + atlas_size++; + } + int atlas_w = font_p->line_height * atlas_size; + int atlas_h = font_p->line_height * (glyph_count / atlas_size + 1); + if(atlas_w > 2048 || atlas_h > 2048) { + /*This atlas texture will be too large to load*/ + return NULL; + } + lv_opa_t * s1 = lv_mem_buf_get(atlas_w * atlas_h * sizeof(lv_opa_t)); + atlas->pos = SDL_malloc(sizeof(SDL_Rect) * glyph_count); + int atlas_y = 0; + int atlas_x = 0; + for(int i = 0; i < glyph_count; i++) { + int glyph_idx = cmap->glyph_id_start + i; + switch(cmap->type) { + case LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL: { + const uint8_t * gid_ofs_8 = cmap->glyph_id_ofs_list; + glyph_idx = gid_ofs_8[i]; + break; + } + case LV_FONT_FMT_TXT_CMAP_SPARSE_FULL: { + const uint16_t * gid_ofs_16 = cmap->glyph_id_ofs_list; + glyph_idx = gid_ofs_16[i]; + break; + } + } + const lv_font_fmt_txt_glyph_dsc_t * gd = &dsc->glyph_dsc[glyph_idx]; + if(atlas_x + gd->box_w >= atlas_w) { + atlas_x = 0; + atlas_y += font_p->line_height; + } + SDL_Rect * rect = &atlas->pos[i]; + rect->x = atlas_x; + rect->y = atlas_y; + rect->w = gd->box_w; + rect->h = gd->box_h; + if(gd->box_w <= 0 || gd->box_h <= 0) { + continue; + } + lv_sdl_to_8bpp(&s1[rect->y * atlas_w + rect->x], &dsc->glyph_bitmap[gd->bitmap_index], rect->w, + rect->h, atlas_w, dsc->bpp); + atlas_x += gd->box_w; + } + SDL_Surface * mask = lv_sdl_create_mask_surface(s1, atlas_w, atlas_h, atlas_w); + SDL_Texture * result = SDL_CreateTextureFromSurface(renderer, mask); + SDL_FreeSurface(mask); + lv_mem_buf_release(s1); + + if(!result) { + if(atlas->pos) { + SDL_free(atlas->pos); + } + SDL_memset(atlas, 0, sizeof(lv_sdl_font_atlas_t)); + } + return result; +} + +static void font_atlas_free(lv_sdl_font_atlas_t * atlas) +{ + if(atlas->pos) { + SDL_free(atlas->pos); + } + SDL_free(atlas); +} + +static bool font_cmap_find_index(const lv_font_fmt_txt_dsc_t * dsc, uint32_t letter, uint32_t * cmap_index, + uint32_t * char_index) +{ + for(int i = 0; i < dsc->cmap_num; i++) { + const lv_font_fmt_txt_cmap_t * cmap = &dsc->cmaps[i]; + /*Relative code point*/ + uint32_t rcp = letter - cmap->range_start; + if(rcp > cmap->range_length) continue; + if(cmap->type == LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY) { + *cmap_index = i; + *char_index = rcp; + return true; + } + else if(cmap->type == LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL) { + *cmap_index = i; + *char_index = rcp; + return true; + } + else if(cmap->type == LV_FONT_FMT_TXT_CMAP_SPARSE_TINY) { + uint16_t key = rcp; + uint16_t * p = _lv_utils_bsearch(&key, cmap->unicode_list, cmap->list_length, + sizeof(cmap->unicode_list[0]), unicode_list_compare); + if(!p) continue; + + *cmap_index = i; + *char_index = p - cmap->unicode_list; + return true; + } + else if(cmap->type == LV_FONT_FMT_TXT_CMAP_SPARSE_FULL) { + uint16_t key = rcp; + uint16_t * p = _lv_utils_bsearch(&key, cmap->unicode_list, cmap->list_length, + sizeof(cmap->unicode_list[0]), unicode_list_compare); + if(!p) continue; + + *cmap_index = i; + *char_index = p - cmap->unicode_list; + return true; + } + } + return 0; +} + +static int32_t unicode_list_compare(const void * ref, const void * element) +{ + return ((int32_t)(*(uint16_t *) ref)) - ((int32_t)(*(uint16_t *) element)); +} + +static lv_font_key_t font_key_create(const lv_font_t * font_p, uint32_t cmap_index) +{ + lv_font_key_t key; + /* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */ + SDL_memset(&key, 0, sizeof(key)); + key.magic = LV_GPU_CACHE_KEY_MAGIC_FONT; + key.font_p = font_p; + key.cmap_index = cmap_index; + return key; +} + +#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_line.c b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_line.c new file mode 100644 index 000000000..d1b3f362a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_line.c @@ -0,0 +1,158 @@ +/** + * @file lv_gpu_sdl_draw_line.c + * + * This implementation does not functioning properly so it's not enabled + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include LV_GPU_SDL_INCLUDE_PATH +#include "../../core/lv_refr.h" +#include "lv_gpu_sdl_utils.h" +#include "lv_gpu_sdl_lru.h" +#include "lv_gpu_sdl_texture_cache.h" +#include "lv_gpu_sdl_mask.h" + +#ifndef M_PI + #include +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_gpu_cache_key_magic_t magic; + lv_coord_t length; + lv_coord_t thickness; +} lv_draw_line_key_t; + +static lv_draw_line_key_t line_key_create(lv_coord_t length, lv_coord_t thickness); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_line2(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, + const lv_draw_line_dsc_t * dsc) +{ + if(dsc->width == 0) return; + if(dsc->opa <= LV_OPA_MIN) return; + + if(point1->x == point2->x && point1->y == point2->y) return; + + lv_area_t clip_line; + clip_line.x1 = LV_MIN(point1->x, point2->x) - dsc->width / 2; + clip_line.x2 = LV_MAX(point1->x, point2->x) + dsc->width / 2; + clip_line.y1 = LV_MIN(point1->y, point2->y) - dsc->width / 2; + clip_line.y2 = LV_MAX(point1->y, point2->y) + dsc->width / 2; + + if(!_lv_area_intersect(&clip_line, &clip_line, clip)) return; + + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Renderer * renderer = (SDL_Renderer *) disp->driver->user_data; + + SDL_Color line_color; + lv_color_to_sdl_color(&dsc->color, &line_color); + + int length = lv_sdl_round(SDL_sqrt(SDL_pow(point2->y - point1->y + 1, 2) + SDL_pow(point2->x - point1->x + 1, 2))); + lv_coord_t thickness = dsc->width; + lv_draw_line_key_t key = line_key_create(length, thickness); + lv_area_t coords = {1, 1, length, dsc->width}; + lv_area_t tex_coords; + lv_area_copy(&tex_coords, &coords); + lv_area_increase(&tex_coords, 1, 1); + + SDL_Texture * texture = lv_gpu_draw_cache_get(&key, sizeof(key), NULL); + + if(texture == NULL) { + lv_draw_mask_radius_param_t mask_rout_param; + lv_draw_mask_radius_init(&mask_rout_param, &coords, 0, false); + int16_t mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); + texture = lv_sdl_gen_mask_texture(renderer, &tex_coords, &mask_rout_id, 1); + lv_draw_mask_remove_id(mask_rout_id); + SDL_assert(texture); + lv_gpu_draw_cache_put(&key, sizeof(key), texture); + } + double angle = SDL_atan2(point2->y - point1->y, point2->x - point1->x) * 180 / M_PI; + + SDL_Rect clip_rect; + lv_area_to_sdl_rect(&clip_line, &clip_rect); + + + SDL_Texture * screen = SDL_GetRenderTarget(renderer); + + SDL_Texture * content = lv_gpu_temp_texture_obtain(renderer, clip_rect.w, clip_rect.h); + SDL_SetTextureBlendMode(content, SDL_BLENDMODE_BLEND); + SDL_SetRenderTarget(renderer, content); + SDL_RenderSetClipRect(renderer, NULL); + + // /* Replace texture with clip mask */ + SDL_Rect mask_rect = {.w = clip_rect.w, .h = clip_rect.h, .x = 0, .y = 0}; + // SDL_Texture *mask = lv_sdl_gen_mask_texture(renderer, &clip_line, NULL, 0); + // SDL_SetTextureBlendMode(mask, SDL_BLENDMODE_NONE); + //// SDL_RenderCopy(renderer, mask, NULL, &mask_rect); + // + // SDL_SetTextureAlphaMod(texture, 0xFF); + // SDL_SetTextureColorMod(texture, 0xFF, 0xFF, 0xFF); + //#if SDL_VERSION_ATLEAST(2, 0, 6) + // SDL_BlendMode mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ZERO, + // SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_ZERO, + // SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDOPERATION_ADD); + // SDL_SetTextureBlendMode(texture, mode); + // SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_NONE); + //#else + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_NONE); + //#endif + + SDL_Rect coords_rect; + lv_area_to_sdl_rect(&tex_coords, &coords_rect); + coords_rect.x = 0 - coords_rect.h / 2; + coords_rect.y = 0 - coords_rect.h / 2; + SDL_Point center = {coords_rect.h / 2, coords_rect.h / 2}; + SDL_RenderCopyEx(renderer, texture, NULL, &coords_rect, angle, ¢er, SDL_FLIP_NONE); + // + // /* Draw composited part on screen */ + SDL_SetTextureBlendMode(content, SDL_BLENDMODE_NONE); + SDL_SetTextureAlphaMod(content, dsc->opa); + SDL_SetTextureColorMod(content, line_color.r, line_color.g, line_color.b); + // + SDL_SetRenderTarget(renderer, screen); + // SDL_RenderSetClipRect(renderer, &clip_rect); + SDL_RenderSetClipRect(renderer, NULL); + SDL_RenderCopy(renderer, content, &mask_rect, &clip_rect); + // SDL_DestroyTexture(mask); +} + +static lv_draw_line_key_t line_key_create(lv_coord_t length, lv_coord_t thickness) +{ + lv_draw_line_key_t key; + /* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */ + SDL_memset(&key, 0, sizeof(key)); + key.magic = LV_GPU_CACHE_KEY_MAGIC_LINE; + key.length = length; + key.thickness = thickness; + return key; +} + + +#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_rect.c b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_rect.c new file mode 100644 index 000000000..689fb3d73 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_rect.c @@ -0,0 +1,733 @@ +/** + * @file lv_gpu_sdl_draw_rect.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include "../../draw/lv_draw_rect.h" +#include "../../hal/lv_hal_disp.h" +#include "../../core/lv_refr.h" +#include "lv_gpu_sdl_utils.h" +#include "lv_gpu_sdl_lru.h" +#include "lv_gpu_sdl_texture_cache.h" +#include "lv_gpu_sdl_mask.h" +#include "lv_gpu_sdl_stack_blur.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_gpu_cache_key_magic_t magic; + lv_coord_t radius; + lv_coord_t size; +} lv_draw_rect_bg_key_t; + +typedef struct { + lv_gpu_cache_key_magic_t magic; + lv_coord_t radius; + lv_coord_t size; + lv_coord_t blur; +} lv_draw_rect_shadow_key_t; + +typedef struct { + lv_gpu_cache_key_magic_t magic; + lv_coord_t rout, rin; + lv_coord_t thickness; + lv_coord_t size; + lv_border_side_t side; +} lv_draw_rect_border_key_t; + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void draw_bg_color(SDL_Renderer * renderer, const lv_area_t * coords, const lv_draw_rect_dsc_t * dsc); + +static void draw_bg_img(const lv_area_t * coords, const lv_area_t * clip, + const lv_draw_rect_dsc_t * dsc); + +static void draw_border(SDL_Renderer * renderer, const lv_area_t * coords, const lv_draw_rect_dsc_t * dsc); + +static void draw_shadow(SDL_Renderer * renderer, const lv_area_t * coords, const lv_area_t * clip, + const lv_draw_rect_dsc_t * dsc); + +static void draw_outline(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc); + +static void draw_border_generic(const lv_area_t * outer_area, const lv_area_t * inner_area, lv_coord_t rout, + lv_coord_t rin, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode); + +static void draw_border_simple(const lv_area_t * outer_area, const lv_area_t * inner_area, lv_color_t color, + lv_opa_t opa); + +static void draw_rect_masked(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc); + +static void draw_rect_masked_simple(const lv_area_t * coords, const lv_area_t * mask, const lv_draw_rect_dsc_t * dsc); + +static void frag_render_corners(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size, + const lv_area_t * coords); + +static void frag_render_borders(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size, + const lv_area_t * coords); + +static void frag_render_center(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size, + const lv_area_t * coords); + +static lv_draw_rect_bg_key_t rect_bg_key_create(lv_coord_t radius, lv_coord_t size); + +static lv_draw_rect_shadow_key_t rect_shadow_key_create(lv_coord_t radius, lv_coord_t size, lv_coord_t blur); + +static lv_draw_rect_border_key_t rect_border_key_create(lv_coord_t rout, lv_coord_t rin, lv_coord_t thickness, + lv_coord_t size, lv_border_side_t side); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ +#define SKIP_BORDER(dsc) ((dsc)->border_opa <= LV_OPA_MIN || (dsc)->border_width == 0 || (dsc)->border_side == LV_BORDER_SIDE_NONE || (dsc)->border_post) +#define SKIP_SHADOW(dsc) ((dsc)->shadow_width == 0 || (dsc)->shadow_opa <= LV_OPA_MIN || ((dsc)->shadow_width == 1 && (dsc)->shadow_spread <= 0 && (dsc)->shadow_ofs_x == 0 && (dsc)->shadow_ofs_y == 0)) +#define SKIP_IMAGE(dsc) ((dsc)->bg_img_src == NULL || (dsc)->bg_img_opa <= LV_OPA_MIN) +#define SKIP_OUTLINE(dsc) ((dsc)->outline_opa <= LV_OPA_MIN || (dsc)->outline_width == 0) + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_rect(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc) +{ + lv_area_t draw_area; + bool has_draw_content = _lv_area_intersect(&draw_area, coords, clip); + + if(lv_draw_mask_is_any(&draw_area)) { + draw_rect_masked(coords, clip, dsc); + return; + } + + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Renderer * renderer = (SDL_Renderer *) disp->driver->user_data; + + + SDL_Rect clip_rect; + lv_area_to_sdl_rect(clip, &clip_rect); + SDL_RenderSetClipRect(renderer, &clip_rect); + draw_shadow(renderer, coords, clip, dsc); + /* Shadows and outlines will also draw in extended area */ + if(has_draw_content) { + draw_bg_color(renderer, coords, dsc); + draw_bg_img(coords, clip, dsc); + draw_border(renderer, coords, dsc); + } + draw_outline(coords, clip, dsc); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void draw_bg_color(SDL_Renderer * renderer, const lv_area_t * coords, const lv_draw_rect_dsc_t * dsc) +{ + SDL_Color bg_color; + lv_color_to_sdl_color(&dsc->bg_color, &bg_color); + lv_coord_t radius = dsc->radius; + if(radius > 0) { + /*A small texture with a quarter of the rect is enough*/ + lv_coord_t bg_w = lv_area_get_width(coords), bg_h = lv_area_get_height(coords), bg_min = LV_MIN(bg_w, bg_h); + /* If size isn't times of 2, increase 1 px */ + lv_coord_t min_half = bg_min % 2 == 0 ? bg_min / 2 : bg_min / 2 + 1; + lv_coord_t frag_size = radius == LV_RADIUS_CIRCLE ? min_half : LV_MIN(radius + 1, min_half); + lv_draw_rect_bg_key_t key = rect_bg_key_create(radius, frag_size); + lv_area_t coords_frag; + lv_area_copy(&coords_frag, coords); + lv_area_set_width(&coords_frag, frag_size); + lv_area_set_height(&coords_frag, frag_size); + SDL_Texture * texture = lv_gpu_draw_cache_get(&key, sizeof(key), NULL); + if(texture == NULL) { + lv_draw_mask_radius_param_t mask_rout_param; + lv_draw_mask_radius_init(&mask_rout_param, coords, radius, false); + int16_t mask_id = lv_draw_mask_add(&mask_rout_param, NULL); + texture = lv_sdl_gen_mask_texture(renderer, &coords_frag, &mask_id, 1); + lv_draw_mask_remove_id(mask_id); + SDL_assert(texture); + lv_gpu_draw_cache_put(&key, sizeof(key), texture); + } + + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + SDL_SetTextureAlphaMod(texture, dsc->bg_opa); + SDL_SetTextureColorMod(texture, bg_color.r, bg_color.g, bg_color.b); + frag_render_corners(renderer, texture, frag_size, coords); + frag_render_borders(renderer, texture, frag_size, coords); + frag_render_center(renderer, texture, frag_size, coords); + } + else { + SDL_Rect coords_rect; + lv_area_to_sdl_rect(coords, &coords_rect); + SDL_SetRenderDrawColor(renderer, bg_color.r, bg_color.g, bg_color.b, dsc->bg_opa); + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); + SDL_RenderFillRect(renderer, &coords_rect); + } +} + +static void draw_bg_img(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc) +{ + if(SKIP_IMAGE(dsc)) return; + + lv_img_src_t src_type = lv_img_src_get_type(dsc->bg_img_src); + if(src_type == LV_IMG_SRC_SYMBOL) { + lv_point_t size; + lv_txt_get_size(&size, dsc->bg_img_src, dsc->bg_img_symbol_font, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + lv_area_t a; + a.x1 = coords->x1 + lv_area_get_width(coords) / 2 - size.x / 2; + a.x2 = a.x1 + size.x - 1; + a.y1 = coords->y1 + lv_area_get_height(coords) / 2 - size.y / 2; + a.y2 = a.y1 + size.y - 1; + + lv_draw_label_dsc_t label_draw_dsc; + lv_draw_label_dsc_init(&label_draw_dsc); + label_draw_dsc.font = dsc->bg_img_symbol_font; + label_draw_dsc.color = dsc->bg_img_recolor; + label_draw_dsc.opa = dsc->bg_img_opa; + lv_draw_label(&a, clip, &label_draw_dsc, dsc->bg_img_src, NULL); + } + else { + lv_img_header_t header; + size_t key_size; + lv_gpu_sdl_cache_key_head_img_t * key = lv_gpu_sdl_img_cache_key_create(dsc->bg_img_src, 0, &key_size); + bool key_found; + lv_img_header_t * cache_header = NULL; + SDL_Texture * texture = lv_gpu_draw_cache_get_with_userdata(key, key_size, &key_found, (void **) &cache_header); + SDL_free(key); + if(texture) { + header = *cache_header; + } + else if(key_found || lv_img_decoder_get_info(dsc->bg_img_src, &header) != LV_RES_OK) { + /* When cache hit but with negative result, use default decoder. If still fail, return.*/ + LV_LOG_WARN("Couldn't read the background image"); + return; + } + + lv_draw_img_dsc_t img_dsc; + lv_draw_img_dsc_init(&img_dsc); + img_dsc.blend_mode = dsc->blend_mode; + img_dsc.recolor = dsc->bg_img_recolor; + img_dsc.recolor_opa = dsc->bg_img_recolor_opa; + img_dsc.opa = dsc->bg_img_opa; + + /*Center align*/ + if(dsc->bg_img_tiled == false) { + lv_area_t area; + area.x1 = coords->x1 + lv_area_get_width(coords) / 2 - header.w / 2; + area.y1 = coords->y1 + lv_area_get_height(coords) / 2 - header.h / 2; + area.x2 = area.x1 + header.w - 1; + area.y2 = area.y1 + header.h - 1; + + lv_draw_img(&area, clip, dsc->bg_img_src, &img_dsc); + } + else { + lv_area_t area; + area.y1 = coords->y1; + area.y2 = area.y1 + header.h - 1; + + for(; area.y1 <= coords->y2; area.y1 += header.h, area.y2 += header.h) { + + area.x1 = coords->x1; + area.x2 = area.x1 + header.w - 1; + for(; area.x1 <= coords->x2; area.x1 += header.w, area.x2 += header.w) { + lv_draw_img(&area, clip, dsc->bg_img_src, &img_dsc); + } + } + } + } +} + +static void draw_shadow(SDL_Renderer * renderer, const lv_area_t * coords, const lv_area_t * clip, + const lv_draw_rect_dsc_t * dsc) +{ + /*Check whether the shadow is visible*/ + if(SKIP_SHADOW(dsc)) return; + + lv_coord_t sw = dsc->shadow_width; + + lv_area_t core_area; + core_area.x1 = coords->x1 + dsc->shadow_ofs_x - dsc->shadow_spread; + core_area.x2 = coords->x2 + dsc->shadow_ofs_x + dsc->shadow_spread; + core_area.y1 = coords->y1 + dsc->shadow_ofs_y - dsc->shadow_spread; + core_area.y2 = coords->y2 + dsc->shadow_ofs_y + dsc->shadow_spread; + + lv_area_t shadow_area; + shadow_area.x1 = core_area.x1 - sw / 2 - 1; + shadow_area.x2 = core_area.x2 + sw / 2 + 1; + shadow_area.y1 = core_area.y1 - sw / 2 - 1; + shadow_area.y2 = core_area.y2 + sw / 2 + 1; + + lv_opa_t opa = dsc->shadow_opa; + + if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; + + /*Get clipped draw area which is the real draw area. + *It is always the same or inside `shadow_area`*/ + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, &shadow_area, clip)) return; + + SDL_Rect core_area_rect; + lv_area_to_sdl_rect(&shadow_area, &core_area_rect); + + lv_coord_t radius = dsc->radius; + lv_coord_t sh_width = lv_area_get_width(&core_area); + lv_coord_t sh_height = lv_area_get_height(&core_area); + lv_coord_t sh_min = LV_MIN(sh_width, sh_height); + /* If size isn't times of 2, increase 1 px */ + lv_coord_t min_half = sh_min % 2 == 0 ? sh_min / 2 : sh_min / 2 + 1; + /* No matter how big the shadow is, what we need is just a corner */ + lv_coord_t frag_size = radius == LV_RADIUS_CIRCLE ? min_half : LV_MIN(radius + 1, min_half); + /* This is how big the corner is after blurring */ + lv_coord_t blur_frag_size = frag_size + sw + 2; + + lv_draw_rect_shadow_key_t key = rect_shadow_key_create(radius, frag_size, sw); + + lv_area_t blur_frag; + lv_area_copy(&blur_frag, &shadow_area); + lv_area_set_width(&blur_frag, blur_frag_size * 2); + lv_area_set_height(&blur_frag, blur_frag_size * 2); + SDL_Texture * texture = lv_gpu_draw_cache_get(&key, sizeof(key), NULL); + if(texture == NULL) { + lv_draw_mask_radius_param_t mask_rout_param; + lv_draw_mask_radius_init(&mask_rout_param, &core_area, radius, false); + int16_t mask_id = lv_draw_mask_add(&mask_rout_param, NULL); + lv_opa_t * mask_buf = lv_draw_mask_dump(&blur_frag, &mask_id, 1); + lv_stack_blur_grayscale(mask_buf, lv_area_get_width(&blur_frag), lv_area_get_height(&blur_frag), sw / 2 + 1); + texture = lv_sdl_create_mask_texture(renderer, mask_buf, blur_frag_size, blur_frag_size, + lv_area_get_width(&blur_frag)); + lv_mem_buf_release(mask_buf); + lv_draw_mask_remove_id(mask_id); + SDL_assert(texture); + lv_gpu_draw_cache_put(&key, sizeof(key), texture); + } + + SDL_Color shadow_color; + lv_color_to_sdl_color(&dsc->shadow_color, &shadow_color); + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + SDL_SetTextureAlphaMod(texture, opa); + SDL_SetTextureColorMod(texture, shadow_color.r, shadow_color.g, shadow_color.b); + + frag_render_corners(renderer, texture, blur_frag_size, &shadow_area); + frag_render_borders(renderer, texture, blur_frag_size, &shadow_area); + frag_render_center(renderer, texture, blur_frag_size, &shadow_area); +} + + +static void draw_border(SDL_Renderer * renderer, const lv_area_t * coords, const lv_draw_rect_dsc_t * dsc) +{ + if(SKIP_BORDER(dsc)) return; + + SDL_Color border_color; + lv_color_to_sdl_color(&dsc->border_color, &border_color); + + + if(dsc->border_side != LV_BORDER_SIDE_FULL) { + SDL_SetRenderDrawColor(renderer, border_color.r, border_color.g, border_color.b, dsc->border_opa); + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); + for(int w = 0; w <= dsc->border_width; w++) { + if(dsc->border_side & LV_BORDER_SIDE_TOP) { + SDL_RenderDrawLine(renderer, coords->x1, coords->y1 + w, coords->x2, coords->y1 + w); + } + if(dsc->border_side & LV_BORDER_SIDE_BOTTOM) { + SDL_RenderDrawLine(renderer, coords->x1, coords->y2 - w, coords->x2, coords->y2 - w); + } + if(dsc->border_side & LV_BORDER_SIDE_LEFT) { + SDL_RenderDrawLine(renderer, coords->x1 + w, coords->y1, coords->x1 + w, coords->y2); + } + if(dsc->border_side & LV_BORDER_SIDE_RIGHT) { + SDL_RenderDrawLine(renderer, coords->x2 - w, coords->y1, coords->x2 - w, coords->y2); + } + } + } + else { + int32_t coords_w = lv_area_get_width(coords); + int32_t coords_h = lv_area_get_height(coords); + int32_t rout = dsc->radius; + int32_t short_side = LV_MIN(coords_w, coords_h); + if(rout > short_side >> 1) rout = short_side >> 1; + + /*Get the inner area*/ + lv_area_t area_inner; + lv_area_copy(&area_inner, coords); + area_inner.x1 += ((dsc->border_side & LV_BORDER_SIDE_LEFT) ? dsc->border_width : -(dsc->border_width + rout)); + area_inner.x2 -= ((dsc->border_side & LV_BORDER_SIDE_RIGHT) ? dsc->border_width : -(dsc->border_width + rout)); + area_inner.y1 += ((dsc->border_side & LV_BORDER_SIDE_TOP) ? dsc->border_width : -(dsc->border_width + rout)); + area_inner.y2 -= ((dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? dsc->border_width : -(dsc->border_width + rout)); + + lv_coord_t rin = rout - dsc->border_width; + if(rin < 0) rin = 0; + draw_border_generic(coords, &area_inner, rout, rin, dsc->border_color, dsc->border_opa, + dsc->blend_mode); + } +} + +static void draw_outline(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc) +{ + if(SKIP_OUTLINE(dsc)) return; + + lv_opa_t opa = dsc->outline_opa; + + if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; + + /*Get the inner radius*/ + lv_area_t area_inner; + lv_area_copy(&area_inner, coords); + + /*Extend the outline into the background area if it's overlapping the edge*/ + lv_coord_t pad = (dsc->outline_pad == 0 ? (dsc->outline_pad - 1) : dsc->outline_pad); + area_inner.x1 -= pad; + area_inner.y1 -= pad; + area_inner.x2 += pad; + area_inner.y2 += pad; + + lv_area_t area_outer; + lv_area_copy(&area_outer, &area_inner); + + area_outer.x1 -= dsc->outline_width; + area_outer.x2 += dsc->outline_width; + area_outer.y1 -= dsc->outline_width; + area_outer.y2 += dsc->outline_width; + + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, &area_outer, clip)) return; + + int32_t inner_w = lv_area_get_width(&area_inner); + int32_t inner_h = lv_area_get_height(&area_inner); + int32_t rin = dsc->radius; + int32_t short_side = LV_MIN(inner_w, inner_h); + if(rin > short_side >> 1) rin = short_side >> 1; + + lv_coord_t rout = rin + dsc->outline_width; + + draw_border_generic(&area_outer, &area_inner, rout, rin, dsc->outline_color, dsc->outline_opa, + dsc->blend_mode); +} + +static void draw_border_generic(const lv_area_t * outer_area, const lv_area_t * inner_area, lv_coord_t rout, + lv_coord_t rin, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode) +{ + opa = opa >= LV_OPA_COVER ? LV_OPA_COVER : opa; + + if(rout == 0 || rin == 0) { + draw_border_simple(outer_area, inner_area, color, opa); + return; + } + + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Renderer * renderer = (SDL_Renderer *) disp->driver->user_data; + + lv_coord_t border_width = lv_area_get_width(outer_area); + lv_coord_t border_height = lv_area_get_height(outer_area); + lv_coord_t border_min = LV_MIN(border_width, border_height); + lv_coord_t min_half = border_min % 2 == 0 ? border_min / 2 : border_min / 2 + 1; + lv_coord_t frag_size = rout == LV_RADIUS_CIRCLE ? min_half : LV_MIN(rout + 1, min_half); + lv_draw_rect_border_key_t key = rect_border_key_create(rout, rin, inner_area->x1 - outer_area->x1 + 1, + frag_size, LV_BORDER_SIDE_FULL); + SDL_Texture * texture = lv_gpu_draw_cache_get(&key, sizeof(key), NULL); + if(texture == NULL) { + /*Create mask for the outer area*/ + int16_t mask_ids[2] = {LV_MASK_ID_INV, LV_MASK_ID_INV}; + lv_draw_mask_radius_param_t mask_rout_param; + if(rout > 0) { + lv_draw_mask_radius_init(&mask_rout_param, outer_area, rout, false); + mask_ids[0] = lv_draw_mask_add(&mask_rout_param, NULL); + } + + /*Create mask for the inner mask*/ + if(rin < 0) rin = 0; + lv_draw_mask_radius_param_t mask_rin_param; + lv_draw_mask_radius_init(&mask_rin_param, inner_area, rin, true); + mask_ids[1] = lv_draw_mask_add(&mask_rin_param, NULL); + + lv_area_t frag_area; + lv_area_copy(&frag_area, outer_area); + lv_area_set_width(&frag_area, frag_size); + lv_area_set_height(&frag_area, frag_size); + + texture = lv_sdl_gen_mask_texture(renderer, &frag_area, mask_ids, 2); + + lv_draw_mask_remove_id(mask_ids[1]); + lv_draw_mask_remove_id(mask_ids[0]); + SDL_assert(texture); + lv_gpu_draw_cache_put(&key, sizeof(key), texture); + } + + SDL_Rect outer_rect; + lv_area_to_sdl_rect(outer_area, &outer_rect); + SDL_Color color_sdl; + lv_color_to_sdl_color(&color, &color_sdl); + + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + SDL_SetTextureAlphaMod(texture, opa); + SDL_SetTextureColorMod(texture, color_sdl.r, color_sdl.g, color_sdl.b); + + frag_render_corners(renderer, texture, frag_size, outer_area); + frag_render_borders(renderer, texture, frag_size, outer_area); +} + +static void draw_border_simple(const lv_area_t * outer_area, const lv_area_t * inner_area, lv_color_t color, + lv_opa_t opa) +{ + + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Renderer * renderer = (SDL_Renderer *) disp->driver->user_data; + + SDL_Color color_sdl; + lv_color_to_sdl_color(&color, &color_sdl); + + SDL_SetRenderDrawColor(renderer, color_sdl.r, color_sdl.g, color_sdl.b, opa); + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); + SDL_Rect simple_rect; + simple_rect.w = inner_area->x2 - outer_area->x1 + 1; + simple_rect.h = inner_area->y1 - outer_area->y1 + 1; + /*Top border*/ + simple_rect.x = outer_area->x1; + simple_rect.y = outer_area->y1; + SDL_RenderFillRect(renderer, &simple_rect); + /*Bottom border*/ + simple_rect.x = inner_area->x1; + simple_rect.y = inner_area->y2; + SDL_RenderFillRect(renderer, &simple_rect); + + simple_rect.w = inner_area->x1 - outer_area->x1 + 1; + simple_rect.h = inner_area->y2 - outer_area->y1 + 1; + /*Left border*/ + simple_rect.x = outer_area->x1; + simple_rect.y = inner_area->y1; + SDL_RenderFillRect(renderer, &simple_rect); + /*Right border*/ + simple_rect.x = inner_area->x2; + simple_rect.y = outer_area->y1; + SDL_RenderFillRect(renderer, &simple_rect); + +} + +static void frag_render_corners(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size, + const lv_area_t * coords) +{ + lv_coord_t bg_w = lv_area_get_width(coords); + lv_coord_t bg_h = lv_area_get_height(coords); + SDL_Rect srcrect = {0, 0, frag_size, frag_size}; + SDL_Rect dstrect = {.x = coords->x1, .y = coords->y1, .w = frag_size, .h = frag_size}; + /* Upper left */ + SDL_RenderCopyEx(renderer, frag, &srcrect, &dstrect, 0, NULL, SDL_FLIP_NONE); + /* Upper right, clip right edge if too big */ + srcrect.w = dstrect.w = LV_MIN(frag_size, bg_w - frag_size); + dstrect.x = coords->x2 - srcrect.w + 1; + SDL_RenderCopyEx(renderer, frag, &srcrect, &dstrect, 0, NULL, SDL_FLIP_HORIZONTAL); + /* Lower right, clip bottom edge if too big */ + srcrect.h = dstrect.h = LV_MIN(frag_size, bg_h - frag_size); + dstrect.y = coords->y2 - srcrect.h + 1; + SDL_RenderCopyEx(renderer, frag, &srcrect, &dstrect, 0, NULL, SDL_FLIP_HORIZONTAL | SDL_FLIP_VERTICAL); + /* Lower left, right edge should not be clipped */ + srcrect.w = dstrect.w = frag_size; + dstrect.x = coords->x1; + SDL_RenderCopyEx(renderer, frag, &srcrect, &dstrect, 0, NULL, SDL_FLIP_VERTICAL); +} + +static void frag_render_borders(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size, + const lv_area_t * coords) +{ + lv_coord_t bg_w = lv_area_get_width(coords); + lv_coord_t bg_h = lv_area_get_height(coords); + SDL_Rect srcrect; + SDL_Rect dstrect; + /* For top/bottom edges, stretch pixels on the right */ + srcrect.h = dstrect.h = frag_size; + dstrect.w = bg_w - frag_size * 2; + /* Has space to fill */ + if(dstrect.w > 0 && dstrect.h > 0) { + srcrect.w = 1; + srcrect.y = 0; + srcrect.x = frag_size - 1; + dstrect.x = coords->x1 + frag_size; + /* Top edge */ + dstrect.y = coords->y1; + SDL_RenderCopy(renderer, frag, &srcrect, &dstrect); + /* Bottom edge */ + dstrect.y = coords->y2 - frag_size + 1; + if(bg_h < frag_size * 2) { + /* Bottom edge will overlap with top, so decrease it by 1 px */ + srcrect.h = dstrect.h = frag_size - 1; + dstrect.y += 1; + } + if(srcrect.h > 0) { + SDL_RenderCopyEx(renderer, frag, &srcrect, &dstrect, 0, NULL, SDL_FLIP_VERTICAL); + } + } + /* For left/right edges, stretch pixels on the bottom */ + srcrect.w = dstrect.w = frag_size; + dstrect.h = bg_h - frag_size * 2; + if(dstrect.w > 0 && dstrect.h > 0) { + srcrect.h = 1; + srcrect.x = 0; + srcrect.y = frag_size - 1; + dstrect.y = coords->y1 + frag_size; + /* Left edge */ + dstrect.x = coords->x1; + SDL_RenderCopy(renderer, frag, &srcrect, &dstrect); + /* Right edge */ + dstrect.x = coords->x2 - frag_size + 1; + if(bg_w < frag_size * 2) { + /* Right edge will overlap with left, so decrease it by 1 px */ + srcrect.w = dstrect.w = frag_size - 1; + dstrect.x += 1; + } + if(srcrect.w > 0) { + SDL_RenderCopyEx(renderer, frag, &srcrect, &dstrect, 0, NULL, SDL_FLIP_HORIZONTAL); + } + } +} + +static void +frag_render_center(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size, const lv_area_t * coords) +{ + lv_coord_t bg_w = lv_area_get_width(coords); + lv_coord_t bg_h = lv_area_get_height(coords); + SDL_Rect dstrect = {coords->x1 + frag_size, coords->y1 + frag_size, bg_w - frag_size * 2, bg_h - frag_size * 2}; + if(dstrect.w > 0 && dstrect.h > 0) { + SDL_Rect srcrect = {frag_size - 1, frag_size - 1, 1, 1}; + SDL_RenderCopy(renderer, frag, &srcrect, &dstrect); + } +} + +static void draw_rect_masked(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc) +{ + if(dsc->radius <= 0 && SKIP_BORDER(dsc) && SKIP_SHADOW(dsc) && SKIP_IMAGE(dsc) && SKIP_OUTLINE(dsc)) { + draw_rect_masked_simple(coords, clip, dsc); + return; + } + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Renderer * renderer = (SDL_Renderer *) disp->driver->user_data; + + SDL_Texture * screen = SDL_GetRenderTarget(renderer); + + lv_coord_t sw = dsc->shadow_width; + + lv_area_t sh_area = *coords; + lv_area_increase(&sh_area, dsc->shadow_spread + sw / 2 + 1, dsc->shadow_spread + sw / 2 + 1); + lv_area_move(&sh_area, dsc->shadow_ofs_x, dsc->shadow_ofs_y); + + lv_coord_t draw_w = lv_area_get_width(&sh_area); + lv_coord_t draw_h = lv_area_get_height(&sh_area); + /* Render drawing area to an offscreen texture */ + SDL_Texture * content = lv_gpu_temp_texture_obtain(renderer, draw_w, draw_h); + SDL_assert(content); + SDL_SetTextureColorMod(content, 0xFF, 0xFF, 0xFF); + SDL_SetTextureAlphaMod(content, 0xFF); + SDL_SetTextureBlendMode(content, SDL_BLENDMODE_BLEND); + + SDL_SetRenderTarget(renderer, content); + SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0x00); + SDL_RenderClear(renderer); + SDL_RenderSetClipRect(renderer, NULL); + lv_area_t content_coords; + lv_area_copy(&content_coords, coords); + lv_area_move(&content_coords, -sh_area.x1, -sh_area.y1); + + draw_shadow(renderer, &content_coords, clip, dsc); + draw_bg_color(renderer, &content_coords, dsc); + draw_bg_img(&content_coords, clip, dsc); + draw_border(renderer, &content_coords, dsc); + draw_outline(&content_coords, clip, dsc); + + SDL_Texture * clip_mask = lv_sdl_gen_mask_texture(renderer, &sh_area, NULL, 0); + SDL_Rect src_rect = {.w = draw_w, .h = draw_h, .x = 0, .y = 0}; +#if SDL_VERSION_ATLEAST(2, 0, 6) + SDL_BlendMode mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, + SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_ZERO, + SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDOPERATION_ADD); + SDL_SetTextureBlendMode(clip_mask, mode); + SDL_RenderCopy(renderer, clip_mask, NULL, &src_rect); +#endif + + SDL_Rect mask_rect; + SDL_Rect draw_rect; + lv_area_to_sdl_rect(&sh_area, &draw_rect); + lv_area_to_sdl_rect(clip, &mask_rect); + + SDL_SetRenderTarget(renderer, screen); + SDL_RenderSetClipRect(renderer, &mask_rect); + SDL_RenderCopy(renderer, content, &src_rect, &draw_rect); + SDL_DestroyTexture(clip_mask); +} + +static void draw_rect_masked_simple(const lv_area_t * coords, const lv_area_t * mask, const lv_draw_rect_dsc_t * dsc) +{ + SDL_Color bg_color; + lv_color_to_sdl_color(&dsc->bg_color, &bg_color); + + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Renderer * renderer = (SDL_Renderer *) disp->driver->user_data; + + SDL_Surface * indexed = lv_sdl_apply_mask_surface(coords, NULL, 0); + SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, indexed); + + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + SDL_SetTextureAlphaMod(texture, dsc->bg_opa); + SDL_SetTextureColorMod(texture, bg_color.r, bg_color.g, bg_color.b); + + SDL_Rect coords_rect, mask_rect; + lv_area_to_sdl_rect(coords, &coords_rect); + lv_area_to_sdl_rect(mask, &mask_rect); + + SDL_RenderSetClipRect(renderer, &mask_rect); + SDL_RenderCopy(renderer, texture, NULL, &coords_rect); + + SDL_DestroyTexture(texture); + SDL_FreeSurface(indexed); +} + +static lv_draw_rect_bg_key_t rect_bg_key_create(lv_coord_t radius, lv_coord_t size) +{ + lv_draw_rect_bg_key_t key; + SDL_memset(&key, 0, sizeof(key)); + key.magic = LV_GPU_CACHE_KEY_MAGIC_RECT_BG; + key.radius = radius; + key.size = size; + return key; +} + +static lv_draw_rect_shadow_key_t rect_shadow_key_create(lv_coord_t radius, lv_coord_t size, lv_coord_t blur) +{ + lv_draw_rect_shadow_key_t key; + SDL_memset(&key, 0, sizeof(key)); + key.magic = LV_GPU_CACHE_KEY_MAGIC_RECT_SHADOW; + key.radius = radius; + key.size = size; + key.blur = blur; + return key; +} + +static lv_draw_rect_border_key_t rect_border_key_create(lv_coord_t rout, lv_coord_t rin, lv_coord_t thickness, + lv_coord_t size, lv_border_side_t side) +{ + lv_draw_rect_border_key_t key; + /* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */ + SDL_memset(&key, 0, sizeof(key)); + key.magic = LV_GPU_CACHE_KEY_MAGIC_RECT_BORDER; + key.rout = rout; + key.rin = rin; + key.thickness = thickness; + key.size = size; + key.side = side; + return key; +} + +#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_lru.c b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_lru.c new file mode 100644 index 000000000..5e67e8a17 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_lru.c @@ -0,0 +1,375 @@ +/** + * @file lv_gpu_sdl_lru.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL +#include "../../misc/lv_log.h" +#include "lv_gpu_sdl_lru.h" + +#include +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/** + * MurmurHash2 + * @author Austin Appleby + * @see http://sites.google.com/site/murmurhash/ + */ +static uint32_t lv_lru_hash(lv_lru_t * cache, const void * key, uint32_t key_length); + +/** compare a key against an existing item's key */ +static int lv_lru_cmp_keys(lruc_item * item, const void * key, uint32_t key_length); + +/** remove an item and push it to the free items queue */ +static void lv_lru_remove_item(lv_lru_t * cache, lruc_item * prev, lruc_item * item, uint32_t hash_index); + +/** + * remove the least recently used item + * + * @todo we can optimise this by finding the n lru items, where n = required_space / average_length + */ +static void lv_lru_remove_lru_item(lv_lru_t * cache); + +/** pop an existing item off the free queue, or create a new one */ +static lruc_item * lv_lru_pop_or_create_item(lv_lru_t * cache); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/* error helpers */ +#define error_for(conditions, error) if(conditions) {return error;} +#define test_for_missing_cache() error_for(!cache, LV_LRU_MISSING_CACHE) +#define test_for_missing_key() error_for(!key, LV_LRU_MISSING_KEY) +#define test_for_missing_value() error_for(!value || value_length == 0, LV_LRU_MISSING_VALUE) +#define test_for_value_too_large() error_for(value_length > cache->total_memory, LV_LRU_VALUE_TOO_LARGE) + +/* lock helpers */ +#define lock_cache() if(SDL_LockMutex(cache->mutex)) {\ + LV_LOG_WARN("LRU Cache unable to obtain mutex lock");\ + return LV_LRU_LOCK_ERROR;\ + } + +#define unlock_cache() if(SDL_UnlockMutex(cache->mutex)) {\ + LV_LOG_WARN("LRU Cache unable to release mutex lock");\ + return LV_LRU_LOCK_ERROR;\ + } + + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_lru_t * lv_lru_new(uint64_t cache_size, uint32_t average_length, lv_lru_free_t * value_free, + lv_lru_free_t * key_free) +{ + // create the cache + lv_lru_t * cache = (lv_lru_t *) calloc(sizeof(lv_lru_t), 1); + if(!cache) { + LV_LOG_WARN("LRU Cache unable to create cache object"); + return NULL; + } + cache->hash_table_size = cache_size / average_length; + cache->average_item_length = average_length; + cache->free_memory = cache_size; + cache->total_memory = cache_size; + cache->seed = time(NULL); + cache->value_free = value_free ? value_free : free; + cache->key_free = key_free ? key_free : free; + + // size the hash table to a guestimate of the number of slots required (assuming a perfect hash) + cache->items = (lruc_item **) calloc(sizeof(lruc_item *), cache->hash_table_size); + if(!cache->items) { + LV_LOG_WARN("LRU Cache unable to create cache hash table"); + free(cache); + return NULL; + } + + // all cache calls are guarded by a mutex + cache->mutex = SDL_CreateMutex(); + if(!cache->mutex) { + LV_LOG_WARN("LRU Cache unable to initialise mutex"); + free(cache->items); + free(cache); + return NULL; + } + return cache; +} + + +lruc_error lv_lru_free(lv_lru_t * cache) +{ + test_for_missing_cache(); + + // free each of the cached items, and the hash table + lruc_item * item = NULL, *next = NULL; + uint32_t i = 0; + if(cache->items) { + for(; i < cache->hash_table_size; i++) { + item = cache->items[i]; + while(item) { + next = (lruc_item *) item->next; + cache->value_free(item->value); + cache->key_free(item->key); + cache->free_memory += item->value_length; + free(item); + item = next; + } + } + free(cache->items); + } + + if(cache->free_items) { + item = cache->free_items; + while(item) { + next = (lruc_item *) item->next; + free(item); + item = next; + } + } + + // free the cache + if(cache->mutex) { + SDL_DestroyMutex(cache->mutex); + } + free(cache); + + return LV_LRU_NO_ERROR; +} + + +lruc_error lv_lru_set(lv_lru_t * cache, const void * key, size_t key_length, void * value, size_t value_length) +{ + test_for_missing_cache(); + test_for_missing_key(); + test_for_missing_value(); + test_for_value_too_large(); + lock_cache(); + + // see if the key already exists + uint32_t hash_index = lv_lru_hash(cache, key, key_length); + int64_t required = 0; + lruc_item * item = NULL, *prev = NULL; + item = cache->items[hash_index]; + + while(item && lv_lru_cmp_keys(item, key, key_length)) { + prev = item; + item = (lruc_item *) item->next; + } + + if(item) { + // update the value and value_lengths + required = (int)(value_length - item->value_length); + cache->value_free(item->value); + item->value = value; + item->value_length = value_length; + + } + else { + // insert a new item + item = lv_lru_pop_or_create_item(cache); + item->value = value; + item->key = malloc(key_length); + memcpy(item->key, key, key_length); + item->value_length = value_length; + item->key_length = key_length; + required = value_length; + + if(prev) + prev->next = item; + else + cache->items[hash_index] = item; + } + item->access_count = ++cache->access_count; + + // remove as many items as necessary to free enough space + if(required > 0 && required > cache->free_memory) { + while(cache->free_memory < required) + lv_lru_remove_lru_item(cache); + } + cache->free_memory -= required; + unlock_cache(); + return LV_LRU_NO_ERROR; +} + + +lruc_error lv_lru_get(lv_lru_t * cache, const void * key, size_t key_size, void ** value) +{ + test_for_missing_cache(); + test_for_missing_key(); + lock_cache(); + + // loop until we find the item, or hit the end of a chain + uint32_t hash_index = lv_lru_hash(cache, key, key_size); + lruc_item * item = cache->items[hash_index]; + + while(item && lv_lru_cmp_keys(item, key, key_size)) + item = (lruc_item *) item->next; + + if(item) { + *value = item->value; + item->access_count = ++cache->access_count; + } + else { + *value = NULL; + } + + unlock_cache(); + return LV_LRU_NO_ERROR; +} + +lruc_error lv_lru_delete(lv_lru_t * cache, const void * key, size_t key_size) +{ + test_for_missing_cache(); + test_for_missing_key(); + lock_cache(); + + // loop until we find the item, or hit the end of a chain + lruc_item * item = NULL, *prev = NULL; + uint32_t hash_index = lv_lru_hash(cache, key, key_size); + item = cache->items[hash_index]; + + while(item && lv_lru_cmp_keys(item, key, key_size)) { + prev = item; + item = (lruc_item *) item->next; + } + + if(item) { + lv_lru_remove_item(cache, prev, item, hash_index); + } + + unlock_cache(); + return LV_LRU_NO_ERROR; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static uint32_t lv_lru_hash(lv_lru_t * cache, const void * key, uint32_t key_length) +{ + uint32_t m = 0x5bd1e995; + uint32_t r = 24; + uint32_t h = cache->seed ^ key_length; + char * data = (char *) key; + + while(key_length >= 4) { + uint32_t k = *(uint32_t *) data; + k *= m; + k ^= k >> r; + k *= m; + h *= m; + h ^= k; + data += 4; + key_length -= 4; + } + + switch(key_length) { + case 3: + h ^= data[2] << 16; + case 2: + h ^= data[1] << 8; + case 1: + h ^= data[0]; + h *= m; + break; + }; + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + return h % cache->hash_table_size; +} + +static int lv_lru_cmp_keys(lruc_item * item, const void * key, uint32_t key_length) +{ + if(key_length != item->key_length) + return 1; + else + return memcmp(key, item->key, key_length); +} + +static void lv_lru_remove_item(lv_lru_t * cache, lruc_item * prev, lruc_item * item, uint32_t hash_index) +{ + if(prev) + prev->next = item->next; + else + cache->items[hash_index] = (lruc_item *) item->next; + + // free memory and update the free memory counter + cache->free_memory += item->value_length; + cache->value_free(item->value); + cache->key_free(item->key); + + // push the item to the free items queue + memset(item, 0, sizeof(lruc_item)); + item->next = cache->free_items; + cache->free_items = item; +} + +static void lv_lru_remove_lru_item(lv_lru_t * cache) +{ + lruc_item * min_item = NULL, *min_prev = NULL; + lruc_item * item = NULL, *prev = NULL; + uint32_t i = 0, min_index = -1; + uint64_t min_access_count = -1; + + for(; i < cache->hash_table_size; i++) { + item = cache->items[i]; + prev = NULL; + + while(item) { + if(item->access_count < min_access_count || min_access_count == -1) { + min_access_count = item->access_count; + min_item = item; + min_prev = prev; + min_index = i; + } + prev = item; + item = item->next; + } + } + + if(min_item) + lv_lru_remove_item(cache, min_prev, min_item, min_index); +} + +static lruc_item * lv_lru_pop_or_create_item(lv_lru_t * cache) +{ + lruc_item * item = NULL; + + if(cache->free_items) { + item = cache->free_items; + cache->free_items = item->next; + memset(item, 0, sizeof(lruc_item)); + } + else { + item = (lruc_item *) calloc(sizeof(lruc_item), 1); + } + + return item; +} + +#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_lru.h b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_lru.h new file mode 100644 index 000000000..a74e9eeac --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_lru.h @@ -0,0 +1,90 @@ +/** + * @file lv_gpu_sdl_lru.h + * + */ + +#ifndef LV_LRU_H +#define LV_LRU_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#include LV_GPU_SDL_INCLUDE_PATH + +#include +#include + + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef enum { + LV_LRU_NO_ERROR = 0, + LV_LRU_MISSING_CACHE, + LV_LRU_MISSING_KEY, + LV_LRU_MISSING_VALUE, + LV_LRU_LOCK_ERROR, + LV_LRU_VALUE_TOO_LARGE +} lruc_error; + +typedef void (lv_lru_free_t)(void * v); + +typedef struct lruc_item { + void * value; + void * key; + size_t value_length; + size_t key_length; + uint64_t access_count; + struct lruc_item * next; +} lruc_item; + +typedef struct { + lruc_item ** items; + uint64_t access_count; + uint64_t free_memory; + uint64_t total_memory; + uint64_t average_item_length; + uint32_t hash_table_size; + time_t seed; + lv_lru_free_t * value_free; + lv_lru_free_t * key_free; + lruc_item * free_items; + SDL_mutex * mutex; +} lv_lru_t; + + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_lru_t * lv_lru_new(uint64_t cache_size, uint32_t average_length, lv_lru_free_t * value_free, + lv_lru_free_t * key_free); + +lruc_error lv_lru_free(lv_lru_t * cache); + +lruc_error lv_lru_set(lv_lru_t * cache, const void * key, size_t key_length, void * value, size_t value_length); + +lruc_error lv_lru_get(lv_lru_t * cache, const void * key, size_t key_size, void ** value); + +lruc_error lv_lru_delete(lv_lru_t * cache, const void * key, size_t key_size); + +/********************** + * MACROS + **********************/ +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_LRU_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_mask.c b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_mask.c new file mode 100644 index 000000000..263c457c5 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_mask.c @@ -0,0 +1,110 @@ +/** + * @file lv_gpu_sdl_mask.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include "../../draw/lv_draw_mask.h" +#include "../../misc/lv_mem.h" +#include "lv_gpu_sdl_mask.h" +#include "lv_gpu_sdl_utils.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + + +SDL_Surface * lv_sdl_create_mask_surface(lv_opa_t * pixels, lv_coord_t width, lv_coord_t height, lv_coord_t stride) +{ + SDL_Surface * indexed = SDL_CreateRGBSurfaceFrom(pixels, width, height, 8, stride, 0, 0, 0, 0); + SDL_SetSurfacePalette(indexed, lv_sdl_get_grayscale_palette(8)); + SDL_Surface * converted = SDL_ConvertSurfaceFormat(indexed, SDL_PIXELFORMAT_ARGB8888, 0); + SDL_FreeSurface(indexed); + return converted; +} + +SDL_Texture * lv_sdl_create_mask_texture(SDL_Renderer * renderer, lv_opa_t * pixels, lv_coord_t width, + lv_coord_t height, lv_coord_t stride) +{ + SDL_Surface * indexed = lv_sdl_create_mask_surface(pixels, width, height, stride); + SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, indexed); + SDL_FreeSurface(indexed); + return texture; +} + +lv_opa_t * lv_draw_mask_dump(const lv_area_t * coords, const int16_t * ids, int16_t ids_count) +{ + SDL_assert(coords->x2 >= coords->x1); + SDL_assert(coords->y2 >= coords->y1); + lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords); + lv_opa_t * mask_buf = lv_mem_buf_get(w * h); + for(lv_coord_t y = 0; y < h; y++) { + lv_opa_t * line_buf = &mask_buf[y * w]; + lv_memset_ff(line_buf, w); + lv_coord_t abs_x = (lv_coord_t) coords->x1, abs_y = (lv_coord_t)(y + coords->y1), len = (lv_coord_t) w; + lv_draw_mask_res_t res; + if(ids) { + res = lv_draw_mask_apply_ids(line_buf, abs_x, abs_y, len, ids, ids_count); + } + else { + res = lv_draw_mask_apply(line_buf, abs_x, abs_y, len); + } + if(res == LV_DRAW_MASK_RES_TRANSP) { + lv_memset_00(line_buf, w); + } + } + return mask_buf; +} + +SDL_Surface * lv_sdl_apply_mask_surface(const lv_area_t * coords, const int16_t * ids, int16_t ids_count) +{ + lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords); + + lv_opa_t * mask_buf = lv_draw_mask_dump(coords, ids, ids_count); + lv_mem_buf_release(mask_buf); + return lv_sdl_create_mask_surface(mask_buf, w, h, w); +} + +SDL_Texture * lv_sdl_gen_mask_texture(SDL_Renderer * renderer, const lv_area_t * coords, const int16_t * ids, + int16_t ids_count) +{ + SDL_Surface * indexed = lv_sdl_apply_mask_surface(coords, ids, ids_count); + SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, indexed); + SDL_FreeSurface(indexed); + return texture; +} + + +/********************** + * STATIC FUNCTIONS + **********************/ + + +#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_mask.h b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_mask.h new file mode 100644 index 000000000..6dbd73b7d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_mask.h @@ -0,0 +1,57 @@ +/** + * @file lv_gpu_sdl_mask.h + * + */ + +#ifndef LV_GPU_SDL_MASK_H +#define LV_GPU_SDL_MASK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#include LV_GPU_SDL_INCLUDE_PATH + +#include "../../misc/lv_area.h" +#include "../../misc/lv_color.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + + +lv_opa_t * lv_draw_mask_dump(const lv_area_t * coords, const int16_t * ids, int16_t ids_count); + +SDL_Surface * lv_sdl_create_mask_surface(lv_opa_t * pixels, lv_coord_t width, lv_coord_t height, lv_coord_t stride); + +SDL_Texture * lv_sdl_create_mask_texture(SDL_Renderer * renderer, lv_opa_t * pixels, lv_coord_t width, + lv_coord_t height, lv_coord_t stride); + +SDL_Surface * lv_sdl_apply_mask_surface(const lv_area_t * coords, const int16_t * ids, int16_t ids_count); + +SDL_Texture * +lv_sdl_gen_mask_texture(SDL_Renderer * renderer, const lv_area_t * coords, const int16_t * ids, int16_t ids_count); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GPU_SDL_MASK_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_stack_blur.c b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_stack_blur.c new file mode 100644 index 000000000..6d68294c9 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_stack_blur.c @@ -0,0 +1,247 @@ +/** + * @file lv_gpu_sdl_stack_blur.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_gpu_sdl_stack_blur.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void +stack_blur_job(lv_opa_t * src, unsigned int w, unsigned int h, unsigned int radius, int cores, int core, int step); + +/********************** + * STATIC VARIABLES + **********************/ + +// Based heavily on http://vitiy.info/Code/stackblur.cpp +// See http://vitiy.info/stackblur-algorithm-multi-threaded-blur-for-cpp/ +// Stack Blur Algorithm by Mario Klingemann + +static unsigned short const stackblur_mul[255] = { + 512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, + 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, + 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, + 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, + 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, + 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, + 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, + 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, + 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, + 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, + 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, + 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, + 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, + 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, + 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, + 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259 +}; + +static unsigned char const stackblur_shr[255] = { + 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, + 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_stack_blur_grayscale(lv_opa_t * buf, uint16_t w, uint16_t h, uint16_t r) +{ + stack_blur_job(buf, w, h, r, 1, 0, 1); + stack_blur_job(buf, w, h, r, 1, 0, 2); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void stack_blur_job(lv_opa_t * src, unsigned int w, unsigned int h, unsigned int radius, int cores, int core, + int step) +{ + if(radius < 2 || radius > 254) { + /* Silently ignore bad radius */ + return; + } + + unsigned int x, y, xp, yp, i; + unsigned int sp; + unsigned int stack_start; + unsigned char * stack_ptr; + + lv_opa_t * src_ptr; + lv_opa_t * dst_ptr; + + unsigned long sum_r; + unsigned long sum_in_r; + unsigned long sum_out_r; + + unsigned int wm = w - 1; + unsigned int hm = h - 1; + unsigned int stride = w; + unsigned int div = (radius * 2) + 1; + unsigned int mul_sum = stackblur_mul[radius]; + unsigned char shr_sum = stackblur_shr[radius]; + unsigned char stack[254 * 2 + 1]; + + if(step == 1) { + unsigned int minY = core * h / cores; + unsigned int maxY = (core + 1) * h / cores; + + for(y = minY; y < maxY; y++) { + sum_r = + sum_in_r = + sum_out_r = 0; + + src_ptr = src + stride * y; // start of line (0,y) + + for(i = 0; i <= radius; i++) { + stack_ptr = &stack[i]; + stack_ptr[0] = src_ptr[0]; + sum_r += src_ptr[0] * (i + 1); + sum_out_r += src_ptr[0]; + } + + + for(i = 1; i <= radius; i++) { + if(i <= wm) src_ptr += 1; + stack_ptr = &stack[i + radius]; + stack_ptr[0] = src_ptr[0]; + sum_r += src_ptr[0] * (radius + 1 - i); + sum_in_r += src_ptr[0]; + } + + + sp = radius; + xp = radius; + if(xp > wm) xp = wm; + src_ptr = src + (xp + y * w); // img.pix_ptr(xp, y); + dst_ptr = src + y * stride; // img.pix_ptr(0, y); + for(x = 0; x < w; x++) { + dst_ptr[0] = LV_CLAMP((sum_r * mul_sum) >> shr_sum, 0, 255); + dst_ptr += 1; + + sum_r -= sum_out_r; + + stack_start = sp + div - radius; + if(stack_start >= div) stack_start -= div; + stack_ptr = &stack[stack_start]; + + sum_out_r -= stack_ptr[0]; + + if(xp < wm) { + src_ptr += 1; + ++xp; + } + + stack_ptr[0] = src_ptr[0]; + + sum_in_r += src_ptr[0]; + sum_r += sum_in_r; + + ++sp; + if(sp >= div) sp = 0; + stack_ptr = &stack[sp]; + + sum_out_r += stack_ptr[0]; + sum_in_r -= stack_ptr[0]; + } + + } + } + + // step 2 + if(step == 2) { + unsigned int minX = core * w / cores; + unsigned int maxX = (core + 1) * w / cores; + + for(x = minX; x < maxX; x++) { + sum_r = + sum_in_r = + sum_out_r = 0; + + src_ptr = src + x; // x,0 + for(i = 0; i <= radius; i++) { + stack_ptr = &stack[i]; + stack_ptr[0] = src_ptr[0]; + sum_r += src_ptr[0] * (i + 1); + sum_out_r += src_ptr[0]; + } + for(i = 1; i <= radius; i++) { + if(i <= hm) src_ptr += stride; // +stride + + stack_ptr = &stack[i + radius]; + stack_ptr[0] = src_ptr[0]; + sum_r += src_ptr[0] * (radius + 1 - i); + sum_in_r += src_ptr[0]; + } + + sp = radius; + yp = radius; + if(yp > hm) yp = hm; + src_ptr = src + (x + yp * w); // img.pix_ptr(x, yp); + dst_ptr = src + x; // img.pix_ptr(x, 0); + for(y = 0; y < h; y++) { + dst_ptr[0] = LV_CLAMP((sum_r * mul_sum) >> shr_sum, 0, 255); + dst_ptr += stride; + + sum_r -= sum_out_r; + + stack_start = sp + div - radius; + if(stack_start >= div) stack_start -= div; + stack_ptr = &stack[stack_start]; + + sum_out_r -= stack_ptr[0]; + + if(yp < hm) { + src_ptr += stride; // stride + ++yp; + } + + stack_ptr[0] = src_ptr[0]; + + sum_in_r += src_ptr[0]; + sum_r += sum_in_r; + + ++sp; + if(sp >= div) sp = 0; + stack_ptr = &stack[sp]; + + sum_out_r += stack_ptr[0]; + sum_in_r -= stack_ptr[0]; + } + } + } +} + diff --git a/lib/libesp32_lvgl/LVGL8/src/lv_api_map.h b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_stack_blur.h similarity index 54% rename from lib/libesp32_lvgl/LVGL8/src/lv_api_map.h rename to lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_stack_blur.h index 2f3c811e8..5e13192a1 100644 --- a/lib/libesp32_lvgl/LVGL8/src/lv_api_map.h +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_stack_blur.h @@ -1,10 +1,9 @@ /** - * @file lv_api_map.h + * @file lv_gpu_sdl_stack_blur.h * */ - -#ifndef LV_API_MAP_H -#define LV_API_MAP_H +#ifndef LV_GPU_SDL_STACK_BLUR_H +#define LV_GPU_SDL_STACK_BLUR_H #ifdef __cplusplus extern "C" { @@ -13,16 +12,15 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../lvgl.h" + +#include "../../lv_conf_internal.h" + +#include "../../misc/lv_color.h" /********************* * DEFINES *********************/ -#define LV_NO_TASK_READY LV_NO_TIMER_READY -#define LV_INDEV_STATE_REL LV_INDEV_STATE_RELEASED -#define LV_INDEV_STATE_PR LV_INDEV_STATE_PRESSED - /********************** * TYPEDEFS **********************/ @@ -31,10 +29,7 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ -static inline LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_task_handler(void) -{ - return lv_timer_handler(); -} +void lv_stack_blur_grayscale(lv_opa_t * buf, uint16_t w, uint16_t h, uint16_t r); /********************** * MACROS @@ -44,4 +39,4 @@ static inline LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_task_handler(void) } /*extern "C"*/ #endif -#endif /*LV_API_MAP_H*/ +#endif /*LV_GPU_SDL_STACK_BLUR_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_texture_cache.c b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_texture_cache.c new file mode 100644 index 000000000..96f7d2d5a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_texture_cache.c @@ -0,0 +1,197 @@ +/** + * @file lv_gpu_sdl_texture_cache.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include "lv_gpu_sdl_texture_cache.h" + +#include "../../misc/lv_log.h" +#include "../../draw/lv_draw_label.h" +#include "../../draw/lv_draw_img.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + SDL_Texture * texture; + void * userdata; + lv_lru_free_t * userdata_free; + lv_gpu_sdl_cache_flag_t flags; +} draw_cache_value_t; + +typedef struct { + lv_gpu_cache_key_magic_t magic; +} temp_texture_key_t; + +typedef struct { + lv_coord_t width, height; +} temp_texture_userdata_t; + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void draw_cache_free_value(draw_cache_value_t *); + +/********************** + * STATIC VARIABLES + **********************/ + +static lv_lru_t * lv_sdl_texture_cache; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void _lv_gpu_sdl_texture_cache_init() +{ + lv_sdl_texture_cache = lv_lru_new(1024 * 1024 * 8, 65536, (lv_lru_free_t *) draw_cache_free_value, + NULL); +} + +void _lv_gpu_sdl_texture_cache_deinit() +{ + lv_lru_free(lv_sdl_texture_cache); +} + +SDL_Texture * lv_gpu_draw_cache_get(const void * key, size_t key_length, bool * found) +{ + return lv_gpu_draw_cache_get_with_userdata(key, key_length, found, NULL); +} + +SDL_Texture * lv_gpu_draw_cache_get_with_userdata(const void * key, size_t key_length, bool * found, void ** userdata) +{ + draw_cache_value_t * value = NULL; + lv_lru_get(lv_sdl_texture_cache, key, key_length, (void **) &value); + if(!value) { + if(found) { + *found = false; + } + return NULL; + } + else { + if(userdata) { + *userdata = value->userdata; + } + } + if(found) { + *found = true; + } + return value->texture; +} + +void lv_gpu_draw_cache_put(const void * key, size_t key_length, SDL_Texture * texture) +{ + lv_gpu_draw_cache_put_advanced(key, key_length, texture, NULL, NULL, 0); +} + +void lv_gpu_draw_cache_put_advanced(const void * key, size_t key_length, SDL_Texture * texture, void * userdata, + lv_lru_free_t userdata_free, lv_gpu_sdl_cache_flag_t flags) +{ + draw_cache_value_t * value = SDL_malloc(sizeof(draw_cache_value_t)); + value->texture = texture; + value->userdata = userdata; + value->userdata_free = userdata_free; + value->flags = flags; + if(!texture) { + lv_lru_set(lv_sdl_texture_cache, key, key_length, value, 1); + return; + } + if(flags & LV_GPU_SDL_CACHE_FLAG_MANAGED) { + /* Managed texture doesn't count into cache size */ + LV_LOG_INFO("cache texture %p, %d*%d@%dbpp", texture, width, height, SDL_BITSPERPIXEL(format)); + lv_lru_set(lv_sdl_texture_cache, key, key_length, value, 1); + return; + } + Uint32 format; + int access, width, height; + if(SDL_QueryTexture(texture, &format, &access, &width, &height) != 0) { + return; + } + LV_LOG_INFO("cache texture %p, %d*%d@%dbpp", texture, width, height, SDL_BITSPERPIXEL(format)); + lv_lru_set(lv_sdl_texture_cache, key, key_length, value, width * height * SDL_BITSPERPIXEL(format) / 8); +} + +SDL_Texture * lv_gpu_temp_texture_obtain(SDL_Renderer * renderer, lv_coord_t width, lv_coord_t height) +{ + temp_texture_key_t key; + SDL_memset(&key, 0, sizeof(key)); + key.magic = LV_GPU_CACHE_KEY_TEMP; + temp_texture_userdata_t * userdata = NULL; + SDL_Texture * texture = lv_gpu_draw_cache_get_with_userdata(&key, sizeof(key), NULL, (void **) &userdata); + if(texture && userdata->width >= width && userdata->height >= height) { + return texture; + } + texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, width, height); + userdata = SDL_malloc(sizeof(temp_texture_userdata_t)); + userdata->width = width; + userdata->height = height; + lv_gpu_draw_cache_put_advanced(&key, sizeof(key), texture, userdata, SDL_free, 0); + return texture; +} + +lv_gpu_sdl_cache_key_head_img_t * lv_gpu_sdl_img_cache_key_create(const void * src, int32_t frame_id, size_t * size) +{ + lv_gpu_sdl_cache_key_head_img_t header; + /* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */ + SDL_memset(&header, 0, sizeof(header)); + header.magic = LV_GPU_CACHE_KEY_MAGIC_IMG; + header.type = lv_img_src_get_type(src); + header.frame_id = frame_id; + void * key; + size_t key_size; + if(header.type == LV_IMG_SRC_FILE || header.type == LV_IMG_SRC_SYMBOL) { + size_t srclen = SDL_strlen(src); + key_size = sizeof(header) + srclen; + key = SDL_malloc(key_size); + SDL_memcpy(key, &header, sizeof(header)); + /*Copy string content as key value*/ + SDL_memcpy(key + sizeof(header), src, srclen); + } + else { + key_size = sizeof(header) + sizeof(void *); + key = SDL_malloc(key_size); + SDL_memcpy(key, &header, sizeof(header)); + /*Copy address number as key value*/ + SDL_memcpy(key + sizeof(header), &src, sizeof(void *)); + } + *size = key_size; + return (lv_gpu_sdl_cache_key_head_img_t *) key; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void draw_cache_free_value(draw_cache_value_t * value) +{ + if(value->texture && !(value->flags & LV_GPU_SDL_CACHE_FLAG_MANAGED)) { + LV_LOG_INFO("destroy texture %p", value->texture); + SDL_DestroyTexture(value->texture); + } + if(value->userdata_free) { + value->userdata_free(value->userdata); + } + SDL_free(value); +} + + +#endif /*LV_USE_GPU_SDL*/ + diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_texture_cache.h b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_texture_cache.h new file mode 100644 index 000000000..5a20d542d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_texture_cache.h @@ -0,0 +1,90 @@ +/** + * @file lv_gpu_sdl_texture_cache.h + * + */ + +#ifndef LV_GPU_SDL_TEXTURE_CACHE_H +#define LV_GPU_SDL_TEXTURE_CACHE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#include LV_GPU_SDL_INCLUDE_PATH +#include "../../draw/lv_img_decoder.h" +#include "../../misc/lv_area.h" +#include "lv_gpu_sdl_lru.h" + +/********************* + * DEFINES + *********************/ + +#define LV_GPU_SDL_DEC_DSC_TEXTURE_HEAD "@LVSDLTex" + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + char head[8]; + SDL_Texture * texture; +} lv_gpu_sdl_dec_dsc_userdata_t; + +typedef enum { + LV_GPU_CACHE_KEY_MAGIC_ARC = 0x01, + LV_GPU_CACHE_KEY_MAGIC_IMG = 0x11, + LV_GPU_CACHE_KEY_MAGIC_LINE = 0x21, + LV_GPU_CACHE_KEY_MAGIC_RECT_BG = 0x31, + LV_GPU_CACHE_KEY_MAGIC_RECT_SHADOW = 0x32, + LV_GPU_CACHE_KEY_MAGIC_RECT_BORDER = 0x33, + LV_GPU_CACHE_KEY_MAGIC_FONT = 0x41, + LV_GPU_CACHE_KEY_TEMP = 0xFF, +} lv_gpu_cache_key_magic_t; + +typedef enum { + LV_GPU_SDL_CACHE_FLAG_NONE = 0, + LV_GPU_SDL_CACHE_FLAG_MANAGED = 1, +} lv_gpu_sdl_cache_flag_t; + +typedef struct { + lv_gpu_cache_key_magic_t magic; + lv_img_src_t type; + int32_t frame_id; +} lv_gpu_sdl_cache_key_head_img_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void _lv_gpu_sdl_texture_cache_init(); + +void _lv_gpu_sdl_texture_cache_deinit(); + +SDL_Texture * lv_gpu_draw_cache_get(const void * key, size_t key_length, bool * found); + +SDL_Texture * lv_gpu_draw_cache_get_with_userdata(const void * key, size_t key_length, bool * found, void ** userdata); + +void lv_gpu_draw_cache_put(const void * key, size_t key_length, SDL_Texture * texture); + +void lv_gpu_draw_cache_put_advanced(const void * key, size_t key_length, SDL_Texture * texture, void * userdata, + lv_lru_free_t userdata_free, lv_gpu_sdl_cache_flag_t flags); + +SDL_Texture * lv_gpu_temp_texture_obtain(SDL_Renderer * renderer, lv_coord_t width, lv_coord_t height); + +lv_gpu_sdl_cache_key_head_img_t * lv_gpu_sdl_img_cache_key_create(const void * src, int32_t frame_id, size_t * size); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GPU_SDL_TEXTURE_CACHE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_utils.c b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_utils.c new file mode 100644 index 000000000..d6486014a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_utils.c @@ -0,0 +1,179 @@ +/** + * @file lv_gpu_sdl_utils.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include "lv_gpu_sdl_utils.h" + +#include "../../draw/lv_draw_label.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +static SDL_Palette * lv_sdl_palette_grayscale1 = NULL; +static SDL_Palette * lv_sdl_palette_grayscale2 = NULL; +static SDL_Palette * lv_sdl_palette_grayscale3 = NULL; +static SDL_Palette * lv_sdl_palette_grayscale4 = NULL; +static SDL_Palette * lv_sdl_palette_grayscale8 = NULL; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void _lv_gpu_sdl_utils_init() +{ + lv_sdl_palette_grayscale1 = lv_sdl_alloc_palette_for_bpp(_lv_bpp1_opa_table, 1); + lv_sdl_palette_grayscale2 = lv_sdl_alloc_palette_for_bpp(_lv_bpp2_opa_table, 2); + lv_sdl_palette_grayscale3 = lv_sdl_alloc_palette_for_bpp(_lv_bpp3_opa_table, 3); + lv_sdl_palette_grayscale4 = lv_sdl_alloc_palette_for_bpp(_lv_bpp4_opa_table, 4); + lv_sdl_palette_grayscale8 = lv_sdl_alloc_palette_for_bpp(_lv_bpp8_opa_table, 8); +} + +void _lv_gpu_sdl_utils_deinit() +{ + SDL_FreePalette(lv_sdl_palette_grayscale1); + SDL_FreePalette(lv_sdl_palette_grayscale2); + SDL_FreePalette(lv_sdl_palette_grayscale3); + SDL_FreePalette(lv_sdl_palette_grayscale4); + SDL_FreePalette(lv_sdl_palette_grayscale8); +} + +void lv_area_to_sdl_rect(const lv_area_t * in, SDL_Rect * out) +{ + out->x = in->x1; + out->y = in->y1; + out->w = in->x2 - in->x1 + 1; + out->h = in->y2 - in->y1 + 1; +} + +void lv_color_to_sdl_color(const lv_color_t * in, SDL_Color * out) +{ + uint32_t color32 = lv_color_to32(*in); + lv_color32_t * color32_t = (lv_color32_t *) &color32; + out->a = color32_t->ch.alpha; + out->r = color32_t->ch.red; + out->g = color32_t->ch.green; + out->b = color32_t->ch.blue; +} + +void lv_area_zoom_to_sdl_rect(const lv_area_t * in, SDL_Rect * out, uint16_t zoom, const lv_point_t * pivot) +{ + if(zoom == LV_IMG_ZOOM_NONE) { + lv_area_to_sdl_rect(in, out); + return; + } + int h = in->y2 - in->y1 + 1; + int w = in->x2 - in->x1 + 1; + int sh = h * zoom >> 8; + int sw = w * zoom >> 8; + out->x = in->x1 - (sw / 2 - pivot->x); + out->y = in->y1 - (sh / 2 - pivot->y); + out->w = sw; + out->h = sh; +} + +double lv_sdl_round(double d) +{ + return (d - (long) d) < 0.5 ? SDL_floor(d) : SDL_ceil(d); +} + +SDL_Palette * lv_sdl_alloc_palette_for_bpp(const uint8_t * mapping, uint8_t bpp) +{ + SDL_assert(bpp >= 1 && bpp <= 8); + int color_cnt = 1 << bpp; + SDL_Palette * result = SDL_AllocPalette(color_cnt); + SDL_Color palette[256]; + for(int i = 0; i < color_cnt; i++) { + palette[i].r = palette[i].g = palette[i].b = 0xFF; + palette[i].a = mapping ? mapping[i] : i; + } + SDL_SetPaletteColors(result, palette, 0, color_cnt); + return result; +} + +SDL_Palette * lv_sdl_get_grayscale_palette(uint8_t bpp) +{ + switch(bpp) { + case 1: + return lv_sdl_palette_grayscale1; + case 2: + return lv_sdl_palette_grayscale2; + case 3: + return lv_sdl_palette_grayscale3; + case 4: + return lv_sdl_palette_grayscale4; + case 8: + return lv_sdl_palette_grayscale8; + } + return NULL; +} + +void lv_sdl_to_8bpp(uint8_t * dest, const uint8_t * src, int width, int height, int stride, uint8_t bpp) +{ + int src_len = width * height; + int cur = 0; + int curbit; + uint8_t opa_mask; + const uint8_t * opa_table; + switch(bpp) { + case 1: + opa_mask = 0x1; + opa_table = _lv_bpp1_opa_table; + break; + case 2: + opa_mask = 0x4; + opa_table = _lv_bpp2_opa_table; + break; + case 4: + opa_mask = 0xF; + opa_table = _lv_bpp4_opa_table; + break; + case 8: + opa_mask = 0xFF; + opa_table = _lv_bpp8_opa_table; + break; + default: + return; + } + /* Does this work well on big endian systems? */ + while(cur < src_len) { + curbit = 8 - bpp; + uint8_t src_byte = src[cur * bpp / 8]; + while(curbit >= 0) { + uint8_t src_bits = opa_mask & (src_byte >> curbit); + dest[(cur / width * stride) + (cur % width)] = opa_table[src_bits]; + curbit -= bpp; + cur++; + } + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_utils.h b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_utils.h new file mode 100644 index 000000000..c2daeb79b --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_utils.h @@ -0,0 +1,61 @@ +/** + * @file lv_gpu_sdl_utils.h + * + */ +#ifndef LV_GPU_SDL_UTILS_H +#define LV_GPU_SDL_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#include "../../misc/lv_color.h" +#include "../../misc/lv_area.h" + +#include LV_GPU_SDL_INCLUDE_PATH + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void _lv_gpu_sdl_utils_init(); + +void _lv_gpu_sdl_utils_deinit(); + +void lv_area_to_sdl_rect(const lv_area_t * in, SDL_Rect * out); + +void lv_color_to_sdl_color(const lv_color_t * in, SDL_Color * out); + +void lv_area_zoom_to_sdl_rect(const lv_area_t * in, SDL_Rect * out, uint16_t zoom, const lv_point_t * pivot); + +double lv_sdl_round(double d); + +SDL_Palette * lv_sdl_alloc_palette_for_bpp(const uint8_t * mapping, uint8_t bpp); + +SDL_Palette * lv_sdl_get_grayscale_palette(uint8_t bpp); + +void lv_sdl_to_8bpp(uint8_t * dest, const uint8_t * src, int width, int height, int stride, uint8_t bpp); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GPU_SDL_UTILS_H*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/hal/lv_hal.h b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/hal/lv_hal.h rename to lib/libesp32_lvgl/lvgl/src/hal/lv_hal.h diff --git a/lib/libesp32_lvgl/LVGL8/src/hal/lv_hal.mk b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal.mk similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/hal/lv_hal.mk rename to lib/libesp32_lvgl/lvgl/src/hal/lv_hal.mk diff --git a/lib/libesp32_lvgl/LVGL8/src/hal/lv_hal_disp.c b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.c similarity index 59% rename from lib/libesp32_lvgl/LVGL8/src/hal/lv_hal_disp.c rename to lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.c index dc658c035..43b7f4367 100644 --- a/lib/libesp32_lvgl/LVGL8/src/hal/lv_hal_disp.c +++ b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.c @@ -18,7 +18,7 @@ #include "../core/lv_refr.h" #include "../core/lv_theme.h" #if LV_USE_THEME_DEFAULT -#include "../extra/themes/default/lv_theme_default.h" + #include "../extra/themes/default/lv_theme_default.h" #endif /********************* @@ -34,6 +34,24 @@ **********************/ static lv_obj_tree_walk_res_t invalidate_layout_cb(lv_obj_t * obj, void * user_data); +static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, + lv_coord_t y, + lv_color_t color, lv_opa_t opa); + +static void set_px_cb_alpha1(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, + lv_color_t color, lv_opa_t opa); + +static void set_px_cb_alpha2(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, + lv_color_t color, lv_opa_t opa); + +static void set_px_cb_alpha4(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, + lv_color_t color, lv_opa_t opa); + +static void set_px_cb_alpha8(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, + lv_color_t color, lv_opa_t opa); + +static void set_px_alpha_generic(lv_img_dsc_t * d, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa); + /********************** * STATIC VARIABLES **********************/ @@ -59,7 +77,11 @@ void lv_disp_drv_init(lv_disp_drv_t * driver) driver->hor_res = 320; driver->ver_res = 240; - driver->antialiasing = LV_COLOR_DEPTH > 8 ? 1: 0; + driver->physical_hor_res = -1; + driver->physical_ver_res = -1; + driver->offset_x = 0; + driver->offset_y = 0; + driver->antialiasing = LV_COLOR_DEPTH > 8 ? 1 : 0; driver->screen_transp = LV_COLOR_SCREEN_TRANSP; driver->dpi = LV_DPI_DEF; driver->color_chroma_key = LV_COLOR_CHROMA_KEY; @@ -121,7 +143,7 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver) if(driver->full_refresh && driver->draw_buf->size < (uint32_t)driver->hor_res * driver->ver_res) { driver->full_refresh = 0; - LV_LOG_WARN("full_refresh requires at least screen sized draw buffer(s)") + LV_LOG_WARN("full_refresh requires at least screen sized draw buffer(s)"); } disp->bg_color = lv_color_white(); @@ -133,7 +155,10 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver) #if LV_USE_THEME_DEFAULT if(lv_theme_default_is_inited() == false) { - disp->theme = lv_theme_default_init(disp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), LV_THEME_DEFAULT_DARK, LV_FONT_DEFAULT); + disp->theme = lv_theme_default_init(disp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), + LV_THEME_DEFAULT_DARK, LV_FONT_DEFAULT); + } else { + disp->theme = lv_theme_default_get(); } #endif @@ -167,9 +192,10 @@ void lv_disp_drv_update(lv_disp_t * disp, lv_disp_drv_t * new_drv) { disp->driver = new_drv; - if(disp->driver->full_refresh && disp->driver->draw_buf->size < (uint32_t)disp->driver->hor_res * disp->driver->ver_res) { + if(disp->driver->full_refresh && + disp->driver->draw_buf->size < (uint32_t)disp->driver->hor_res * disp->driver->ver_res) { disp->driver->full_refresh = 0; - LV_LOG_WARN("full_refresh requires at least screen sized draw buffer(s)") + LV_LOG_WARN("full_refresh requires at least screen sized draw buffer(s)"); } lv_coord_t w = lv_disp_get_hor_res(disp); @@ -218,22 +244,22 @@ void lv_disp_remove(lv_disp_t * disp) indev = lv_indev_get_next(indev); } - _lv_ll_remove(&LV_GC_ROOT(_lv_disp_ll), disp); - lv_timer_del(disp->refr_timer); - /** delete screen and other obj */ - if (disp->sys_layer) { + if(disp->sys_layer) { lv_obj_del(disp->sys_layer); disp->sys_layer = NULL; } - if (disp->top_layer) { + if(disp->top_layer) { lv_obj_del(disp->top_layer); disp->top_layer = NULL; } - while (disp->screen_cnt != 0) { + while(disp->screen_cnt != 0) { /*Delete the screenst*/ lv_obj_del(disp->screens[0]); } + + _lv_ll_remove(&LV_GC_ROOT(_lv_disp_ll), disp); + lv_timer_del(disp->refr_timer); lv_mem_free(disp); if(was_default) lv_disp_set_default(_lv_ll_get_head(&LV_GC_ROOT(_lv_disp_ll))); @@ -268,7 +294,8 @@ lv_coord_t lv_disp_get_hor_res(lv_disp_t * disp) if(disp == NULL) { return 0; - } else { + } + else { switch(disp->driver->rotated) { case LV_DISP_ROT_90: case LV_DISP_ROT_270: @@ -290,7 +317,8 @@ lv_coord_t lv_disp_get_ver_res(lv_disp_t * disp) if(disp == NULL) { return 0; - } else { + } + else { switch(disp->driver->rotated) { case LV_DISP_ROT_90: case LV_DISP_ROT_270: @@ -301,6 +329,104 @@ lv_coord_t lv_disp_get_ver_res(lv_disp_t * disp) } } +/** + * Get the full / physical horizontal resolution of a display + * @param disp pointer to a display (NULL to use the default display) + * @return the full / physical horizontal resolution of the display + */ +lv_coord_t lv_disp_get_physical_hor_res(lv_disp_t * disp) +{ + if(disp == NULL) disp = lv_disp_get_default(); + + if(disp == NULL) { + return 0; + } + else { + switch(disp->driver->rotated) { + case LV_DISP_ROT_90: + case LV_DISP_ROT_270: + return disp->driver->physical_ver_res > 0 ? disp->driver->physical_ver_res : disp->driver->ver_res; + default: + return disp->driver->physical_hor_res > 0 ? disp->driver->physical_hor_res : disp->driver->hor_res; + } + } +} + +/** + * Get the full / physical vertical resolution of a display + * @param disp pointer to a display (NULL to use the default display) + * @return the full / physical vertical resolution of the display + */ +lv_coord_t lv_disp_get_physical_ver_res(lv_disp_t * disp) +{ + if(disp == NULL) disp = lv_disp_get_default(); + + if(disp == NULL) { + return 0; + } + else { + switch(disp->driver->rotated) { + case LV_DISP_ROT_90: + case LV_DISP_ROT_270: + return disp->driver->physical_hor_res > 0 ? disp->driver->physical_hor_res : disp->driver->hor_res; + default: + return disp->driver->physical_ver_res > 0 ? disp->driver->physical_ver_res : disp->driver->ver_res; + } + } +} + +/** + * Get the horizontal offset from the full / physical display + * @param disp pointer to a display (NULL to use the default display) + * @return the horizontal offset from the full / physical display + */ +lv_coord_t lv_disp_get_offset_x(lv_disp_t * disp) +{ + if(disp == NULL) disp = lv_disp_get_default(); + + if(disp == NULL) { + return 0; + } + else { + switch(disp->driver->rotated) { + case LV_DISP_ROT_90: + return disp->driver->offset_y; + case LV_DISP_ROT_180: + return lv_disp_get_physical_hor_res(disp) - disp->driver->offset_x; + case LV_DISP_ROT_270: + return lv_disp_get_physical_hor_res(disp) - disp->driver->offset_y; + default: + return disp->driver->offset_x; + } + } +} + +/** + * Get the vertical offset from the full / physical display + * @param disp pointer to a display (NULL to use the default display) + * @return the horizontal offset from the full / physical display + */ +lv_coord_t lv_disp_get_offset_y(lv_disp_t * disp) +{ + if(disp == NULL) disp = lv_disp_get_default(); + + if(disp == NULL) { + return 0; + } + else { + switch(disp->driver->rotated) { + case LV_DISP_ROT_90: + return disp->driver->offset_x; + case LV_DISP_ROT_180: + return lv_disp_get_physical_ver_res(disp) - disp->driver->offset_y; + case LV_DISP_ROT_270: + return lv_disp_get_physical_ver_res(disp) - disp->driver->offset_x; + default: + return disp->driver->offset_y; + } + } +} + /** * Get if anti-aliasing is enabled for a display or not * @param disp pointer to a display (NULL to use the default display) @@ -403,6 +529,29 @@ lv_disp_rot_t lv_disp_get_rotation(lv_disp_t * disp) return disp->driver->rotated; } +void lv_disp_drv_use_generic_set_px_cb(lv_disp_drv_t * disp_drv, lv_img_cf_t cf) +{ + switch(cf) { + case LV_IMG_CF_TRUE_COLOR_ALPHA: + disp_drv->set_px_cb = set_px_true_color_alpha; + break; + case LV_IMG_CF_ALPHA_1BIT: + disp_drv->set_px_cb = set_px_cb_alpha1; + break; + case LV_IMG_CF_ALPHA_2BIT: + disp_drv->set_px_cb = set_px_cb_alpha2; + break; + case LV_IMG_CF_ALPHA_4BIT: + disp_drv->set_px_cb = set_px_cb_alpha4; + break; + case LV_IMG_CF_ALPHA_8BIT: + disp_drv->set_px_cb = set_px_cb_alpha8; + break; + default: + disp_drv->set_px_cb = NULL; + } +} + /********************** * STATIC FUNCTIONS **********************/ @@ -413,3 +562,99 @@ static lv_obj_tree_walk_res_t invalidate_layout_cb(lv_obj_t * obj, void * user_d lv_obj_mark_layout_as_dirty(obj); return LV_OBJ_TREE_WALK_NEXT; } + +static void set_px_cb_alpha1(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, + lv_color_t color, lv_opa_t opa) +{ + (void) disp_drv; /*Unused*/ + + if(opa <= LV_OPA_MIN) return; + lv_img_dsc_t d; + d.data = buf; + d.header.w = buf_w; + d.header.cf = LV_IMG_CF_ALPHA_1BIT; + + set_px_alpha_generic(&d, x, y, color, opa); +} + +static void set_px_cb_alpha2(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, + lv_color_t color, lv_opa_t opa) +{ + (void) disp_drv; /*Unused*/ + + if(opa <= LV_OPA_MIN) return; + lv_img_dsc_t d; + d.data = buf; + d.header.w = buf_w; + d.header.cf = LV_IMG_CF_ALPHA_2BIT; + + set_px_alpha_generic(&d, x, y, color, opa); +} + +static void set_px_cb_alpha4(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, + lv_color_t color, lv_opa_t opa) +{ + (void) disp_drv; /*Unused*/ + + if(opa <= LV_OPA_MIN) return; + lv_img_dsc_t d; + d.data = buf; + d.header.w = buf_w; + d.header.cf = LV_IMG_CF_ALPHA_4BIT; + + set_px_alpha_generic(&d, x, y, color, opa); +} + +static void set_px_cb_alpha8(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, + lv_color_t color, lv_opa_t opa) +{ + (void) disp_drv; /*Unused*/ + + if(opa <= LV_OPA_MIN) return; + lv_img_dsc_t d; + d.data = buf; + d.header.w = buf_w; + d.header.cf = LV_IMG_CF_ALPHA_8BIT; + + set_px_alpha_generic(&d, x, y, color, opa); +} + +static void set_px_alpha_generic(lv_img_dsc_t * d, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa) +{ + d->header.always_zero = 0; + d->header.h = 1; /*Doesn't matter*/ + + uint8_t br = lv_color_brightness(color); + if(opa < LV_OPA_MAX) { + uint8_t bg = lv_img_buf_get_px_alpha(d, x, y); + br = (uint16_t)((uint16_t)br * opa + (bg * (255 - opa))) >> 8; + } + + lv_img_buf_set_px_alpha(d, x, y, br); +} + +static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, + lv_coord_t y, + lv_color_t color, lv_opa_t opa) +{ + (void) disp_drv; /*Unused*/ + + if(opa <= LV_OPA_MIN) return; + lv_img_dsc_t d; + d.data = buf; + d.header.always_zero = 0; + d.header.h = 1; /*Doesn't matter*/; + d.header.w = buf_w; + d.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA; + + lv_color_t bg_color = lv_img_buf_get_px_color(&d, x, y, lv_color_black()); + lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&d, x, y); + + lv_opa_t res_opa; + lv_color_t res_color; + + lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &res_opa); + + lv_img_buf_set_px_alpha(&d, x, y, res_opa); + lv_img_buf_set_px_color(&d, x, y, res_color); +} diff --git a/lib/libesp32_lvgl/LVGL8/src/hal/lv_hal_disp.h b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.h similarity index 85% rename from lib/libesp32_lvgl/LVGL8/src/hal/lv_hal_disp.h rename to lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.h index 9a6315320..3626a34ef 100644 --- a/lib/libesp32_lvgl/LVGL8/src/hal/lv_hal_disp.h +++ b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.h @@ -18,6 +18,7 @@ extern "C" { #include #include #include "lv_hal.h" +#include "../draw/lv_img_buf.h" #include "../misc/lv_color.h" #include "../misc/lv_area.h" #include "../misc/lv_ll.h" @@ -46,7 +47,7 @@ struct _lv_theme_t; /** * Structure for holding display buffer information. */ -typedef struct _lv_disp_draw_buf_t{ +typedef struct _lv_disp_draw_buf_t { void * buf1; /**< First display buffer.*/ void * buf2; /**< Second display buffer.*/ @@ -79,10 +80,16 @@ typedef struct _lv_disp_drv_t { lv_coord_t hor_res; /**< Horizontal resolution.*/ lv_coord_t ver_res; /**< Vertical resolution.*/ + lv_coord_t physical_hor_res; /**< Horizontal resolution of the full / physical display. Set to -1 for fullscreen mode.*/ + lv_coord_t physical_ver_res; /**< Vertical resolution of the full / physical display. Set to -1 for fullscreen mode.*/ + lv_coord_t offset_x; /**< Horizontal offset from the full / physical display. Set to 0 for fullscreen mode.*/ + lv_coord_t offset_y; /**< Vertical offset from the full / physical display. Set to 0 for fullscreen mode.*/ + /** Pointer to a buffer initialized with `lv_disp_draw_buf_init()`. * LVGL will use this buffer(s) to draw the screens contents*/ lv_disp_draw_buf_t * draw_buf; + uint32_t direct_mode : 1; /**< 1: Use screen-sized buffers and draw to absolute coordinates*/ uint32_t full_refresh : 1; /**< 1: Always make the whole screen redrawn*/ uint32_t sw_rotate : 1; /**< 1: use software rotation (slower)*/ uint32_t antialiasing : 1; /**< 1: anti-aliasing is enabled on this display.*/ @@ -160,11 +167,13 @@ typedef struct _lv_disp_t { struct _lv_obj_t * top_layer; /**< @see lv_disp_get_layer_top*/ struct _lv_obj_t * sys_layer; /**< @see lv_disp_get_layer_sys*/ uint32_t screen_cnt; - uint8_t del_prev : 1; /**< 1: Automatically delete the previous screen when the screen load animation is ready*/ +uint8_t del_prev : + 1; /**< 1: Automatically delete the previous screen when the screen load animation is ready*/ lv_opa_t bg_opa; /** /* Handle special Kconfig options */ #ifndef LV_KCONFIG_IGNORE -# include "lv_conf_kconfig.h" -# ifdef CONFIG_LV_CONF_SKIP -# define LV_CONF_SKIP -# endif +# include "lv_conf_kconfig.h" +# ifdef CONFIG_LV_CONF_SKIP +# define LV_CONF_SKIP +# endif #endif /*If "lv_conf.h" is available from here try to use it later.*/ -#if defined __has_include +#ifdef __has_include # if __has_include("lv_conf.h") -# ifndef LV_CONF_INCLUDE_SIMPLE -# define LV_CONF_INCLUDE_SIMPLE -# endif +# ifndef LV_CONF_INCLUDE_SIMPLE +# define LV_CONF_INCLUDE_SIMPLE +# endif # endif #endif /*If lv_conf.h is not skipped include it*/ -#if !defined(LV_CONF_SKIP) -# if defined(LV_CONF_PATH) /*If there is a path defined for lv_conf.h use it*/ +#ifndef LV_CONF_SKIP +# ifdef LV_CONF_PATH /*If there is a path defined for lv_conf.h use it*/ # define __LV_TO_STR_AUX(x) #x # define __LV_TO_STR(x) __LV_TO_STR_AUX(x) # include __LV_TO_STR(LV_CONF_PATH) @@ -42,15 +42,16 @@ # endif #endif +#ifdef CONFIG_LV_COLOR_DEPTH +# define _LV_KCONFIG_PRESENT +#endif /*---------------------------------- * Start parsing lv_conf_template.h -----------------------------------*/ -/*clang-format off*/ #include - /*==================== COLOR SETTINGS *====================*/ @@ -60,36 +61,46 @@ # ifdef CONFIG_LV_COLOR_DEPTH # define LV_COLOR_DEPTH CONFIG_LV_COLOR_DEPTH # else -# define LV_COLOR_DEPTH 32 +# define LV_COLOR_DEPTH 16 # endif #endif -/*Swap the 2 bytes of RGB565 color. Useful if the display has a 8 bit interface (e.g. SPI)*/ +/*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/ #ifndef LV_COLOR_16_SWAP # ifdef CONFIG_LV_COLOR_16_SWAP # define LV_COLOR_16_SWAP CONFIG_LV_COLOR_16_SWAP # else -# define LV_COLOR_16_SWAP 0 +# define LV_COLOR_16_SWAP 0 # endif #endif /*Enable more complex drawing routines to manage screens transparency. - *Can be used if the UI is above an other layer, e.g. an OSD menu or video player. + *Can be used if the UI is above another layer, e.g. an OSD menu or video player. *Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to non LV_OPA_COVER value*/ #ifndef LV_COLOR_SCREEN_TRANSP # ifdef CONFIG_LV_COLOR_SCREEN_TRANSP # define LV_COLOR_SCREEN_TRANSP CONFIG_LV_COLOR_SCREEN_TRANSP # else -# define LV_COLOR_SCREEN_TRANSP 0 +# define LV_COLOR_SCREEN_TRANSP 0 # endif #endif -/*Images pixels with this color will not be drawn if they are chroma keyed)*/ +/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. + * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */ +#ifndef LV_COLOR_MIX_ROUND_OFS +# ifdef CONFIG_LV_COLOR_MIX_ROUND_OFS +# define LV_COLOR_MIX_ROUND_OFS CONFIG_LV_COLOR_MIX_ROUND_OFS +# else +# define LV_COLOR_MIX_ROUND_OFS (LV_COLOR_DEPTH == 32 ? 0: 128) +# endif +#endif + +/*Images pixels with this color will not be drawn if they are chroma keyed)*/ #ifndef LV_COLOR_CHROMA_KEY # ifdef CONFIG_LV_COLOR_CHROMA_KEY # define LV_COLOR_CHROMA_KEY CONFIG_LV_COLOR_CHROMA_KEY # else -# define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/ +# define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/ # endif #endif @@ -102,7 +113,7 @@ # ifdef CONFIG_LV_MEM_CUSTOM # define LV_MEM_CUSTOM CONFIG_LV_MEM_CUSTOM # else -# define LV_MEM_CUSTOM 0 +# define LV_MEM_CUSTOM 0 # endif #endif #if LV_MEM_CUSTOM == 0 @@ -111,7 +122,7 @@ # ifdef CONFIG_LV_MEM_SIZE # define LV_MEM_SIZE CONFIG_LV_MEM_SIZE # else -# define LV_MEM_SIZE (32U * 1024U) /*[bytes]*/ +# define LV_MEM_SIZE (32U * 1024U) /*[bytes]*/ # endif #endif @@ -120,46 +131,62 @@ # ifdef CONFIG_LV_MEM_ADR # define LV_MEM_ADR CONFIG_LV_MEM_ADR # else -# define LV_MEM_ADR 0 /*0: unused*/ +# define LV_MEM_ADR 0 /*0: unused*/ # endif #endif +/*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/ +#if LV_MEM_ADR == 0 +//#define LV_MEM_POOL_INCLUDE your_alloc_library /* Uncomment if using an external allocator*/ +//#define LV_MEM_POOL_ALLOC your_alloc /* Uncomment if using an external allocator*/ +#endif + #else /*LV_MEM_CUSTOM*/ #ifndef LV_MEM_CUSTOM_INCLUDE # ifdef CONFIG_LV_MEM_CUSTOM_INCLUDE # define LV_MEM_CUSTOM_INCLUDE CONFIG_LV_MEM_CUSTOM_INCLUDE # else -# define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ +# define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ # endif #endif #ifndef LV_MEM_CUSTOM_ALLOC # ifdef CONFIG_LV_MEM_CUSTOM_ALLOC # define LV_MEM_CUSTOM_ALLOC CONFIG_LV_MEM_CUSTOM_ALLOC # else -# define LV_MEM_CUSTOM_ALLOC malloc +# define LV_MEM_CUSTOM_ALLOC malloc # endif #endif #ifndef LV_MEM_CUSTOM_FREE # ifdef CONFIG_LV_MEM_CUSTOM_FREE # define LV_MEM_CUSTOM_FREE CONFIG_LV_MEM_CUSTOM_FREE # else -# define LV_MEM_CUSTOM_FREE free +# define LV_MEM_CUSTOM_FREE free # endif #endif #ifndef LV_MEM_CUSTOM_REALLOC # ifdef CONFIG_LV_MEM_CUSTOM_REALLOC # define LV_MEM_CUSTOM_REALLOC CONFIG_LV_MEM_CUSTOM_REALLOC # else -# define LV_MEM_CUSTOM_REALLOC realloc +# define LV_MEM_CUSTOM_REALLOC realloc # endif #endif #endif /*LV_MEM_CUSTOM*/ +/*Number of the intermediate memory buffer used during rendering and other internal processing mechanisms. + *You will see an error log message if there wasn't enough buffers. */ +#ifndef LV_MEM_BUF_MAX_NUM +# ifdef CONFIG_LV_MEM_BUF_MAX_NUM +# define LV_MEM_BUF_MAX_NUM CONFIG_LV_MEM_BUF_MAX_NUM +# else +# define LV_MEM_BUF_MAX_NUM 16 +# endif +#endif + /*Use the standard `memcpy` and `memset` instead of LVGL's own functions. (Might or might not be faster).*/ #ifndef LV_MEMCPY_MEMSET_STD # ifdef CONFIG_LV_MEMCPY_MEMSET_STD # define LV_MEMCPY_MEMSET_STD CONFIG_LV_MEMCPY_MEMSET_STD # else -# define LV_MEMCPY_MEMSET_STD 0 +# define LV_MEMCPY_MEMSET_STD 0 # endif #endif @@ -167,12 +194,12 @@ HAL SETTINGS *====================*/ -/*Default display refresh period. LVG will redraw changed ares with this period time*/ +/*Default display refresh period. LVG will redraw changed areas with this period time*/ #ifndef LV_DISP_DEF_REFR_PERIOD # ifdef CONFIG_LV_DISP_DEF_REFR_PERIOD # define LV_DISP_DEF_REFR_PERIOD CONFIG_LV_DISP_DEF_REFR_PERIOD # else -# define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ +# define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ # endif #endif @@ -181,7 +208,7 @@ # ifdef CONFIG_LV_INDEV_DEF_READ_PERIOD # define LV_INDEV_DEF_READ_PERIOD CONFIG_LV_INDEV_DEF_READ_PERIOD # else -# define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/ +# define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/ # endif #endif @@ -191,7 +218,7 @@ # ifdef CONFIG_LV_TICK_CUSTOM # define LV_TICK_CUSTOM CONFIG_LV_TICK_CUSTOM # else -# define LV_TICK_CUSTOM 0 +# define LV_TICK_CUSTOM 0 # endif #endif #if LV_TICK_CUSTOM @@ -199,14 +226,14 @@ # ifdef CONFIG_LV_TICK_CUSTOM_INCLUDE # define LV_TICK_CUSTOM_INCLUDE CONFIG_LV_TICK_CUSTOM_INCLUDE # else -# define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ +# define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ # endif #endif #ifndef LV_TICK_CUSTOM_SYS_TIME_EXPR # ifdef CONFIG_LV_TICK_CUSTOM_SYS_TIME_EXPR # define LV_TICK_CUSTOM_SYS_TIME_EXPR CONFIG_LV_TICK_CUSTOM_SYS_TIME_EXPR # else -# define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ +# define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ # endif #endif #endif /*LV_TICK_CUSTOM*/ @@ -217,7 +244,7 @@ # ifdef CONFIG_LV_DPI_DEF # define LV_DPI_DEF CONFIG_LV_DPI_DEF # else -# define LV_DPI_DEF 130 /*[px/inch]*/ +# define LV_DPI_DEF 130 /*[px/inch]*/ # endif #endif @@ -232,10 +259,14 @@ /*Enable complex draw engine. *Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/ #ifndef LV_DRAW_COMPLEX -# ifdef CONFIG_LV_DRAW_COMPLEX -# define LV_DRAW_COMPLEX CONFIG_LV_DRAW_COMPLEX +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_DRAW_COMPLEX +# define LV_DRAW_COMPLEX CONFIG_LV_DRAW_COMPLEX +# else +# define LV_DRAW_COMPLEX 0 +# endif # else -# define LV_DRAW_COMPLEX 1 +# define LV_DRAW_COMPLEX 1 # endif #endif #if LV_DRAW_COMPLEX != 0 @@ -247,9 +278,22 @@ # ifdef CONFIG_LV_SHADOW_CACHE_SIZE # define LV_SHADOW_CACHE_SIZE CONFIG_LV_SHADOW_CACHE_SIZE # else -# define LV_SHADOW_CACHE_SIZE 0 +# define LV_SHADOW_CACHE_SIZE 0 # endif #endif + +/* Set number of maximally cached circle data. + * The circumference of 1/4 circle are saved for anti-aliasing + * radius * 4 bytes are used per circle (the most often used radiuses are saved) + * 0: to disable caching */ +#ifndef LV_CIRCLE_CACHE_SIZE +# ifdef CONFIG_LV_CIRCLE_CACHE_SIZE +# define LV_CIRCLE_CACHE_SIZE CONFIG_LV_CIRCLE_CACHE_SIZE +# else +# define LV_CIRCLE_CACHE_SIZE 4 +# endif +#endif + #endif /*LV_DRAW_COMPLEX*/ /*Default image cache size. Image caching keeps the images opened. @@ -261,7 +305,7 @@ # ifdef CONFIG_LV_IMG_CACHE_DEF_SIZE # define LV_IMG_CACHE_DEF_SIZE CONFIG_LV_IMG_CACHE_DEF_SIZE # else -# define LV_IMG_CACHE_DEF_SIZE 0 +# define LV_IMG_CACHE_DEF_SIZE 0 # endif #endif @@ -270,9 +314,10 @@ # ifdef CONFIG_LV_DISP_ROT_MAX_BUF # define LV_DISP_ROT_MAX_BUF CONFIG_LV_DISP_ROT_MAX_BUF # else -# define LV_DISP_ROT_MAX_BUF (10*1024) +# define LV_DISP_ROT_MAX_BUF (10*1024) # endif #endif + /*------------- * GPU *-----------*/ @@ -282,7 +327,7 @@ # ifdef CONFIG_LV_USE_GPU_STM32_DMA2D # define LV_USE_GPU_STM32_DMA2D CONFIG_LV_USE_GPU_STM32_DMA2D # else -# define LV_USE_GPU_STM32_DMA2D 0 +# define LV_USE_GPU_STM32_DMA2D 0 # endif #endif #if LV_USE_GPU_STM32_DMA2D @@ -292,7 +337,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_GPU_DMA2D_CMSIS_INCLUDE # define LV_GPU_DMA2D_CMSIS_INCLUDE CONFIG_LV_GPU_DMA2D_CMSIS_INCLUDE # else -# define LV_GPU_DMA2D_CMSIS_INCLUDE +# define LV_GPU_DMA2D_CMSIS_INCLUDE # endif #endif #endif @@ -302,7 +347,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_USE_GPU_NXP_PXP # define LV_USE_GPU_NXP_PXP CONFIG_LV_USE_GPU_NXP_PXP # else -# define LV_USE_GPU_NXP_PXP 0 +# define LV_USE_GPU_NXP_PXP 0 # endif #endif #if LV_USE_GPU_NXP_PXP @@ -315,7 +360,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_USE_GPU_NXP_PXP_AUTO_INIT # define LV_USE_GPU_NXP_PXP_AUTO_INIT CONFIG_LV_USE_GPU_NXP_PXP_AUTO_INIT # else -# define LV_USE_GPU_NXP_PXP_AUTO_INIT 0 +# define LV_USE_GPU_NXP_PXP_AUTO_INIT 0 # endif #endif #endif @@ -325,10 +370,37 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_USE_GPU_NXP_VG_LITE # define LV_USE_GPU_NXP_VG_LITE CONFIG_LV_USE_GPU_NXP_VG_LITE # else -# define LV_USE_GPU_NXP_VG_LITE 0 +# define LV_USE_GPU_NXP_VG_LITE 0 # endif #endif +/*Use exnternal renderer*/ +#ifndef LV_USE_EXTERNAL_RENDERER +# ifdef CONFIG_LV_USE_EXTERNAL_RENDERER +# define LV_USE_EXTERNAL_RENDERER CONFIG_LV_USE_EXTERNAL_RENDERER +# else +# define LV_USE_EXTERNAL_RENDERER 0 +# endif +#endif + +/*Use SDL renderer API. Requires LV_USE_EXTERNAL_RENDERER*/ +#ifndef LV_USE_GPU_SDL +# ifdef CONFIG_LV_USE_GPU_SDL +# define LV_USE_GPU_SDL CONFIG_LV_USE_GPU_SDL +# else +# define LV_USE_GPU_SDL 0 +# endif +#endif +#if LV_USE_GPU_SDL +#ifndef LV_GPU_SDL_INCLUDE_PATH +# ifdef CONFIG_LV_GPU_SDL_INCLUDE_PATH +# define LV_GPU_SDL_INCLUDE_PATH CONFIG_LV_GPU_SDL_INCLUDE_PATH +# else +# define LV_GPU_SDL_INCLUDE_PATH +# endif +#endif +#endif + /*------------- * Logging *-----------*/ @@ -338,7 +410,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_USE_LOG # define LV_USE_LOG CONFIG_LV_USE_LOG # else -# define LV_USE_LOG 0 +# define LV_USE_LOG 0 # endif #endif #if LV_USE_LOG @@ -354,7 +426,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_LOG_LEVEL # define LV_LOG_LEVEL CONFIG_LV_LOG_LEVEL # else -# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN +# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN # endif #endif @@ -364,65 +436,97 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_LOG_PRINTF # define LV_LOG_PRINTF CONFIG_LV_LOG_PRINTF # else -# define LV_LOG_PRINTF 0 +# define LV_LOG_PRINTF 0 # endif #endif /*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/ #ifndef LV_LOG_TRACE_MEM -# ifdef CONFIG_LV_LOG_TRACE_MEM -# define LV_LOG_TRACE_MEM CONFIG_LV_LOG_TRACE_MEM +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_LOG_TRACE_MEM +# define LV_LOG_TRACE_MEM CONFIG_LV_LOG_TRACE_MEM +# else +# define LV_LOG_TRACE_MEM 0 +# endif # else -# define LV_LOG_TRACE_MEM 1 +# define LV_LOG_TRACE_MEM 1 # endif #endif #ifndef LV_LOG_TRACE_TIMER -# ifdef CONFIG_LV_LOG_TRACE_TIMER -# define LV_LOG_TRACE_TIMER CONFIG_LV_LOG_TRACE_TIMER +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_LOG_TRACE_TIMER +# define LV_LOG_TRACE_TIMER CONFIG_LV_LOG_TRACE_TIMER +# else +# define LV_LOG_TRACE_TIMER 0 +# endif # else -# define LV_LOG_TRACE_TIMER 1 +# define LV_LOG_TRACE_TIMER 1 # endif #endif #ifndef LV_LOG_TRACE_INDEV -# ifdef CONFIG_LV_LOG_TRACE_INDEV -# define LV_LOG_TRACE_INDEV CONFIG_LV_LOG_TRACE_INDEV +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_LOG_TRACE_INDEV +# define LV_LOG_TRACE_INDEV CONFIG_LV_LOG_TRACE_INDEV +# else +# define LV_LOG_TRACE_INDEV 0 +# endif # else -# define LV_LOG_TRACE_INDEV 1 +# define LV_LOG_TRACE_INDEV 1 # endif #endif #ifndef LV_LOG_TRACE_DISP_REFR -# ifdef CONFIG_LV_LOG_TRACE_DISP_REFR -# define LV_LOG_TRACE_DISP_REFR CONFIG_LV_LOG_TRACE_DISP_REFR +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_LOG_TRACE_DISP_REFR +# define LV_LOG_TRACE_DISP_REFR CONFIG_LV_LOG_TRACE_DISP_REFR +# else +# define LV_LOG_TRACE_DISP_REFR 0 +# endif # else -# define LV_LOG_TRACE_DISP_REFR 1 +# define LV_LOG_TRACE_DISP_REFR 1 # endif #endif #ifndef LV_LOG_TRACE_EVENT -# ifdef CONFIG_LV_LOG_TRACE_EVENT -# define LV_LOG_TRACE_EVENT CONFIG_LV_LOG_TRACE_EVENT +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_LOG_TRACE_EVENT +# define LV_LOG_TRACE_EVENT CONFIG_LV_LOG_TRACE_EVENT +# else +# define LV_LOG_TRACE_EVENT 0 +# endif # else -# define LV_LOG_TRACE_EVENT 1 +# define LV_LOG_TRACE_EVENT 1 # endif #endif #ifndef LV_LOG_TRACE_OBJ_CREATE -# ifdef CONFIG_LV_LOG_TRACE_OBJ_CREATE -# define LV_LOG_TRACE_OBJ_CREATE CONFIG_LV_LOG_TRACE_OBJ_CREATE +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_LOG_TRACE_OBJ_CREATE +# define LV_LOG_TRACE_OBJ_CREATE CONFIG_LV_LOG_TRACE_OBJ_CREATE +# else +# define LV_LOG_TRACE_OBJ_CREATE 0 +# endif # else -# define LV_LOG_TRACE_OBJ_CREATE 1 +# define LV_LOG_TRACE_OBJ_CREATE 1 # endif #endif #ifndef LV_LOG_TRACE_LAYOUT -# ifdef CONFIG_LV_LOG_TRACE_LAYOUT -# define LV_LOG_TRACE_LAYOUT CONFIG_LV_LOG_TRACE_LAYOUT +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_LOG_TRACE_LAYOUT +# define LV_LOG_TRACE_LAYOUT CONFIG_LV_LOG_TRACE_LAYOUT +# else +# define LV_LOG_TRACE_LAYOUT 0 +# endif # else -# define LV_LOG_TRACE_LAYOUT 1 +# define LV_LOG_TRACE_LAYOUT 1 # endif #endif #ifndef LV_LOG_TRACE_ANIM -# ifdef CONFIG_LV_LOG_TRACE_ANIM -# define LV_LOG_TRACE_ANIM CONFIG_LV_LOG_TRACE_ANIM +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_LOG_TRACE_ANIM +# define LV_LOG_TRACE_ANIM CONFIG_LV_LOG_TRACE_ANIM +# else +# define LV_LOG_TRACE_ANIM 0 +# endif # else -# define LV_LOG_TRACE_ANIM 1 +# define LV_LOG_TRACE_ANIM 1 # endif #endif @@ -438,35 +542,35 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_USE_ASSERT_NULL # define LV_USE_ASSERT_NULL CONFIG_LV_USE_ASSERT_NULL # else -# define LV_USE_ASSERT_NULL 1 /*Check if the parameter is NULL. (Very fast, recommended)*/ +# define LV_USE_ASSERT_NULL 1 /*Check if the parameter is NULL. (Very fast, recommended)*/ # endif #endif #ifndef LV_USE_ASSERT_MALLOC # ifdef CONFIG_LV_USE_ASSERT_MALLOC # define LV_USE_ASSERT_MALLOC CONFIG_LV_USE_ASSERT_MALLOC # else -# define LV_USE_ASSERT_MALLOC 1 /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/ +# define LV_USE_ASSERT_MALLOC 1 /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/ # endif #endif #ifndef LV_USE_ASSERT_STYLE # ifdef CONFIG_LV_USE_ASSERT_STYLE # define LV_USE_ASSERT_STYLE CONFIG_LV_USE_ASSERT_STYLE # else -# define LV_USE_ASSERT_STYLE 0 /*Check if the styles are properly initialized. (Very fast, recommended)*/ +# define LV_USE_ASSERT_STYLE 0 /*Check if the styles are properly initialized. (Very fast, recommended)*/ # endif #endif #ifndef LV_USE_ASSERT_MEM_INTEGRITY # ifdef CONFIG_LV_USE_ASSERT_MEM_INTEGRITY # define LV_USE_ASSERT_MEM_INTEGRITY CONFIG_LV_USE_ASSERT_MEM_INTEGRITY # else -# define LV_USE_ASSERT_MEM_INTEGRITY 0 /*Check the integrity of `lv_mem` after critical operations. (Slow)*/ +# define LV_USE_ASSERT_MEM_INTEGRITY 0 /*Check the integrity of `lv_mem` after critical operations. (Slow)*/ # endif #endif #ifndef LV_USE_ASSERT_OBJ # ifdef CONFIG_LV_USE_ASSERT_OBJ # define LV_USE_ASSERT_OBJ CONFIG_LV_USE_ASSERT_OBJ # else -# define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/ +# define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/ # endif #endif @@ -475,14 +579,14 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_ASSERT_HANDLER_INCLUDE # define LV_ASSERT_HANDLER_INCLUDE CONFIG_LV_ASSERT_HANDLER_INCLUDE # else -# define LV_ASSERT_HANDLER_INCLUDE +# define LV_ASSERT_HANDLER_INCLUDE # endif #endif #ifndef LV_ASSERT_HANDLER # ifdef CONFIG_LV_ASSERT_HANDLER # define LV_ASSERT_HANDLER CONFIG_LV_ASSERT_HANDLER # else -# define LV_ASSERT_HANDLER while(1); /*Halt by default*/ +# define LV_ASSERT_HANDLER while(1); /*Halt by default*/ # endif #endif @@ -495,26 +599,44 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_USE_PERF_MONITOR # define LV_USE_PERF_MONITOR CONFIG_LV_USE_PERF_MONITOR # else -# define LV_USE_PERF_MONITOR 0 +# define LV_USE_PERF_MONITOR 0 # endif #endif +#if LV_USE_PERF_MONITOR +#ifndef LV_USE_PERF_MONITOR_POS +# ifdef CONFIG_LV_USE_PERF_MONITOR_POS +# define LV_USE_PERF_MONITOR_POS CONFIG_LV_USE_PERF_MONITOR_POS +# else +# define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT +# endif +#endif +#endif -/*1: Show the used memory and the memory fragmentation in the left bottom corner +/*1: Show the used memory and the memory fragmentation in the left bottom corner * Requires LV_MEM_CUSTOM = 0*/ #ifndef LV_USE_MEM_MONITOR # ifdef CONFIG_LV_USE_MEM_MONITOR # define LV_USE_MEM_MONITOR CONFIG_LV_USE_MEM_MONITOR # else -# define LV_USE_MEM_MONITOR 0 +# define LV_USE_MEM_MONITOR 0 # endif #endif +#if LV_USE_PERF_MONITOR +#ifndef LV_USE_MEM_MONITOR_POS +# ifdef CONFIG_LV_USE_MEM_MONITOR_POS +# define LV_USE_MEM_MONITOR_POS CONFIG_LV_USE_MEM_MONITOR_POS +# else +# define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT +# endif +#endif +#endif /*1: Draw random colored rectangles over the redrawn areas*/ #ifndef LV_USE_REFR_DEBUG # ifdef CONFIG_LV_USE_REFR_DEBUG # define LV_USE_REFR_DEBUG CONFIG_LV_USE_REFR_DEBUG # else -# define LV_USE_REFR_DEBUG 0 +# define LV_USE_REFR_DEBUG 0 # endif #endif @@ -523,7 +645,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_SPRINTF_CUSTOM # define LV_SPRINTF_CUSTOM CONFIG_LV_SPRINTF_CUSTOM # else -# define LV_SPRINTF_CUSTOM 0 +# define LV_SPRINTF_CUSTOM 0 # endif #endif #if LV_SPRINTF_CUSTOM @@ -531,21 +653,21 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_SPRINTF_INCLUDE # define LV_SPRINTF_INCLUDE CONFIG_LV_SPRINTF_INCLUDE # else -# define LV_SPRINTF_INCLUDE +# define LV_SPRINTF_INCLUDE # endif #endif #ifndef lv_snprintf # ifdef CONFIG_LV_SNPRINTF # define lv_snprintf CONFIG_LV_SNPRINTF # else -# define lv_snprintf snprintf +# define lv_snprintf snprintf # endif #endif #ifndef lv_vsnprintf # ifdef CONFIG_LV_VSNPRINTF # define lv_vsnprintf CONFIG_LV_VSNPRINTF # else -# define lv_vsnprintf vsnprintf +# define lv_vsnprintf vsnprintf # endif #endif #else /*LV_SPRINTF_CUSTOM*/ @@ -553,26 +675,30 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_SPRINTF_USE_FLOAT # define LV_SPRINTF_USE_FLOAT CONFIG_LV_SPRINTF_USE_FLOAT # else -# define LV_SPRINTF_USE_FLOAT 0 +# define LV_SPRINTF_USE_FLOAT 0 # endif #endif #endif /*LV_SPRINTF_CUSTOM*/ #ifndef LV_USE_USER_DATA -# ifdef CONFIG_LV_USE_USER_DATA -# define LV_USE_USER_DATA CONFIG_LV_USE_USER_DATA +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_USER_DATA +# define LV_USE_USER_DATA CONFIG_LV_USE_USER_DATA +# else +# define LV_USE_USER_DATA 0 +# endif # else -# define LV_USE_USER_DATA 1 +# define LV_USE_USER_DATA 1 # endif #endif /*Garbage Collector settings - *Used if lvgl is binded to higher level language and the memory is managed by that language*/ + *Used if lvgl is bound to higher level language and the memory is managed by that language*/ #ifndef LV_ENABLE_GC # ifdef CONFIG_LV_ENABLE_GC # define LV_ENABLE_GC CONFIG_LV_ENABLE_GC # else -# define LV_ENABLE_GC 0 +# define LV_ENABLE_GC 0 # endif #endif #if LV_ENABLE_GC != 0 @@ -580,7 +706,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_GC_INCLUDE # define LV_GC_INCLUDE CONFIG_LV_GC_INCLUDE # else -# define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ +# define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ # endif #endif #endif /*LV_ENABLE_GC*/ @@ -594,7 +720,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_BIG_ENDIAN_SYSTEM # define LV_BIG_ENDIAN_SYSTEM CONFIG_LV_BIG_ENDIAN_SYSTEM # else -# define LV_BIG_ENDIAN_SYSTEM 0 +# define LV_BIG_ENDIAN_SYSTEM 0 # endif #endif @@ -603,7 +729,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_ATTRIBUTE_TICK_INC # define LV_ATTRIBUTE_TICK_INC CONFIG_LV_ATTRIBUTE_TICK_INC # else -# define LV_ATTRIBUTE_TICK_INC +# define LV_ATTRIBUTE_TICK_INC # endif #endif @@ -612,7 +738,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_ATTRIBUTE_TIMER_HANDLER # define LV_ATTRIBUTE_TIMER_HANDLER CONFIG_LV_ATTRIBUTE_TIMER_HANDLER # else -# define LV_ATTRIBUTE_TIMER_HANDLER +# define LV_ATTRIBUTE_TIMER_HANDLER # endif #endif @@ -621,16 +747,20 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_ATTRIBUTE_FLUSH_READY # define LV_ATTRIBUTE_FLUSH_READY CONFIG_LV_ATTRIBUTE_FLUSH_READY # else -# define LV_ATTRIBUTE_FLUSH_READY +# define LV_ATTRIBUTE_FLUSH_READY # endif #endif /*Required alignment size for buffers*/ #ifndef LV_ATTRIBUTE_MEM_ALIGN_SIZE -# ifdef CONFIG_LV_ATTRIBUTE_MEM_ALIGN_SIZE -# define LV_ATTRIBUTE_MEM_ALIGN_SIZE CONFIG_LV_ATTRIBUTE_MEM_ALIGN_SIZE +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_ATTRIBUTE_MEM_ALIGN_SIZE +# define LV_ATTRIBUTE_MEM_ALIGN_SIZE CONFIG_LV_ATTRIBUTE_MEM_ALIGN_SIZE +# else +# define LV_ATTRIBUTE_MEM_ALIGN_SIZE 0 +# endif # else -# define LV_ATTRIBUTE_MEM_ALIGN_SIZE +# define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1 # endif #endif @@ -640,7 +770,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_ATTRIBUTE_MEM_ALIGN # define LV_ATTRIBUTE_MEM_ALIGN CONFIG_LV_ATTRIBUTE_MEM_ALIGN # else -# define LV_ATTRIBUTE_MEM_ALIGN +# define LV_ATTRIBUTE_MEM_ALIGN # endif #endif @@ -649,7 +779,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_ATTRIBUTE_LARGE_CONST # define LV_ATTRIBUTE_LARGE_CONST CONFIG_LV_ATTRIBUTE_LARGE_CONST # else -# define LV_ATTRIBUTE_LARGE_CONST +# define LV_ATTRIBUTE_LARGE_CONST # endif #endif @@ -658,7 +788,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_ATTRIBUTE_LARGE_RAM_ARRAY # define LV_ATTRIBUTE_LARGE_RAM_ARRAY CONFIG_LV_ATTRIBUTE_LARGE_RAM_ARRAY # else -# define LV_ATTRIBUTE_LARGE_RAM_ARRAY +# define LV_ATTRIBUTE_LARGE_RAM_ARRAY # endif #endif @@ -667,7 +797,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_ATTRIBUTE_FAST_MEM # define LV_ATTRIBUTE_FAST_MEM CONFIG_LV_ATTRIBUTE_FAST_MEM # else -# define LV_ATTRIBUTE_FAST_MEM +# define LV_ATTRIBUTE_FAST_MEM # endif #endif @@ -676,7 +806,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_ATTRIBUTE_DMA # define LV_ATTRIBUTE_DMA CONFIG_LV_ATTRIBUTE_DMA # else -# define LV_ATTRIBUTE_DMA +# define LV_ATTRIBUTE_DMA # endif #endif @@ -686,7 +816,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_EXPORT_CONST_INT # define LV_EXPORT_CONST_INT CONFIG_LV_EXPORT_CONST_INT # else -# define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/ +# define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/ # endif #endif @@ -695,7 +825,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_USE_LARGE_COORD # define LV_USE_LARGE_COORD CONFIG_LV_USE_LARGE_COORD # else -# define LV_USE_LARGE_COORD 0 +# define LV_USE_LARGE_COORD 0 # endif #endif @@ -709,147 +839,151 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_FONT_MONTSERRAT_8 # define LV_FONT_MONTSERRAT_8 CONFIG_LV_FONT_MONTSERRAT_8 # else -# define LV_FONT_MONTSERRAT_8 0 +# define LV_FONT_MONTSERRAT_8 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_10 # ifdef CONFIG_LV_FONT_MONTSERRAT_10 # define LV_FONT_MONTSERRAT_10 CONFIG_LV_FONT_MONTSERRAT_10 # else -# define LV_FONT_MONTSERRAT_10 0 +# define LV_FONT_MONTSERRAT_10 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_12 # ifdef CONFIG_LV_FONT_MONTSERRAT_12 # define LV_FONT_MONTSERRAT_12 CONFIG_LV_FONT_MONTSERRAT_12 # else -# define LV_FONT_MONTSERRAT_12 0 +# define LV_FONT_MONTSERRAT_12 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_14 -# ifdef CONFIG_LV_FONT_MONTSERRAT_14 -# define LV_FONT_MONTSERRAT_14 CONFIG_LV_FONT_MONTSERRAT_14 +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_FONT_MONTSERRAT_14 +# define LV_FONT_MONTSERRAT_14 CONFIG_LV_FONT_MONTSERRAT_14 +# else +# define LV_FONT_MONTSERRAT_14 0 +# endif # else -# define LV_FONT_MONTSERRAT_14 1 +# define LV_FONT_MONTSERRAT_14 1 # endif #endif #ifndef LV_FONT_MONTSERRAT_16 # ifdef CONFIG_LV_FONT_MONTSERRAT_16 # define LV_FONT_MONTSERRAT_16 CONFIG_LV_FONT_MONTSERRAT_16 # else -# define LV_FONT_MONTSERRAT_16 0 +# define LV_FONT_MONTSERRAT_16 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_18 # ifdef CONFIG_LV_FONT_MONTSERRAT_18 # define LV_FONT_MONTSERRAT_18 CONFIG_LV_FONT_MONTSERRAT_18 # else -# define LV_FONT_MONTSERRAT_18 0 +# define LV_FONT_MONTSERRAT_18 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_20 # ifdef CONFIG_LV_FONT_MONTSERRAT_20 # define LV_FONT_MONTSERRAT_20 CONFIG_LV_FONT_MONTSERRAT_20 # else -# define LV_FONT_MONTSERRAT_20 0 +# define LV_FONT_MONTSERRAT_20 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_22 # ifdef CONFIG_LV_FONT_MONTSERRAT_22 # define LV_FONT_MONTSERRAT_22 CONFIG_LV_FONT_MONTSERRAT_22 # else -# define LV_FONT_MONTSERRAT_22 0 +# define LV_FONT_MONTSERRAT_22 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_24 # ifdef CONFIG_LV_FONT_MONTSERRAT_24 # define LV_FONT_MONTSERRAT_24 CONFIG_LV_FONT_MONTSERRAT_24 # else -# define LV_FONT_MONTSERRAT_24 0 +# define LV_FONT_MONTSERRAT_24 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_26 # ifdef CONFIG_LV_FONT_MONTSERRAT_26 # define LV_FONT_MONTSERRAT_26 CONFIG_LV_FONT_MONTSERRAT_26 # else -# define LV_FONT_MONTSERRAT_26 0 +# define LV_FONT_MONTSERRAT_26 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_28 # ifdef CONFIG_LV_FONT_MONTSERRAT_28 # define LV_FONT_MONTSERRAT_28 CONFIG_LV_FONT_MONTSERRAT_28 # else -# define LV_FONT_MONTSERRAT_28 0 +# define LV_FONT_MONTSERRAT_28 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_30 # ifdef CONFIG_LV_FONT_MONTSERRAT_30 # define LV_FONT_MONTSERRAT_30 CONFIG_LV_FONT_MONTSERRAT_30 # else -# define LV_FONT_MONTSERRAT_30 0 +# define LV_FONT_MONTSERRAT_30 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_32 # ifdef CONFIG_LV_FONT_MONTSERRAT_32 # define LV_FONT_MONTSERRAT_32 CONFIG_LV_FONT_MONTSERRAT_32 # else -# define LV_FONT_MONTSERRAT_32 0 +# define LV_FONT_MONTSERRAT_32 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_34 # ifdef CONFIG_LV_FONT_MONTSERRAT_34 # define LV_FONT_MONTSERRAT_34 CONFIG_LV_FONT_MONTSERRAT_34 # else -# define LV_FONT_MONTSERRAT_34 0 +# define LV_FONT_MONTSERRAT_34 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_36 # ifdef CONFIG_LV_FONT_MONTSERRAT_36 # define LV_FONT_MONTSERRAT_36 CONFIG_LV_FONT_MONTSERRAT_36 # else -# define LV_FONT_MONTSERRAT_36 0 +# define LV_FONT_MONTSERRAT_36 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_38 # ifdef CONFIG_LV_FONT_MONTSERRAT_38 # define LV_FONT_MONTSERRAT_38 CONFIG_LV_FONT_MONTSERRAT_38 # else -# define LV_FONT_MONTSERRAT_38 0 +# define LV_FONT_MONTSERRAT_38 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_40 # ifdef CONFIG_LV_FONT_MONTSERRAT_40 # define LV_FONT_MONTSERRAT_40 CONFIG_LV_FONT_MONTSERRAT_40 # else -# define LV_FONT_MONTSERRAT_40 0 +# define LV_FONT_MONTSERRAT_40 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_42 # ifdef CONFIG_LV_FONT_MONTSERRAT_42 # define LV_FONT_MONTSERRAT_42 CONFIG_LV_FONT_MONTSERRAT_42 # else -# define LV_FONT_MONTSERRAT_42 0 +# define LV_FONT_MONTSERRAT_42 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_44 # ifdef CONFIG_LV_FONT_MONTSERRAT_44 # define LV_FONT_MONTSERRAT_44 CONFIG_LV_FONT_MONTSERRAT_44 # else -# define LV_FONT_MONTSERRAT_44 0 +# define LV_FONT_MONTSERRAT_44 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_46 # ifdef CONFIG_LV_FONT_MONTSERRAT_46 # define LV_FONT_MONTSERRAT_46 CONFIG_LV_FONT_MONTSERRAT_46 # else -# define LV_FONT_MONTSERRAT_46 0 +# define LV_FONT_MONTSERRAT_46 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_48 # ifdef CONFIG_LV_FONT_MONTSERRAT_48 # define LV_FONT_MONTSERRAT_48 CONFIG_LV_FONT_MONTSERRAT_48 # else -# define LV_FONT_MONTSERRAT_48 0 +# define LV_FONT_MONTSERRAT_48 0 # endif #endif @@ -858,28 +992,28 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_FONT_MONTSERRAT_12_SUBPX # define LV_FONT_MONTSERRAT_12_SUBPX CONFIG_LV_FONT_MONTSERRAT_12_SUBPX # else -# define LV_FONT_MONTSERRAT_12_SUBPX 0 +# define LV_FONT_MONTSERRAT_12_SUBPX 0 # endif #endif #ifndef LV_FONT_MONTSERRAT_28_COMPRESSED # ifdef CONFIG_LV_FONT_MONTSERRAT_28_COMPRESSED # define LV_FONT_MONTSERRAT_28_COMPRESSED CONFIG_LV_FONT_MONTSERRAT_28_COMPRESSED # else -# define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/ +# define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/ # endif #endif #ifndef LV_FONT_DEJAVU_16_PERSIAN_HEBREW # ifdef CONFIG_LV_FONT_DEJAVU_16_PERSIAN_HEBREW # define LV_FONT_DEJAVU_16_PERSIAN_HEBREW CONFIG_LV_FONT_DEJAVU_16_PERSIAN_HEBREW # else -# define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, Perisan letters and all their forms*/ +# define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, Perisan letters and all their forms*/ # endif #endif #ifndef LV_FONT_SIMSUN_16_CJK # ifdef CONFIG_LV_FONT_SIMSUN_16_CJK # define LV_FONT_SIMSUN_16_CJK CONFIG_LV_FONT_SIMSUN_16_CJK # else -# define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/ +# define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/ # endif #endif @@ -888,14 +1022,14 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_FONT_UNSCII_8 # define LV_FONT_UNSCII_8 CONFIG_LV_FONT_UNSCII_8 # else -# define LV_FONT_UNSCII_8 0 +# define LV_FONT_UNSCII_8 0 # endif #endif #ifndef LV_FONT_UNSCII_16 # ifdef CONFIG_LV_FONT_UNSCII_16 # define LV_FONT_UNSCII_16 CONFIG_LV_FONT_UNSCII_16 # else -# define LV_FONT_UNSCII_16 0 +# define LV_FONT_UNSCII_16 0 # endif #endif @@ -906,7 +1040,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_FONT_CUSTOM_DECLARE # define LV_FONT_CUSTOM_DECLARE CONFIG_LV_FONT_CUSTOM_DECLARE # else -# define LV_FONT_CUSTOM_DECLARE +# define LV_FONT_CUSTOM_DECLARE # endif #endif @@ -915,7 +1049,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_FONT_DEFAULT # define LV_FONT_DEFAULT CONFIG_LV_FONT_DEFAULT # else -# define LV_FONT_DEFAULT &lv_font_montserrat_14 +# define LV_FONT_DEFAULT &lv_font_montserrat_14 # endif #endif @@ -926,7 +1060,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_FONT_FMT_TXT_LARGE # define LV_FONT_FMT_TXT_LARGE CONFIG_LV_FONT_FMT_TXT_LARGE # else -# define LV_FONT_FMT_TXT_LARGE 0 +# define LV_FONT_FMT_TXT_LARGE 0 # endif #endif @@ -935,7 +1069,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_USE_FONT_COMPRESSED # define LV_USE_FONT_COMPRESSED CONFIG_LV_USE_FONT_COMPRESSED # else -# define LV_USE_FONT_COMPRESSED 0 +# define LV_USE_FONT_COMPRESSED 0 # endif #endif @@ -944,7 +1078,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_USE_FONT_SUBPX # define LV_USE_FONT_SUBPX CONFIG_LV_USE_FONT_SUBPX # else -# define LV_USE_FONT_SUBPX 0 +# define LV_USE_FONT_SUBPX 0 # endif #endif #if LV_USE_FONT_SUBPX @@ -953,7 +1087,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_FONT_SUBPX_BGR # define LV_FONT_SUBPX_BGR CONFIG_LV_FONT_SUBPX_BGR # else -# define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/ +# define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/ # endif #endif #endif @@ -972,7 +1106,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_TXT_ENC # define LV_TXT_ENC CONFIG_LV_TXT_ENC # else -# define LV_TXT_ENC LV_TXT_ENC_UTF8 +# define LV_TXT_ENC LV_TXT_ENC_UTF8 # endif #endif @@ -981,7 +1115,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_TXT_BREAK_CHARS # define LV_TXT_BREAK_CHARS CONFIG_LV_TXT_BREAK_CHARS # else -# define LV_TXT_BREAK_CHARS " ,.;:-_" +# define LV_TXT_BREAK_CHARS " ,.;:-_" # endif #endif @@ -991,7 +1125,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_TXT_LINE_BREAK_LONG_LEN # define LV_TXT_LINE_BREAK_LONG_LEN CONFIG_LV_TXT_LINE_BREAK_LONG_LEN # else -# define LV_TXT_LINE_BREAK_LONG_LEN 0 +# define LV_TXT_LINE_BREAK_LONG_LEN 0 # endif #endif @@ -1001,7 +1135,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN # define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN CONFIG_LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN # else -# define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 +# define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 # endif #endif @@ -1011,7 +1145,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN # define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN CONFIG_LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN # else -# define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3 +# define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3 # endif #endif @@ -1020,18 +1154,18 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_TXT_COLOR_CMD # define LV_TXT_COLOR_CMD CONFIG_LV_TXT_COLOR_CMD # else -# define LV_TXT_COLOR_CMD "#" +# define LV_TXT_COLOR_CMD "#" # endif #endif /*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts. - *The direction will be processed according to the Unicode Bidirectioanl Algorithm: + *The direction will be processed according to the Unicode Bidirectional Algorithm: *https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ #ifndef LV_USE_BIDI # ifdef CONFIG_LV_USE_BIDI # define LV_USE_BIDI CONFIG_LV_USE_BIDI # else -# define LV_USE_BIDI 0 +# define LV_USE_BIDI 0 # endif #endif #if LV_USE_BIDI @@ -1043,7 +1177,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_BIDI_BASE_DIR_DEF # define LV_BIDI_BASE_DIR_DEF CONFIG_LV_BIDI_BASE_DIR_DEF # else -# define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO +# define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO # endif #endif #endif @@ -1054,7 +1188,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_USE_ARABIC_PERSIAN_CHARS # define LV_USE_ARABIC_PERSIAN_CHARS CONFIG_LV_USE_ARABIC_PERSIAN_CHARS # else -# define LV_USE_ARABIC_PERSIAN_CHARS 0 +# define LV_USE_ARABIC_PERSIAN_CHARS 0 # endif #endif @@ -1065,67 +1199,94 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/ #ifndef LV_USE_ARC -# ifdef CONFIG_LV_USE_ARC -# define LV_USE_ARC CONFIG_LV_USE_ARC +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_ARC +# define LV_USE_ARC CONFIG_LV_USE_ARC +# else +# define LV_USE_ARC 0 +# endif # else -# define LV_USE_ARC 1 +# define LV_USE_ARC 1 # endif #endif #ifndef LV_USE_ANIMIMG -# ifdef CONFIG_LV_USE_ANIMIMG -# define LV_USE_ANIMIMG CONFIG_LV_USE_ANIMIMG +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_ANIMIMG +# define LV_USE_ANIMIMG CONFIG_LV_USE_ANIMIMG +# else +# define LV_USE_ANIMIMG 0 +# endif # else -# define LV_USE_ANIMIMG 1 +# define LV_USE_ANIMIMG 1 # endif #endif #ifndef LV_USE_BAR -# ifdef CONFIG_LV_USE_BAR -# define LV_USE_BAR CONFIG_LV_USE_BAR +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_BAR +# define LV_USE_BAR CONFIG_LV_USE_BAR +# else +# define LV_USE_BAR 0 +# endif # else -# define LV_USE_BAR 1 +# define LV_USE_BAR 1 # endif #endif #ifndef LV_USE_BTN -# ifdef CONFIG_LV_USE_BTN -# define LV_USE_BTN CONFIG_LV_USE_BTN +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_BTN +# define LV_USE_BTN CONFIG_LV_USE_BTN +# else +# define LV_USE_BTN 0 +# endif # else -# define LV_USE_BTN 1 +# define LV_USE_BTN 1 # endif #endif #ifndef LV_USE_BTNMATRIX -# ifdef CONFIG_LV_USE_BTNMATRIX -# define LV_USE_BTNMATRIX CONFIG_LV_USE_BTNMATRIX +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_BTNMATRIX +# define LV_USE_BTNMATRIX CONFIG_LV_USE_BTNMATRIX +# else +# define LV_USE_BTNMATRIX 0 +# endif # else -# define LV_USE_BTNMATRIX 1 +# define LV_USE_BTNMATRIX 1 # endif #endif #ifndef LV_USE_CANVAS -# ifdef CONFIG_LV_USE_CANVAS -# define LV_USE_CANVAS CONFIG_LV_USE_CANVAS +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_CANVAS +# define LV_USE_CANVAS CONFIG_LV_USE_CANVAS +# else +# define LV_USE_CANVAS 0 +# endif # else -# define LV_USE_CANVAS 1 +# define LV_USE_CANVAS 1 # endif #endif #ifndef LV_USE_CHECKBOX -# ifdef CONFIG_LV_USE_CHECKBOX -# define LV_USE_CHECKBOX CONFIG_LV_USE_CHECKBOX +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_CHECKBOX +# define LV_USE_CHECKBOX CONFIG_LV_USE_CHECKBOX +# else +# define LV_USE_CHECKBOX 0 +# endif # else -# define LV_USE_CHECKBOX 1 +# define LV_USE_CHECKBOX 1 # endif #endif - #ifndef LV_USE_DROPDOWN # ifdef CONFIG_LV_USE_DROPDOWN # define LV_USE_DROPDOWN CONFIG_LV_USE_DROPDOWN # else -# define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ +# define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ # endif #endif @@ -1133,15 +1294,19 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_USE_IMG # define LV_USE_IMG CONFIG_LV_USE_IMG # else -# define LV_USE_IMG 1 /*Requires: lv_label*/ +# define LV_USE_IMG 1 /*Requires: lv_label*/ # endif #endif #ifndef LV_USE_LABEL -# ifdef CONFIG_LV_USE_LABEL -# define LV_USE_LABEL CONFIG_LV_USE_LABEL +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_LABEL +# define LV_USE_LABEL CONFIG_LV_USE_LABEL +# else +# define LV_USE_LABEL 0 +# endif # else -# define LV_USE_LABEL 1 +# define LV_USE_LABEL 1 # endif #endif #if LV_USE_LABEL @@ -1149,23 +1314,27 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_LABEL_TEXT_SELECTION # define LV_LABEL_TEXT_SELECTION CONFIG_LV_LABEL_TEXT_SELECTION # else -# define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ +# define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ # endif #endif #ifndef LV_LABEL_LONG_TXT_HINT # ifdef CONFIG_LV_LABEL_LONG_TXT_HINT # define LV_LABEL_LONG_TXT_HINT CONFIG_LV_LABEL_LONG_TXT_HINT # else -# define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ +# define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ # endif #endif #endif #ifndef LV_USE_LINE -# ifdef CONFIG_LV_USE_LINE -# define LV_USE_LINE CONFIG_LV_USE_LINE +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_LINE +# define LV_USE_LINE CONFIG_LV_USE_LINE +# else +# define LV_USE_LINE 0 +# endif # else -# define LV_USE_LINE 1 +# define LV_USE_LINE 1 # endif #endif @@ -1173,7 +1342,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_USE_ROLLER # define LV_USE_ROLLER CONFIG_LV_USE_ROLLER # else -# define LV_USE_ROLLER 1 /*Requires: lv_label*/ +# define LV_USE_ROLLER 1 /*Requires: lv_label*/ # endif #endif #if LV_USE_ROLLER @@ -1181,7 +1350,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_ROLLER_INF_PAGES # define LV_ROLLER_INF_PAGES CONFIG_LV_ROLLER_INF_PAGES # else -# define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/ +# define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/ # endif #endif #endif @@ -1190,15 +1359,19 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_USE_SLIDER # define LV_USE_SLIDER CONFIG_LV_USE_SLIDER # else -# define LV_USE_SLIDER 1 /*Requires: lv_bar*/ +# define LV_USE_SLIDER 1 /*Requires: lv_bar*/ # endif #endif #ifndef LV_USE_SWITCH -# ifdef CONFIG_LV_USE_SWITCH -# define LV_USE_SWITCH CONFIG_LV_USE_SWITCH +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_SWITCH +# define LV_USE_SWITCH CONFIG_LV_USE_SWITCH +# else +# define LV_USE_SWITCH 0 +# endif # else -# define LV_USE_SWITCH 1 +# define LV_USE_SWITCH 1 # endif #endif @@ -1206,7 +1379,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_USE_TEXTAREA # define LV_USE_TEXTAREA CONFIG_LV_USE_TEXTAREA # else -# define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ +# define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ # endif #endif #if LV_USE_TEXTAREA != 0 @@ -1214,16 +1387,20 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_TEXTAREA_DEF_PWD_SHOW_TIME # define LV_TEXTAREA_DEF_PWD_SHOW_TIME CONFIG_LV_TEXTAREA_DEF_PWD_SHOW_TIME # else -# define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ +# define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ # endif #endif #endif #ifndef LV_USE_TABLE -# ifdef CONFIG_LV_USE_TABLE -# define LV_USE_TABLE CONFIG_LV_USE_TABLE +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_TABLE +# define LV_USE_TABLE CONFIG_LV_USE_TABLE +# else +# define LV_USE_TABLE 0 +# endif # else -# define LV_USE_TABLE 1 +# define LV_USE_TABLE 1 # endif #endif @@ -1235,10 +1412,14 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ * Widgets *----------*/ #ifndef LV_USE_CALENDAR -# ifdef CONFIG_LV_USE_CALENDAR -# define LV_USE_CALENDAR CONFIG_LV_USE_CALENDAR +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_CALENDAR +# define LV_USE_CALENDAR CONFIG_LV_USE_CALENDAR +# else +# define LV_USE_CALENDAR 0 +# endif # else -# define LV_USE_CALENDAR 1 +# define LV_USE_CALENDAR 1 # endif #endif #if LV_USE_CALENDAR @@ -1246,7 +1427,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_CALENDAR_WEEK_STARTS_MONDAY # define LV_CALENDAR_WEEK_STARTS_MONDAY CONFIG_LV_CALENDAR_WEEK_STARTS_MONDAY # else -# define LV_CALENDAR_WEEK_STARTS_MONDAY 0 +# define LV_CALENDAR_WEEK_STARTS_MONDAY 0 # endif #endif # if LV_CALENDAR_WEEK_STARTS_MONDAY @@ -1254,7 +1435,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES # define LV_CALENDAR_DEFAULT_DAY_NAMES CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES # else -# define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"} +# define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"} # endif #endif # else @@ -1262,7 +1443,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES # define LV_CALENDAR_DEFAULT_DAY_NAMES CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES # else -# define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"} +# define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"} # endif #endif # endif @@ -1271,134 +1452,198 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_CALENDAR_DEFAULT_MONTH_NAMES # define LV_CALENDAR_DEFAULT_MONTH_NAMES CONFIG_LV_CALENDAR_DEFAULT_MONTH_NAMES # else -# define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"} +# define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"} # endif #endif #ifndef LV_USE_CALENDAR_HEADER_ARROW -# ifdef CONFIG_LV_USE_CALENDAR_HEADER_ARROW -# define LV_USE_CALENDAR_HEADER_ARROW CONFIG_LV_USE_CALENDAR_HEADER_ARROW +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_CALENDAR_HEADER_ARROW +# define LV_USE_CALENDAR_HEADER_ARROW CONFIG_LV_USE_CALENDAR_HEADER_ARROW +# else +# define LV_USE_CALENDAR_HEADER_ARROW 0 +# endif # else -# define LV_USE_CALENDAR_HEADER_ARROW 1 +# define LV_USE_CALENDAR_HEADER_ARROW 1 # endif #endif #ifndef LV_USE_CALENDAR_HEADER_DROPDOWN -# ifdef CONFIG_LV_USE_CALENDAR_HEADER_DROPDOWN -# define LV_USE_CALENDAR_HEADER_DROPDOWN CONFIG_LV_USE_CALENDAR_HEADER_DROPDOWN +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_CALENDAR_HEADER_DROPDOWN +# define LV_USE_CALENDAR_HEADER_DROPDOWN CONFIG_LV_USE_CALENDAR_HEADER_DROPDOWN +# else +# define LV_USE_CALENDAR_HEADER_DROPDOWN 0 +# endif # else -# define LV_USE_CALENDAR_HEADER_DROPDOWN 1 +# define LV_USE_CALENDAR_HEADER_DROPDOWN 1 # endif #endif #endif /*LV_USE_CALENDAR*/ #ifndef LV_USE_CHART -# ifdef CONFIG_LV_USE_CHART -# define LV_USE_CHART CONFIG_LV_USE_CHART +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_CHART +# define LV_USE_CHART CONFIG_LV_USE_CHART +# else +# define LV_USE_CHART 0 +# endif # else -# define LV_USE_CHART 1 +# define LV_USE_CHART 1 # endif #endif #ifndef LV_USE_COLORWHEEL -# ifdef CONFIG_LV_USE_COLORWHEEL -# define LV_USE_COLORWHEEL CONFIG_LV_USE_COLORWHEEL +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_COLORWHEEL +# define LV_USE_COLORWHEEL CONFIG_LV_USE_COLORWHEEL +# else +# define LV_USE_COLORWHEEL 0 +# endif # else -# define LV_USE_COLORWHEEL 1 +# define LV_USE_COLORWHEEL 1 # endif #endif #ifndef LV_USE_IMGBTN -# ifdef CONFIG_LV_USE_IMGBTN -# define LV_USE_IMGBTN CONFIG_LV_USE_IMGBTN +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_IMGBTN +# define LV_USE_IMGBTN CONFIG_LV_USE_IMGBTN +# else +# define LV_USE_IMGBTN 0 +# endif # else -# define LV_USE_IMGBTN 1 +# define LV_USE_IMGBTN 1 # endif #endif #ifndef LV_USE_KEYBOARD -# ifdef CONFIG_LV_USE_KEYBOARD -# define LV_USE_KEYBOARD CONFIG_LV_USE_KEYBOARD +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_KEYBOARD +# define LV_USE_KEYBOARD CONFIG_LV_USE_KEYBOARD +# else +# define LV_USE_KEYBOARD 0 +# endif # else -# define LV_USE_KEYBOARD 1 +# define LV_USE_KEYBOARD 1 # endif #endif #ifndef LV_USE_LED -# ifdef CONFIG_LV_USE_LED -# define LV_USE_LED CONFIG_LV_USE_LED +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_LED +# define LV_USE_LED CONFIG_LV_USE_LED +# else +# define LV_USE_LED 0 +# endif # else -# define LV_USE_LED 1 +# define LV_USE_LED 1 # endif #endif #ifndef LV_USE_LIST -# ifdef CONFIG_LV_USE_LIST -# define LV_USE_LIST CONFIG_LV_USE_LIST +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_LIST +# define LV_USE_LIST CONFIG_LV_USE_LIST +# else +# define LV_USE_LIST 0 +# endif # else -# define LV_USE_LIST 1 +# define LV_USE_LIST 1 # endif #endif #ifndef LV_USE_METER -# ifdef CONFIG_LV_USE_METER -# define LV_USE_METER CONFIG_LV_USE_METER +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_METER +# define LV_USE_METER CONFIG_LV_USE_METER +# else +# define LV_USE_METER 0 +# endif # else -# define LV_USE_METER 1 +# define LV_USE_METER 1 # endif #endif #ifndef LV_USE_MSGBOX -# ifdef CONFIG_LV_USE_MSGBOX -# define LV_USE_MSGBOX CONFIG_LV_USE_MSGBOX +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_MSGBOX +# define LV_USE_MSGBOX CONFIG_LV_USE_MSGBOX +# else +# define LV_USE_MSGBOX 0 +# endif # else -# define LV_USE_MSGBOX 1 +# define LV_USE_MSGBOX 1 # endif #endif #ifndef LV_USE_SPINBOX -# ifdef CONFIG_LV_USE_SPINBOX -# define LV_USE_SPINBOX CONFIG_LV_USE_SPINBOX +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_SPINBOX +# define LV_USE_SPINBOX CONFIG_LV_USE_SPINBOX +# else +# define LV_USE_SPINBOX 0 +# endif # else -# define LV_USE_SPINBOX 1 +# define LV_USE_SPINBOX 1 # endif #endif #ifndef LV_USE_SPINNER -# ifdef CONFIG_LV_USE_SPINNER -# define LV_USE_SPINNER CONFIG_LV_USE_SPINNER +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_SPINNER +# define LV_USE_SPINNER CONFIG_LV_USE_SPINNER +# else +# define LV_USE_SPINNER 0 +# endif # else -# define LV_USE_SPINNER 1 +# define LV_USE_SPINNER 1 # endif #endif #ifndef LV_USE_TABVIEW -# ifdef CONFIG_LV_USE_TABVIEW -# define LV_USE_TABVIEW CONFIG_LV_USE_TABVIEW +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_TABVIEW +# define LV_USE_TABVIEW CONFIG_LV_USE_TABVIEW +# else +# define LV_USE_TABVIEW 0 +# endif # else -# define LV_USE_TABVIEW 1 +# define LV_USE_TABVIEW 1 # endif #endif #ifndef LV_USE_TILEVIEW -# ifdef CONFIG_LV_USE_TILEVIEW -# define LV_USE_TILEVIEW CONFIG_LV_USE_TILEVIEW +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_TILEVIEW +# define LV_USE_TILEVIEW CONFIG_LV_USE_TILEVIEW +# else +# define LV_USE_TILEVIEW 0 +# endif # else -# define LV_USE_TILEVIEW 1 +# define LV_USE_TILEVIEW 1 # endif #endif #ifndef LV_USE_WIN -# ifdef CONFIG_LV_USE_WIN -# define LV_USE_WIN CONFIG_LV_USE_WIN +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_WIN +# define LV_USE_WIN CONFIG_LV_USE_WIN +# else +# define LV_USE_WIN 0 +# endif # else -# define LV_USE_WIN 1 +# define LV_USE_WIN 1 # endif #endif #ifndef LV_USE_SPAN -# ifdef CONFIG_LV_USE_SPAN -# define LV_USE_SPAN CONFIG_LV_USE_SPAN +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_SPAN +# define LV_USE_SPAN CONFIG_LV_USE_SPAN +# else +# define LV_USE_SPAN 0 +# endif # else -# define LV_USE_SPAN 1 +# define LV_USE_SPAN 1 # endif #endif #if LV_USE_SPAN @@ -1407,7 +1652,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_SPAN_SNIPPET_STACK_SIZE # define LV_SPAN_SNIPPET_STACK_SIZE CONFIG_LV_SPAN_SNIPPET_STACK_SIZE # else -# define LV_SPAN_SNIPPET_STACK_SIZE 64 +# define LV_SPAN_SNIPPET_STACK_SIZE 64 # endif #endif #endif @@ -1415,12 +1660,17 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*----------- * Themes *----------*/ + /*A simple, impressive and very complete theme*/ #ifndef LV_USE_THEME_DEFAULT -# ifdef CONFIG_LV_USE_THEME_DEFAULT -# define LV_USE_THEME_DEFAULT CONFIG_LV_USE_THEME_DEFAULT +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_THEME_DEFAULT +# define LV_USE_THEME_DEFAULT CONFIG_LV_USE_THEME_DEFAULT +# else +# define LV_USE_THEME_DEFAULT 0 +# endif # else -# define LV_USE_THEME_DEFAULT 1 +# define LV_USE_THEME_DEFAULT 1 # endif #endif #if LV_USE_THEME_DEFAULT @@ -1430,44 +1680,56 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # ifdef CONFIG_LV_THEME_DEFAULT_DARK # define LV_THEME_DEFAULT_DARK CONFIG_LV_THEME_DEFAULT_DARK # else -# define LV_THEME_DEFAULT_DARK 0 +# define LV_THEME_DEFAULT_DARK 0 # endif #endif /*1: Enable grow on press*/ #ifndef LV_THEME_DEFAULT_GROW -# ifdef CONFIG_LV_THEME_DEFAULT_GROW -# define LV_THEME_DEFAULT_GROW CONFIG_LV_THEME_DEFAULT_GROW +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_THEME_DEFAULT_GROW +# define LV_THEME_DEFAULT_GROW CONFIG_LV_THEME_DEFAULT_GROW +# else +# define LV_THEME_DEFAULT_GROW 0 +# endif # else -# define LV_THEME_DEFAULT_GROW 1 +# define LV_THEME_DEFAULT_GROW 1 # endif #endif /*Default transition time in [ms]*/ -#ifndef LV_THEME_DEFAULT_TRANSITON_TIME -# ifdef CONFIG_LV_THEME_DEFAULT_TRANSITON_TIME -# define LV_THEME_DEFAULT_TRANSITON_TIME CONFIG_LV_THEME_DEFAULT_TRANSITON_TIME +#ifndef LV_THEME_DEFAULT_TRANSITION_TIME +# ifdef CONFIG_LV_THEME_DEFAULT_TRANSITION_TIME +# define LV_THEME_DEFAULT_TRANSITION_TIME CONFIG_LV_THEME_DEFAULT_TRANSITION_TIME # else -# define LV_THEME_DEFAULT_TRANSITON_TIME 80 +# define LV_THEME_DEFAULT_TRANSITION_TIME 80 # endif #endif #endif /*LV_USE_THEME_DEFAULT*/ -/*An very simple them that is a good starting point for a custom theme*/ +/*A very simple theme that is a good starting point for a custom theme*/ #ifndef LV_USE_THEME_BASIC -# ifdef CONFIG_LV_USE_THEME_BASIC -# define LV_USE_THEME_BASIC CONFIG_LV_USE_THEME_BASIC +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_THEME_BASIC +# define LV_USE_THEME_BASIC CONFIG_LV_USE_THEME_BASIC +# else +# define LV_USE_THEME_BASIC 0 +# endif # else -# define LV_USE_THEME_BASIC 1 +# define LV_USE_THEME_BASIC 1 # endif #endif /*A theme designed for monochrome displays*/ #ifndef LV_USE_THEME_MONO -# ifdef CONFIG_LV_USE_THEME_MONO -# define LV_USE_THEME_MONO CONFIG_LV_USE_THEME_MONO +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_THEME_MONO +# define LV_USE_THEME_MONO CONFIG_LV_USE_THEME_MONO +# else +# define LV_USE_THEME_MONO 0 +# endif # else -# define LV_USE_THEME_MONO 1 +# define LV_USE_THEME_MONO 1 # endif #endif @@ -1477,32 +1739,177 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*A layout similar to Flexbox in CSS.*/ #ifndef LV_USE_FLEX -# ifdef CONFIG_LV_USE_FLEX -# define LV_USE_FLEX CONFIG_LV_USE_FLEX +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_FLEX +# define LV_USE_FLEX CONFIG_LV_USE_FLEX +# else +# define LV_USE_FLEX 0 +# endif # else -# define LV_USE_FLEX 1 +# define LV_USE_FLEX 1 # endif #endif /*A layout similar to Grid in CSS.*/ #ifndef LV_USE_GRID -# ifdef CONFIG_LV_USE_GRID -# define LV_USE_GRID CONFIG_LV_USE_GRID +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_GRID +# define LV_USE_GRID CONFIG_LV_USE_GRID +# else +# define LV_USE_GRID 0 +# endif # else -# define LV_USE_GRID 1 +# define LV_USE_GRID 1 # endif #endif +/*--------------------- + * 3rd party libraries + *--------------------*/ + +/*File system interfaces for common APIs + *To enable set a driver letter for that API*/ +#ifndef LV_USE_FS_STDIO +# ifdef CONFIG_LV_USE_FS_STDIO +# define LV_USE_FS_STDIO CONFIG_LV_USE_FS_STDIO +# else +# define LV_USE_FS_STDIO '\0' /*Uses fopen, fread, etc*/ +# endif +#endif +//#define LV_FS_STDIO_PATH "/home/john/" /*Set the working directory. If commented it will be "./" */ + +#ifndef LV_USE_FS_POSIX +# ifdef CONFIG_LV_USE_FS_POSIX +# define LV_USE_FS_POSIX CONFIG_LV_USE_FS_POSIX +# else +# define LV_USE_FS_POSIX '\0' /*Uses open, read, etc*/ +# endif +#endif +//#define LV_FS_POSIX_PATH "/home/john/" /*Set the working directory. If commented it will be "./" */ + +#ifndef LV_USE_FS_WIN32 +# ifdef CONFIG_LV_USE_FS_WIN32 +# define LV_USE_FS_WIN32 CONFIG_LV_USE_FS_WIN32 +# else +# define LV_USE_FS_WIN32 '\0' /*Uses CreateFile, ReadFile, etc*/ +# endif +#endif +//#define LV_FS_WIN32_PATH "C:\\Users\\john\\" /*Set the working directory. If commented it will be ".\\" */ + +#ifndef LV_USE_FS_FATFS +# ifdef CONFIG_LV_USE_FS_FATFS +# define LV_USE_FS_FATFS CONFIG_LV_USE_FS_FATFS +# else +# define LV_USE_FS_FATFS '\0' /*Uses f_open, f_read, etc*/ +# endif +#endif + +/*PNG decoder library*/ +#ifndef LV_USE_PNG +# ifdef CONFIG_LV_USE_PNG +# define LV_USE_PNG CONFIG_LV_USE_PNG +# else +# define LV_USE_PNG 0 +# endif +#endif + +/*BMP decoder library*/ +#ifndef LV_USE_BMP +# ifdef CONFIG_LV_USE_BMP +# define LV_USE_BMP CONFIG_LV_USE_BMP +# else +# define LV_USE_BMP 0 +# endif +#endif + +/* JPG + split JPG decoder library. + * Split JPG is a custom format optimized for embedded systems. */ +#ifndef LV_USE_SJPG +# ifdef CONFIG_LV_USE_SJPG +# define LV_USE_SJPG CONFIG_LV_USE_SJPG +# else +# define LV_USE_SJPG 0 +# endif +#endif + +/*GIF decoder library*/ +#ifndef LV_USE_GIF +# ifdef CONFIG_LV_USE_GIF +# define LV_USE_GIF CONFIG_LV_USE_GIF +# else +# define LV_USE_GIF 0 +# endif +#endif + +/*QR code library*/ +#ifndef LV_USE_QRCODE +# ifdef CONFIG_LV_USE_QRCODE +# define LV_USE_QRCODE CONFIG_LV_USE_QRCODE +# else +# define LV_USE_QRCODE 0 +# endif +#endif + +/*FreeType library*/ +#ifndef LV_USE_FREETYPE +# ifdef CONFIG_LV_USE_FREETYPE +# define LV_USE_FREETYPE CONFIG_LV_USE_FREETYPE +# else +# define LV_USE_FREETYPE 0 +# endif +#endif +#if LV_USE_FREETYPE +/*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/ +#ifndef LV_FREETYPE_CACHE_SIZE +# ifdef CONFIG_LV_FREETYPE_CACHE_SIZE +# define LV_FREETYPE_CACHE_SIZE CONFIG_LV_FREETYPE_CACHE_SIZE +# else +# define LV_FREETYPE_CACHE_SIZE (16 * 1024) +# endif +#endif +#endif + +/*Rlottie library*/ +#ifndef LV_USE_RLOTTIE +# ifdef CONFIG_LV_USE_RLOTTIE +# define LV_USE_RLOTTIE CONFIG_LV_USE_RLOTTIE +# else +# define LV_USE_RLOTTIE 0 +# endif +#endif + +/*----------- + * Others + *----------*/ + +/*1: Enable API to take snapshot for object*/ +#ifndef LV_USE_SNAPSHOT +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_USE_SNAPSHOT +# define LV_USE_SNAPSHOT CONFIG_LV_USE_SNAPSHOT +# else +# define LV_USE_SNAPSHOT 0 +# endif +# else +# define LV_USE_SNAPSHOT 1 +# endif +#endif + + /*================== * EXAMPLES *==================*/ /*Enable the examples to be built with the library*/ #ifndef LV_BUILD_EXAMPLES -# ifdef CONFIG_LV_BUILD_EXAMPLES -# define LV_BUILD_EXAMPLES CONFIG_LV_BUILD_EXAMPLES +# ifdef _LV_KCONFIG_PRESENT +# ifdef CONFIG_LV_BUILD_EXAMPLES +# define LV_BUILD_EXAMPLES CONFIG_LV_BUILD_EXAMPLES +# else +# define LV_BUILD_EXAMPLES 0 +# endif # else -# define LV_BUILD_EXAMPLES 1 +# define LV_BUILD_EXAMPLES 1 # endif #endif @@ -1514,13 +1921,13 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ LV_EXPORT_CONST_INT(LV_DPI_DEF); +#undef _LV_KCONFIG_PRESENT + /*If running without lv_conf.h add typdesf with default value*/ -#if defined(LV_CONF_SKIP) - -# if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) /*Disable warnings for Visual Studio*/ -# define _CRT_SECURE_NO_WARNINGS -# endif - +#ifdef LV_CONF_SKIP +# if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) /*Disable warnings for Visual Studio*/ +# define _CRT_SECURE_NO_WARNINGS +# endif #endif /*defined(LV_CONF_SKIP)*/ #endif /*LV_CONF_INTERNAL_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/lv_conf_kconfig.h b/lib/libesp32_lvgl/lvgl/src/lv_conf_kconfig.h new file mode 100644 index 000000000..d12803875 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/lv_conf_kconfig.h @@ -0,0 +1,138 @@ +/** * @file lv_conf_kconfig.h * Configs that need special handling when LVGL is used with Kconfig */ + +#ifndef LV_CONF_KCONFIG_H +#define LV_CONF_KCONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LV_CONF_KCONFIG_EXTERNAL_INCLUDE +# include LV_CONF_KCONFIG_EXTERNAL_INCLUDE +#else + +# ifdef ESP_PLATFORM +# include "sdkconfig.h" +# include "esp_attr.h" +# endif + +# ifdef __NuttX__ +# include +# elif defined(__RTTHREAD__) +# define LV_CONF_INCLUDE_SIMPLE +# include +# endif + +#endif /*LV_CONF_KCONFIG_EXTERNAL_INCLUDE*/ + +/******************* + * LV COLOR CHROMA KEY + *******************/ + +#ifdef CONFIG_LV_COLOR_CHROMA_KEY_HEX +# define CONFIG_LV_COLOR_CHROMA_KEY lv_color_hex(CONFIG_LV_COLOR_CHROMA_KEY_HEX) +#endif + +/******************* + * LV_MEM_SIZE + *******************/ + +#ifdef CONFIG_LV_MEM_SIZE_KILOBYTES +# define CONFIG_LV_MEM_SIZE (CONFIG_LV_MEM_SIZE_KILOBYTES * 1024U) +#endif + +/******************** + * FONT SELECTION + *******************/ + +/** + * NOTE: In Kconfig instead of `LV_DEFAULT_FONT` + * `CONFIG_LV_FONT_DEFAULT_` is defined + * hence the large selection with if-s + */ + +/*------------------ + * DEFAULT FONT + *-----------------*/ +#ifdef CONFIG_LV_FONT_DEFAULT_MONTSERRAT_8 +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_8 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_10) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_10 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_12) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_12 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_14) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_14 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_16) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_16 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_18) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_18 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_20) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_20 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_22) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_22 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_24) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_24 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_26) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_26 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_28) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_28 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_30) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_30 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_32) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_32 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_34) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_34 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_36) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_36 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_38) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_38 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_40) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_40 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_42) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_42 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_44) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_44 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_46) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_46 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_48) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_48 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_12_SUBPX) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_12_subpx +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_28_COMPRESSED) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_28_compressed +#elif defined(CONFIG_LV_FONT_DEFAULT_DEJAVU_16_PERSIAN_HEBREW) +# define CONFIG_LV_FONT_DEFAULT &lv_font_dejavu_16_persian_hebrew +#elif defined(CONFIG_LV_FONT_DEFAULT_SIMSUN_16_CJK) +# define CONFIG_LV_FONT_DEFAULT &lv_font_simsun_16_cjk +#elif defined(CONFIG_LV_FONT_DEFAULT_UNSCII_8) +# define CONFIG_LV_FONT_DEFAULT &lv_font_unscii_8 +#elif defined(CONFIG_LV_FONT_DEFAULT_UNSCII_16) +# define CONFIG_LV_FONT_DEFAULT &lv_font_unscii_16 +#endif + +/*------------------ + * TEXT ENCODING + *-----------------*/ +#ifdef CONFIG_LV_TXT_ENC_UTF8 +# define CONFIG_LV_TXT_ENC LV_TXT_ENC_UTF8 +#elif defined(CONFIG_LV_TXT_ENC_ASCII) +# define CONFIG_LV_TXT_ENC LV_TXT_ENC_ASCII +#endif + +/*------------------ + * BIDI DIRECTION + *-----------------*/ + +#ifdef CONFIG_LV_BASE_DIR_LTR +# define CONFIG_LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_LTR +#elif defined(CONFIG_LV_BASE_DIR_RTL) +# define CONFIG_LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_RTL +#elif defined(CONFIG_LV_BASE_DIR_AUTO) +# define CONFIG_LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO +#endif + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_CONF_KCONFIG_H*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/lvgl.h b/lib/libesp32_lvgl/lvgl/src/lvgl.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/lvgl.h rename to lib/libesp32_lvgl/lvgl/src/lvgl.h diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_anim.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.c similarity index 81% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_anim.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_anim.c index e46ec8a99..ecb95840d 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_anim.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.c @@ -8,10 +8,8 @@ *********************/ #include "lv_anim.h" -#include -#include -#include "../misc/lv_assert.h" #include "../hal/lv_hal_tick.h" +#include "lv_assert.h" #include "lv_timer.h" #include "lv_math.h" #include "lv_mem.h" @@ -46,9 +44,9 @@ static lv_timer_t * _lv_anim_tmr; * MACROS **********************/ #if LV_LOG_TRACE_ANIM -# define TRACE_ANIM(...) LV_LOG_TRACE( __VA_ARGS__) + #define TRACE_ANIM(...) LV_LOG_TRACE(__VA_ARGS__) #else -# define TRACE_ANIM(...) + #define TRACE_ANIM(...) #endif @@ -67,9 +65,9 @@ void _lv_anim_core_init(void) void lv_anim_init(lv_anim_t * a) { lv_memset_00(a, sizeof(lv_anim_t)); - a->time = 500; - a->start_value = 0; - a->end_value = 100; + a->time = 500; + a->start_value = 0; + a->end_value = 100; a->repeat_cnt = 1; a->path_cb = lv_anim_path_linear; a->early_apply = 1; @@ -95,13 +93,12 @@ lv_anim_t * lv_anim_start(const lv_anim_t * a) /*Initialize the animation descriptor*/ lv_memcpy(new_anim, a, sizeof(lv_anim_t)); if(a->var == a) new_anim->var = new_anim; - new_anim->time_orig = a->time; new_anim->run_round = anim_run_round; /*Set the start value*/ if(new_anim->early_apply) { if(new_anim->get_value_cb) { - int32_t v_ofs = new_anim->get_value_cb(new_anim); + int32_t v_ofs = new_anim->get_value_cb(new_anim); new_anim->start_value += v_ofs; new_anim->end_value += v_ofs; } @@ -117,6 +114,27 @@ lv_anim_t * lv_anim_start(const lv_anim_t * a) return new_anim; } +uint32_t lv_anim_get_playtime(lv_anim_t * a) +{ + uint32_t playtime = LV_ANIM_PLAYTIME_INFINITE; + + if(a->repeat_cnt == LV_ANIM_REPEAT_INFINITE) + return playtime; + + playtime = a->time - a->act_time; + if(a->playback_now == 0) + playtime += a->playback_delay + a->playback_time; + + if(a->repeat_cnt <= 1) + return playtime; + + playtime += (a->repeat_delay + a->time + + a->playback_delay + a->playback_time) * + (a->repeat_cnt - 1); + + return playtime; +} + bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb) { lv_anim_t * a; @@ -131,7 +149,7 @@ bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb) _lv_ll_remove(&LV_GC_ROOT(_lv_anim_ll), a); lv_mem_free(a); anim_mark_list_change(); /*Read by `anim_timer`. It need to know if a delete occurred in - the linked list*/ + the linked list*/ del = true; } @@ -151,7 +169,7 @@ lv_anim_t * lv_anim_get(void * var, lv_anim_exec_xcb_t exec_cb) { lv_anim_t * a; _LV_LL_READ(&LV_GC_ROOT(_lv_anim_ll), a) { - if(a->var == var && a->exec_cb == exec_cb) { + if(a->var == var && (a->exec_cb == exec_cb || exec_cb == NULL)) { return a; } } @@ -203,12 +221,12 @@ int32_t lv_anim_path_linear(const lv_anim_t * a) int32_t lv_anim_path_ease_in(const lv_anim_t * a) { /*Calculate the current step*/ - uint32_t t = lv_map(a->act_time, 0, a->time, 0, 1024); - int32_t step = lv_bezier3(t, 0, 50, 100, 1024); + uint32_t t = lv_map(a->act_time, 0, a->time, 0, LV_BEZIER_VAL_MAX); + int32_t step = lv_bezier3(t, 0, 50, 100, LV_BEZIER_VAL_MAX); int32_t new_value; new_value = step * (a->end_value - a->start_value); - new_value = new_value >> 10; + new_value = new_value >> LV_BEZIER_VAL_SHIFT; new_value += a->start_value; return new_value; @@ -217,12 +235,12 @@ int32_t lv_anim_path_ease_in(const lv_anim_t * a) int32_t lv_anim_path_ease_out(const lv_anim_t * a) { /*Calculate the current step*/ - uint32_t t = lv_map(a->act_time, 0, a->time, 0, 1024); - int32_t step = lv_bezier3(t, 0, 900, 950, 1024); + uint32_t t = lv_map(a->act_time, 0, a->time, 0, LV_BEZIER_VAL_MAX); + int32_t step = lv_bezier3(t, 0, 900, 950, LV_BEZIER_VAL_MAX); int32_t new_value; new_value = step * (a->end_value - a->start_value); - new_value = new_value >> 10; + new_value = new_value >> LV_BEZIER_VAL_SHIFT; new_value += a->start_value; return new_value; @@ -231,12 +249,12 @@ int32_t lv_anim_path_ease_out(const lv_anim_t * a) int32_t lv_anim_path_ease_in_out(const lv_anim_t * a) { /*Calculate the current step*/ - uint32_t t = lv_map(a->act_time, 0, a->time, 0, 1024); - int32_t step = lv_bezier3(t, 0, 50, 952, 1024); + uint32_t t = lv_map(a->act_time, 0, a->time, 0, LV_BEZIER_VAL_MAX); + int32_t step = lv_bezier3(t, 0, 50, 952, LV_BEZIER_VAL_MAX); int32_t new_value; new_value = step * (a->end_value - a->start_value); - new_value = new_value >> 10; + new_value = new_value >> LV_BEZIER_VAL_SHIFT; new_value += a->start_value; return new_value; @@ -245,12 +263,12 @@ int32_t lv_anim_path_ease_in_out(const lv_anim_t * a) int32_t lv_anim_path_overshoot(const lv_anim_t * a) { /*Calculate the current step*/ - uint32_t t = lv_map(a->act_time, 0, a->time, 0, 1024); - int32_t step = lv_bezier3(t, 0, 1000, 1300, 1024); + uint32_t t = lv_map(a->act_time, 0, a->time, 0, LV_BEZIER_VAL_MAX); + int32_t step = lv_bezier3(t, 0, 1000, 1300, LV_BEZIER_VAL_MAX); int32_t new_value; new_value = step * (a->end_value - a->start_value); - new_value = new_value >> 10; + new_value = new_value >> LV_BEZIER_VAL_SHIFT; new_value += a->start_value; return new_value; @@ -259,20 +277,20 @@ int32_t lv_anim_path_overshoot(const lv_anim_t * a) int32_t lv_anim_path_bounce(const lv_anim_t * a) { /*Calculate the current step*/ - int32_t t = lv_map(a->act_time, 0, a->time, 0, 1024); + int32_t t = lv_map(a->act_time, 0, a->time, 0, LV_BEZIER_VAL_MAX); int32_t diff = (a->end_value - a->start_value); /*3 bounces has 5 parts: 3 down and 2 up. One part is t / 5 long*/ if(t < 408) { /*Go down*/ - t = (t * 2500) >> 10; /*[0..1024] range*/ + t = (t * 2500) >> LV_BEZIER_VAL_SHIFT; /*[0..1024] range*/ } else if(t >= 408 && t < 614) { /*First bounce back*/ t -= 408; t = t * 5; /*to [0..1024] range*/ - t = 1024 - t; + t = LV_BEZIER_VAL_MAX - t; diff = diff / 20; } else if(t >= 614 && t < 819) { @@ -285,23 +303,23 @@ int32_t lv_anim_path_bounce(const lv_anim_t * a) /*Second bounce back*/ t -= 819; t = t * 10; /*to [0..1024] range*/ - t = 1024 - t; + t = LV_BEZIER_VAL_MAX - t; diff = diff / 40; } - else if(t >= 921 && t <= 1024) { + else if(t >= 921 && t <= LV_BEZIER_VAL_MAX) { /*Fall back*/ t -= 921; t = t * 10; /*to [0..1024] range*/ diff = diff / 40; } - if(t > 1024) t = 1024; + if(t > LV_BEZIER_VAL_MAX) t = LV_BEZIER_VAL_MAX; if(t < 0) t = 0; - int32_t step = lv_bezier3(t, 1024, 800, 500, 0); + int32_t step = lv_bezier3(t, LV_BEZIER_VAL_MAX, 800, 500, 0); int32_t new_value; new_value = step * diff; - new_value = new_value >> 10; + new_value = new_value >> LV_BEZIER_VAL_SHIFT; new_value = a->end_value - new_value; return new_value; @@ -325,7 +343,7 @@ int32_t lv_anim_path_step(const lv_anim_t * a) */ static void anim_timer(lv_timer_t * param) { - (void)param; + LV_UNUSED(param); uint32_t elaps = lv_tick_elaps(last_timer_run); @@ -348,7 +366,7 @@ static void anim_timer(lv_timer_t * param) int32_t new_act_time = a->act_time + elaps; if(!a->start_cb_called && a->act_time <= 0 && new_act_time >= 0) { if(a->early_apply == 0 && a->get_value_cb) { - int32_t v_ofs = a->get_value_cb(a); + int32_t v_ofs = a->get_value_cb(a); a->start_value += v_ofs; a->end_value += v_ofs; } @@ -401,19 +419,17 @@ static void anim_ready_handler(lv_anim_t * a) /*Delete the animation if * - no repeat left and no play back (simple one shot animation) * - no repeat, play back is enabled and play back is ready*/ - if(a->repeat_cnt == 0 && ((a->playback_time == 0) || (a->playback_time && a->playback_now == 1))) { + if(a->repeat_cnt == 0 && (a->playback_time == 0 || a->playback_now == 1)) { - /*Create copy from the animation and delete the animation from the list. + /*Delete the animation from the list. * This way the `ready_cb` will see the animations like it's animation is ready deleted*/ - lv_anim_t a_tmp; - lv_memcpy(&a_tmp, a, sizeof(lv_anim_t)); _lv_ll_remove(&LV_GC_ROOT(_lv_anim_ll), a); - lv_mem_free(a); /*Flag that the list has changed*/ anim_mark_list_change(); /*Call the callback function at the end*/ - if(a_tmp.ready_cb != NULL) a_tmp.ready_cb(&a_tmp); + if(a->ready_cb != NULL) a->ready_cb(a); + lv_mem_free(a); } /*If the animation is not deleted then restart it*/ else { @@ -426,15 +442,17 @@ static void anim_ready_handler(lv_anim_t * a) /*Toggle the play back state*/ a->playback_now = a->playback_now == 0 ? 1 : 0; /*Swap the start and end values*/ - int32_t tmp; - tmp = a->start_value; + int32_t tmp = a->start_value; a->start_value = a->end_value; a->end_value = tmp; - - a->time = a->playback_now == 0 ? a->time_orig : a->playback_time; + /*Swap the time and playback_time*/ + tmp = a->time; + a->time = a->playback_time; + a->playback_time = tmp; } } } + static void anim_mark_list_change(void) { anim_list_changed = true; diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_anim.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.h similarity index 86% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_anim.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_anim.h index e97fbc5c1..6f51bf001 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_anim.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.h @@ -17,12 +17,18 @@ extern "C" { #include #include -#include +#include /********************* * DEFINES *********************/ +#define LV_ANIM_REPEAT_INFINITE 0xFFFF +#define LV_ANIM_PLAYTIME_INFINITE 0xFFFFFFFF + +LV_EXPORT_CONST_INT(LV_ANIM_REPEAT_INFINITE); +LV_EXPORT_CONST_INT(LV_ANIM_PLAYTIME_INFINITE); + /********************** * TYPEDEFS **********************/ @@ -31,10 +37,7 @@ extern "C" { typedef enum { LV_ANIM_OFF, LV_ANIM_ON, -}lv_anim_enable_t; - -#define LV_ANIM_REPEAT_INFINITE 0xFFFF -LV_EXPORT_CONST_INT(LV_ANIM_REPEAT_INFINITE); +} lv_anim_enable_t; struct _lv_anim_t; @@ -45,7 +48,7 @@ typedef int32_t (*lv_anim_path_cb_t)(const struct _lv_anim_t *); * First parameter is the variable to animate. * Second parameter is the value to set. * Compatible with `lv_xxx_set_yyy(obj, value)` functions - * The `x` in `_xcb_t` means its not a fully generic prototype because + * The `x` in `_xcb_t` means it's not a fully generic prototype because * it doesn't receive `lv_anim_t *` as its first argument*/ typedef void (*lv_anim_exec_xcb_t)(void *, int32_t); @@ -88,7 +91,6 @@ typedef struct _lv_anim_t { uint8_t playback_now : 1; /**< Play back is in progress*/ uint8_t run_round : 1; /**< Indicates the animation has run in this round*/ uint8_t start_cb_called : 1; /**< Indicates that the `start_cb` was already called*/ - uint32_t time_orig; } lv_anim_t; /********************** @@ -169,9 +171,9 @@ static inline void lv_anim_set_values(lv_anim_t * a, int32_t start, int32_t end) /** * Similar to `lv_anim_set_exec_cb` but `lv_anim_custom_exec_cb_t` receives * `lv_anim_t * ` as its first parameter instead of `void *`. - * This function might be used when LVGL is binded to other languages because + * This function might be used when LVGL is bound to other languages because * it's more consistent to have `lv_anim_t *` as first parameter. - * The variable to animate can be stored in the animation's `user_sata` + * The variable to animate can be stored in the animation's `user_data` * @param a pointer to an initialized `lv_anim_t` variable * @param exec_cb a function to execute. */ @@ -184,7 +186,7 @@ static inline void lv_anim_set_custom_exec_cb(lv_anim_t * a, lv_anim_custom_exec /** * Set the path (curve) of the animation. * @param a pointer to an initialized `lv_anim_t` variable - * @param path_cb a function the get the current value of the animation. + * @param path_cb a function to set the current value of the animation. */ static inline void lv_anim_set_path_cb(lv_anim_t * a, lv_anim_path_cb_t path_cb) { @@ -196,7 +198,7 @@ static inline void lv_anim_set_path_cb(lv_anim_t * a, lv_anim_path_cb_t path_cb) * @param a pointer to an initialized `lv_anim_t` variable * @param start_cb a function call when the animation starts */ -static inline void lv_anim_set_start_cb(lv_anim_t * a, lv_anim_ready_cb_t start_cb) +static inline void lv_anim_set_start_cb(lv_anim_t * a, lv_anim_start_cb_t start_cb) { a->start_cb = start_cb; } @@ -221,10 +223,11 @@ static inline void lv_anim_set_ready_cb(lv_anim_t * a, lv_anim_ready_cb_t ready_ { a->ready_cb = ready_cb; } + /** * Make the animation to play back to when the forward direction is ready * @param a pointer to an initialized `lv_anim_t` variable - * @param time the duration of the playback animation in in milliseconds. 0: disable playback + * @param time the duration of the playback animation in milliseconds. 0: disable playback */ static inline void lv_anim_set_playback_time(lv_anim_t * a, uint32_t time) { @@ -272,6 +275,18 @@ static inline void lv_anim_set_early_apply(lv_anim_t * a, bool en) a->early_apply = en; } +/** + * Set the custom user data field of the animation. + * @param a pointer to an initialized `lv_anim_t` variable + * @param user_data pointer to the new user_data. + */ +#if LV_USE_USER_DATA +static inline void lv_anim_set_user_data(lv_anim_t * a, void * user_data) +{ + a->user_data = user_data; +} +#endif + /** * Create an animation * @param a an initialized 'anim_t' variable. Not required after call. @@ -289,6 +304,25 @@ static inline uint32_t lv_anim_get_delay(lv_anim_t * a) return -a->act_time; } +/** + * Get the time used to play the animation. + * @param a pointer to an animation. + * @return the play time in milliseconds. + */ +uint32_t lv_anim_get_playtime(lv_anim_t * a); + +/** + * Get the user_data field of the animation + * @param a pointer to an initialized `lv_anim_t` variable + * @return the pointer to the custom user_data of the animation + */ +#if LV_USE_USER_DATA +static inline void * lv_anim_get_user_data(lv_anim_t * a) +{ + return a->user_data; +} +#endif + /** * Delete an animation of a variable with a given animator function * @param var pointer to variable @@ -299,7 +333,7 @@ static inline uint32_t lv_anim_get_delay(lv_anim_t * a) bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb); /** - * Delete all the animations animation + * Delete all the animations */ void lv_anim_del_all(void); @@ -320,13 +354,27 @@ lv_anim_t * lv_anim_get(void * var, lv_anim_exec_xcb_t exec_cb); * @param a pointer to an animation. * @param exec_cb a function pointer which is animating 'var', * or NULL to ignore it and delete all the animations of 'var - * @return true: at least 1 animation is deleted, false: no animation is deleted + * @return true: at least 1 animation is deleted, false: no animation is deleted */ static inline bool lv_anim_custom_del(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) { return lv_anim_del(a ? a->var : NULL, (lv_anim_exec_xcb_t)exec_cb); } +/** + * Get the animation of a variable and its `exec_cb`. + * This function exists because it's logical that all anim. functions receives an + * `lv_anim_t` as their first parameter. It's not practical in C but might make + * the API more consequent and makes easier to generate bindings. + * @param a pointer to an animation. + * @param exec_cb a function pointer which is animating 'var', or NULL to return first matching 'var' + * @return pointer to the animation. + */ +static inline lv_anim_t * lv_anim_custom_get(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) +{ + return lv_anim_get(a ? a->var : NULL, (lv_anim_exec_xcb_t)exec_cb); +} + /** * Get the number of currently running animations * @return the number of running animations diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_anim_timeline.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim_timeline.c new file mode 100644 index 000000000..930b6952c --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim_timeline.c @@ -0,0 +1,198 @@ +/** + * @file lv_anim_timeline.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_anim_timeline.h" +#include "lv_mem.h" +#include "lv_assert.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Data of anim_timeline_dsc*/ +typedef struct { + lv_anim_t anim; + uint32_t start_time; +} lv_anim_timeline_dsc_t; + +/*Data of anim_timeline*/ +struct _lv_anim_timeline_t { + lv_anim_timeline_dsc_t * anim_dsc; /**< Dynamically allocated anim dsc array*/ + uint32_t anim_dsc_cnt; /**< The length of anim dsc array*/ + bool reverse; /**< Reverse playback*/ +}; + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_anim_timeline_virtual_exec_cb(void * var, int32_t v); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_anim_timeline_t * lv_anim_timeline_create(void) +{ + lv_anim_timeline_t * at = (lv_anim_timeline_t *)lv_mem_alloc(sizeof(lv_anim_timeline_t)); + + LV_ASSERT_MALLOC(at); + + if(at) lv_memset_00(at, sizeof(lv_anim_timeline_t)); + + return at; +} + +void lv_anim_timeline_del(lv_anim_timeline_t * at) +{ + LV_ASSERT_NULL(at); + + lv_anim_timeline_stop(at); + + lv_mem_free(at->anim_dsc); + lv_mem_free(at); +} + +void lv_anim_timeline_add(lv_anim_timeline_t * at, uint32_t start_time, lv_anim_t * a) +{ + LV_ASSERT_NULL(at); + + at->anim_dsc_cnt++; + at->anim_dsc = lv_mem_realloc(at->anim_dsc, at->anim_dsc_cnt * sizeof(lv_anim_timeline_dsc_t)); + + LV_ASSERT_MALLOC(at->anim_dsc); + + at->anim_dsc[at->anim_dsc_cnt - 1].anim = *a; + at->anim_dsc[at->anim_dsc_cnt - 1].start_time = start_time; + + /*Add default var and virtual exec_cb, used to delete animation.*/ + if(a->var == NULL && a->exec_cb == NULL) { + at->anim_dsc[at->anim_dsc_cnt - 1].anim.var = at; + at->anim_dsc[at->anim_dsc_cnt - 1].anim.exec_cb = lv_anim_timeline_virtual_exec_cb; + } +} + +uint32_t lv_anim_timeline_start(lv_anim_timeline_t * at) +{ + LV_ASSERT_NULL(at); + + const uint32_t playtime = lv_anim_timeline_get_playtime(at); + bool reverse = at->reverse; + + for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) { + lv_anim_t a = at->anim_dsc[i].anim; + uint32_t start_time = at->anim_dsc[i].start_time; + + if(reverse) { + int32_t temp = a.start_value; + a.start_value = a.end_value; + a.end_value = temp; + lv_anim_set_delay(&a, playtime - (start_time + a.time)); + } + else { + lv_anim_set_delay(&a, start_time); + } + + lv_anim_start(&a); + } + + return playtime; +} + +void lv_anim_timeline_stop(lv_anim_timeline_t * at) +{ + LV_ASSERT_NULL(at); + + for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) { + lv_anim_t * a = &(at->anim_dsc[i].anim); + lv_anim_del(a->var, a->exec_cb); + } +} + +void lv_anim_timeline_set_reverse(lv_anim_timeline_t * at, bool reverse) +{ + LV_ASSERT_NULL(at); + at->reverse = reverse; +} + +void lv_anim_timeline_set_progress(lv_anim_timeline_t * at, uint16_t progress) +{ + LV_ASSERT_NULL(at); + + const uint32_t playtime = lv_anim_timeline_get_playtime(at); + const uint32_t act_time = progress * playtime / 0xFFFF; + + for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) { + lv_anim_t * a = &(at->anim_dsc[i].anim); + + if(a->exec_cb == NULL) { + continue; + } + + uint32_t start_time = at->anim_dsc[i].start_time; + int32_t value = 0; + + if(act_time < start_time) { + value = a->start_value; + } + else if(act_time < (start_time + a->time)) { + a->act_time = act_time - start_time; + value = a->path_cb(a); + } + else { + value = a->end_value; + } + + a->exec_cb(a->var, value); + } +} + +uint32_t lv_anim_timeline_get_playtime(lv_anim_timeline_t * at) +{ + LV_ASSERT_NULL(at); + + uint32_t playtime = 0; + for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) { + uint32_t end = lv_anim_get_playtime(&at->anim_dsc[i].anim); + if (end == LV_ANIM_PLAYTIME_INFINITE) + return end; + end += at->anim_dsc[i].start_time; + if(end > playtime) { + playtime = end; + } + } + + return playtime; +} + +bool lv_anim_timeline_get_reverse(lv_anim_timeline_t * at) +{ + LV_ASSERT_NULL(at); + return at->reverse; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_anim_timeline_virtual_exec_cb(void * var, int32_t v) +{ + LV_UNUSED(var); + LV_UNUSED(v); +} diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_anim_timeline.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim_timeline.h new file mode 100644 index 000000000..ed8782e19 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim_timeline.h @@ -0,0 +1,103 @@ +/** + * @file lv_anim_timeline.h + * + */ + +#ifndef LV_ANIM_TIMELINE_H +#define LV_ANIM_TIMELINE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_anim.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_anim_timeline_t; + +typedef struct _lv_anim_timeline_t lv_anim_timeline_t; + +/********************** +* GLOBAL PROTOTYPES +**********************/ + +/** + * Create a animation timeline. + * @return pointer to the animation timeline. + */ +lv_anim_timeline_t * lv_anim_timeline_create(void); + +/** + * Delete animation timeline. + * @param at pointer to the animation timeline. + */ +void lv_anim_timeline_del(lv_anim_timeline_t * at); + +/** + * Add animation to the animation timeline. + * @param at pointer to the animation timeline. + * @param start_time the time the animation started on the timeline, note that start_time will override the value of delay. + * @param a pointer to an animation. + */ +void lv_anim_timeline_add(lv_anim_timeline_t * at, uint32_t start_time, lv_anim_t * a); + +/** + * Start the animation timeline. + * @param at pointer to the animation timeline. + * @return total time spent in animation timeline. + */ +uint32_t lv_anim_timeline_start(lv_anim_timeline_t * at); + +/** + * Stop the animation timeline. + * @param at pointer to the animation timeline. + */ +void lv_anim_timeline_stop(lv_anim_timeline_t * at); + +/** + * Set the playback direction of the animation timeline. + * @param at pointer to the animation timeline. + * @param reverse whether to play in reverse. + */ +void lv_anim_timeline_set_reverse(lv_anim_timeline_t * at, bool reverse); + +/** + * Set the progress of the animation timeline. + * @param at pointer to the animation timeline. + * @param progress set value 0~65535 to map 0~100% animation progress. + */ +void lv_anim_timeline_set_progress(lv_anim_timeline_t * at, uint16_t progress); + +/** + * Get the time used to play the animation timeline. + * @param at pointer to the animation timeline. + * @return total time spent in animation timeline. + */ +uint32_t lv_anim_timeline_get_playtime(lv_anim_timeline_t * at); + +/** + * Get whether the animation timeline is played in reverse. + * @param at pointer to the animation timeline. + * @return return true if it is reverse playback. + */ +bool lv_anim_timeline_get_reverse(lv_anim_timeline_t * at); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_ANIM_TIMELINE_H*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_area.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_area.c similarity index 91% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_area.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_area.c index aef222f3e..08a8f16e1 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_area.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_area.c @@ -134,7 +134,7 @@ bool _lv_area_intersect(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area res_p->x2 = LV_MIN(a1_p->x2, a2_p->x2); res_p->y2 = LV_MIN(a1_p->y2, a2_p->y2); - /*If x1 or y1 greater then x2 or y2 then the areas union is empty*/ + /*If x1 or y1 greater than x2 or y2 then the areas union is empty*/ bool union_ok = true; if((res_p->x1 > res_p->x2) || (res_p->y1 > res_p->y2)) { union_ok = false; @@ -142,6 +142,7 @@ bool _lv_area_intersect(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area return union_ok; } + /** * Join two areas into a third which involves the other two * @param res_p pointer to an area, the result will be stored here @@ -280,6 +281,44 @@ bool _lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p, lv_coo return true; } +/** + * Check if an area is fully out of an other + * @param aout_p pointer to an area which could be in 'aholder_p' + * @param aholder_p pointer to an area which could involve 'ain_p' + * @param radius radius of `aholder_p` (e.g. for rounded rectangle) + * @return true: `aout_p` is fully outside `aholder_p` + */ +bool _lv_area_is_out(const lv_area_t * aout_p, const lv_area_t * aholder_p, lv_coord_t radius) +{ + if(aout_p->x2 < aholder_p->x1 || aout_p->y2 < aholder_p->y1 || aout_p->x1 > aholder_p->x2 || + aout_p->y1 > aholder_p->y2) { + return true; + } + + if(radius == 0) return false; + + /*Check if the corner points are outside the radius or not*/ + lv_point_t p; + + p.x = aout_p->x1; + p.y = aout_p->y1; + if(_lv_area_is_point_on(aholder_p, &p, radius)) return false; + + p.x = aout_p->x2; + p.y = aout_p->y1; + if(_lv_area_is_point_on(aholder_p, &p, radius)) return false; + + p.x = aout_p->x1; + p.y = aout_p->y2; + if(_lv_area_is_point_on(aholder_p, &p, radius)) return false; + + p.x = aout_p->x2; + p.y = aout_p->y2; + if(_lv_area_is_point_on(aholder_p, &p, radius)) return false; + + return true; +} + /** * Align an area to an other * @param base an are where the other will be aligned diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_area.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_area.h similarity index 86% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_area.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_area.h index 9bf3e6ec2..e2a70eb4c 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_area.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_area.h @@ -14,7 +14,6 @@ extern "C" { * INCLUDES *********************/ #include "../lv_conf_internal.h" -#include #include #include @@ -22,21 +21,12 @@ extern "C" { * DEFINES *********************/ -#define _LV_COORD_MAX_REDUCE 8192 - #if LV_USE_LARGE_COORD typedef int32_t lv_coord_t; #else typedef int16_t lv_coord_t; #endif -/*To allow some special values in the end reduce the max value*/ -#define LV_COORD_MAX ((lv_coord_t)((uint32_t)((uint32_t)1 << (8 * sizeof(lv_coord_t) - 1)) - _LV_COORD_MAX_REDUCE)) -#define LV_COORD_MIN (-LV_COORD_MAX) - -LV_EXPORT_CONST_INT(LV_COORD_MAX); -LV_EXPORT_CONST_INT(LV_COORD_MIN); - /********************** * TYPEDEFS **********************/ @@ -221,6 +211,16 @@ bool _lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p); */ bool _lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p, lv_coord_t radius); + +/** + * Check if an area is fully out of an other + * @param aout_p pointer to an area which could be in 'aholder_p' + * @param aholder_p pointer to an area which could involve 'ain_p' + * @param radius radius of `aholder_p` (e.g. for rounded rectangle) + * @return true: `aout_p` is fully outside `aholder_p` + */ +bool _lv_area_is_out(const lv_area_t * aout_p, const lv_area_t * aholder_p, lv_coord_t radius); + /** * Align an area to an other * @param base an are where the other will be aligned @@ -240,16 +240,18 @@ void lv_area_align(const lv_area_t * base, lv_area_t * to_align, lv_align_t alig #endif #define _LV_COORD_TYPE_MASK (3 << _LV_COORD_TYPE_SHIFT) -#define _LV_COORD_PLAIN(x) ((x) & (~_LV_COORD_TYPE_MASK)) /*Remove type specifiers*/ +#define _LV_COORD_TYPE(x) ((x) & _LV_COORD_TYPE_MASK) /*Extract type specifiers*/ +#define _LV_COORD_PLAIN(x) ((x) & ~_LV_COORD_TYPE_MASK) /*Remove type specifiers*/ #define _LV_COORD_TYPE_PX (0 << _LV_COORD_TYPE_SHIFT) #define _LV_COORD_TYPE_SPEC (1 << _LV_COORD_TYPE_SHIFT) -#define _LV_COORD_TYPE_RESERVED (3 << _LV_COORD_TYPE_SHIFT) +#define _LV_COORD_TYPE_PX_NEG (3 << _LV_COORD_TYPE_SHIFT) -#define LV_COORD_IS_PX(x) ((((x) & _LV_COORD_TYPE_MASK) == _LV_COORD_TYPE_PX) ? true : false) -#define LV_COORD_IS_SPEC(x) ((((x) & _LV_COORD_TYPE_MASK) == _LV_COORD_TYPE_SPEC) ? true : false) +#define LV_COORD_IS_PX(x) (_LV_COORD_TYPE(x) == _LV_COORD_TYPE_PX) || \ + _LV_COORD_TYPE(x) == _LV_COORD_TYPE_PX_NEG ? true : false) +#define LV_COORD_IS_SPEC(x) (_LV_COORD_TYPE(x) == _LV_COORD_TYPE_SPEC ? true : false) -#define LV_COORD_SET_SPEC(x) ((x) | _LV_COORD_TYPE_SPEC) +#define LV_COORD_SET_SPEC(x) ((x) | _LV_COORD_TYPE_SPEC) /*Special coordinates*/ #define LV_PCT(x) (x < 0 ? LV_COORD_SET_SPEC(1000 - (x)) : LV_COORD_SET_SPEC(x)) @@ -259,6 +261,13 @@ void lv_area_align(const lv_area_t * base, lv_area_t * to_align, lv_align_t alig LV_EXPORT_CONST_INT(LV_SIZE_CONTENT); +/*Max coordinate value*/ +#define LV_COORD_MAX ((1 << _LV_COORD_TYPE_SHIFT) - 1) +#define LV_COORD_MIN (-LV_COORD_MAX) + +LV_EXPORT_CONST_INT(LV_COORD_MAX); +LV_EXPORT_CONST_INT(LV_COORD_MIN); + /** * Convert a percentage value to `lv_coord_t`. * Percentage values are stored in special range diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_assert.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_assert.h similarity index 59% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_assert.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_assert.h index 0132ac4d5..48db7443c 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_assert.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_assert.h @@ -14,7 +14,8 @@ extern "C" { * INCLUDES *********************/ #include "../lv_conf_internal.h" -#include +#include "lv_log.h" +#include "lv_mem.h" #include LV_ASSERT_HANDLER_INCLUDE /********************* @@ -33,20 +34,20 @@ extern "C" { * MACROS **********************/ -#define LV_ASSERT(expr) \ - do { \ - if(!(expr)) { \ - LV_LOG_ERROR("Asserted at expression: %s", #expr); \ - LV_ASSERT_HANDLER \ - } \ +#define LV_ASSERT(expr) \ + do { \ + if(!(expr)) { \ + LV_LOG_ERROR("Asserted at expression: %s", #expr); \ + LV_ASSERT_HANDLER \ + } \ } while(0) -#define LV_ASSERT_MSG(expr, msg) \ - do { \ - if(!(expr)) { \ - LV_LOG_ERROR("Asserted at expression: %s (%s)", #expr, msg); \ - LV_ASSERT_HANDLER \ - } \ +#define LV_ASSERT_MSG(expr, msg) \ + do { \ + if(!(expr)) { \ + LV_LOG_ERROR("Asserted at expression: %s (%s)", #expr, msg); \ + LV_ASSERT_HANDLER \ + } \ } while(0) /*----------------- diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_async.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_async.c similarity index 95% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_async.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_async.c index d2324406a..45a043154 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_async.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_async.c @@ -8,6 +8,8 @@ *********************/ #include "lv_async.h" +#include "lv_mem.h" +#include "lv_timer.h" /********************* * DEFINES @@ -49,7 +51,6 @@ lv_res_t lv_async_call(lv_async_cb_t async_xcb, void * user_data) return LV_RES_INV; /*Create a new timer*/ - /*Use highest priority so that it will run before a refresh*/ lv_timer_t * timer = lv_timer_create(lv_async_timer_cb, 0, info); if(timer == NULL) { @@ -73,6 +74,5 @@ static void lv_async_timer_cb(lv_timer_t * timer) lv_async_info_t * info = (lv_async_info_t *)timer->user_data; info->cb(info->user_data); - lv_mem_free(info); } diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_async.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_async.h similarity index 93% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_async.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_async.h index 2a687cde1..3e6cb638d 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_async.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_async.h @@ -14,7 +14,6 @@ extern "C" { * INCLUDES *********************/ -#include "lv_timer.h" #include "lv_types.h" /********************* @@ -38,7 +37,7 @@ typedef void (*lv_async_cb_t)(void *); * Call an asynchronous function the next time lv_timer_handler() is run. This function is likely to return * **before** the call actually happens! * @param async_xcb a callback which is the task itself. - * (the 'x' in the argument name indicates that its not a fully generic function because it not follows + * (the 'x' in the argument name indicates that it's not a fully generic function because it not follows * the `func_name(object, callback, ...)` convention) * @param user_data custom parameter */ diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_bidi.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.c similarity index 96% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_bidi.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.c index 906338348..3b084d3d7 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_bidi.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.c @@ -305,6 +305,16 @@ void _lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t le } } +void lv_bidi_calculate_align(lv_text_align_t * align, lv_base_dir_t * base_dir, const char * txt) +{ + if(*base_dir == LV_BASE_DIR_AUTO) *base_dir = _lv_bidi_detect_base_dir(txt); + + if(*align == LV_TEXT_ALIGN_AUTO) { + if(*base_dir == LV_BASE_DIR_RTL) *align = LV_TEXT_ALIGN_RIGHT; + else *align = LV_TEXT_ALIGN_LEFT; + } +} + /********************** * STATIC FUNCTIONS **********************/ @@ -430,10 +440,13 @@ static lv_base_dir_t get_next_run(const char * txt, lv_base_dir_t base_dir, uint /*Find the first strong char. Skip the neutrals*/ while(dir == LV_BASE_DIR_NEUTRAL || dir == LV_BASE_DIR_WEAK) { letter = _lv_txt_encoded_next(txt, &i); + pos_conv_i++; dir = lv_bidi_get_letter_dir(letter); if(dir == LV_BASE_DIR_NEUTRAL) dir = bracket_process(txt, i, max_len, letter, base_dir); - + + if(dir==LV_BASE_DIR_LTR || dir==LV_BASE_DIR_RTL) break; + if(i >= max_len || txt[i] == '\0' || txt[i] == '\n' || txt[i] == '\r') { *len = i; *pos_conv_len = pos_conv_i; @@ -455,6 +468,14 @@ static lv_base_dir_t get_next_run(const char * txt, lv_base_dir_t base_dir, uint pos_conv_i++; next_dir = lv_bidi_get_letter_dir(letter); if(next_dir == LV_BASE_DIR_NEUTRAL) next_dir = bracket_process(txt, i, max_len, letter, base_dir); + + if(next_dir == LV_BASE_DIR_WEAK){ + if(run_dir == LV_BASE_DIR_RTL){ + if(base_dir == LV_BASE_DIR_RTL){ + next_dir = LV_BASE_DIR_LTR; + } + } + } /*New dir found?*/ if((next_dir == LV_BASE_DIR_RTL || next_dir == LV_BASE_DIR_LTR) && next_dir != run_dir) { @@ -589,7 +610,7 @@ static lv_base_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32 /*Is the letter an opening bracket?*/ for(i = 0; bracket_left[i] != '\0'; i++) { if(bracket_left[i] == letter) { - /*If so find it's matching closing bracket. + /*If so find its matching closing bracket. *If a char with base dir. direction is found then the brackets will have `base_dir` direction*/ uint32_t txt_i = next_pos; while(txt_i < len) { diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_bidi.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.h similarity index 78% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_bidi.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.h index d3a646e7d..a27b58086 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_bidi.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.h @@ -17,6 +17,7 @@ extern "C" { #include #include +#include "lv_txt.h" /********************* * DEFINES @@ -104,10 +105,33 @@ uint16_t _lv_bidi_get_visual_pos(const char * str_in, char ** bidi_txt, uint16_t void _lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_base_dir_t base_dir, uint16_t * pos_conv_out, uint16_t pos_conv_len); +/** + * Get the real text alignment from the a text alignment, base direction and a text. + * @param align LV_TEXT_ALIGN_..., write back the calculated align here (LV_TEXT_ALIGN_LEFT/RIGHT/CENTER) + * @param base_dir LV_BASE_DIR_..., write the calculated base dir here (LV_BASE_DIR_LTR/RTL) + * @param txt a text, used with LV_BASE_DIR_AUTO to determine the base direction + */ +void lv_bidi_calculate_align(lv_text_align_t * align, lv_base_dir_t * base_dir, const char * txt); + + /********************** * MACROS **********************/ +#else /*LV_USE_BIDI*/ +/** + * For compatibility if LV_USE_BIDI = 0 + * Get the real text alignment from the a text alignment, base direction and a text. + * @param align For LV_TEXT_ALIGN_AUTO give LV_TEXT_ALIGN_LEFT else leave unchanged, write back the calculated align here + * @param base_dir Unused + * @param txt Unused + */ +static inline void lv_bidi_calculate_align(lv_text_align_t * align, lv_base_dir_t * base_dir, const char * txt) +{ + LV_UNUSED(txt); + LV_UNUSED(base_dir); + if(*align == LV_TEXT_ALIGN_AUTO) * align = LV_TEXT_ALIGN_LEFT; +} #endif /*LV_USE_BIDI*/ #ifdef __cplusplus diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_color.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_color.c new file mode 100644 index 000000000..0e26624fb --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_color.c @@ -0,0 +1,369 @@ +/** + * @file lv_color.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_color.h" +#include "lv_log.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +LV_ATTRIBUTE_FAST_MEM void lv_color_fill(lv_color_t * buf, lv_color_t color, uint32_t px_num) +{ +#if LV_COLOR_DEPTH == 16 + uintptr_t buf_int = (uintptr_t)buf; + if(buf_int & 0x3) { + *buf = color; + buf++; + px_num--; + } + + uint32_t c32 = (uint32_t)color.full + ((uint32_t)color.full << 16); + uint32_t * buf32 = (uint32_t *)buf; + + while(px_num > 16) { + *buf32 = c32; + buf32++; + *buf32 = c32; + buf32++; + *buf32 = c32; + buf32++; + *buf32 = c32; + buf32++; + + *buf32 = c32; + buf32++; + *buf32 = c32; + buf32++; + *buf32 = c32; + buf32++; + *buf32 = c32; + buf32++; + + px_num -= 16; + } + + buf = (lv_color_t *)buf32; + + while(px_num) { + *buf = color; + buf++; + px_num--; + } +#else + while(px_num > 16) { + *buf = color; + buf++; + *buf = color; + buf++; + *buf = color; + buf++; + *buf = color; + buf++; + + *buf = color; + buf++; + *buf = color; + buf++; + *buf = color; + buf++; + *buf = color; + buf++; + + *buf = color; + buf++; + *buf = color; + buf++; + *buf = color; + buf++; + *buf = color; + buf++; + + *buf = color; + buf++; + *buf = color; + buf++; + *buf = color; + buf++; + *buf = color; + buf++; + + px_num -= 16; + } + while(px_num) { + *buf = color; + buf++; + px_num--; + } +#endif +} + +lv_color_t lv_color_lighten(lv_color_t c, lv_opa_t lvl) +{ + return lv_color_mix(lv_color_white(), c, lvl); +} + +lv_color_t lv_color_darken(lv_color_t c, lv_opa_t lvl) +{ + return lv_color_mix(lv_color_black(), c, lvl); +} + +lv_color_t lv_color_change_lightness(lv_color_t c, lv_opa_t lvl) +{ + /*It'd be better to convert the color to HSL, change L and convert back to RGB.*/ + if(lvl == LV_OPA_50) return c; + else if(lvl < LV_OPA_50) return lv_color_darken(c, (LV_OPA_50 - lvl) * 2); + else return lv_color_lighten(c, (lvl - LV_OPA_50) * 2); +} + +/** + * Convert a HSV color to RGB + * @param h hue [0..359] + * @param s saturation [0..100] + * @param v value [0..100] + * @return the given RGB color in RGB (with LV_COLOR_DEPTH depth) + */ +lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v) +{ + h = (uint32_t)((uint32_t)h * 255) / 360; + s = (uint16_t)((uint16_t)s * 255) / 100; + v = (uint16_t)((uint16_t)v * 255) / 100; + + uint8_t r, g, b; + + uint8_t region, remainder, p, q, t; + + if(s == 0) { + return lv_color_make(v, v, v); + } + + region = h / 43; + remainder = (h - (region * 43)) * 6; + + p = (v * (255 - s)) >> 8; + q = (v * (255 - ((s * remainder) >> 8))) >> 8; + t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8; + + switch(region) { + case 0: + r = v; + g = t; + b = p; + break; + case 1: + r = q; + g = v; + b = p; + break; + case 2: + r = p; + g = v; + b = t; + break; + case 3: + r = p; + g = q; + b = v; + break; + case 4: + r = t; + g = p; + b = v; + break; + default: + r = v; + g = p; + b = q; + break; + } + + lv_color_t result = lv_color_make(r, g, b); + return result; +} + +/** + * Convert a 32-bit RGB color to HSV + * @param r8 8-bit red + * @param g8 8-bit green + * @param b8 8-bit blue + * @return the given RGB color in HSV + */ +lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8) +{ + uint16_t r = ((uint32_t)r8 << 10) / 255; + uint16_t g = ((uint32_t)g8 << 10) / 255; + uint16_t b = ((uint32_t)b8 << 10) / 255; + + uint16_t rgbMin = r < g ? (r < b ? r : b) : (g < b ? g : b); + uint16_t rgbMax = r > g ? (r > b ? r : b) : (g > b ? g : b); + + lv_color_hsv_t hsv; + + // https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness + hsv.v = (100 * rgbMax) >> 10; + + int32_t delta = rgbMax - rgbMin; + if(delta < 3) { + hsv.h = 0; + hsv.s = 0; + return hsv; + } + + // https://en.wikipedia.org/wiki/HSL_and_HSV#Saturation + hsv.s = 100 * delta / rgbMax; + if(hsv.s < 3) { + hsv.h = 0; + return hsv; + } + + // https://en.wikipedia.org/wiki/HSL_and_HSV#Hue_and_chroma + int32_t h; + if(rgbMax == r) + h = (((g - b) << 10) / delta) + (g < b ? (6 << 10) : 0); // between yellow & magenta + else if(rgbMax == g) + h = (((b - r) << 10) / delta) + (2 << 10); // between cyan & yellow + else if(rgbMax == b) + h = (((r - g) << 10) / delta) + (4 << 10); // between magenta & cyan + else + h = 0; + h *= 60; + h >>= 10; + if(h < 0) h += 360; + + hsv.h = h; + return hsv; +} + +/** + * Convert a color to HSV + * @param color color + * @return the given color in HSV + */ +lv_color_hsv_t lv_color_to_hsv(lv_color_t color) +{ + lv_color32_t color32; + color32.full = lv_color_to32(color); + return lv_color_rgb_to_hsv(color32.ch.red, color32.ch.green, color32.ch.blue); +} + +lv_color_t lv_palette_main(lv_palette_t p) +{ + static const lv_color_t colors[] = { + LV_COLOR_MAKE(0xF4, 0x43, 0x36), LV_COLOR_MAKE(0xE9, 0x1E, 0x63), LV_COLOR_MAKE(0x9C, 0x27, 0xB0), LV_COLOR_MAKE(0x67, 0x3A, 0xB7), + LV_COLOR_MAKE(0x3F, 0x51, 0xB5), LV_COLOR_MAKE(0x21, 0x96, 0xF3), LV_COLOR_MAKE(0x03, 0xA9, 0xF4), LV_COLOR_MAKE(0x00, 0xBC, 0xD4), + LV_COLOR_MAKE(0x00, 0x96, 0x88), LV_COLOR_MAKE(0x4C, 0xAF, 0x50), LV_COLOR_MAKE(0x8B, 0xC3, 0x4A), LV_COLOR_MAKE(0xCD, 0xDC, 0x39), + LV_COLOR_MAKE(0xFF, 0xEB, 0x3B), LV_COLOR_MAKE(0xFF, 0xC1, 0x07), LV_COLOR_MAKE(0xFF, 0x98, 0x00), LV_COLOR_MAKE(0xFF, 0x57, 0x22), + LV_COLOR_MAKE(0x79, 0x55, 0x48), LV_COLOR_MAKE(0x60, 0x7D, 0x8B), LV_COLOR_MAKE(0x9E, 0x9E, 0x9E) + }; + + if(p >= _LV_PALETTE_LAST) { + LV_LOG_WARN("Invalid palette: %d", p); + return lv_color_black(); + } + + return colors[p]; + +} + +lv_color_t lv_palette_lighten(lv_palette_t p, uint8_t lvl) +{ + static const lv_color_t colors[][5] = { + {LV_COLOR_MAKE(0xEF, 0x53, 0x50), LV_COLOR_MAKE(0xE5, 0x73, 0x73), LV_COLOR_MAKE(0xEF, 0x9A, 0x9A), LV_COLOR_MAKE(0xFF, 0xCD, 0xD2), LV_COLOR_MAKE(0xFF, 0xEB, 0xEE)}, + {LV_COLOR_MAKE(0xEC, 0x40, 0x7A), LV_COLOR_MAKE(0xF0, 0x62, 0x92), LV_COLOR_MAKE(0xF4, 0x8F, 0xB1), LV_COLOR_MAKE(0xF8, 0xBB, 0xD0), LV_COLOR_MAKE(0xFC, 0xE4, 0xEC)}, + {LV_COLOR_MAKE(0xAB, 0x47, 0xBC), LV_COLOR_MAKE(0xBA, 0x68, 0xC8), LV_COLOR_MAKE(0xCE, 0x93, 0xD8), LV_COLOR_MAKE(0xE1, 0xBE, 0xE7), LV_COLOR_MAKE(0xF3, 0xE5, 0xF5)}, + {LV_COLOR_MAKE(0x7E, 0x57, 0xC2), LV_COLOR_MAKE(0x95, 0x75, 0xCD), LV_COLOR_MAKE(0xB3, 0x9D, 0xDB), LV_COLOR_MAKE(0xD1, 0xC4, 0xE9), LV_COLOR_MAKE(0xED, 0xE7, 0xF6)}, + {LV_COLOR_MAKE(0x5C, 0x6B, 0xC0), LV_COLOR_MAKE(0x79, 0x86, 0xCB), LV_COLOR_MAKE(0x9F, 0xA8, 0xDA), LV_COLOR_MAKE(0xC5, 0xCA, 0xE9), LV_COLOR_MAKE(0xE8, 0xEA, 0xF6)}, + {LV_COLOR_MAKE(0x42, 0xA5, 0xF5), LV_COLOR_MAKE(0x64, 0xB5, 0xF6), LV_COLOR_MAKE(0x90, 0xCA, 0xF9), LV_COLOR_MAKE(0xBB, 0xDE, 0xFB), LV_COLOR_MAKE(0xE3, 0xF2, 0xFD)}, + {LV_COLOR_MAKE(0x29, 0xB6, 0xF6), LV_COLOR_MAKE(0x4F, 0xC3, 0xF7), LV_COLOR_MAKE(0x81, 0xD4, 0xFA), LV_COLOR_MAKE(0xB3, 0xE5, 0xFC), LV_COLOR_MAKE(0xE1, 0xF5, 0xFE)}, + {LV_COLOR_MAKE(0x26, 0xC6, 0xDA), LV_COLOR_MAKE(0x4D, 0xD0, 0xE1), LV_COLOR_MAKE(0x80, 0xDE, 0xEA), LV_COLOR_MAKE(0xB2, 0xEB, 0xF2), LV_COLOR_MAKE(0xE0, 0xF7, 0xFA)}, + {LV_COLOR_MAKE(0x26, 0xA6, 0x9A), LV_COLOR_MAKE(0x4D, 0xB6, 0xAC), LV_COLOR_MAKE(0x80, 0xCB, 0xC4), LV_COLOR_MAKE(0xB2, 0xDF, 0xDB), LV_COLOR_MAKE(0xE0, 0xF2, 0xF1)}, + {LV_COLOR_MAKE(0x66, 0xBB, 0x6A), LV_COLOR_MAKE(0x81, 0xC7, 0x84), LV_COLOR_MAKE(0xA5, 0xD6, 0xA7), LV_COLOR_MAKE(0xC8, 0xE6, 0xC9), LV_COLOR_MAKE(0xE8, 0xF5, 0xE9)}, + {LV_COLOR_MAKE(0x9C, 0xCC, 0x65), LV_COLOR_MAKE(0xAE, 0xD5, 0x81), LV_COLOR_MAKE(0xC5, 0xE1, 0xA5), LV_COLOR_MAKE(0xDC, 0xED, 0xC8), LV_COLOR_MAKE(0xF1, 0xF8, 0xE9)}, + {LV_COLOR_MAKE(0xD4, 0xE1, 0x57), LV_COLOR_MAKE(0xDC, 0xE7, 0x75), LV_COLOR_MAKE(0xE6, 0xEE, 0x9C), LV_COLOR_MAKE(0xF0, 0xF4, 0xC3), LV_COLOR_MAKE(0xF9, 0xFB, 0xE7)}, + {LV_COLOR_MAKE(0xFF, 0xEE, 0x58), LV_COLOR_MAKE(0xFF, 0xF1, 0x76), LV_COLOR_MAKE(0xFF, 0xF5, 0x9D), LV_COLOR_MAKE(0xFF, 0xF9, 0xC4), LV_COLOR_MAKE(0xFF, 0xFD, 0xE7)}, + {LV_COLOR_MAKE(0xFF, 0xCA, 0x28), LV_COLOR_MAKE(0xFF, 0xD5, 0x4F), LV_COLOR_MAKE(0xFF, 0xE0, 0x82), LV_COLOR_MAKE(0xFF, 0xEC, 0xB3), LV_COLOR_MAKE(0xFF, 0xF8, 0xE1)}, + {LV_COLOR_MAKE(0xFF, 0xA7, 0x26), LV_COLOR_MAKE(0xFF, 0xB7, 0x4D), LV_COLOR_MAKE(0xFF, 0xCC, 0x80), LV_COLOR_MAKE(0xFF, 0xE0, 0xB2), LV_COLOR_MAKE(0xFF, 0xF3, 0xE0)}, + {LV_COLOR_MAKE(0xFF, 0x70, 0x43), LV_COLOR_MAKE(0xFF, 0x8A, 0x65), LV_COLOR_MAKE(0xFF, 0xAB, 0x91), LV_COLOR_MAKE(0xFF, 0xCC, 0xBC), LV_COLOR_MAKE(0xFB, 0xE9, 0xE7)}, + {LV_COLOR_MAKE(0x8D, 0x6E, 0x63), LV_COLOR_MAKE(0xA1, 0x88, 0x7F), LV_COLOR_MAKE(0xBC, 0xAA, 0xA4), LV_COLOR_MAKE(0xD7, 0xCC, 0xC8), LV_COLOR_MAKE(0xEF, 0xEB, 0xE9)}, + {LV_COLOR_MAKE(0x78, 0x90, 0x9C), LV_COLOR_MAKE(0x90, 0xA4, 0xAE), LV_COLOR_MAKE(0xB0, 0xBE, 0xC5), LV_COLOR_MAKE(0xCF, 0xD8, 0xDC), LV_COLOR_MAKE(0xEC, 0xEF, 0xF1)}, + {LV_COLOR_MAKE(0xBD, 0xBD, 0xBD), LV_COLOR_MAKE(0xE0, 0xE0, 0xE0), LV_COLOR_MAKE(0xEE, 0xEE, 0xEE), LV_COLOR_MAKE(0xF5, 0xF5, 0xF5), LV_COLOR_MAKE(0xFA, 0xFA, 0xFA)}, + }; + + if(p >= _LV_PALETTE_LAST) { + LV_LOG_WARN("Invalid palette: %d", p); + return lv_color_black(); + } + + if(lvl == 0 || lvl > 5) { + LV_LOG_WARN("Invalid level: %d. Must be 1..5", lvl); + return lv_color_black(); + } + + lvl--; + + return colors[p][lvl]; +} + +lv_color_t lv_palette_darken(lv_palette_t p, uint8_t lvl) +{ + static const lv_color_t colors[][4] = { + {LV_COLOR_MAKE(0xE5, 0x39, 0x35), LV_COLOR_MAKE(0xD3, 0x2F, 0x2F), LV_COLOR_MAKE(0xC6, 0x28, 0x28), LV_COLOR_MAKE(0xB7, 0x1C, 0x1C)}, + {LV_COLOR_MAKE(0xD8, 0x1B, 0x60), LV_COLOR_MAKE(0xC2, 0x18, 0x5B), LV_COLOR_MAKE(0xAD, 0x14, 0x57), LV_COLOR_MAKE(0x88, 0x0E, 0x4F)}, + {LV_COLOR_MAKE(0x8E, 0x24, 0xAA), LV_COLOR_MAKE(0x7B, 0x1F, 0xA2), LV_COLOR_MAKE(0x6A, 0x1B, 0x9A), LV_COLOR_MAKE(0x4A, 0x14, 0x8C)}, + {LV_COLOR_MAKE(0x5E, 0x35, 0xB1), LV_COLOR_MAKE(0x51, 0x2D, 0xA8), LV_COLOR_MAKE(0x45, 0x27, 0xA0), LV_COLOR_MAKE(0x31, 0x1B, 0x92)}, + {LV_COLOR_MAKE(0x39, 0x49, 0xAB), LV_COLOR_MAKE(0x30, 0x3F, 0x9F), LV_COLOR_MAKE(0x28, 0x35, 0x93), LV_COLOR_MAKE(0x1A, 0x23, 0x7E)}, + {LV_COLOR_MAKE(0x1E, 0x88, 0xE5), LV_COLOR_MAKE(0x19, 0x76, 0xD2), LV_COLOR_MAKE(0x15, 0x65, 0xC0), LV_COLOR_MAKE(0x0D, 0x47, 0xA1)}, + {LV_COLOR_MAKE(0x03, 0x9B, 0xE5), LV_COLOR_MAKE(0x02, 0x88, 0xD1), LV_COLOR_MAKE(0x02, 0x77, 0xBD), LV_COLOR_MAKE(0x01, 0x57, 0x9B)}, + {LV_COLOR_MAKE(0x00, 0xAC, 0xC1), LV_COLOR_MAKE(0x00, 0x97, 0xA7), LV_COLOR_MAKE(0x00, 0x83, 0x8F), LV_COLOR_MAKE(0x00, 0x60, 0x64)}, + {LV_COLOR_MAKE(0x00, 0x89, 0x7B), LV_COLOR_MAKE(0x00, 0x79, 0x6B), LV_COLOR_MAKE(0x00, 0x69, 0x5C), LV_COLOR_MAKE(0x00, 0x4D, 0x40)}, + {LV_COLOR_MAKE(0x43, 0xA0, 0x47), LV_COLOR_MAKE(0x38, 0x8E, 0x3C), LV_COLOR_MAKE(0x2E, 0x7D, 0x32), LV_COLOR_MAKE(0x1B, 0x5E, 0x20)}, + {LV_COLOR_MAKE(0x7C, 0xB3, 0x42), LV_COLOR_MAKE(0x68, 0x9F, 0x38), LV_COLOR_MAKE(0x55, 0x8B, 0x2F), LV_COLOR_MAKE(0x33, 0x69, 0x1E)}, + {LV_COLOR_MAKE(0xC0, 0xCA, 0x33), LV_COLOR_MAKE(0xAF, 0xB4, 0x2B), LV_COLOR_MAKE(0x9E, 0x9D, 0x24), LV_COLOR_MAKE(0x82, 0x77, 0x17)}, + {LV_COLOR_MAKE(0xFD, 0xD8, 0x35), LV_COLOR_MAKE(0xFB, 0xC0, 0x2D), LV_COLOR_MAKE(0xF9, 0xA8, 0x25), LV_COLOR_MAKE(0xF5, 0x7F, 0x17)}, + {LV_COLOR_MAKE(0xFF, 0xB3, 0x00), LV_COLOR_MAKE(0xFF, 0xA0, 0x00), LV_COLOR_MAKE(0xFF, 0x8F, 0x00), LV_COLOR_MAKE(0xFF, 0x6F, 0x00)}, + {LV_COLOR_MAKE(0xFB, 0x8C, 0x00), LV_COLOR_MAKE(0xF5, 0x7C, 0x00), LV_COLOR_MAKE(0xEF, 0x6C, 0x00), LV_COLOR_MAKE(0xE6, 0x51, 0x00)}, + {LV_COLOR_MAKE(0xF4, 0x51, 0x1E), LV_COLOR_MAKE(0xE6, 0x4A, 0x19), LV_COLOR_MAKE(0xD8, 0x43, 0x15), LV_COLOR_MAKE(0xBF, 0x36, 0x0C)}, + {LV_COLOR_MAKE(0x6D, 0x4C, 0x41), LV_COLOR_MAKE(0x5D, 0x40, 0x37), LV_COLOR_MAKE(0x4E, 0x34, 0x2E), LV_COLOR_MAKE(0x3E, 0x27, 0x23)}, + {LV_COLOR_MAKE(0x54, 0x6E, 0x7A), LV_COLOR_MAKE(0x45, 0x5A, 0x64), LV_COLOR_MAKE(0x37, 0x47, 0x4F), LV_COLOR_MAKE(0x26, 0x32, 0x38)}, + {LV_COLOR_MAKE(0x75, 0x75, 0x75), LV_COLOR_MAKE(0x61, 0x61, 0x61), LV_COLOR_MAKE(0x42, 0x42, 0x42), LV_COLOR_MAKE(0x21, 0x21, 0x21)}, + }; + + if(p >= _LV_PALETTE_LAST) { + LV_LOG_WARN("Invalid palette: %d", p); + return lv_color_black(); + } + + if(lvl == 0 || lvl > 4) { + LV_LOG_WARN("Invalid level: %d. Must be 1..4", lvl); + return lv_color_black(); + } + + lvl--; + + return colors[p][lvl]; +} diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_color.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_color.h similarity index 92% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_color.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_color.h index fffd7dabd..ca226102a 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_color.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_color.h @@ -14,6 +14,7 @@ extern "C" { * INCLUDES *********************/ #include "../lv_conf_internal.h" +#include "lv_assert.h" #include "lv_math.h" #include "lv_types.h" @@ -35,6 +36,8 @@ extern "C" { /********************* * DEFINES *********************/ +LV_EXPORT_CONST_INT(LV_COLOR_DEPTH); +LV_EXPORT_CONST_INT(LV_COLOR_16_SWAP); /** * Opacity percentages. @@ -70,23 +73,6 @@ enum { #error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!" #endif -/** - * Adjust color mix functions rounding. - * GPUs might calculate color mix (blending) differently. - * Should be in range of 0..254 - * 0: no adjustment, get the integer part of the result (round down) - * 64: round up from x.75 - * 128: round up from half - * 192: round up from x.25 - * 254: round up*/ -#ifndef LV_COLOR_MIX_ROUND_OFS -#if LV_COLOR_DEPTH == 32 -#define LV_COLOR_MIX_ROUND_OFS 0 -#else -#define LV_COLOR_MIX_ROUND_OFS 128 -#endif -#endif - #if defined(__cplusplus) && !defined(_LV_COLOR_HAS_MODERN_CPP) /** * MSVC compiler's definition of the __cplusplus indicating 199711L regardless to C++ standard version @@ -201,8 +187,6 @@ enum { #define _LV_COLOR_ZERO_INITIALIZER LV_CONCAT(_LV_COLOR_ZERO_INITIALIZER, LV_COLOR_DEPTH) #define LV_COLOR_MAKE(r8, g8, b8) LV_CONCAT(LV_COLOR_MAKE, LV_COLOR_DEPTH)(r8, g8, b8) -#define LV_UDIV255(x) ((uint32_t)((uint32_t) (x) * 0x8081) >> 0x17) - /********************** * TYPEDEFS **********************/ @@ -272,7 +256,7 @@ typedef lv_color_t (*lv_color_filter_cb_t)(const struct _lv_color_filter_dsc_t * typedef struct _lv_color_filter_dsc_t { lv_color_filter_cb_t filter_cb; void * user_data; -}lv_color_filter_dsc_t; +} lv_color_filter_dsc_t; typedef enum { @@ -297,7 +281,7 @@ typedef enum { LV_PALETTE_GREY, _LV_PALETTE_LAST, LV_PALETTE_NONE = 0xff, -}lv_palette_t; +} lv_palette_t; /********************** * GLOBAL PROTOTYPES @@ -459,14 +443,23 @@ static inline uint32_t lv_color_to32(lv_color_t color) LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix) { lv_color_t ret; -#if LV_COLOR_DEPTH != 1 + +#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0 + /*Source: https://stackoverflow.com/a/50012418/1999969*/ + mix = (mix + 4) >> 3; + uint32_t bg = (uint32_t)((uint32_t)c2.full | ((uint32_t)c2.full << 16)) & + 0x7E0F81F; /*0b00000111111000001111100000011111*/ + uint32_t fg = (uint32_t)((uint32_t)c1.full | ((uint32_t)c1.full << 16)) & 0x7E0F81F; + uint32_t result = ((((fg - bg) * mix) >> 5) + bg) & 0x7E0F81F; + ret.full = (uint16_t)((result >> 16) | result); +#elif LV_COLOR_DEPTH != 1 /*LV_COLOR_DEPTH == 8, 16 or 32*/ - LV_COLOR_SET_R(ret, LV_UDIV255((uint16_t) LV_COLOR_GET_R(c1) * mix + LV_COLOR_GET_R(c2) * - (255 - mix) + LV_COLOR_MIX_ROUND_OFS)); - LV_COLOR_SET_G(ret, LV_UDIV255((uint16_t) LV_COLOR_GET_G(c1) * mix + LV_COLOR_GET_G(c2) * - (255 - mix) + LV_COLOR_MIX_ROUND_OFS)); - LV_COLOR_SET_B(ret, LV_UDIV255((uint16_t) LV_COLOR_GET_B(c1) * mix + LV_COLOR_GET_B(c2) * - (255 - mix) + LV_COLOR_MIX_ROUND_OFS)); + LV_COLOR_SET_R(ret, LV_UDIV255((uint16_t)LV_COLOR_GET_R(c1) * mix + LV_COLOR_GET_R(c2) * + (255 - mix) + LV_COLOR_MIX_ROUND_OFS)); + LV_COLOR_SET_G(ret, LV_UDIV255((uint16_t)LV_COLOR_GET_G(c1) * mix + LV_COLOR_GET_G(c2) * + (255 - mix) + LV_COLOR_MIX_ROUND_OFS)); + LV_COLOR_SET_B(ret, LV_UDIV255((uint16_t)LV_COLOR_GET_B(c1) * mix + LV_COLOR_GET_B(c2) * + (255 - mix) + LV_COLOR_MIX_ROUND_OFS)); LV_COLOR_SET_A(ret, 0xFF); #else /*LV_COLOR_DEPTH == 1*/ @@ -479,9 +472,9 @@ LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix(lv_color_t c1, lv_co LV_ATTRIBUTE_FAST_MEM static inline void lv_color_premult(lv_color_t c, uint8_t mix, uint16_t * out) { #if LV_COLOR_DEPTH != 1 - out[0] = (uint16_t) LV_COLOR_GET_R(c) * mix; - out[1] = (uint16_t) LV_COLOR_GET_G(c) * mix; - out[2] = (uint16_t) LV_COLOR_GET_B(c) * mix; + out[0] = (uint16_t)LV_COLOR_GET_R(c) * mix; + out[1] = (uint16_t)LV_COLOR_GET_G(c) * mix; + out[2] = (uint16_t)LV_COLOR_GET_B(c) * mix; #else (void) mix; /*Pre-multiplication can't be used with 1 bpp*/ @@ -505,7 +498,7 @@ LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix_premult(uint16_t * p { lv_color_t ret; #if LV_COLOR_DEPTH != 1 - /*LV_COLOR_DEPTH == 8, 16 or 32*/ + /*LV_COLOR_DEPTH == 8 or 32*/ LV_COLOR_SET_R(ret, LV_UDIV255(premult_c1[0] + LV_COLOR_GET_R(c2) * mix + LV_COLOR_MIX_ROUND_OFS)); LV_COLOR_SET_G(ret, LV_UDIV255(premult_c1[1] + LV_COLOR_GET_G(c2) * mix + LV_COLOR_MIX_ROUND_OFS)); LV_COLOR_SET_B(ret, LV_UDIV255(premult_c1[2] + LV_COLOR_GET_B(c2) * mix + LV_COLOR_MIX_ROUND_OFS)); @@ -570,10 +563,7 @@ LV_ATTRIBUTE_FAST_MEM static inline void lv_color_mix_with_alpha(lv_color_t bg_c /*Info: * https://en.wikipedia.org/wiki/Alpha_compositing#Analytical_derivation_of_the_over_operator*/ res_opa_saved = 255 - ((uint16_t)((uint16_t)(255 - fg_opa) * (255 - bg_opa)) >> 8); - if(res_opa_saved == 0) { - while(1) - ; - } + LV_ASSERT(res_opa_saved != 0); lv_opa_t ratio = (uint16_t)((uint16_t)fg_opa * 255) / res_opa_saved; res_color_saved = lv_color_mix(fg_color, bg_color, ratio); @@ -671,8 +661,14 @@ static inline lv_color_t lv_color_chroma_key(void) /*Source: https://vuetifyjs.com/en/styles/colors/#material-colors*/ lv_color_t lv_palette_main(lv_palette_t p); -static inline lv_color_t lv_color_white(void) { return lv_color_make(0xff, 0xff, 0xff);} -static inline lv_color_t lv_color_black(void) { return lv_color_make(0x00, 0x0, 0x00);} +static inline lv_color_t lv_color_white(void) +{ + return lv_color_make(0xff, 0xff, 0xff); +} +static inline lv_color_t lv_color_black(void) +{ + return lv_color_make(0x00, 0x0, 0x00); +} lv_color_t lv_palette_lighten(lv_palette_t p, uint8_t lvl); lv_color_t lv_palette_darken(lv_palette_t p, uint8_t lvl); diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_fs.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.c similarity index 88% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_fs.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_fs.c index 6d6444331..8011b4cf4 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_fs.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.c @@ -8,9 +8,9 @@ *********************/ #include "lv_fs.h" -#include "../misc/lv_assert.h" -#include "lv_ll.h" #include +#include "lv_assert.h" +#include "lv_ll.h" #include "lv_gc.h" /********************* @@ -91,9 +91,9 @@ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mo } const char * real_path = lv_fs_get_real_path(path); - void *file_d = drv->open_cb(drv, real_path, mode); + void * file_d = drv->open_cb(drv, real_path, mode); - if(file_d == NULL || file_d == (void*)(-1)) { + if(file_d == NULL || file_d == (void *)(-1)) { return LV_FS_RES_UNKNOWN; } @@ -163,26 +163,22 @@ lv_fs_res_t lv_fs_seek(lv_fs_file_t * file_p, uint32_t pos, lv_fs_whence_t whenc return LV_FS_RES_NOT_IMP; } - lv_fs_res_t res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, pos, whence); - - return res; + return file_p->drv->seek_cb(file_p->drv, file_p->file_d, pos, whence); } lv_fs_res_t lv_fs_tell(lv_fs_file_t * file_p, uint32_t * pos) { + *pos = 0; + if(file_p->drv == NULL) { - *pos = 0; return LV_FS_RES_INV_PARAM; } if(file_p->drv->tell_cb == NULL) { - *pos = 0; return LV_FS_RES_NOT_IMP; } - lv_fs_res_t res = file_p->drv->tell_cb(file_p->drv, file_p->file_d, pos); - - return res; + return file_p->drv->tell_cb(file_p->drv, file_p->file_d, pos); } lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path) @@ -207,9 +203,9 @@ lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path) } const char * real_path = lv_fs_get_real_path(path); - void *dir_d = drv->dir_open_cb(drv, real_path); + void * dir_d = drv->dir_open_cb(drv, real_path); - if(dir_d == NULL || dir_d == (void*)(-1)) { + if(dir_d == NULL || dir_d == (void *)(-1)) { return LV_FS_RES_UNKNOWN; } @@ -221,19 +217,17 @@ lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path) lv_fs_res_t lv_fs_dir_read(lv_fs_dir_t * rddir_p, char * fn) { + fn[0] = '\0'; + if(rddir_p->drv == NULL || rddir_p->dir_d == NULL) { - fn[0] = '\0'; return LV_FS_RES_INV_PARAM; } if(rddir_p->drv->dir_read_cb == NULL) { - fn[0] = '\0'; return LV_FS_RES_NOT_IMP; } - lv_fs_res_t res = rddir_p->drv->dir_read_cb(rddir_p->drv, rddir_p->dir_d, fn); - - return res; + return rddir_p->drv->dir_read_cb(rddir_p->drv, rddir_p->dir_d, fn); } lv_fs_res_t lv_fs_dir_close(lv_fs_dir_t * rddir_p) @@ -302,10 +296,10 @@ const char * lv_fs_get_ext(const char * fn) { size_t i; for(i = strlen(fn); i > 0; i--) { - if(fn[i] == '.') { - return &fn[i + 1]; + if(fn[i - 1] == '.') { + return &fn[i]; } - else if(fn[i] == '/' || fn[i] == '\\') { + else if(fn[i - 1] == '/' || fn[i - 1] == '\\') { return ""; /*No extension if a '\' or '/' found*/ } } @@ -331,11 +325,12 @@ char * lv_fs_up(char * path) size_t i; for(i = len; i > 0; i--) { - if(path[i] == '/' || path[i] == '\\') break; + if(path[i - 1] == '/' || path[i - 1] == '\\') { + path[i - 1] = '\0'; + break; + } } - if(i > 0) path[i] = '\0'; - return path; } @@ -356,14 +351,12 @@ const char * lv_fs_get_last(const char * path) size_t i; for(i = len; i > 0; i--) { - if(path[i] == '/' || path[i] == '\\') break; + if(path[i - 1] == '/' || path[i - 1] == '\\') break; } - /*No '/' or '\' in the path so return with path itself*/ - if(i == 0) return path; - - return &path[i + 1]; + return &path[i]; } + /********************** * STATIC FUNCTIONS **********************/ diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_fs.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.h similarity index 62% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_fs.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_fs.h index 85c1e33f3..9afc2bf57 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_fs.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.h @@ -65,7 +65,7 @@ typedef enum { LV_FS_SEEK_SET = 0x00, /**< Set the position from absolutely (from the start of file)*/ LV_FS_SEEK_CUR = 0x01, /**< Set the position from the current position*/ LV_FS_SEEK_END = 0x02, /**< Set the position from the end of the file*/ -}lv_fs_whence_t; +} lv_fs_whence_t; typedef struct _lv_fs_drv_t { char letter; @@ -110,134 +110,135 @@ void _lv_fs_init(void); * Initialize a file system driver with default values. * It is used to surly have known values in the fields ant not memory junk. * After it you can set the fields. - * @param drv pointer to driver variable to initialize + * @param drv pointer to driver variable to initialize */ void lv_fs_drv_init(lv_fs_drv_t * drv); /** * Add a new drive - * @param drv_p pointer to an lv_fs_drv_t structure which is inited with the - * corresponding function pointers. - * Only pointer is saved, so the driver should be static or dynamically allocated. + * @param drv pointer to an lv_fs_drv_t structure which is inited with the + * corresponding function pointers. Only pointer is saved, so the + * driver should be static or dynamically allocated. */ -void lv_fs_drv_register(lv_fs_drv_t * drv_p); +void lv_fs_drv_register(lv_fs_drv_t * drv); /** * Give a pointer to a driver from its letter - * @param letter the driver letter - * @return pointer to a driver or NULL if not found + * @param letter the driver letter + * @return pointer to a driver or NULL if not found */ lv_fs_drv_t * lv_fs_get_drv(char letter); /** * Test if a drive is ready or not. If the `ready` function was not initialized `true` will be * returned. - * @param letter letter of the drive - * @return true: drive is ready; false: drive is not ready + * @param letter letter of the drive + * @return true: drive is ready; false: drive is not ready */ bool lv_fs_is_ready(char letter); /** * Open a file - * @param file_p pointer to a lv_fs_file_t variable - * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) - * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR - * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + * @param file_p pointer to a lv_fs_file_t variable + * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) + * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mode); /** * Close an already opened file - * @param file_p pointer to a lv_fs_file_t variable - * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + * @param file_p pointer to a lv_fs_file_t variable + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ lv_fs_res_t lv_fs_close(lv_fs_file_t * file_p); /** * Read from a file - * @param file_p pointer to a lv_fs_file_t variable - * @param buf pointer to a buffer where the read bytes are stored - * @param btr Bytes To Read - * @param br the number of real read bytes (Bytes Read). NULL if unused. - * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + * @param file_p pointer to a lv_fs_file_t variable + * @param buf pointer to a buffer where the read bytes are stored + * @param btr Bytes To Read + * @param br the number of real read bytes (Bytes Read). NULL if unused. + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ lv_fs_res_t lv_fs_read(lv_fs_file_t * file_p, void * buf, uint32_t btr, uint32_t * br); /** * Write into a file - * @param file_p pointer to a lv_fs_file_t variable - * @param buf pointer to a buffer with the bytes to write - * @param btr Bytes To Write - * @param br the number of real written bytes (Bytes Written). NULL if unused. - * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + * @param file_p pointer to a lv_fs_file_t variable + * @param buf pointer to a buffer with the bytes to write + * @param btr Bytes To Write + * @param br the number of real written bytes (Bytes Written). NULL if unused. + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ lv_fs_res_t lv_fs_write(lv_fs_file_t * file_p, const void * buf, uint32_t btw, uint32_t * bw); /** * Set the position of the 'cursor' (read write pointer) in a file - * @param file_p pointer to a lv_fs_file_t variable - * @param pos the new position expressed in bytes index (0: start of file) - * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + * @param file_p pointer to a lv_fs_file_t variable + * @param pos the new position expressed in bytes index (0: start of file) + * @param whence tells from where set the position. See @lv_fs_whence_t + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ lv_fs_res_t lv_fs_seek(lv_fs_file_t * file_p, uint32_t pos, lv_fs_whence_t whence); /** * Give the position of the read write pointer - * @param file_p pointer to a lv_fs_file_t variable - * @param pos_p pointer to store the position of the read write pointer - * @return LV_FS_RES_OK or any error from 'fs_res_t' + * @param file_p pointer to a lv_fs_file_t variable + * @param pos_p pointer to store the position of the read write pointer + * @return LV_FS_RES_OK or any error from 'fs_res_t' */ lv_fs_res_t lv_fs_tell(lv_fs_file_t * file_p, uint32_t * pos); /** * Initialize a 'fs_dir_t' variable for directory reading - * @param rddir_p pointer to a 'lv_fs_dir_t' variable - * @param path path to a directory - * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + * @param rddir_p pointer to a 'lv_fs_dir_t' variable + * @param path path to a directory + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path); /** * Read the next filename form a directory. * The name of the directories will begin with '/' - * @param rddir_p pointer to an initialized 'fs_dir_t' variable - * @param fn pointer to a buffer to store the filename - * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + * @param rddir_p pointer to an initialized 'fs_dir_t' variable + * @param fn pointer to a buffer to store the filename + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ lv_fs_res_t lv_fs_dir_read(lv_fs_dir_t * rddir_p, char * fn); /** * Close the directory reading - * @param rddir_p pointer to an initialized 'fs_dir_t' variable - * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + * @param rddir_p pointer to an initialized 'fs_dir_t' variable + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ lv_fs_res_t lv_fs_dir_close(lv_fs_dir_t * rddir_p); /** * Fill a buffer with the letters of existing drivers - * @param buf buffer to store the letters ('\0' added after the last letter) - * @return the buffer + * @param buf buffer to store the letters ('\0' added after the last letter) + * @return the buffer */ char * lv_fs_get_letters(char * buf); /** * Return with the extension of the filename - * @param fn string with a filename - * @return pointer to the beginning extension or empty string if no extension + * @param fn string with a filename + * @return pointer to the beginning extension or empty string if no extension */ const char * lv_fs_get_ext(const char * fn); /** * Step up one level - * @param path pointer to a file name - * @return the truncated file name + * @param path pointer to a file name + * @return the truncated file name */ char * lv_fs_up(char * path); /** * Get the last element of a path (e.g. U:/folder/file -> file) - * @param path pointer to a file name - * @return pointer to the beginning of the last element in the path + * @param path pointer to a file name + * @return pointer to the beginning of the last element in the path */ const char * lv_fs_get_last(const char * path); diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_gc.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_gc.c similarity index 97% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_gc.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_gc.c index ca163fee0..95bb5499a 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_gc.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_gc.c @@ -6,9 +6,7 @@ /********************* * INCLUDES *********************/ - #include "lv_gc.h" -#include "string.h" /********************* * DEFINES diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_gc.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_gc.h similarity index 74% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_gc.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_gc.h index 00b5fee7d..dac62be26 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_gc.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_gc.h @@ -13,11 +13,12 @@ extern "C" { /********************* * INCLUDES *********************/ +#include "../lv_conf_internal.h" #include -#include #include "lv_mem.h" #include "lv_ll.h" #include "lv_timer.h" +#include "lv_types.h" #include "../draw/lv_img_cache.h" #include "../draw/lv_draw_mask.h" #include "../core/lv_obj_pos.h" @@ -39,22 +40,23 @@ extern "C" { #define LV_DISPATCH10(f, t, n) #define LV_DISPATCH11(f, t, n) LV_DISPATCH(f, t, n) -#define LV_ITERATE_ROOTS(f) \ - LV_DISPATCH(f, lv_ll_t, _lv_timer_ll) /*Linked list to store the lv_timers*/ \ - LV_DISPATCH(f, lv_ll_t, _lv_disp_ll) /*Linked list of display device*/ \ - LV_DISPATCH(f, lv_ll_t, _lv_indev_ll) /*Linked list of input device*/ \ - LV_DISPATCH(f, lv_ll_t, _lv_fsdrv_ll) \ - LV_DISPATCH(f, lv_ll_t, _lv_anim_ll) \ - LV_DISPATCH(f, lv_ll_t, _lv_group_ll) \ - LV_DISPATCH(f, lv_ll_t, _lv_img_decoder_ll) \ - LV_DISPATCH(f, lv_ll_t, _lv_obj_style_trans_ll) \ - LV_DISPATCH(f, lv_layout_dsc_t *, _lv_layout_list) \ - LV_DISPATCH_COND(f, _lv_img_cache_entry_t*, _lv_img_cache_array, LV_IMG_CACHE_DEF, 1) \ - LV_DISPATCH_COND(f, _lv_img_cache_entry_t, _lv_img_cache_single, LV_IMG_CACHE_DEF, 0) \ - LV_DISPATCH(f, lv_timer_t*, _lv_timer_act) \ - LV_DISPATCH(f, lv_mem_buf_arr_t , lv_mem_buf) \ - LV_DISPATCH_COND(f, _lv_draw_mask_saved_arr_t , _lv_draw_mask_list, LV_DRAW_COMPLEX, 1) \ - LV_DISPATCH(f, void * , _lv_theme_default_styles) \ +#define LV_ITERATE_ROOTS(f) \ + LV_DISPATCH(f, lv_ll_t, _lv_timer_ll) /*Linked list to store the lv_timers*/ \ + LV_DISPATCH(f, lv_ll_t, _lv_disp_ll) /*Linked list of display device*/ \ + LV_DISPATCH(f, lv_ll_t, _lv_indev_ll) /*Linked list of input device*/ \ + LV_DISPATCH(f, lv_ll_t, _lv_fsdrv_ll) \ + LV_DISPATCH(f, lv_ll_t, _lv_anim_ll) \ + LV_DISPATCH(f, lv_ll_t, _lv_group_ll) \ + LV_DISPATCH(f, lv_ll_t, _lv_img_decoder_ll) \ + LV_DISPATCH(f, lv_ll_t, _lv_obj_style_trans_ll) \ + LV_DISPATCH(f, lv_layout_dsc_t *, _lv_layout_list) \ + LV_DISPATCH_COND(f, _lv_img_cache_entry_t*, _lv_img_cache_array, LV_IMG_CACHE_DEF, 1) \ + LV_DISPATCH_COND(f, _lv_img_cache_entry_t, _lv_img_cache_single, LV_IMG_CACHE_DEF, 0) \ + LV_DISPATCH(f, lv_timer_t*, _lv_timer_act) \ + LV_DISPATCH(f, lv_mem_buf_arr_t , lv_mem_buf) \ + LV_DISPATCH_COND(f, _lv_draw_mask_radius_circle_dsc_arr_t , _lv_circle_cache, LV_DRAW_COMPLEX, 1) \ + LV_DISPATCH_COND(f, _lv_draw_mask_saved_arr_t , _lv_draw_mask_list, LV_DRAW_COMPLEX, 1) \ + LV_DISPATCH(f, void * , _lv_theme_default_styles) \ LV_DISPATCH_COND(f, uint8_t *, _lv_font_decompr_buf, LV_USE_FONT_COMPRESSED, 1) #define LV_DEFINE_ROOT(root_type, root_name) root_type root_name; diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_ll.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.c similarity index 98% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_ll.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_ll.c index 30fb329a6..c84647ccf 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_ll.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.c @@ -7,9 +7,6 @@ /********************* * INCLUDES *********************/ -#include -#include - #include "lv_ll.h" #include "lv_mem.h" @@ -44,7 +41,7 @@ static void node_set_next(lv_ll_t * ll_p, lv_ll_node_t * act, lv_ll_node_t * nex /** * Initialize linked list - * @param ll_dsc pointer to ll_dsc variable + * @param ll_p pointer to lv_ll_t variable * @param node_size the size of 1 node in bytes */ void _lv_ll_init(lv_ll_t * ll_p, uint32_t node_size) @@ -94,7 +91,7 @@ void * _lv_ll_ins_head(lv_ll_t * ll_p) * Insert a new node in front of the n_act node * @param ll_p pointer to linked list * @param n_act pointer a node - * @return pointer to the new head + * @return pointer to the new node */ void * _lv_ll_ins_prev(lv_ll_t * ll_p, void * n_act) { @@ -215,7 +212,7 @@ void _lv_ll_clear(lv_ll_t * ll_p) * @param ll_new_p pointer to the new linked list * @param node pointer to a node * @param head true: be the head in the new list - * false be the head in the new list + * false be the tail in the new list */ void _lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool head) { @@ -265,7 +262,7 @@ void * _lv_ll_get_head(const lv_ll_t * ll_p) /** * Return with tail node of the linked list * @param ll_p pointer to linked list - * @return pointer to the head of 'll_p' + * @return pointer to the tail of 'll_p' */ void * _lv_ll_get_tail(const lv_ll_t * ll_p) { diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_ll.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.h similarity index 95% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_ll.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_ll.h index f5ce966a6..d38f69285 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_ll.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.h @@ -41,7 +41,7 @@ typedef struct { /** * Initialize linked list - * @param ll_dsc pointer to ll_dsc variable + * @param ll_p pointer to lv_ll_t variable * @param node_size the size of 1 node in bytes */ void _lv_ll_init(lv_ll_t * ll_p, uint32_t node_size); @@ -57,7 +57,7 @@ void * _lv_ll_ins_head(lv_ll_t * ll_p); * Insert a new node in front of the n_act node * @param ll_p pointer to linked list * @param n_act pointer a node - * @return pointer to the new head + * @return pointer to the new node */ void * _lv_ll_ins_prev(lv_ll_t * ll_p, void * n_act); @@ -88,7 +88,7 @@ void _lv_ll_clear(lv_ll_t * ll_p); * @param ll_new_p pointer to the new linked list * @param node pointer to a node * @param head true: be the head in the new list - * false be the head in the new list + * false be the tail in the new list */ void _lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool head); @@ -102,7 +102,7 @@ void * _lv_ll_get_head(const lv_ll_t * ll_p); /** * Return with tail node of the linked list * @param ll_p pointer to linked list - * @return pointer to the head of 'll_p' + * @return pointer to the tail of 'll_p' */ void * _lv_ll_get_tail(const lv_ll_t * ll_p); diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_log.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_log.c similarity index 69% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_log.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_log.c index 7e8661482..777849f9b 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_log.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_log.c @@ -72,9 +72,6 @@ void _lv_log_add(lv_log_level_t level, const char * file, int line, const char * if(level >= LV_LOG_LEVEL) { va_list args; va_start(args, format); - char msg[256]; - lv_vsnprintf(msg, sizeof(msg), format, args); - va_end(args); /*Use only the file name not the path*/ size_t p; @@ -85,22 +82,43 @@ void _lv_log_add(lv_log_level_t level, const char * file, int line, const char * } } - char buf[512]; uint32_t t = lv_tick_get(); static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error", "User"}; - lv_snprintf(buf, sizeof(buf), "[%s]\t(%d.%03d, +%d)\t %s: %s \t(in %s line #%d)\n", lvl_prefix[level], t / 1000, t % 1000, t - last_log_time, func, msg, &file[p], line); + +#if LV_LOG_PRINTF + printf("[%s]\t(%" LV_PRId32 ".%03" LV_PRId32 ", +%" LV_PRId32 ")\t %s: ", + lvl_prefix[level], t / 1000, t % 1000, t - last_log_time, func); + vprintf(format, args); + printf(" \t(in %s line #%d)\n", &file[p], line); +#else + if (custom_print_cb) { + char buf[512]; +#if LV_SPRINTF_CUSTOM + char msg[256]; + lv_vsnprintf(msg, sizeof(msg), format, args); + lv_snprintf(buf, sizeof(buf), "[%s]\t(%" LV_PRId32 ".%03" LV_PRId32 ", +%" LV_PRId32 ")\t %s: %s \t(in %s line #%d)\n", + lvl_prefix[level], t / 1000, t % 1000, t - last_log_time, func, msg, &file[p], line); +#else + lv_vaformat_t vaf = {format, &args}; + lv_snprintf(buf, sizeof(buf), "[%s]\t(%" LV_PRId32 ".%03" LV_PRId32 ", +%" LV_PRId32 ")\t %s: %pV \t(in %s line #%d)\n", + lvl_prefix[level], t / 1000, t % 1000, t - last_log_time, func, (void *)&vaf, &file[p], line); +#endif + custom_print_cb(buf); + } +#endif + last_log_time = t; - lv_log(buf); + va_end(args); } } void lv_log(const char * buf) { #if LV_LOG_PRINTF - printf("%s", buf); -#endif + puts(buf); +#else if(custom_print_cb) custom_print_cb(buf); - +#endif } /********************** diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_log.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_log.h similarity index 64% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_log.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_log.h index 7fd4b5e3e..fa6f5ac6b 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_log.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_log.h @@ -16,6 +16,8 @@ extern "C" { #include "../lv_conf_internal.h" #include +#include "lv_types.h" + /********************* * DEFINES *********************/ @@ -47,7 +49,7 @@ typedef int8_t lv_log_level_t; /** * Log print function. Receives a string buffer to print". */ -typedef void (*lv_log_print_g_cb_t)(const char *buf); +typedef void (*lv_log_print_g_cb_t)(const char * buf); /********************** * GLOBAL PROTOTYPES @@ -77,51 +79,61 @@ void lv_log(const char * buf); * @param format printf-like format string * @param ... parameters for `format` */ -void _lv_log_add(lv_log_level_t level, const char * file, int line, const char * func, const char * format, ...); +void _lv_log_add(lv_log_level_t level, const char * file, int line, + const char * func, const char * format, ...) LV_FORMAT_ATTRIBUTE(5, 6); /********************** * MACROS **********************/ - -#if LV_LOG_LEVEL <= LV_LOG_LEVEL_TRACE -#define LV_LOG_TRACE(...) _lv_log_add(LV_LOG_LEVEL_TRACE, __FILE__, __LINE__, __func__, __VA_ARGS__); -#else -#define LV_LOG_TRACE(...) +#ifndef LV_LOG_TRACE +# if LV_LOG_LEVEL <= LV_LOG_LEVEL_TRACE +# define LV_LOG_TRACE(...) _lv_log_add(LV_LOG_LEVEL_TRACE, __FILE__, __LINE__, __func__, __VA_ARGS__) +# else +# define LV_LOG_TRACE(...) do {}while(0) +# endif #endif -#if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO -#define LV_LOG_INFO(...) _lv_log_add(LV_LOG_LEVEL_INFO, __FILE__, __LINE__, __func__, __VA_ARGS__); -#else -#define LV_LOG_INFO(...) +#ifndef LV_LOG_INFO +# if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO +# define LV_LOG_INFO(...) _lv_log_add(LV_LOG_LEVEL_INFO, __FILE__, __LINE__, __func__, __VA_ARGS__) +# else +# define LV_LOG_INFO(...) do {}while(0) +# endif #endif -#if LV_LOG_LEVEL <= LV_LOG_LEVEL_WARN -#define LV_LOG_WARN(...) _lv_log_add(LV_LOG_LEVEL_WARN, __FILE__, __LINE__, __func__, __VA_ARGS__); -#else -#define LV_LOG_WARN(...) +#ifndef LV_LOG_WARN +# if LV_LOG_LEVEL <= LV_LOG_LEVEL_WARN +# define LV_LOG_WARN(...) _lv_log_add(LV_LOG_LEVEL_WARN, __FILE__, __LINE__, __func__, __VA_ARGS__) +# else +# define LV_LOG_WARN(...) do {}while(0) +# endif #endif -#if LV_LOG_LEVEL <= LV_LOG_LEVEL_ERROR -#define LV_LOG_ERROR(...) _lv_log_add(LV_LOG_LEVEL_ERROR, __FILE__, __LINE__, __func__, __VA_ARGS__); -#else -#define LV_LOG_ERROR(...) +#ifndef LV_LOG_ERROR +# if LV_LOG_LEVEL <= LV_LOG_LEVEL_ERROR +# define LV_LOG_ERROR(...) _lv_log_add(LV_LOG_LEVEL_ERROR, __FILE__, __LINE__, __func__, __VA_ARGS__) +# else +# define LV_LOG_ERROR(...) do {}while(0) +# endif #endif -#if LV_LOG_LEVEL <= LV_LOG_LEVEL_USER -#define LV_LOG_USER(...) _lv_log_add(LV_LOG_LEVEL_USER, __FILE__, __LINE__, __func__, __VA_ARGS__); -#else -#define LV_LOG_USER(...) +#ifndef LV_LOG_USER +# if LV_LOG_LEVEL <= LV_LOG_LEVEL_USER +# define LV_LOG_USER(...) _lv_log_add(LV_LOG_LEVEL_USER, __FILE__, __LINE__, __func__, __VA_ARGS__) +# else +# define LV_LOG_USER(...) do {}while(0) +# endif #endif #else /*LV_USE_LOG*/ /*Do nothing if `LV_USE_LOG 0`*/ #define _lv_log_add(level, file, line, ...) -#define LV_LOG_TRACE(...) -#define LV_LOG_INFO(...) -#define LV_LOG_WARN(...) -#define LV_LOG_ERROR(...) -#define LV_LOG_USER(...) +#define LV_LOG_TRACE(...) do {}while(0) +#define LV_LOG_INFO(...) do {}while(0) +#define LV_LOG_WARN(...) do {}while(0) +#define LV_LOG_ERROR(...) do {}while(0) +#define LV_LOG_USER(...) do {}while(0) #endif /*LV_USE_LOG*/ #ifdef __cplusplus diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_math.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_math.c similarity index 99% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_math.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_math.c index fc107b138..2144a50ca 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_math.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_math.c @@ -7,7 +7,6 @@ * INCLUDES *********************/ #include "lv_math.h" -#include /********************* * DEFINES diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_math.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_math.h similarity index 94% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_math.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_math.h index 395322484..4b2860a90 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_math.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_math.h @@ -105,7 +105,7 @@ int64_t lv_pow(int64_t base, int8_t exp); * @param max_out max output range * @return the mapped number */ -int32_t lv_map(int32_t x, int32_t min_in, int32_t max_in, int32_t min, int32_t max); +int32_t lv_map(int32_t x, int32_t min_in, int32_t max_in, int32_t min_out, int32_t max_out); /** * Get a pseudo random number in the given range @@ -129,11 +129,12 @@ uint32_t lv_rand(uint32_t min, uint32_t max); #define LV_CLAMP(min, val, max) (LV_MAX(min, (LV_MIN(val, max)))) #define LV_ABS(x) ((x) > 0 ? (x) : (-(x))) +#define LV_UDIV255(x) (((x) * 0x8081U) >> 0x17) -#define LV_IS_SIGNED(t) (((t)(-1)) < ((t) 0)) +#define LV_IS_SIGNED(t) (((t)(-1)) < ((t)0)) #define LV_UMAX_OF(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | (0xFULL << ((sizeof(t) * 8ULL) - 4ULL))) #define LV_SMAX_OF(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | (0x7ULL << ((sizeof(t) * 8ULL) - 4ULL))) -#define LV_MAX_OF(t) ((unsigned long) (LV_IS_SIGNED(t) ? LV_SMAX_OF(t) : LV_UMAX_OF(t))) +#define LV_MAX_OF(t) ((unsigned long)(LV_IS_SIGNED(t) ? LV_SMAX_OF(t) : LV_UMAX_OF(t))) #ifdef __cplusplus } /*extern "C"*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_mem.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_mem.c similarity index 91% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_mem.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_mem.c index 87d532a9a..91d50678b 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_mem.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_mem.c @@ -11,27 +11,30 @@ #include "lv_tlsf.h" #include "lv_gc.h" #include "lv_assert.h" -#include +#include "lv_log.h" #if LV_MEM_CUSTOM != 0 #include LV_MEM_CUSTOM_INCLUDE #endif +#ifdef LV_MEM_POOL_INCLUDE + #include LV_MEM_POOL_INCLUDE +#endif /********************* * DEFINES *********************/ /*memset the allocated memories to 0xaa and freed memories to 0xbb (just for testing purposes)*/ #ifndef LV_MEM_ADD_JUNK -# define LV_MEM_ADD_JUNK 0 + #define LV_MEM_ADD_JUNK 0 #endif #ifdef LV_ARCH_64 -# define MEM_UNIT uint64_t -# define ALIGN_MASK 0x7 + #define MEM_UNIT uint64_t + #define ALIGN_MASK 0x7 #else -# define MEM_UNIT uint32_t -# define ALIGN_MASK 0x7 + #define MEM_UNIT uint32_t + #define ALIGN_MASK 0x3 #endif #define ZERO_MEM_SENTINEL 0xa1b2c3d4 @@ -60,9 +63,9 @@ static uint32_t zero_mem = ZERO_MEM_SENTINEL; /*Give the address of this variabl * MACROS **********************/ #if LV_LOG_TRACE_MEM -# define MEM_TRACE(...) LV_LOG_TRACE( __VA_ARGS__) + #define MEM_TRACE(...) LV_LOG_TRACE(__VA_ARGS__) #else -# define MEM_TRACE(...) + #define MEM_TRACE(...) #endif #define COPY32 *d32 = *s32; d32++; s32++; @@ -83,16 +86,20 @@ void lv_mem_init(void) #if LV_MEM_CUSTOM == 0 #if LV_MEM_ADR == 0 +#ifdef LV_MEM_POOL_ALLOC + tlsf = lv_tlsf_create_with_pool((void *)LV_MEM_POOL_ALLOC(LV_MEM_SIZE), LV_MEM_SIZE); +#else /*Allocate a large array to store the dynamically allocated data*/ static LV_ATTRIBUTE_LARGE_RAM_ARRAY MEM_UNIT work_mem_int[LV_MEM_SIZE / sizeof(MEM_UNIT)]; tlsf = lv_tlsf_create_with_pool((void *)work_mem_int, LV_MEM_SIZE); +#endif #else tlsf = lv_tlsf_create_with_pool((void *)LV_MEM_ADR, LV_MEM_SIZE); #endif #endif #if LV_MEM_ADD_JUNK - LV_LOG_WARN("LV_MEM_ADD_JUNK is enabled which makes LVGL much slower") + LV_LOG_WARN("LV_MEM_ADD_JUNK is enabled which makes LVGL much slower"); #endif } @@ -115,7 +122,7 @@ void lv_mem_deinit(void) */ void * lv_mem_alloc(size_t size) { - MEM_TRACE("allocating %d bytes", size); + MEM_TRACE("allocating %lu bytes", (unsigned long)size); if(size == 0) { MEM_TRACE("using zero_mem"); return &zero_mem; @@ -127,18 +134,19 @@ void * lv_mem_alloc(size_t size) void * alloc = LV_MEM_CUSTOM_ALLOC(size); #endif -#if LV_MEM_ADD_JUNK - if(alloc != NULL) lv_memset(alloc, 0xaa, size); -#endif - if(alloc == NULL) { - LV_LOG_ERROR("couldn't allocate memory (%d bytes)", size); + LV_LOG_ERROR("couldn't allocate memory (%lu bytes)", (unsigned long)size); lv_mem_monitor_t mon; lv_mem_monitor(&mon); LV_LOG_ERROR("used: %6d (%3d %%), frag: %3d %%, biggest free: %6d", - (int)mon.total_size - mon.free_size, mon.used_pct, mon.frag_pct, - (int)mon.free_biggest_size); + (int)(mon.total_size - mon.free_size), mon.used_pct, mon.frag_pct, + (int)mon.free_biggest_size); } +#if LV_MEM_ADD_JUNK + else { + lv_memset(alloc, 0xaa, size); + } +#endif MEM_TRACE("allocated at %p", alloc); return alloc; @@ -173,7 +181,7 @@ void lv_mem_free(void * data) */ void * lv_mem_realloc(void * data_p, size_t new_size) { - MEM_TRACE("reallocating %p with %d size", data_p, new_size); + MEM_TRACE("reallocating %p with %lu size", data_p, (unsigned long)new_size); if(new_size == 0) { MEM_TRACE("using zero_mem"); lv_mem_free(data_p); @@ -209,7 +217,7 @@ lv_res_t lv_mem_test(void) return LV_RES_INV; } - if (lv_tlsf_check_pool(lv_tlsf_get_pool(tlsf))) { + if(lv_tlsf_check_pool(lv_tlsf_get_pool(tlsf))) { LV_LOG_WARN("pool failed"); return LV_RES_INV; } @@ -220,7 +228,7 @@ lv_res_t lv_mem_test(void) /** * Give information about the work memory of dynamic allocation - * @param mon_p pointer to a dm_mon_p variable, + * @param mon_p pointer to a lv_mem_monitor_t variable, * the result of the analysis will be stored here */ void lv_mem_monitor(lv_mem_monitor_t * mon_p) @@ -277,7 +285,8 @@ void * lv_mem_buf_get(uint32_t size) if(i_guess >= 0) { LV_GC_ROOT(lv_mem_buf[i_guess]).used = 1; - MEM_TRACE("returning already allocated buffer (buffer id: %d, address: %p)", i_guess, LV_GC_ROOT(lv_mem_buf[i_guess]).p); + MEM_TRACE("returning already allocated buffer (buffer id: %d, address: %p)", i_guess, + LV_GC_ROOT(lv_mem_buf[i_guess]).p); return LV_GC_ROOT(lv_mem_buf[i_guess]).p; } @@ -317,7 +326,7 @@ void lv_mem_buf_release(void * p) } } - LV_LOG_ERROR("p is not a known buffer") + LV_LOG_ERROR("p is not a known buffer"); } /** diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_mem.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_mem.h similarity index 97% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_mem.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_mem.h index bf419f8de..0d1817fed 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_mem.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_mem.h @@ -17,21 +17,14 @@ extern "C" { #include #include -#include "lv_log.h" -#include "lv_types.h" - -#if LV_MEMCPY_MEMSET_STD #include -#endif + +#include "lv_types.h" /********************* * DEFINES *********************/ -#ifndef LV_MEM_BUF_MAX_NUM -#define LV_MEM_BUF_MAX_NUM 16 -#endif - /********************** * TYPEDEFS **********************/ @@ -103,7 +96,7 @@ lv_res_t lv_mem_test(void); /** * Give information about the work memory of dynamic allocation - * @param mon_p pointer to a dm_mon_p variable, + * @param mon_p pointer to a lv_mem_monitor_t variable, * the result of the analysis will be stored here */ void lv_mem_monitor(lv_mem_monitor_t * mon_p); diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_misc.mk b/lib/libesp32_lvgl/lvgl/src/misc/lv_misc.mk similarity index 94% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_misc.mk rename to lib/libesp32_lvgl/lvgl/src/misc/lv_misc.mk index 0079a8b7b..5e053f877 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_misc.mk +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_misc.mk @@ -1,4 +1,5 @@ CSRCS += lv_anim.c +CSRCS += lv_anim_timeline.c CSRCS += lv_area.c CSRCS += lv_async.c CSRCS += lv_bidi.c diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_printf.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_printf.c similarity index 98% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_printf.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_printf.c index 852c77c64..ebe8a55c0 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_printf.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_printf.c @@ -37,7 +37,6 @@ #if LV_SPRINTF_CUSTOM == 0 #include -#include #define PRINTF_DISABLE_SUPPORT_FLOAT (!LV_SPRINTF_USE_FLOAT) @@ -133,10 +132,10 @@ static inline void _out_buffer(char character, void * buffer, size_t idx, size_t // internal null output static inline void _out_null(char character, void * buffer, size_t idx, size_t maxlen) { - (void)character; - (void)buffer; - (void)idx; - (void)maxlen; + LV_UNUSED(character); + LV_UNUSED(buffer); + LV_UNUSED(idx); + LV_UNUSED(maxlen); } // internal secure strlen @@ -699,6 +698,9 @@ static int _vsnprintf(out_fct_type out, char * buffer, const size_t maxlen, cons else #endif flags |= FLAGS_LONG; + + if(*(format + 1) == 'V') + format++; } else if(*format == 'o') { base = 8U; @@ -747,6 +749,14 @@ static int _vsnprintf(out_fct_type out, char * buffer, const size_t maxlen, cons width, flags); } } + else if (*format == 'V') { + lv_vaformat_t * vaf = va_arg(va, lv_vaformat_t *); + va_list copy; + + va_copy(copy, *vaf->va); + idx += _vsnprintf(out, buffer + idx, maxlen - idx, vaf->fmt, copy); + va_end(copy); + } else { // unsigned if(flags & FLAGS_LONG_LONG) { diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_printf.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_printf.h similarity index 82% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_printf.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_printf.h index c29d18dad..304c5b9cc 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_printf.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_printf.h @@ -34,6 +34,22 @@ #ifndef _LV_PRINTF_H_ #define _LV_PRINTF_H_ +#if defined(__has_include) +# if __has_include() +# include + /* platform-specific printf format for int32_t, usually "d" or "ld" */ +# define LV_PRId32 PRId32 +# define LV_PRIu32 PRIu32 +# else +# define LV_PRId32 "d" +# define LV_PRIu32 "u" +# endif +#else + /* hope this is correct for ports without __has_include or without inttypes.h */ +# define LV_PRId32 "d" +# define LV_PRIu32 "u" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -45,6 +61,13 @@ extern "C" { #include #include +#include "lv_types.h" + +typedef struct { + const char * fmt; + va_list * va; +} lv_vaformat_t; + /** * Tiny snprintf/vsnprintf implementation * \param buffer A pointer to the buffer where to store the formatted string @@ -55,8 +78,8 @@ extern "C" { * null character. A value equal or larger than count indicates truncation. Only when the returned value * is non-negative and less than count, the string has been completely written. */ -int lv_snprintf(char * buffer, size_t count, const char * format, ...); -int lv_vsnprintf(char * buffer, size_t count, const char * format, va_list va); +int lv_snprintf(char * buffer, size_t count, const char * format, ...) LV_FORMAT_ATTRIBUTE(3, 4); +int lv_vsnprintf(char * buffer, size_t count, const char * format, va_list va) LV_FORMAT_ATTRIBUTE(3, 0); #else #include LV_SPRINTF_INCLUDE diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_style.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_style.c similarity index 89% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_style.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_style.c index 704ccee7c..160c1de53 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_style.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_style.c @@ -41,7 +41,7 @@ void lv_style_init(lv_style_t * style) { #if LV_USE_ASSERT_STYLE if(style->sentinel == LV_STYLE_SENTINEL_VALUE && style->prop_cnt > 1) { - LV_LOG_WARN("Style might be already inited. (Potential memory leak)") + LV_LOG_WARN("Style might be already inited. (Potential memory leak)"); } #endif @@ -106,7 +106,8 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop) style->prop_cnt = 1; style->prop1 = i == 0 ? old_props[1] : old_props[0]; style->v_p.value1 = i == 0 ? old_values[1] : old_values[0]; - } else { + } + else { size_t size = (style->prop_cnt - 1) * (sizeof(lv_style_value_t) + sizeof(uint16_t)); uint8_t * new_values_and_props = lv_mem_alloc(size); if(new_values_and_props == NULL) return false; @@ -118,7 +119,8 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop) lv_style_value_t * new_values = (lv_style_value_t *)new_values_and_props; uint32_t j; - for(i = j = 0; j <= style->prop_cnt; j++) { /*<=: because prop_cnt already reduced but all the old props. needs to be checked.*/ + for(i = j = 0; j <= style->prop_cnt; + j++) { /*<=: because prop_cnt already reduced but all the old props. needs to be checked.*/ if(old_props[j] != prop) { new_values[i] = old_values[j]; new_props[i++] = old_props[j]; @@ -164,7 +166,7 @@ void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_ props = (uint16_t *)tmp; /*Shift all props to make place for the value before them*/ for(i = style->prop_cnt - 1; i >= 0; i--) { - props[i + sizeof(lv_style_value_t) /sizeof(uint16_t)] = props[i]; + props[i + sizeof(lv_style_value_t) / sizeof(uint16_t)] = props[i]; } style->prop_cnt++; @@ -176,7 +178,8 @@ void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_ /*Set the new property and value*/ props[style->prop_cnt - 1] = prop; values[style->prop_cnt - 1] = value; - } else if(style->prop_cnt == 1) { + } + else if(style->prop_cnt == 1) { if(style->prop1 == prop) { style->v_p.value1 = value; return; @@ -195,7 +198,8 @@ void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_ props[1] = prop; values[0] = value_tmp; values[1] = value; - } else { + } + else { style->prop_cnt = 1; style->prop1 = prop; style->v_p.value1 = value; @@ -207,10 +211,11 @@ void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_ lv_res_t lv_style_get_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value) { - return lv_style_get_prop_inlined(style, prop, value); + return lv_style_get_prop_inlined(style, prop, value); } -void lv_style_transition_dsc_init(lv_style_transition_dsc_t * tr, const lv_style_prop_t props[], lv_anim_path_cb_t path_cb, uint32_t time, uint32_t delay, void * user_data) +void lv_style_transition_dsc_init(lv_style_transition_dsc_t * tr, const lv_style_prop_t props[], + lv_anim_path_cb_t path_cb, uint32_t time, uint32_t delay, void * user_data) { lv_memset_00(tr, sizeof(lv_style_transition_dsc_t)); tr->props = props; @@ -234,6 +239,16 @@ lv_style_value_t lv_style_prop_get_default(lv_style_prop_t prop) case LV_STYLE_BG_COLOR: value.color = lv_color_white(); break; + case LV_STYLE_BG_GRAD_COLOR: + case LV_STYLE_BORDER_COLOR: + case LV_STYLE_SHADOW_COLOR: + case LV_STYLE_OUTLINE_COLOR: + case LV_STYLE_ARC_COLOR: + case LV_STYLE_LINE_COLOR: + case LV_STYLE_TEXT_COLOR: + case LV_STYLE_IMG_RECOLOR: + value.color = lv_color_black(); + break; case LV_STYLE_OPA: case LV_STYLE_BORDER_OPA: case LV_STYLE_TEXT_OPA: @@ -280,6 +295,7 @@ uint8_t _lv_style_get_prop_group(lv_style_prop_t prop) if(group > 7) group = 7; /*The MSB marks all the custom properties*/ return (uint8_t)group; } + /********************** * STATIC FUNCTIONS **********************/ diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_style.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_style.h similarity index 89% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_style.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_style.h index 0f4ae1f52..9b4d012c8 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_style.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_style.h @@ -61,6 +61,7 @@ enum { LV_BLEND_MODE_NORMAL, /**< Simply mix according to the opacity value*/ LV_BLEND_MODE_ADDITIVE, /**< Add the respective color channels*/ LV_BLEND_MODE_SUBTRACTIVE,/**< Subtract the foreground from the background*/ + LV_BLEND_MODE_MULTIPLY, /**< Multiply the foreground and background*/ }; typedef uint8_t lv_blend_mode_t; @@ -110,7 +111,7 @@ typedef union { int32_t num; /**< Number integer number (opacity, enums, booleans or "normal" numbers)*/ const void * ptr; /**< Constant pointers (font, cone text, etc)*/ lv_color_t color; /**< Colors*/ -}lv_style_value_t; +} lv_style_value_t; /** * Enumeration of all built in style properties @@ -132,16 +133,16 @@ typedef enum { LV_STYLE_TRANSFORM_HEIGHT = 11 | LV_STYLE_PROP_EXT_DRAW, LV_STYLE_TRANSLATE_X = 12 | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, LV_STYLE_TRANSLATE_Y = 13 | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, - LV_STYLE_TRANSFORM_ZOOM = 14 | LV_STYLE_PROP_EXT_DRAW, - LV_STYLE_TRANSFORM_ANGLE = 15 | LV_STYLE_PROP_EXT_DRAW, + LV_STYLE_TRANSFORM_ZOOM = 14 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, + LV_STYLE_TRANSFORM_ANGLE = 15 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, /*Group 1*/ - LV_STYLE_PAD_TOP = 16 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_PAD_BOTTOM = 17 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_PAD_LEFT = 18 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_PAD_RIGHT = 19 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_PAD_ROW = 20 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_PAD_COLUMN = 21 | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_PAD_TOP = 16 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_PAD_BOTTOM = 17 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_PAD_LEFT = 18 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_PAD_RIGHT = 19 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_PAD_ROW = 20 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_PAD_COLUMN = 21 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, /*Group 2*/ LV_STYLE_BG_COLOR = 32, @@ -153,7 +154,7 @@ typedef enum { LV_STYLE_BG_MAIN_STOP = 36, LV_STYLE_BG_GRAD_STOP = 37, - LV_STYLE_BG_IMG_SRC = 38, + LV_STYLE_BG_IMG_SRC = 38 | LV_STYLE_PROP_EXT_DRAW, LV_STYLE_BG_IMG_OPA = 39, LV_STYLE_BG_IMG_RECOLOR = 40, LV_STYLE_BG_IMG_RECOLOR_FILTERED = 40 | LV_STYLE_PROP_FILTER, @@ -229,7 +230,7 @@ typedef enum { _LV_STYLE_LAST_BUILT_IN_PROP = 111, LV_STYLE_PROP_ANY = 0xFFFF -}lv_style_prop_t; +} lv_style_prop_t; /** * Descriptor for style transitions @@ -242,7 +243,7 @@ typedef struct { lv_anim_path_cb_t path_xcb; /**< A path for the animation.*/ uint32_t time; /**< Duration of the transition in [ms]*/ uint32_t delay; /**< Delay before the transition in [ms]*/ -}lv_style_transition_dsc_t; +} lv_style_transition_dsc_t; /** * Descriptor of a constant style property. @@ -269,8 +270,8 @@ typedef struct { const lv_style_const_prop_t * const_props; } v_p; - uint16_t prop1 :15; - uint16_t is_const :1; + uint16_t prop1 : 15; + uint16_t is_const : 1; uint8_t has_group; uint8_t prop_cnt; } lv_style_t; @@ -283,8 +284,8 @@ typedef struct { /** * Initialize a style * @param style pointer to a style to initialize - * @note Do not call `lv_style_init` on styles that are already have some properties - * because this function won't free the used memory just set a default state for the style. + * @note Do not call `lv_style_init` on styles that already have some properties + * because this function won't free the used memory, just sets a default state for the style. * In other words be sure to initialize styles only once! */ void lv_style_init(lv_style_t * style); @@ -323,8 +324,8 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop); * This function shouldn't be used directly by the user. * Instead use `lv_style_set_()`. E.g. `lv_style_set_bg_color()` * @param style pointer to style - * @param prop the ID of a property (e.g. `LV_STLYE_BG_COLOR`) - * @param value `lv_style_value_t` variable in which a filed is set according to the type of `prop` + * @param prop the ID of a property (e.g. `LV_STYLE_BG_COLOR`) + * @param value `lv_style_value_t` variable in which a field is set according to the type of `prop` */ void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_t value); @@ -333,7 +334,7 @@ void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_ * @param style pointer to a style * @param prop the ID of a property * @param value pointer to a `lv_style_value_t` variable to store the value - * @return LV_RES_INV: the property wsn't found in the style (`value` is unchanged) + * @return LV_RES_INV: the property wasn't found in the style (`value` is unchanged) * LV_RES_OK: the property was fond, and `value` is set accordingly * @note For performance reasons there are no sanity check on `style` */ @@ -345,7 +346,7 @@ lv_res_t lv_style_get_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_va * @param style pointer to a style * @param prop the ID of a property * @param value pointer to a `lv_style_value_t` variable to store the value - * @return LV_RES_INV: the property wsn't found in the style (`value` is unchanged) + * @return LV_RES_INV: the property wasn't found in the style (`value` is unchanged) * LV_RES_OK: the property was fond, and `value` is set accordingly * @note For performance reasons there are no sanity check on `style` * @note This function is the same as ::lv_style_get_prop but inlined. Use it only on performance critical places @@ -353,7 +354,7 @@ lv_res_t lv_style_get_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_va static inline lv_res_t lv_style_get_prop_inlined(lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value) { if(style->is_const) { - const lv_style_const_prop_t *const_prop; + const lv_style_const_prop_t * const_prop; for(const_prop = style->v_p.const_props; const_prop->prop != LV_STYLE_PROP_INV; const_prop++) { if(const_prop->prop == prop) { *value = const_prop->value; @@ -376,7 +377,8 @@ static inline lv_res_t lv_style_get_prop_inlined(lv_style_t * style, lv_style_pr return LV_RES_OK; } } - } else if(style->prop1 == prop) { + } + else if(style->prop1 == prop) { *value = style->v_p.value1; return LV_RES_OK; } @@ -396,7 +398,8 @@ static inline lv_res_t lv_style_get_prop_inlined(lv_style_t * style, lv_style_pr * static lv_style_transition_dsc_t trans1; * lv_style_transition_dsc_init(&trans1, trans_props, NULL, 300, 0, NULL); */ -void lv_style_transition_dsc_init(lv_style_transition_dsc_t * tr, const lv_style_prop_t props[], lv_anim_path_cb_t path_cb, uint32_t time, uint32_t delay, void * user_data); +void lv_style_transition_dsc_init(lv_style_transition_dsc_t * tr, const lv_style_prop_t props[], + lv_anim_path_cb_t path_cb, uint32_t time, uint32_t delay, void * user_data); /** * Get the default value of a property @@ -422,29 +425,34 @@ uint8_t _lv_style_get_prop_group(lv_style_prop_t prop); #include "lv_style_gen.h" -static inline void lv_style_set_pad_all(lv_style_t * style, lv_coord_t value) { +static inline void lv_style_set_pad_all(lv_style_t * style, lv_coord_t value) +{ lv_style_set_pad_left(style, value); lv_style_set_pad_right(style, value); lv_style_set_pad_top(style, value); lv_style_set_pad_bottom(style, value); } -static inline void lv_style_set_pad_hor(lv_style_t * style, lv_coord_t value) { +static inline void lv_style_set_pad_hor(lv_style_t * style, lv_coord_t value) +{ lv_style_set_pad_left(style, value); lv_style_set_pad_right(style, value); } -static inline void lv_style_set_pad_ver(lv_style_t * style, lv_coord_t value) { +static inline void lv_style_set_pad_ver(lv_style_t * style, lv_coord_t value) +{ lv_style_set_pad_top(style, value); lv_style_set_pad_bottom(style, value); } -static inline void lv_style_set_pad_gap(lv_style_t * style, lv_coord_t value) { +static inline void lv_style_set_pad_gap(lv_style_t * style, lv_coord_t value) +{ lv_style_set_pad_row(style, value); lv_style_set_pad_column(style, value); } -static inline void lv_style_set_size(lv_style_t * style, lv_coord_t value) { +static inline void lv_style_set_size(lv_style_t * style, lv_coord_t value) +{ lv_style_set_width(style, value); lv_style_set_height(style, value); } @@ -460,7 +468,7 @@ static inline void lv_style_set_size(lv_style_t * style, lv_coord_t value) { #if LV_USE_ASSERT_STYLE # define LV_ASSERT_STYLE(style_p) LV_ASSERT_MSG(style_p != NULL, "The style is NULL"); \ - LV_ASSERT_MSG(style_p->sentinel == LV_STYLE_SENTINEL_VALUE, "Style is not initialized or corrupted"); + LV_ASSERT_MSG(style_p->sentinel == LV_STYLE_SENTINEL_VALUE, "Style is not initialized or corrupted"); #else # define LV_ASSERT_STYLE(p) #endif diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_style_gen.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.c similarity index 99% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_style_gen.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.c index bdcd1d147..f26884e7f 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_style_gen.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.c @@ -632,7 +632,7 @@ void lv_style_set_line_dash_gap(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_LINE_DASH_GAP, v); } -void lv_style_set_line_rounded(lv_style_t * style, lv_coord_t value) +void lv_style_set_line_rounded(lv_style_t * style, bool value) { lv_style_value_t v = { .num = (int32_t)value @@ -672,7 +672,7 @@ void lv_style_set_arc_width(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_ARC_WIDTH, v); } -void lv_style_set_arc_rounded(lv_style_t * style, lv_coord_t value) +void lv_style_set_arc_rounded(lv_style_t * style, bool value) { lv_style_value_t v = { .num = (int32_t)value diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_style_gen.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.h similarity index 99% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_style_gen.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.h index 08afb0476..eeb648ece 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_style_gen.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.h @@ -77,12 +77,12 @@ void lv_style_set_shadow_opa(lv_style_t * style, lv_opa_t value); void lv_style_set_line_width(lv_style_t * style, lv_coord_t value); void lv_style_set_line_dash_width(lv_style_t * style, lv_coord_t value); void lv_style_set_line_dash_gap(lv_style_t * style, lv_coord_t value); -void lv_style_set_line_rounded(lv_style_t * style, lv_coord_t value); +void lv_style_set_line_rounded(lv_style_t * style, bool value); void lv_style_set_line_color(lv_style_t * style, lv_color_t value); void lv_style_set_line_color_filtered(lv_style_t * style, lv_color_t value); void lv_style_set_line_opa(lv_style_t * style, lv_opa_t value); void lv_style_set_arc_width(lv_style_t * style, lv_coord_t value); -void lv_style_set_arc_rounded(lv_style_t * style, lv_coord_t value); +void lv_style_set_arc_rounded(lv_style_t * style, bool value); void lv_style_set_arc_color(lv_style_t * style, lv_color_t value); void lv_style_set_arc_color_filtered(lv_style_t * style, lv_color_t value); void lv_style_set_arc_opa(lv_style_t * style, lv_opa_t value); diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_templ.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_templ.c similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_templ.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_templ.c diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_templ.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_templ.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_templ.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_templ.h diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_timer.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.c similarity index 89% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_timer.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_timer.c index 94dc59163..d8dd55b7a 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_timer.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.c @@ -6,9 +6,10 @@ * INCLUDES *********************/ #include "lv_timer.h" -#include -#include "../misc/lv_assert.h" #include "../hal/lv_hal_tick.h" +#include "lv_assert.h" +#include "lv_mem.h" +#include "lv_ll.h" #include "lv_gc.h" /********************* @@ -39,9 +40,9 @@ static bool timer_created; * MACROS **********************/ #if LV_LOG_TRACE_TIMER -# define TIMER_TRACE(...) LV_LOG_TRACE( __VA_ARGS__) + #define TIMER_TRACE(...) LV_LOG_TRACE(__VA_ARGS__) #else -# define TIMER_TRACE(...) + #define TIMER_TRACE(...) #endif /********************** @@ -60,7 +61,7 @@ void _lv_timer_core_init(void) } /** - * Call it periodically to handle lv_timers. + * Call it periodically to handle lv_timers. * @return the time after which it must be called again */ LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void) @@ -69,12 +70,14 @@ LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void) /*Avoid concurrent running of the timer handler*/ static bool already_running = false; - if(already_running) return 1; + if(already_running) { + TIMER_TRACE("already running, concurrent calls are not allow, returning"); + return 1; + } already_running = true; if(lv_timer_run == false) { already_running = false; /*Release mutex*/ - TIMER_TRACE("already running, concurrent calls are not allow, returning"); return 1; } @@ -85,7 +88,7 @@ LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void) if(handler_start == 0) { static uint32_t run_cnt = 0; - run_cnt ++; + run_cnt++; if(run_cnt > 100) { run_cnt = 0; LV_LOG_WARN("It seems lv_tick_inc() is not called."); @@ -141,6 +144,7 @@ LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void) TIMER_TRACE("finished (%d ms until the next timer call)", time_till_next); return time_till_next; } + /** * Create an "empty" timer. It needs to initialized with at least * `lv_timer_set_cb` and `lv_timer_set_period` @@ -154,7 +158,7 @@ lv_timer_t * lv_timer_create_basic(void) /** * Create a new lv_timer * @param timer_xcb a callback which is the timer itself. It will be called periodically. - * (the 'x' in the argument name indicates that its not a fully generic function because it not follows + * (the 'x' in the argument name indicates that it's not a fully generic function because it not follows * the `func_name(object, callback, ...)` convention) * @param period call period in ms unit * @param user_data custom parameter @@ -168,7 +172,7 @@ lv_timer_t * lv_timer_create(lv_timer_cb_t timer_xcb, uint32_t period, void * us LV_ASSERT_MALLOC(new_timer); if(new_timer == NULL) return NULL; - new_timer->period = period; + new_timer->period = period; new_timer->timer_cb = timer_xcb; new_timer->repeat_count = -1; new_timer->paused = 0; @@ -289,7 +293,7 @@ lv_timer_t * lv_timer_get_next(lv_timer_t * timer) **********************/ /** - * Execute timer if its the priority is appropriate + * Execute timer if its remaining time is zero * @param timer pointer to lv_timer * @return true: execute, false: not executed */ @@ -297,12 +301,6 @@ static bool lv_timer_exec(lv_timer_t * timer) { if(timer->paused) return false; - if(timer->repeat_count == 0) { - TIMER_TRACE("deleting timer with %p callback because the repeat count is over", timer->timer_cb); - lv_timer_del(timer); - return false; - } - bool exec = false; if(lv_timer_time_remaining(timer) == 0) { /* Decrement the repeat count before executing the timer_cb. @@ -311,21 +309,20 @@ static bool lv_timer_exec(lv_timer_t * timer) int32_t original_repeat_count = timer->repeat_count; if(timer->repeat_count > 0) timer->repeat_count--; timer->last_run = lv_tick_get(); - TIMER_TRACE("calling timer callback: %p", timer->timer_cb); + TIMER_TRACE("calling timer callback: %p", *((void **)&timer->timer_cb)); if(timer->timer_cb && original_repeat_count != 0) timer->timer_cb(timer); - TIMER_TRACE("timer callback %p finished", timer->timer_cb); + TIMER_TRACE("timer callback %p finished", *((void **)&timer->timer_cb)); LV_ASSERT_MEM_INTEGRITY(); - - /*Delete if it was a one shot lv_timer*/ - if(timer_deleted == false) { /*The timer might be deleted by itself as well*/ - if(timer->repeat_count == 0) { - TIMER_TRACE("deleting timer with %p callback because the repeat count is over", timer->timer_cb); - lv_timer_del(timer); - } - } exec = true; } + if(timer_deleted == false) { /*The timer might be deleted by itself as well*/ + if(timer->repeat_count == 0) { /*The repeat count is over, delete the timer*/ + TIMER_TRACE("deleting timer with %p callback because the repeat count is over", *((void **)&timer->timer_cb)); + lv_timer_del(timer); + } + } + return exec; } diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_timer.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.h similarity index 94% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_timer.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_timer.h index 015543734..ce94c7b04 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_timer.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.h @@ -16,8 +16,6 @@ extern "C" { #include #include -#include "lv_mem.h" -#include "lv_ll.h" /********************* * DEFINES @@ -48,7 +46,7 @@ typedef struct _lv_timer_t { lv_timer_cb_t timer_cb; /**< Timer function*/ void * user_data; /**< Custom user data*/ int32_t repeat_count; /**< 1: One time; -1 : infinity; n>0: residual times*/ - uint32_t paused :1; + uint32_t paused : 1; } lv_timer_t; /********************** @@ -63,7 +61,7 @@ void _lv_timer_core_init(void); //! @cond Doxygen_Suppress /** - * Call it periodically to handle lv_timers. + * Call it periodically to handle lv_timers. * @return time till it needs to be run next (in ms) */ LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void); @@ -80,7 +78,7 @@ lv_timer_t * lv_timer_create_basic(void); /** * Create a new lv_timer * @param timer_xcb a callback to call periodically. - * (the 'x' in the argument name indicates that its not a fully generic function because it not follows + * (the 'x' in the argument name indicates that it's not a fully generic function because it not follows * the `func_name(object, callback, ...)` convention) * @param period call period in ms unit * @param user_data custom parameter @@ -97,7 +95,6 @@ void lv_timer_del(lv_timer_t * timer); /** * Pause/resume a timer. * @param timer pointer to an lv_timer - * @param pause true: pause the timer; false: resume */ void lv_timer_pause(lv_timer_t * timer); diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.c new file mode 100644 index 000000000..63d1842d6 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.c @@ -0,0 +1,1238 @@ +#include "../lv_conf_internal.h" +#if LV_MEM_CUSTOM == 0 + +#include +#include "lv_tlsf.h" +#include "lv_mem.h" +#include "lv_log.h" +#include "lv_assert.h" + +#undef printf +#define printf LV_LOG_ERROR + +#define TLSF_MAX_POOL_SIZE LV_MEM_SIZE + +#if !defined(_DEBUG) + #define _DEBUG 0 +#endif + +#if defined(__cplusplus) + #define tlsf_decl inline +#else + #define tlsf_decl static +#endif + +/* +** Architecture-specific bit manipulation routines. +** +** TLSF achieves O(1) cost for malloc and free operations by limiting +** the search for a free block to a free list of guaranteed size +** adequate to fulfill the request, combined with efficient free list +** queries using bitmasks and architecture-specific bit-manipulation +** routines. +** +** Most modern processors provide instructions to count leading zeroes +** in a word, find the lowest and highest set bit, etc. These +** specific implementations will be used when available, falling back +** to a reasonably efficient generic implementation. +** +** NOTE: TLSF spec relies on ffs/fls returning value 0..31. +** ffs/fls return 1-32 by default, returning 0 for error. +*/ + +/* +** Detect whether or not we are building for a 32- or 64-bit (LP/LLP) +** architecture. There is no reliable portable method at compile-time. +*/ +#if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) \ + || defined (_WIN64) || defined (__LP64__) || defined (__LLP64__) + #define TLSF_64BIT +#endif + +/* +** Returns one plus the index of the most significant 1-bit of n, +** or if n is zero, returns zero. +*/ +#ifdef TLSF_64BIT + #define TLSF_FLS(n) ((n) & 0xffffffff00000000ull ? 32 + TLSF_FLS32((size_t)(n) >> 32) : TLSF_FLS32(n)) +#else + #define TLSF_FLS(n) TLSF_FLS32(n) +#endif + +#define TLSF_FLS32(n) ((n) & 0xffff0000 ? 16 + TLSF_FLS16((n) >> 16) : TLSF_FLS16(n)) +#define TLSF_FLS16(n) ((n) & 0xff00 ? 8 + TLSF_FLS8 ((n) >> 8) : TLSF_FLS8 (n)) +#define TLSF_FLS8(n) ((n) & 0xf0 ? 4 + TLSF_FLS4 ((n) >> 4) : TLSF_FLS4 (n)) +#define TLSF_FLS4(n) ((n) & 0xc ? 2 + TLSF_FLS2 ((n) >> 2) : TLSF_FLS2 (n)) +#define TLSF_FLS2(n) ((n) & 0x2 ? 1 + TLSF_FLS1 ((n) >> 1) : TLSF_FLS1 (n)) +#define TLSF_FLS1(n) ((n) & 0x1 ? 1 : 0) + +/* +** Returns round up value of log2(n). +** Note: it is used at compile time. +*/ +#define TLSF_LOG2_CEIL(n) ((n) & (n - 1) ? TLSF_FLS(n) : TLSF_FLS(n) - 1) + +/* +** gcc 3.4 and above have builtin support, specialized for architecture. +** Some compilers masquerade as gcc; patchlevel test filters them out. +*/ +#if defined (__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \ + && defined (__GNUC_PATCHLEVEL__) + +#if defined (__SNC__) +/* SNC for Playstation 3. */ + +tlsf_decl int tlsf_ffs(unsigned int word) +{ + const unsigned int reverse = word & (~word + 1); + const int bit = 32 - __builtin_clz(reverse); + return bit - 1; +} + +#else + +tlsf_decl int tlsf_ffs(unsigned int word) +{ + return __builtin_ffs(word) - 1; +} + +#endif + +tlsf_decl int tlsf_fls(unsigned int word) +{ + const int bit = word ? 32 - __builtin_clz(word) : 0; + return bit - 1; +} + +#elif defined (_MSC_VER) && (_MSC_VER >= 1400) && (defined (_M_IX86) || defined (_M_X64)) +/* Microsoft Visual C++ support on x86/X64 architectures. */ + +#include + +#pragma intrinsic(_BitScanReverse) +#pragma intrinsic(_BitScanForward) + +tlsf_decl int tlsf_fls(unsigned int word) +{ + unsigned long index; + return _BitScanReverse(&index, word) ? index : -1; +} + +tlsf_decl int tlsf_ffs(unsigned int word) +{ + unsigned long index; + return _BitScanForward(&index, word) ? index : -1; +} + +#elif defined (_MSC_VER) && defined (_M_PPC) +/* Microsoft Visual C++ support on PowerPC architectures. */ + +#include + +tlsf_decl int tlsf_fls(unsigned int word) +{ + const int bit = 32 - _CountLeadingZeros(word); + return bit - 1; +} + +tlsf_decl int tlsf_ffs(unsigned int word) +{ + const unsigned int reverse = word & (~word + 1); + const int bit = 32 - _CountLeadingZeros(reverse); + return bit - 1; +} + +#elif defined (__ARMCC_VERSION) +/* RealView Compilation Tools for ARM */ + +tlsf_decl int tlsf_ffs(unsigned int word) +{ + const unsigned int reverse = word & (~word + 1); + const int bit = 32 - __clz(reverse); + return bit - 1; +} + +tlsf_decl int tlsf_fls(unsigned int word) +{ + const int bit = word ? 32 - __clz(word) : 0; + return bit - 1; +} + +#elif defined (__ghs__) +/* Green Hills support for PowerPC */ + +#include + +tlsf_decl int tlsf_ffs(unsigned int word) +{ + const unsigned int reverse = word & (~word + 1); + const int bit = 32 - __CLZ32(reverse); + return bit - 1; +} + +tlsf_decl int tlsf_fls(unsigned int word) +{ + const int bit = word ? 32 - __CLZ32(word) : 0; + return bit - 1; +} + +#else +/* Fall back to generic implementation. */ + +/* Implement ffs in terms of fls. */ +tlsf_decl int tlsf_ffs(unsigned int word) +{ + const unsigned int reverse = word & (~word + 1); + return TLSF_FLS32(reverse) - 1; +} + +tlsf_decl int tlsf_fls(unsigned int word) +{ + return TLSF_FLS32(word) - 1; +} + +#endif + +/* Possibly 64-bit version of tlsf_fls. */ +#if defined (TLSF_64BIT) +tlsf_decl int tlsf_fls_sizet(size_t size) +{ + int high = (int)(size >> 32); + int bits = 0; + if(high) { + bits = 32 + tlsf_fls(high); + } + else { + bits = tlsf_fls((int)size & 0xffffffff); + + } + return bits; +} +#else +#define tlsf_fls_sizet tlsf_fls +#endif + +#undef tlsf_decl + +/* +** Constants. +*/ + +/* Public constants: may be modified. */ +enum tlsf_public { + /* log2 of number of linear subdivisions of block sizes. Larger + ** values require more memory in the control structure. Values of + ** 4 or 5 are typical. + */ + SL_INDEX_COUNT_LOG2 = 5, +}; + +/* Private constants: do not modify. */ +enum tlsf_private { +#if defined (TLSF_64BIT) + /* All allocation sizes and addresses are aligned to 8 bytes. */ + ALIGN_SIZE_LOG2 = 3, +#else + /* All allocation sizes and addresses are aligned to 4 bytes. */ + ALIGN_SIZE_LOG2 = 2, +#endif + ALIGN_SIZE = (1 << ALIGN_SIZE_LOG2), + + /* + ** We support allocations of sizes up to (1 << FL_INDEX_MAX) bits. + ** However, because we linearly subdivide the second-level lists, and + ** our minimum size granularity is 4 bytes, it doesn't make sense to + ** create first-level lists for sizes smaller than SL_INDEX_COUNT * 4, + ** or (1 << (SL_INDEX_COUNT_LOG2 + 2)) bytes, as there we will be + ** trying to split size ranges into more slots than we have available. + ** Instead, we calculate the minimum threshold size, and place all + ** blocks below that size into the 0th first-level list. + */ + +#if defined (TLSF_MAX_POOL_SIZE) + FL_INDEX_MAX = TLSF_LOG2_CEIL(TLSF_MAX_POOL_SIZE), +#elif defined (TLSF_64BIT) + /* + ** TODO: We can increase this to support larger sizes, at the expense + ** of more overhead in the TLSF structure. + */ + FL_INDEX_MAX = 32, +#else + FL_INDEX_MAX = 30, +#endif + SL_INDEX_COUNT = (1 << SL_INDEX_COUNT_LOG2), + FL_INDEX_SHIFT = (SL_INDEX_COUNT_LOG2 + ALIGN_SIZE_LOG2), + FL_INDEX_COUNT = (FL_INDEX_MAX - FL_INDEX_SHIFT + 1), + + SMALL_BLOCK_SIZE = (1 << FL_INDEX_SHIFT), +}; + +/* +** Cast and min/max macros. +*/ + +#define tlsf_cast(t, exp) ((t) (exp)) +#define tlsf_min(a, b) ((a) < (b) ? (a) : (b)) +#define tlsf_max(a, b) ((a) > (b) ? (a) : (b)) + +/* +** Set assert macro, if it has not been provided by the user. +*/ +#define tlsf_assert LV_ASSERT + +#if !defined (tlsf_assert) + #define tlsf_assert assert +#endif + +/* +** Static assertion mechanism. +*/ + +#define _tlsf_glue2(x, y) x ## y +#define _tlsf_glue(x, y) _tlsf_glue2(x, y) +#define tlsf_static_assert(exp) \ + typedef char _tlsf_glue(static_assert, __LINE__) [(exp) ? 1 : -1] + +/* This code has been tested on 32- and 64-bit (LP/LLP) architectures. */ +tlsf_static_assert(sizeof(int) * CHAR_BIT == 32); +tlsf_static_assert(sizeof(size_t) * CHAR_BIT >= 32); +tlsf_static_assert(sizeof(size_t) * CHAR_BIT <= 64); + +/* SL_INDEX_COUNT must be <= number of bits in sl_bitmap's storage type. */ +tlsf_static_assert(sizeof(unsigned int) * CHAR_BIT >= SL_INDEX_COUNT); + +/* Ensure we've properly tuned our sizes. */ +tlsf_static_assert(ALIGN_SIZE == SMALL_BLOCK_SIZE / SL_INDEX_COUNT); + +/* +** Data structures and associated constants. +*/ + +/* +** Block header structure. +** +** There are several implementation subtleties involved: +** - The prev_phys_block field is only valid if the previous block is free. +** - The prev_phys_block field is actually stored at the end of the +** previous block. It appears at the beginning of this structure only to +** simplify the implementation. +** - The next_free / prev_free fields are only valid if the block is free. +*/ +typedef struct block_header_t { + /* Points to the previous physical block. */ + struct block_header_t * prev_phys_block; + + /* The size of this block, excluding the block header. */ + size_t size; + + /* Next and previous free blocks. */ + struct block_header_t * next_free; + struct block_header_t * prev_free; +} block_header_t; + +/* +** Since block sizes are always at least a multiple of 4, the two least +** significant bits of the size field are used to store the block status: +** - bit 0: whether block is busy or free +** - bit 1: whether previous block is busy or free +*/ +static const size_t block_header_free_bit = 1 << 0; +static const size_t block_header_prev_free_bit = 1 << 1; + +/* +** The size of the block header exposed to used blocks is the size field. +** The prev_phys_block field is stored *inside* the previous free block. +*/ +static const size_t block_header_overhead = sizeof(size_t); + +/* User data starts directly after the size field in a used block. */ +static const size_t block_start_offset = + offsetof(block_header_t, size) + sizeof(size_t); + +/* +** A free block must be large enough to store its header minus the size of +** the prev_phys_block field, and no larger than the number of addressable +** bits for FL_INDEX. +*/ +static const size_t block_size_min = + sizeof(block_header_t) - sizeof(block_header_t *); +static const size_t block_size_max = tlsf_cast(size_t, 1) << FL_INDEX_MAX; + + +/* The TLSF control structure. */ +typedef struct control_t { + /* Empty lists point at this block to indicate they are free. */ + block_header_t block_null; + + /* Bitmaps for free lists. */ + unsigned int fl_bitmap; + unsigned int sl_bitmap[FL_INDEX_COUNT]; + + /* Head of free lists. */ + block_header_t * blocks[FL_INDEX_COUNT][SL_INDEX_COUNT]; +} control_t; + +/* A type used for casting when doing pointer arithmetic. */ +typedef ptrdiff_t tlsfptr_t; + +/* +** block_header_t member functions. +*/ + +static size_t block_size(const block_header_t * block) +{ + return block->size & ~(block_header_free_bit | block_header_prev_free_bit); +} + +static void block_set_size(block_header_t * block, size_t size) +{ + const size_t oldsize = block->size; + block->size = size | (oldsize & (block_header_free_bit | block_header_prev_free_bit)); +} + +static int block_is_last(const block_header_t * block) +{ + return block_size(block) == 0; +} + +static int block_is_free(const block_header_t * block) +{ + return tlsf_cast(int, block->size & block_header_free_bit); +} + +static void block_set_free(block_header_t * block) +{ + block->size |= block_header_free_bit; +} + +static void block_set_used(block_header_t * block) +{ + block->size &= ~block_header_free_bit; +} + +static int block_is_prev_free(const block_header_t * block) +{ + return tlsf_cast(int, block->size & block_header_prev_free_bit); +} + +static void block_set_prev_free(block_header_t * block) +{ + block->size |= block_header_prev_free_bit; +} + +static void block_set_prev_used(block_header_t * block) +{ + block->size &= ~block_header_prev_free_bit; +} + +static block_header_t * block_from_ptr(const void * ptr) +{ + return tlsf_cast(block_header_t *, + tlsf_cast(unsigned char *, ptr) - block_start_offset); +} + +static void * block_to_ptr(const block_header_t * block) +{ + return tlsf_cast(void *, + tlsf_cast(unsigned char *, block) + block_start_offset); +} + +/* Return location of next block after block of given size. */ +static block_header_t * offset_to_block(const void * ptr, size_t size) +{ + return tlsf_cast(block_header_t *, tlsf_cast(tlsfptr_t, ptr) + size); +} + +/* Return location of previous block. */ +static block_header_t * block_prev(const block_header_t * block) +{ + tlsf_assert(block_is_prev_free(block) && "previous block must be free"); + return block->prev_phys_block; +} + +/* Return location of next existing block. */ +static block_header_t * block_next(const block_header_t * block) +{ + block_header_t * next = offset_to_block(block_to_ptr(block), + block_size(block) - block_header_overhead); + tlsf_assert(!block_is_last(block)); + return next; +} + +/* Link a new block with its physical neighbor, return the neighbor. */ +static block_header_t * block_link_next(block_header_t * block) +{ + block_header_t * next = block_next(block); + next->prev_phys_block = block; + return next; +} + +static void block_mark_as_free(block_header_t * block) +{ + /* Link the block to the next block, first. */ + block_header_t * next = block_link_next(block); + block_set_prev_free(next); + block_set_free(block); +} + +static void block_mark_as_used(block_header_t * block) +{ + block_header_t * next = block_next(block); + block_set_prev_used(next); + block_set_used(block); +} + +static size_t align_up(size_t x, size_t align) +{ + tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two"); + return (x + (align - 1)) & ~(align - 1); +} + +static size_t align_down(size_t x, size_t align) +{ + tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two"); + return x - (x & (align - 1)); +} + +static void * align_ptr(const void * ptr, size_t align) +{ + const tlsfptr_t aligned = + (tlsf_cast(tlsfptr_t, ptr) + (align - 1)) & ~(align - 1); + tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two"); + return tlsf_cast(void *, aligned); +} + +/* +** Adjust an allocation size to be aligned to word size, and no smaller +** than internal minimum. +*/ +static size_t adjust_request_size(size_t size, size_t align) +{ + size_t adjust = 0; + if(size) { + const size_t aligned = align_up(size, align); + + /* aligned sized must not exceed block_size_max or we'll go out of bounds on sl_bitmap */ + if(aligned < block_size_max) { + adjust = tlsf_max(aligned, block_size_min); + } + } + return adjust; +} + +/* +** TLSF utility functions. In most cases, these are direct translations of +** the documentation found in the white paper. +*/ + +static void mapping_insert(size_t size, int * fli, int * sli) +{ + int fl, sl; + if(size < SMALL_BLOCK_SIZE) { + /* Store small blocks in first list. */ + fl = 0; + sl = tlsf_cast(int, size) / (SMALL_BLOCK_SIZE / SL_INDEX_COUNT); + } + else { + fl = tlsf_fls_sizet(size); + sl = tlsf_cast(int, size >> (fl - SL_INDEX_COUNT_LOG2)) ^ (1 << SL_INDEX_COUNT_LOG2); + fl -= (FL_INDEX_SHIFT - 1); + } + *fli = fl; + *sli = sl; +} + +/* This version rounds up to the next block size (for allocations) */ +static void mapping_search(size_t size, int * fli, int * sli) +{ + if(size >= SMALL_BLOCK_SIZE) { + const size_t round = (1 << (tlsf_fls_sizet(size) - SL_INDEX_COUNT_LOG2)) - 1; + size += round; + } + mapping_insert(size, fli, sli); +} + +static block_header_t * search_suitable_block(control_t * control, int * fli, int * sli) +{ + int fl = *fli; + int sl = *sli; + + /* + ** First, search for a block in the list associated with the given + ** fl/sl index. + */ + unsigned int sl_map = control->sl_bitmap[fl] & (~0U << sl); + if(!sl_map) { + /* No block exists. Search in the next largest first-level list. */ + const unsigned int fl_map = control->fl_bitmap & (~0U << (fl + 1)); + if(!fl_map) { + /* No free blocks available, memory has been exhausted. */ + return 0; + } + + fl = tlsf_ffs(fl_map); + *fli = fl; + sl_map = control->sl_bitmap[fl]; + } + tlsf_assert(sl_map && "internal error - second level bitmap is null"); + sl = tlsf_ffs(sl_map); + *sli = sl; + + /* Return the first block in the free list. */ + return control->blocks[fl][sl]; +} + +/* Remove a free block from the free list.*/ +static void remove_free_block(control_t * control, block_header_t * block, int fl, int sl) +{ + block_header_t * prev = block->prev_free; + block_header_t * next = block->next_free; + tlsf_assert(prev && "prev_free field can not be null"); + tlsf_assert(next && "next_free field can not be null"); + next->prev_free = prev; + prev->next_free = next; + + /* If this block is the head of the free list, set new head. */ + if(control->blocks[fl][sl] == block) { + control->blocks[fl][sl] = next; + + /* If the new head is null, clear the bitmap. */ + if(next == &control->block_null) { + control->sl_bitmap[fl] &= ~(1U << sl); + + /* If the second bitmap is now empty, clear the fl bitmap. */ + if(!control->sl_bitmap[fl]) { + control->fl_bitmap &= ~(1U << fl); + } + } + } +} + +/* Insert a free block into the free block list. */ +static void insert_free_block(control_t * control, block_header_t * block, int fl, int sl) +{ + block_header_t * current = control->blocks[fl][sl]; + tlsf_assert(current && "free list cannot have a null entry"); + tlsf_assert(block && "cannot insert a null entry into the free list"); + block->next_free = current; + block->prev_free = &control->block_null; + current->prev_free = block; + + tlsf_assert(block_to_ptr(block) == align_ptr(block_to_ptr(block), ALIGN_SIZE) + && "block not aligned properly"); + /* + ** Insert the new block at the head of the list, and mark the first- + ** and second-level bitmaps appropriately. + */ + control->blocks[fl][sl] = block; + control->fl_bitmap |= (1U << fl); + control->sl_bitmap[fl] |= (1U << sl); +} + +/* Remove a given block from the free list. */ +static void block_remove(control_t * control, block_header_t * block) +{ + int fl, sl; + mapping_insert(block_size(block), &fl, &sl); + remove_free_block(control, block, fl, sl); +} + +/* Insert a given block into the free list. */ +static void block_insert(control_t * control, block_header_t * block) +{ + int fl, sl; + mapping_insert(block_size(block), &fl, &sl); + insert_free_block(control, block, fl, sl); +} + +static int block_can_split(block_header_t * block, size_t size) +{ + return block_size(block) >= sizeof(block_header_t) + size; +} + +/* Split a block into two, the second of which is free. */ +static block_header_t * block_split(block_header_t * block, size_t size) +{ + /* Calculate the amount of space left in the remaining block. */ + block_header_t * remaining = + offset_to_block(block_to_ptr(block), size - block_header_overhead); + + const size_t remain_size = block_size(block) - (size + block_header_overhead); + + tlsf_assert(block_to_ptr(remaining) == align_ptr(block_to_ptr(remaining), ALIGN_SIZE) + && "remaining block not aligned properly"); + + tlsf_assert(block_size(block) == remain_size + size + block_header_overhead); + block_set_size(remaining, remain_size); + tlsf_assert(block_size(remaining) >= block_size_min && "block split with invalid size"); + + block_set_size(block, size); + block_mark_as_free(remaining); + + return remaining; +} + +/* Absorb a free block's storage into an adjacent previous free block. */ +static block_header_t * block_absorb(block_header_t * prev, block_header_t * block) +{ + tlsf_assert(!block_is_last(prev) && "previous block can't be last"); + /* Note: Leaves flags untouched. */ + prev->size += block_size(block) + block_header_overhead; + block_link_next(prev); + return prev; +} + +/* Merge a just-freed block with an adjacent previous free block. */ +static block_header_t * block_merge_prev(control_t * control, block_header_t * block) +{ + if(block_is_prev_free(block)) { + block_header_t * prev = block_prev(block); + tlsf_assert(prev && "prev physical block can't be null"); + tlsf_assert(block_is_free(prev) && "prev block is not free though marked as such"); + block_remove(control, prev); + block = block_absorb(prev, block); + } + + return block; +} + +/* Merge a just-freed block with an adjacent free block. */ +static block_header_t * block_merge_next(control_t * control, block_header_t * block) +{ + block_header_t * next = block_next(block); + tlsf_assert(next && "next physical block can't be null"); + + if(block_is_free(next)) { + tlsf_assert(!block_is_last(block) && "previous block can't be last"); + block_remove(control, next); + block = block_absorb(block, next); + } + + return block; +} + +/* Trim any trailing block space off the end of a block, return to pool. */ +static void block_trim_free(control_t * control, block_header_t * block, size_t size) +{ + tlsf_assert(block_is_free(block) && "block must be free"); + if(block_can_split(block, size)) { + block_header_t * remaining_block = block_split(block, size); + block_link_next(block); + block_set_prev_free(remaining_block); + block_insert(control, remaining_block); + } +} + +/* Trim any trailing block space off the end of a used block, return to pool. */ +static void block_trim_used(control_t * control, block_header_t * block, size_t size) +{ + tlsf_assert(!block_is_free(block) && "block must be used"); + if(block_can_split(block, size)) { + /* If the next block is free, we must coalesce. */ + block_header_t * remaining_block = block_split(block, size); + block_set_prev_used(remaining_block); + + remaining_block = block_merge_next(control, remaining_block); + block_insert(control, remaining_block); + } +} + +static block_header_t * block_trim_free_leading(control_t * control, block_header_t * block, size_t size) +{ + block_header_t * remaining_block = block; + if(block_can_split(block, size)) { + /* We want the 2nd block. */ + remaining_block = block_split(block, size - block_header_overhead); + block_set_prev_free(remaining_block); + + block_link_next(block); + block_insert(control, block); + } + + return remaining_block; +} + +static block_header_t * block_locate_free(control_t * control, size_t size) +{ + int fl = 0, sl = 0; + block_header_t * block = 0; + + if(size) { + mapping_search(size, &fl, &sl); + + /* + ** mapping_search can futz with the size, so for excessively large sizes it can sometimes wind up + ** with indices that are off the end of the block array. + ** So, we protect against that here, since this is the only callsite of mapping_search. + ** Note that we don't need to check sl, since it comes from a modulo operation that guarantees it's always in range. + */ + if(fl < FL_INDEX_COUNT) { + block = search_suitable_block(control, &fl, &sl); + } + } + + if(block) { + tlsf_assert(block_size(block) >= size); + remove_free_block(control, block, fl, sl); + } + + return block; +} + +static void * block_prepare_used(control_t * control, block_header_t * block, size_t size) +{ + void * p = 0; + if(block) { + tlsf_assert(size && "size must be non-zero"); + block_trim_free(control, block, size); + block_mark_as_used(block); + p = block_to_ptr(block); + } + return p; +} + +/* Clear structure and point all empty lists at the null block. */ +static void control_constructor(control_t * control) +{ + int i, j; + + control->block_null.next_free = &control->block_null; + control->block_null.prev_free = &control->block_null; + + control->fl_bitmap = 0; + for(i = 0; i < FL_INDEX_COUNT; ++i) { + control->sl_bitmap[i] = 0; + for(j = 0; j < SL_INDEX_COUNT; ++j) { + control->blocks[i][j] = &control->block_null; + } + } +} + +/* +** Debugging utilities. +*/ + +typedef struct integrity_t { + int prev_status; + int status; +} integrity_t; + +#define tlsf_insist(x) { tlsf_assert(x); if (!(x)) { status--; } } + +static void integrity_walker(void * ptr, size_t size, int used, void * user) +{ + block_header_t * block = block_from_ptr(ptr); + integrity_t * integ = tlsf_cast(integrity_t *, user); + const int this_prev_status = block_is_prev_free(block) ? 1 : 0; + const int this_status = block_is_free(block) ? 1 : 0; + const size_t this_block_size = block_size(block); + + int status = 0; + LV_UNUSED(used); + tlsf_insist(integ->prev_status == this_prev_status && "prev status incorrect"); + tlsf_insist(size == this_block_size && "block size incorrect"); + + integ->prev_status = this_status; + integ->status += status; +} + +int lv_tlsf_check(lv_tlsf_t tlsf) +{ + int i, j; + + control_t * control = tlsf_cast(control_t *, tlsf); + int status = 0; + + /* Check that the free lists and bitmaps are accurate. */ + for(i = 0; i < FL_INDEX_COUNT; ++i) { + for(j = 0; j < SL_INDEX_COUNT; ++j) { + const int fl_map = control->fl_bitmap & (1U << i); + const int sl_list = control->sl_bitmap[i]; + const int sl_map = sl_list & (1U << j); + const block_header_t * block = control->blocks[i][j]; + + /* Check that first- and second-level lists agree. */ + if(!fl_map) { + tlsf_insist(!sl_map && "second-level map must be null"); + } + + if(!sl_map) { + tlsf_insist(block == &control->block_null && "block list must be null"); + continue; + } + + /* Check that there is at least one free block. */ + tlsf_insist(sl_list && "no free blocks in second-level map"); + tlsf_insist(block != &control->block_null && "block should not be null"); + + while(block != &control->block_null) { + int fli, sli; + tlsf_insist(block_is_free(block) && "block should be free"); + tlsf_insist(!block_is_prev_free(block) && "blocks should have coalesced"); + tlsf_insist(!block_is_free(block_next(block)) && "blocks should have coalesced"); + tlsf_insist(block_is_prev_free(block_next(block)) && "block should be free"); + tlsf_insist(block_size(block) >= block_size_min && "block not minimum size"); + + mapping_insert(block_size(block), &fli, &sli); + tlsf_insist(fli == i && sli == j && "block size indexed in wrong list"); + block = block->next_free; + } + } + } + + return status; +} + +#undef tlsf_insist + +static void default_walker(void * ptr, size_t size, int used, void * user) +{ + LV_UNUSED(user); + printf("\t%p %s size: %x (%p)\n", ptr, used ? "used" : "free", (unsigned int)size, (void *)block_from_ptr(ptr)); +} + +void lv_tlsf_walk_pool(lv_pool_t pool, lv_tlsf_walker walker, void * user) +{ + lv_tlsf_walker pool_walker = walker ? walker : default_walker; + block_header_t * block = + offset_to_block(pool, -(int)block_header_overhead); + + while(block && !block_is_last(block)) { + pool_walker( + block_to_ptr(block), + block_size(block), + !block_is_free(block), + user); + block = block_next(block); + } +} + +size_t lv_tlsf_block_size(void * ptr) +{ + size_t size = 0; + if(ptr) { + const block_header_t * block = block_from_ptr(ptr); + size = block_size(block); + } + return size; +} + +int lv_tlsf_check_pool(lv_pool_t pool) +{ + /* Check that the blocks are physically correct. */ + integrity_t integ = { 0, 0 }; + lv_tlsf_walk_pool(pool, integrity_walker, &integ); + + return integ.status; +} + +/* +** Size of the TLSF structures in a given memory block passed to +** lv_tlsf_create, equal to the size of a control_t +*/ +size_t lv_tlsf_size(void) +{ + return sizeof(control_t); +} + +size_t lv_tlsf_align_size(void) +{ + return ALIGN_SIZE; +} + +size_t lv_tlsf_block_size_min(void) +{ + return block_size_min; +} + +size_t lv_tlsf_block_size_max(void) +{ + return block_size_max; +} + +/* +** Overhead of the TLSF structures in a given memory block passed to +** lv_tlsf_add_pool, equal to the overhead of a free block and the +** sentinel block. +*/ +size_t lv_tlsf_pool_overhead(void) +{ + return 2 * block_header_overhead; +} + +size_t lv_tlsf_alloc_overhead(void) +{ + return block_header_overhead; +} + +lv_pool_t lv_tlsf_add_pool(lv_tlsf_t tlsf, void * mem, size_t bytes) +{ + block_header_t * block; + block_header_t * next; + + const size_t pool_overhead = lv_tlsf_pool_overhead(); + const size_t pool_bytes = align_down(bytes - pool_overhead, ALIGN_SIZE); + + if(((ptrdiff_t)mem % ALIGN_SIZE) != 0) { + printf("lv_tlsf_add_pool: Memory must be aligned by %u bytes.\n", + (unsigned int)ALIGN_SIZE); + return 0; + } + + if(pool_bytes < block_size_min || pool_bytes > block_size_max) { +#if defined (TLSF_64BIT) + printf("lv_tlsf_add_pool: Memory size must be between 0x%x and 0x%x00 bytes.\n", + (unsigned int)(pool_overhead + block_size_min), + (unsigned int)((pool_overhead + block_size_max) / 256)); +#else + printf("lv_tlsf_add_pool: Memory size must be between %u and %u bytes.\n", + (unsigned int)(pool_overhead + block_size_min), + (unsigned int)(pool_overhead + block_size_max)); +#endif + return 0; + } + + /* + ** Create the main free block. Offset the start of the block slightly + ** so that the prev_phys_block field falls outside of the pool - + ** it will never be used. + */ + block = offset_to_block(mem, -(tlsfptr_t)block_header_overhead); + block_set_size(block, pool_bytes); + block_set_free(block); + block_set_prev_used(block); + block_insert(tlsf_cast(control_t *, tlsf), block); + + /* Split the block to create a zero-size sentinel block. */ + next = block_link_next(block); + block_set_size(next, 0); + block_set_used(next); + block_set_prev_free(next); + + return mem; +} + +void lv_tlsf_remove_pool(lv_tlsf_t tlsf, lv_pool_t pool) +{ + control_t * control = tlsf_cast(control_t *, tlsf); + block_header_t * block = offset_to_block(pool, -(int)block_header_overhead); + + int fl = 0, sl = 0; + + tlsf_assert(block_is_free(block) && "block should be free"); + tlsf_assert(!block_is_free(block_next(block)) && "next block should not be free"); + tlsf_assert(block_size(block_next(block)) == 0 && "next block size should be zero"); + + mapping_insert(block_size(block), &fl, &sl); + remove_free_block(control, block, fl, sl); +} + +/* +** TLSF main interface. +*/ + +#if _DEBUG +int test_ffs_fls() +{ + /* Verify ffs/fls work properly. */ + int rv = 0; + rv += (tlsf_ffs(0) == -1) ? 0 : 0x1; + rv += (tlsf_fls(0) == -1) ? 0 : 0x2; + rv += (tlsf_ffs(1) == 0) ? 0 : 0x4; + rv += (tlsf_fls(1) == 0) ? 0 : 0x8; + rv += (tlsf_ffs(0x80000000) == 31) ? 0 : 0x10; + rv += (tlsf_ffs(0x80008000) == 15) ? 0 : 0x20; + rv += (tlsf_fls(0x80000008) == 31) ? 0 : 0x40; + rv += (tlsf_fls(0x7FFFFFFF) == 30) ? 0 : 0x80; + +#if defined (TLSF_64BIT) + rv += (tlsf_fls_sizet(0x80000000) == 31) ? 0 : 0x100; + rv += (tlsf_fls_sizet(0x100000000) == 32) ? 0 : 0x200; + rv += (tlsf_fls_sizet(0xffffffffffffffff) == 63) ? 0 : 0x400; +#endif + + if(rv) { + printf("test_ffs_fls: %x ffs/fls tests failed.\n", rv); + } + return rv; +} +#endif + +lv_tlsf_t lv_tlsf_create(void * mem) +{ +#if _DEBUG + if(test_ffs_fls()) { + return 0; + } +#endif + + if(((tlsfptr_t)mem % ALIGN_SIZE) != 0) { + printf("lv_tlsf_create: Memory must be aligned to %u bytes.\n", + (unsigned int)ALIGN_SIZE); + return 0; + } + + control_constructor(tlsf_cast(control_t *, mem)); + + return tlsf_cast(lv_tlsf_t, mem); +} + +lv_tlsf_t lv_tlsf_create_with_pool(void * mem, size_t bytes) +{ + lv_tlsf_t tlsf = lv_tlsf_create(mem); + lv_tlsf_add_pool(tlsf, (char *)mem + lv_tlsf_size(), bytes - lv_tlsf_size()); + return tlsf; +} + +void lv_tlsf_destroy(lv_tlsf_t tlsf) +{ + /* Nothing to do. */ + LV_UNUSED(tlsf); +} + +lv_pool_t lv_tlsf_get_pool(lv_tlsf_t tlsf) +{ + return tlsf_cast(lv_pool_t, (char *)tlsf + lv_tlsf_size()); +} + +void * lv_tlsf_malloc(lv_tlsf_t tlsf, size_t size) +{ + control_t * control = tlsf_cast(control_t *, tlsf); + const size_t adjust = adjust_request_size(size, ALIGN_SIZE); + block_header_t * block = block_locate_free(control, adjust); + return block_prepare_used(control, block, adjust); +} + +void * lv_tlsf_memalign(lv_tlsf_t tlsf, size_t align, size_t size) +{ + control_t * control = tlsf_cast(control_t *, tlsf); + const size_t adjust = adjust_request_size(size, ALIGN_SIZE); + + /* + ** We must allocate an additional minimum block size bytes so that if + ** our free block will leave an alignment gap which is smaller, we can + ** trim a leading free block and release it back to the pool. We must + ** do this because the previous physical block is in use, therefore + ** the prev_phys_block field is not valid, and we can't simply adjust + ** the size of that block. + */ + const size_t gap_minimum = sizeof(block_header_t); + const size_t size_with_gap = adjust_request_size(adjust + align + gap_minimum, align); + + /* + ** If alignment is less than or equals base alignment, we're done. + ** If we requested 0 bytes, return null, as lv_tlsf_malloc(0) does. + */ + const size_t aligned_size = (adjust && align > ALIGN_SIZE) ? size_with_gap : adjust; + + block_header_t * block = block_locate_free(control, aligned_size); + + /* This can't be a static assert. */ + tlsf_assert(sizeof(block_header_t) == block_size_min + block_header_overhead); + + if(block) { + void * ptr = block_to_ptr(block); + void * aligned = align_ptr(ptr, align); + size_t gap = tlsf_cast(size_t, + tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr)); + + /* If gap size is too small, offset to next aligned boundary. */ + if(gap && gap < gap_minimum) { + const size_t gap_remain = gap_minimum - gap; + const size_t offset = tlsf_max(gap_remain, align); + const void * next_aligned = tlsf_cast(void *, + tlsf_cast(tlsfptr_t, aligned) + offset); + + aligned = align_ptr(next_aligned, align); + gap = tlsf_cast(size_t, + tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr)); + } + + if(gap) { + tlsf_assert(gap >= gap_minimum && "gap size too small"); + block = block_trim_free_leading(control, block, gap); + } + } + + return block_prepare_used(control, block, adjust); +} + +void lv_tlsf_free(lv_tlsf_t tlsf, void * ptr) +{ + /* Don't attempt to free a NULL pointer. */ + if(ptr) { + control_t * control = tlsf_cast(control_t *, tlsf); + block_header_t * block = block_from_ptr(ptr); + tlsf_assert(!block_is_free(block) && "block already marked as free"); + block_mark_as_free(block); + block = block_merge_prev(control, block); + block = block_merge_next(control, block); + block_insert(control, block); + } +} + +/* +** The TLSF block information provides us with enough information to +** provide a reasonably intelligent implementation of realloc, growing or +** shrinking the currently allocated block as required. +** +** This routine handles the somewhat esoteric edge cases of realloc: +** - a non-zero size with a null pointer will behave like malloc +** - a zero size with a non-null pointer will behave like free +** - a request that cannot be satisfied will leave the original buffer +** untouched +** - an extended buffer size will leave the newly-allocated area with +** contents undefined +*/ +void * lv_tlsf_realloc(lv_tlsf_t tlsf, void * ptr, size_t size) +{ + control_t * control = tlsf_cast(control_t *, tlsf); + void * p = 0; + + /* Zero-size requests are treated as free. */ + if(ptr && size == 0) { + lv_tlsf_free(tlsf, ptr); + } + /* Requests with NULL pointers are treated as malloc. */ + else if(!ptr) { + p = lv_tlsf_malloc(tlsf, size); + } + else { + block_header_t * block = block_from_ptr(ptr); + block_header_t * next = block_next(block); + + const size_t cursize = block_size(block); + const size_t combined = cursize + block_size(next) + block_header_overhead; + const size_t adjust = adjust_request_size(size, ALIGN_SIZE); + + tlsf_assert(!block_is_free(block) && "block already marked as free"); + + /* + ** If the next block is used, or when combined with the current + ** block, does not offer enough space, we must reallocate and copy. + */ + if(adjust > cursize && (!block_is_free(next) || adjust > combined)) { + p = lv_tlsf_malloc(tlsf, size); + if(p) { + const size_t minsize = tlsf_min(cursize, size); + lv_memcpy(p, ptr, minsize); + lv_tlsf_free(tlsf, ptr); + } + } + else { + /* Do we need to expand to the next block? */ + if(adjust > cursize) { + block_merge_next(control, block); + block_mark_as_used(block); + } + + /* Trim the resulting block and return the original pointer. */ + block_trim_used(control, block, adjust); + p = ptr; + } + } + + return p; +} + +#endif /* LV_MEM_CUSTOM == 0 */ diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_tlsf.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.h similarity index 78% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_tlsf.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.h index 0510dbfa2..77424ab83 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_tlsf.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.h @@ -1,95 +1,95 @@ -#include "../lv_conf_internal.h" -#if LV_MEM_CUSTOM == 0 - -#ifndef INCLUDED_tlsf -#define INCLUDED_tlsf - -/* -** Two Level Segregated Fit memory allocator, version 3.1. -** Written by Matthew Conte -** http://tlsf.baisoku.org -** -** Based on the original documentation by Miguel Masmano: -** http://www.gii.upv.es/tlsf/main/docs -** -** This implementation was written to the specification -** of the document, therefore no GPL restrictions apply. -** -** Copyright (c) 2006-2016, Matthew Conte -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** * Neither the name of the copyright holder nor the -** names of its contributors may be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -** DISCLAIMED. IN NO EVENT SHALL MATTHEW CONTE BE LIABLE FOR ANY -** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/* lv_tlsf_t: a TLSF structure. Can contain 1 to N pools. */ -/* lv_pool_t: a block of memory that TLSF can manage. */ -typedef void* lv_tlsf_t; -typedef void* lv_pool_t; - -/* Create/destroy a memory pool. */ -lv_tlsf_t lv_tlsf_create(void* mem); -lv_tlsf_t lv_tlsf_create_with_pool(void* mem, size_t bytes); -void lv_tlsf_destroy(lv_tlsf_t tlsf); -lv_pool_t lv_tlsf_get_pool(lv_tlsf_t tlsf); - -/* Add/remove memory pools. */ -lv_pool_t lv_tlsf_add_pool(lv_tlsf_t tlsf, void* mem, size_t bytes); -void lv_tlsf_remove_pool(lv_tlsf_t tlsf, lv_pool_t pool); - -/* malloc/memalign/realloc/free replacements. */ -void* lv_tlsf_malloc(lv_tlsf_t tlsf, size_t bytes); -void* lv_tlsf_memalign(lv_tlsf_t tlsf, size_t align, size_t bytes); -void* lv_tlsf_realloc(lv_tlsf_t tlsf, void* ptr, size_t size); -void lv_tlsf_free(lv_tlsf_t tlsf, void* ptr); - -/* Returns internal block size, not original request size */ -size_t lv_tlsf_block_size(void* ptr); - -/* Overheads/limits of internal structures. */ -size_t lv_tlsf_size(void); -size_t lv_tlsf_align_size(void); -size_t lv_tlsf_block_size_min(void); -size_t lv_tlsf_block_size_max(void); -size_t lv_tlsf_pool_overhead(void); -size_t lv_tlsf_alloc_overhead(void); - -/* Debugging. */ -typedef void (*lv_tlsf_walker)(void* ptr, size_t size, int used, void* user); -void lv_tlsf_walk_pool(lv_pool_t pool, lv_tlsf_walker walker, void* user); -/* Returns nonzero if any internal consistency check fails. */ -int lv_tlsf_check(lv_tlsf_t tlsf); -int lv_tlsf_check_pool(lv_pool_t pool); - -#if defined(__cplusplus) -}; -#endif - -#endif - -#endif /* LV_MEM_CUSTOM == 0 */ +#include "../lv_conf_internal.h" +#if LV_MEM_CUSTOM == 0 + +#ifndef LV_TLSF_H +#define LV_TLSF_H + +/* +** Two Level Segregated Fit memory allocator, version 3.1. +** Written by Matthew Conte +** http://tlsf.baisoku.org +** +** Based on the original documentation by Miguel Masmano: +** http://www.gii.upv.es/tlsf/main/docs +** +** This implementation was written to the specification +** of the document, therefore no GPL restrictions apply. +** +** Copyright (c) 2006-2016, Matthew Conte +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the copyright holder nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL MATTHEW CONTE BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/* lv_tlsf_t: a TLSF structure. Can contain 1 to N pools. */ +/* lv_pool_t: a block of memory that TLSF can manage. */ +typedef void * lv_tlsf_t; +typedef void * lv_pool_t; + +/* Create/destroy a memory pool. */ +lv_tlsf_t lv_tlsf_create(void * mem); +lv_tlsf_t lv_tlsf_create_with_pool(void * mem, size_t bytes); +void lv_tlsf_destroy(lv_tlsf_t tlsf); +lv_pool_t lv_tlsf_get_pool(lv_tlsf_t tlsf); + +/* Add/remove memory pools. */ +lv_pool_t lv_tlsf_add_pool(lv_tlsf_t tlsf, void * mem, size_t bytes); +void lv_tlsf_remove_pool(lv_tlsf_t tlsf, lv_pool_t pool); + +/* malloc/memalign/realloc/free replacements. */ +void * lv_tlsf_malloc(lv_tlsf_t tlsf, size_t bytes); +void * lv_tlsf_memalign(lv_tlsf_t tlsf, size_t align, size_t bytes); +void * lv_tlsf_realloc(lv_tlsf_t tlsf, void * ptr, size_t size); +void lv_tlsf_free(lv_tlsf_t tlsf, void * ptr); + +/* Returns internal block size, not original request size */ +size_t lv_tlsf_block_size(void * ptr); + +/* Overheads/limits of internal structures. */ +size_t lv_tlsf_size(void); +size_t lv_tlsf_align_size(void); +size_t lv_tlsf_block_size_min(void); +size_t lv_tlsf_block_size_max(void); +size_t lv_tlsf_pool_overhead(void); +size_t lv_tlsf_alloc_overhead(void); + +/* Debugging. */ +typedef void (*lv_tlsf_walker)(void * ptr, size_t size, int used, void * user); +void lv_tlsf_walk_pool(lv_pool_t pool, lv_tlsf_walker walker, void * user); +/* Returns nonzero if any internal consistency check fails. */ +int lv_tlsf_check(lv_tlsf_t tlsf); +int lv_tlsf_check_pool(lv_pool_t pool); + +#if defined(__cplusplus) +}; +#endif + +#endif /*LV_TLSF_H*/ + +#endif /* LV_MEM_CUSTOM == 0 */ diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_txt.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.c similarity index 87% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_txt.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_txt.c index 0b524ea23..b8c31e5b7 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_txt.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.c @@ -78,23 +78,18 @@ * MACROS **********************/ +#define LV_IS_ASCII(value) ((value & 0x80U) == 0x00U) +#define LV_IS_2BYTES_UTF8_CODE(value) ((value & 0xE0U) == 0xC0U) +#define LV_IS_3BYTES_UTF8_CODE(value) ((value & 0xF0U) == 0xE0U) +#define LV_IS_4BYTES_UTF8_CODE(value) ((value & 0xF8U) == 0xF0U) +#define LV_IS_INVALID_UTF8_CODE(value) ((value & 0xC0U) != 0x80U) + /********************** * GLOBAL FUNCTIONS **********************/ -/** - * Get size of a text - * @param size_res pointer to a 'point_t' variable to store the result - * @param text pointer to a text - * @param font pointer to font of the text - * @param letter_space letter space of the text - * @param txt.line_space line space of the text - * @param flags settings for the text from ::lv_text_flag_t - * @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid - * line breaks - */ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, lv_coord_t letter_space, - lv_coord_t line_space, lv_coord_t max_width, lv_text_flag_t flag) + lv_coord_t line_space, lv_coord_t max_width, lv_text_flag_t flag) { size_res->x = 0; size_res->y = 0; @@ -123,7 +118,7 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * /*Calculate the longest line*/ lv_coord_t act_line_length = lv_txt_get_width(&text[line_start], new_line_start - line_start, font, letter_space, - flag); + flag); size_res->x = LV_MAX(act_line_length, size_res->x); line_start = new_line_start; @@ -204,7 +199,7 @@ static uint32_t lv_txt_get_next_word(const char * txt, const lv_font_t * font, i = i_next; i_next = i_next_next; letter = letter_next; - continue; /*Skip the letter is it is part of a command*/ + continue; /*Skip the letter if it is part of a command*/ } } @@ -280,22 +275,11 @@ static uint32_t lv_txt_get_next_word(const char * txt, const lv_font_t * font, #endif } -/** - * Get the next line of text. Check line length and break chars too. - * - * A line of txt includes the \n character. - * - * @param txt a '\0' terminated string - * @param font pointer to a font - * @param letter_space letter space - * @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid line breaks - * @param flags settings for the text from 'txt_flag_type' enum - * @return the index of the first char of the new line (in byte index not letter index. With UTF-8 they are different) - */ uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coord_t letter_space, lv_coord_t max_width, lv_text_flag_t flag) { if(txt == NULL) return 0; + if(txt[0] == '\0') return 0; if(font == NULL) return 0; /*If max_width doesn't mater simply find the new line character @@ -342,18 +326,8 @@ uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, return i; } -/** - * Give the length of a text with a given font - * @param txt a '\0' terminate string - * @param length length of 'txt' in byte count and not characters (Á is 1 character but 2 bytes in - * UTF-8) - * @param font pointer to a font - * @param letter_space letter space - * @param flags settings for the text from 'txt_flag_t' enum - * @return length of a char_num long text - */ lv_coord_t lv_txt_get_width(const char * txt, uint32_t length, const lv_font_t * font, lv_coord_t letter_space, - lv_text_flag_t flag) + lv_text_flag_t flag) { if(txt == NULL) return 0; if(font == NULL) return 0; @@ -391,14 +365,6 @@ lv_coord_t lv_txt_get_width(const char * txt, uint32_t length, const lv_font_t * return width; } -/** - * Check next character in a string and decide if the character is part of the command or not - * @param state pointer to a txt_cmd_state_t variable which stores the current state of command - * processing (Inited to TXT_CMD_STATE_WAIT ) - * @param c the current character - * @return true: the character is part of a command and should not be written, - * false: the character should be written - */ bool _lv_txt_is_cmd(lv_text_cmd_state_t * state, uint32_t c) { bool ret = false; @@ -430,15 +396,10 @@ bool _lv_txt_is_cmd(lv_text_cmd_state_t * state, uint32_t c) return ret; } -/** - * Insert a string into an other - * @param txt_buf the original text (must be big enough for the result text) - * @param pos position to insert. Expressed in character index and not byte index (Different in - * UTF-8) 0: before the original text, 1: after the first char etc. - * @param ins_txt text to insert - */ void _lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt) { + if(txt_buf == NULL || ins_txt == NULL) return; + size_t old_len = strlen(txt_buf); size_t ins_len = strlen(ins_txt); if(ins_len == 0) return; @@ -456,15 +417,9 @@ void _lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt) lv_memcpy_small(txt_buf + pos, ins_txt, ins_len); } -/** - * Delete a part of a string - * @param txt string to modify - * @param pos position where to start the deleting (0: before the first char, 1: after the first - * char etc.) - * @param len number of characters to delete - */ void _lv_txt_cut(char * txt, uint32_t pos, uint32_t len) { + if(txt == NULL) return; size_t old_len = strlen(txt); @@ -478,12 +433,7 @@ void _lv_txt_cut(char * txt, uint32_t pos, uint32_t len) } } -/** - * return a new formatted text. Memory will be allocated to store the text. - * @param fmt `printf`-like format - * @return pointer to the allocated text string. - */ -LV_FORMAT_ATTRIBUTE(1, 0) char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap) +char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap) { /*Allocate space for the new text by using trick from C99 standard section 7.19.6.12*/ va_list ap_copy; @@ -526,7 +476,7 @@ LV_FORMAT_ATTRIBUTE(1, 0) char * _lv_txt_set_text_vfmt(const char * fmt, va_list return text; } -void _lv_txt_encoded_letter_next_2(const char * txt, uint32_t * letter, uint32_t * letter_next, uint32_t *ofs) +void _lv_txt_encoded_letter_next_2(const char * txt, uint32_t * letter, uint32_t * letter_next, uint32_t * ofs) { *letter = _lv_txt_encoded_next(txt, ofs); *letter_next = *letter != '\0' ? _lv_txt_encoded_next(&txt[*ofs], NULL) : 0; @@ -540,19 +490,19 @@ void _lv_txt_encoded_letter_next_2(const char * txt, uint32_t * letter, uint32_t /** * Give the size of an UTF-8 coded character * @param str pointer to a character in a string - * @return length of the UTF-8 character (1,2,3 or 4). O on invalid code + * @return length of the UTF-8 character (1,2,3 or 4), 0 on invalid code. */ static uint8_t lv_txt_utf8_size(const char * str) { - if((str[0] & 0x80) == 0) + if(LV_IS_ASCII(str[0])) return 1; - else if((str[0] & 0xE0) == 0xC0) + else if(LV_IS_2BYTES_UTF8_CODE(str[0])) return 2; - else if((str[0] & 0xF0) == 0xE0) + else if(LV_IS_3BYTES_UTF8_CODE(str[0])) return 3; - else if((str[0] & 0xF8) == 0xF0) + else if(LV_IS_4BYTES_UTF8_CODE(str[0])) return 4; - return 0; /*If the char was invalid tell it's 1 byte long*/ + return 0; } /** @@ -638,47 +588,47 @@ static uint32_t lv_txt_utf8_next(const char * txt, uint32_t * i) if(i == NULL) i = &i_tmp; /*Normal ASCII*/ - if((txt[*i] & 0x80) == 0) { + if(LV_IS_ASCII(txt[*i])) { result = txt[*i]; (*i)++; } /*Real UTF-8 decode*/ else { /*2 bytes UTF-8 code*/ - if((txt[*i] & 0xE0) == 0xC0) { + if(LV_IS_2BYTES_UTF8_CODE(txt[*i])) { result = (uint32_t)(txt[*i] & 0x1F) << 6; (*i)++; - if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/ + if(LV_IS_INVALID_UTF8_CODE(txt[*i])) return 0; result += (txt[*i] & 0x3F); (*i)++; } /*3 bytes UTF-8 code*/ - else if((txt[*i] & 0xF0) == 0xE0) { + else if(LV_IS_3BYTES_UTF8_CODE(txt[*i])) { result = (uint32_t)(txt[*i] & 0x0F) << 12; (*i)++; - if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/ + if(LV_IS_INVALID_UTF8_CODE(txt[*i])) return 0; result += (uint32_t)(txt[*i] & 0x3F) << 6; (*i)++; - if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/ + if(LV_IS_INVALID_UTF8_CODE(txt[*i])) return 0; result += (txt[*i] & 0x3F); (*i)++; } /*4 bytes UTF-8 code*/ - else if((txt[*i] & 0xF8) == 0xF0) { + else if(LV_IS_4BYTES_UTF8_CODE(txt[*i])) { result = (uint32_t)(txt[*i] & 0x07) << 18; (*i)++; - if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/ + if(LV_IS_INVALID_UTF8_CODE(txt[*i])) return 0; result += (uint32_t)(txt[*i] & 0x3F) << 12; (*i)++; - if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/ + if(LV_IS_INVALID_UTF8_CODE(txt[*i])) return 0; result += (uint32_t)(txt[*i] & 0x3F) << 6; (*i)++; - if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/ + if(LV_IS_INVALID_UTF8_CODE(txt[*i])) return 0; result += txt[*i] & 0x3F; (*i)++; } @@ -735,7 +685,8 @@ static uint32_t lv_txt_utf8_get_byte_id(const char * txt, uint32_t utf8_id) uint32_t byte_cnt = 0; for(i = 0; i < utf8_id && txt[byte_cnt] != '\0'; i++) { uint8_t c_size = _lv_txt_encoded_size(&txt[byte_cnt]); - byte_cnt += c_size > 0 ? c_size : 1; + /* If the char was invalid tell it's 1 byte long*/ + byte_cnt += c_size ? c_size : 1; } return byte_cnt; @@ -792,7 +743,7 @@ static uint32_t lv_txt_utf8_get_length(const char * txt) */ static uint8_t lv_txt_iso8859_1_size(const char * str) { - (void)str; /*Unused*/ + LV_UNUSED(str); /*Unused*/ return 1; } @@ -862,7 +813,7 @@ static uint32_t lv_txt_iso8859_1_prev(const char * txt, uint32_t * i) */ static uint32_t lv_txt_iso8859_1_get_byte_id(const char * txt, uint32_t utf8_id) { - (void)txt; /*Unused*/ + LV_UNUSED(txt); /*Unused*/ return utf8_id; /*In Non encoded no difference*/ } @@ -875,7 +826,7 @@ static uint32_t lv_txt_iso8859_1_get_byte_id(const char * txt, uint32_t utf8_id) */ static uint32_t lv_txt_iso8859_1_get_char_id(const char * txt, uint32_t byte_id) { - (void)txt; /*Unused*/ + LV_UNUSED(txt); /*Unused*/ return byte_id; /*In Non encoded no difference*/ } diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_txt.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.h similarity index 94% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_txt.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_txt.h index f44c27d75..4d3b8453a 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_txt.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.h @@ -81,7 +81,7 @@ typedef uint8_t lv_text_align_t; * line breaks */ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, lv_coord_t letter_space, - lv_coord_t line_space, lv_coord_t max_width, lv_text_flag_t flag); + lv_coord_t line_space, lv_coord_t max_width, lv_text_flag_t flag); /** * Get the next line of text. Check line length and break chars too. @@ -108,7 +108,7 @@ uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coor * @return length of a char_num long text */ lv_coord_t lv_txt_get_width(const char * txt, uint32_t length, const lv_font_t * font, lv_coord_t letter_space, - lv_text_flag_t flag); + lv_text_flag_t flag); /** * Check next character in a string and decide if the character is part of the command or not @@ -122,15 +122,15 @@ bool _lv_txt_is_cmd(lv_text_cmd_state_t * state, uint32_t c); /** * Insert a string into an other - * @param txt_buf the original text (must be big enough for the result text) + * @param txt_buf the original text (must be big enough for the result text and NULL terminated) * @param pos position to insert (0: before the original text, 1: after the first char etc.) - * @param ins_txt text to insert + * @param ins_txt text to insert, must be '\0' terminated */ void _lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt); /** * Delete a part of a string - * @param txt string to modify + * @param txt string to modify, must be '\0' terminated and should point to a heap or stack frame, not read-only memory. * @param pos position where to start the deleting (0: before the first char, 1: after the first * char etc.) * @param len number of characters to delete @@ -153,7 +153,7 @@ char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap) LV_FORMAT_ATTRIBUTE(1 * After the call it will point to the next encoded char in 'txt'. * NULL to use txt[0] as index */ -void _lv_txt_encoded_letter_next_2(const char * txt, uint32_t * letter, uint32_t * letter_next, uint32_t *ofs); +void _lv_txt_encoded_letter_next_2(const char * txt, uint32_t * letter, uint32_t * letter_next, uint32_t * ofs); /** * Test if char is break char or not (a text can broken here or not) @@ -166,7 +166,7 @@ static inline bool _lv_txt_is_break_char(uint32_t letter) bool ret = false; /* each chinese character can be break */ - if (letter >= 0x4E00 && letter <= 0x9FA5) { + if(letter >= 0x4E00 && letter <= 0x9FA5) { return true; } @@ -226,7 +226,7 @@ extern uint32_t (*_lv_txt_encoded_next)(const char *, uint32_t *); extern uint32_t (*_lv_txt_encoded_prev)(const char *, uint32_t *); /** - * Convert a letter index (in an the encoded text) to byte index. + * Convert a letter index (in the encoded text) to byte index. * E.g. in UTF-8 "AÁRT" index of 'R' is 2 but start at byte 3 because 'Á' is 2 bytes long * @param txt a '\0' terminated UTF-8 string * @param enc_id letter index diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_txt_ap.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_txt_ap.c similarity index 94% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_txt_ap.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_txt_ap.c index 2341a34e6..54faf8b4f 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_txt_ap.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_txt_ap.c @@ -38,6 +38,7 @@ typedef struct { #if LV_USE_ARABIC_PERSIAN_CHARS == 1 static uint32_t lv_ap_get_char_index(uint16_t c); static uint32_t lv_txt_lam_alef(uint32_t ch_curr, uint32_t ch_next); +static bool lv_txt_is_arabic_vowel(uint16_t c); /********************** * STATIC VARIABLES @@ -166,6 +167,16 @@ void _lv_txt_ap_proc(const char * txt, char * txt_out) index_current = lv_ap_get_char_index(ch_enc[i]); idx_next = lv_ap_get_char_index(ch_enc[i + 1]); + if(lv_txt_is_arabic_vowel(ch_enc[i])) { // Current character is a vowel + ch_fin[j] = ch_enc[i]; + i++; + j++; + continue; // Skip this character + } + else if(lv_txt_is_arabic_vowel(ch_enc[i + 1])) { // Next character is a vowel + idx_next = lv_ap_get_char_index(ch_enc[i + 2]); // Skip the vowel character to join with the character after it + } + if(index_current == LV_UNDEF_ARABIC_PERSIAN_CHARS) { ch_fin[j] = ch_enc[i]; j++; @@ -282,4 +293,9 @@ static uint32_t lv_txt_lam_alef(uint32_t ch_curr, uint32_t ch_next) return 0; } +static bool lv_txt_is_arabic_vowel(uint16_t c) +{ + return (c >= 0x064B) && (c <= 0x0652); +} + #endif diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_txt_ap.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_txt_ap.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_txt_ap.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_txt_ap.h diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_types.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_types.h similarity index 76% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_types.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_types.h index 9a32423e6..172f21c43 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_types.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_types.h @@ -13,15 +13,12 @@ extern "C" { /********************* * INCLUDES *********************/ +#include /********************* * DEFINES *********************/ -#if defined(__cplusplus) || __STDC_VERSION__ >= 199901L // If c99 or newer, use stdint.h to determine arch size -#include -#endif - // If __UINTPTR_MAX__ or UINTPTR_MAX are available, use them to determine arch size #if defined(__UINTPTR_MAX__) && __UINTPTR_MAX__ > 0xFFFFFFFF #define LV_ARCH_64 @@ -44,7 +41,7 @@ extern "C" { */ enum { LV_RES_INV = 0, /*Typically indicates that the object is deleted (become invalid) in the action - function or an operation was failed*/ + function or an operation was failed*/ LV_RES_OK, /*The object is valid (no deleted) after the action*/ }; typedef uint8_t lv_res_t; @@ -72,7 +69,7 @@ typedef uint32_t lv_uintptr_t; * MACROS **********************/ -#define LV_UNUSED(x) ((void) x) +#define LV_UNUSED(x) ((void)x) #define _LV_CONCAT(x, y) x ## y #define LV_CONCAT(x, y) _LV_CONCAT(x, y) @@ -80,14 +77,18 @@ typedef uint32_t lv_uintptr_t; #define _LV_CONCAT3(x, y, z) x ## y ## z #define LV_CONCAT3(x, y, z) _LV_CONCAT3(x, y, z) -#if (defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)) && !defined(PYCPARSER) -#define LV_FORMAT_ATTRIBUTE(fmtstr, vararg) __attribute__ ((format(printf, fmtstr, vararg))) +#if defined(PYCPARSER) +#define LV_FORMAT_ATTRIBUTE(fmtstr, vararg) +#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __GNUC__ > 4) +#define LV_FORMAT_ATTRIBUTE(fmtstr, vararg) __attribute__((format(gnu_printf, fmtstr, vararg))) +#elif (defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)) +#define LV_FORMAT_ATTRIBUTE(fmtstr, vararg) __attribute__((format(printf, fmtstr, vararg))) #else #define LV_FORMAT_ATTRIBUTE(fmtstr, vararg) #endif #ifdef __cplusplus -} /*extern "C"*/ +} /*extern "C"*/ #endif #endif /*LV_TYPES_H*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_utils.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_utils.c similarity index 95% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_utils.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_utils.c index 7f73ba18b..f097ad937 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_utils.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_utils.c @@ -6,12 +6,9 @@ /********************* * INCLUDES *********************/ -#include +#include #include "lv_utils.h" -#include "lv_math.h" -#include "lv_printf.h" -#include "lv_txt.h" /********************* * DEFINES diff --git a/lib/libesp32_lvgl/LVGL8/src/misc/lv_utils.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_utils.h similarity index 89% rename from lib/libesp32_lvgl/LVGL8/src/misc/lv_utils.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_utils.h index c798f1b15..5d17d7698 100644 --- a/lib/libesp32_lvgl/LVGL8/src/misc/lv_utils.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_utils.h @@ -14,7 +14,6 @@ extern "C" { * INCLUDES *********************/ #include -#include /********************* * DEFINES @@ -30,8 +29,8 @@ extern "C" { /** Searches base[0] to base[n - 1] for an item that matches *key. * - * @note The function cmp must return negative if its first - * argument (the search key) is less that its second (a table entry), + * @note The function cmp must return negative if it's first + * argument (the search key) is less that it's second (a table entry), * zero if equal, and positive if greater. * * @note Items in the array must be in ascending order. diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.c new file mode 100644 index 000000000..08cfe03f5 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.c @@ -0,0 +1,775 @@ +/** + * @file lv_arc.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_arc.h" +#if LV_USE_ARC != 0 + +#include "../core/lv_group.h" +#include "../core/lv_indev.h" +#include "../misc/lv_assert.h" +#include "../misc/lv_math.h" +#include "../draw/lv_draw_arc.h" + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_arc_class + +#define VALUE_UNSET INT16_MIN + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void lv_arc_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_arc_draw(lv_event_t * e); +static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e); +static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angle, lv_part_t part); +static void get_center(lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r); +static void get_knob_area(lv_obj_t * arc, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area); +static void value_update(lv_obj_t * arc); + +/********************** + * STATIC VARIABLES + **********************/ +const lv_obj_class_t lv_arc_class = { + .constructor_cb = lv_arc_constructor, + .event_cb = lv_arc_event, + .instance_size = sizeof(lv_arc_t), + .editable = LV_OBJ_CLASS_EDITABLE_TRUE, + .base_class = &lv_obj_class +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_arc_create(lv_obj_t * parent) +{ + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + return obj; +} + +/*====================== + * Add/remove functions + *=====================*/ + +/* + * New object specific "add" or "remove" functions come here + */ + +/*===================== + * Setter functions + *====================*/ + +void lv_arc_set_start_angle(lv_obj_t * obj, uint16_t start) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_arc_t * arc = (lv_arc_t *)obj; + + if(start > 360) start -= 360; + + int16_t old_delta = arc->indic_angle_end - arc->indic_angle_start; + int16_t new_delta = arc->indic_angle_end - start; + + if(old_delta < 0) old_delta = 360 + old_delta; + if(new_delta < 0) new_delta = 360 + new_delta; + + if(LV_ABS(new_delta - old_delta) > 180) lv_obj_invalidate(obj); + else if(new_delta < old_delta) inv_arc_area(obj, arc->indic_angle_start, start, LV_PART_INDICATOR); + else if(old_delta < new_delta) inv_arc_area(obj, start, arc->indic_angle_start, LV_PART_INDICATOR); + + arc->indic_angle_start = start; +} + +void lv_arc_set_end_angle(lv_obj_t * obj, uint16_t end) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_arc_t * arc = (lv_arc_t *)obj; + if(end > 360) end -= 360; + + int16_t old_delta = arc->indic_angle_end - arc->indic_angle_start; + int16_t new_delta = end - arc->indic_angle_start; + + if(old_delta < 0) old_delta = 360 + old_delta; + if(new_delta < 0) new_delta = 360 + new_delta; + + if(LV_ABS(new_delta - old_delta) > 180) lv_obj_invalidate(obj); + else if(new_delta < old_delta) inv_arc_area(obj, end, arc->indic_angle_end, LV_PART_INDICATOR); + else if(old_delta < new_delta) inv_arc_area(obj, arc->indic_angle_end, end, LV_PART_INDICATOR); + + arc->indic_angle_end = end; +} + +void lv_arc_set_angles(lv_obj_t * obj, uint16_t start, uint16_t end) +{ + lv_arc_set_end_angle(obj, end); + lv_arc_set_start_angle(obj, start); +} + +void lv_arc_set_bg_start_angle(lv_obj_t * obj, uint16_t start) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_arc_t * arc = (lv_arc_t *)obj; + + if(start > 360) start -= 360; + + int16_t old_delta = arc->bg_angle_end - arc->bg_angle_start; + int16_t new_delta = arc->bg_angle_end - start; + + if(old_delta < 0) old_delta = 360 + old_delta; + if(new_delta < 0) new_delta = 360 + new_delta; + + if(LV_ABS(new_delta - old_delta) > 180) lv_obj_invalidate(obj); + else if(new_delta < old_delta) inv_arc_area(obj, arc->bg_angle_start, start, LV_PART_MAIN); + else if(old_delta < new_delta) inv_arc_area(obj, start, arc->bg_angle_start, LV_PART_MAIN); + + arc->bg_angle_start = start; + + value_update(obj); +} + +void lv_arc_set_bg_end_angle(lv_obj_t * obj, uint16_t end) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_arc_t * arc = (lv_arc_t *)obj; + + if(end > 360) end -= 360; + + int16_t old_delta = arc->bg_angle_end - arc->bg_angle_start; + int16_t new_delta = end - arc->bg_angle_start; + + if(old_delta < 0) old_delta = 360 + old_delta; + if(new_delta < 0) new_delta = 360 + new_delta; + + if(LV_ABS(new_delta - old_delta) > 180) lv_obj_invalidate(obj); + else if(new_delta < old_delta) inv_arc_area(obj, end, arc->bg_angle_end, LV_PART_MAIN); + else if(old_delta < new_delta) inv_arc_area(obj, arc->bg_angle_end, end, LV_PART_MAIN); + + arc->bg_angle_end = end; + + value_update(obj); +} + +void lv_arc_set_bg_angles(lv_obj_t * obj, uint16_t start, uint16_t end) +{ + lv_arc_set_bg_end_angle(obj, end); + lv_arc_set_bg_start_angle(obj, start); +} + +void lv_arc_set_rotation(lv_obj_t * obj, uint16_t rotation) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_arc_t * arc = (lv_arc_t *)obj; + + arc->rotation = rotation; + + lv_obj_invalidate(obj); +} + +void lv_arc_set_mode(lv_obj_t * obj, lv_arc_mode_t type) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_arc_t * arc = (lv_arc_t *)obj; + + int16_t val = arc->value; + + arc->type = type; + arc->value = -1; /** Force set_value handling*/ + + int16_t bg_midpoint, bg_end = arc->bg_angle_end; + if(arc->bg_angle_end < arc->bg_angle_start) bg_end = arc->bg_angle_end + 360; + + switch(arc->type) { + case LV_ARC_MODE_SYMMETRICAL: + bg_midpoint = (arc->bg_angle_start + bg_end) / 2; + lv_arc_set_start_angle(obj, bg_midpoint); + lv_arc_set_end_angle(obj, bg_midpoint); + break; + case LV_ARC_MODE_REVERSE: + lv_arc_set_end_angle(obj, arc->bg_angle_end); + break; + default: /** LV_ARC_TYPE_NORMAL*/ + lv_arc_set_start_angle(obj, arc->bg_angle_start); + } + + lv_arc_set_value(obj, val); +} + +void lv_arc_set_value(lv_obj_t * obj, int16_t value) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_arc_t * arc = (lv_arc_t *)obj; + + if(arc->value == value) return; + + int16_t new_value; + new_value = value > arc->max_value ? arc->max_value : value; + new_value = new_value < arc->min_value ? arc->min_value : new_value; + + if(arc->value == new_value) return; + arc->value = new_value; + + value_update(obj); +} + +void lv_arc_set_range(lv_obj_t * obj, int16_t min, int16_t max) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_arc_t * arc = (lv_arc_t *)obj; + + if(arc->min_value == min && arc->max_value == max) return; + + arc->min_value = min; + arc->max_value = max; + + if(arc->value < min) { + arc->value = min; + } + if(arc->value > max) { + arc->value = max; + } + + value_update(obj); /*value has changed relative to the new range*/ +} + +void lv_arc_set_change_rate(lv_obj_t * obj, uint16_t rate) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_arc_t * arc = (lv_arc_t *)obj; + + arc->chg_rate = rate; +} + +/*===================== + * Getter functions + *====================*/ + +uint16_t lv_arc_get_angle_start(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + return ((lv_arc_t *) obj)->indic_angle_start; +} + +uint16_t lv_arc_get_angle_end(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + return ((lv_arc_t *) obj)->indic_angle_end; +} + +uint16_t lv_arc_get_bg_angle_start(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + return ((lv_arc_t *) obj)->bg_angle_start; +} + +uint16_t lv_arc_get_bg_angle_end(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + return ((lv_arc_t *) obj)->bg_angle_end; +} + +int16_t lv_arc_get_value(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + return ((lv_arc_t *) obj)->value; +} + +int16_t lv_arc_get_min_value(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + return ((lv_arc_t *) obj)->min_value; +} + +int16_t lv_arc_get_max_value(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + return ((lv_arc_t *) obj)->max_value; +} + +lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + return ((lv_arc_t *) obj)->type; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_arc_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + LV_TRACE_OBJ_CREATE("begin"); + + lv_arc_t * arc = (lv_arc_t *)obj; + + /*Initialize the allocated 'ext'*/ + arc->rotation = 0; + arc->bg_angle_start = 135; + arc->bg_angle_end = 45; + arc->indic_angle_start = 135; + arc->indic_angle_end = 270; + arc->type = LV_ARC_MODE_NORMAL; + arc->value = VALUE_UNSET; + arc->min_close = 1; + arc->min_value = 0; + arc->max_value = 100; + arc->dragging = false; + arc->chg_rate = 720; + arc->last_tick = lv_tick_get(); + arc->last_angle = arc->indic_angle_end; + + lv_obj_add_flag(obj, LV_OBJ_FLAG_CLICKABLE); + lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN); + lv_obj_set_ext_click_area(obj, LV_DPI_DEF / 10); + + + LV_TRACE_OBJ_CREATE("finished"); +} + +static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) +{ + LV_UNUSED(class_p); + + lv_res_t res; + + /*Call the ancestor's event handler*/ + res = lv_obj_event_base(MY_CLASS, e); + if(res != LV_RES_OK) return; + + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * obj = lv_event_get_target(e); + lv_arc_t * arc = (lv_arc_t *)lv_event_get_target(e); + if(code == LV_EVENT_PRESSING) { + lv_indev_t * indev = lv_indev_get_act(); + if(indev == NULL) return; + + /*Handle only pointers here*/ + lv_indev_type_t indev_type = lv_indev_get_type(indev); + if(indev_type != LV_INDEV_TYPE_POINTER) return; + + lv_point_t p; + lv_indev_get_point(indev, &p); + + /*Make point relative to the arc's center*/ + lv_point_t center; + lv_coord_t r; + get_center(obj, ¢er, &r); + + p.x -= center.x; + p.y -= center.y; + + /*Enter dragging mode if pressed out of the knob*/ + if(arc->dragging == false) { + lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); + r -= indic_width; + /*Add some more sensitive area if there is no advanced git testing. + * (Advanced hit testing is more precise)*/ + if(lv_obj_has_flag(obj, LV_OBJ_FLAG_ADV_HITTEST)) { + r -= indic_width; + + } else { + r -= LV_MAX(r / 4, indic_width); + } + if(r < 1) r = 1; + + if(p.x * p.x + p.y * p.y > r * r) { + arc->dragging = true; + arc->last_tick = lv_tick_get(); /*Capture timestamp at dragging start*/ + } + } + + /*It must be in "dragging" mode to turn the arc*/ + if(arc->dragging == false) return; + + /*No angle can be determined if exactly the middle of the arc is being pressed*/ + if(p.x == 0 && p.y == 0) return; + + /*Calculate the angle of the pressed point*/ + int16_t angle; + int16_t bg_end = arc->bg_angle_end; + if(arc->bg_angle_end < arc->bg_angle_start) { + bg_end = arc->bg_angle_end + 360; + } + + angle = lv_atan2(p.y, p.x); + angle -= arc->rotation; + angle -= arc->bg_angle_start; /*Make the angle relative to the start angle*/ + + if(angle < 0) angle += 360; + + int16_t deg_range = bg_end - arc->bg_angle_start; + + int16_t last_angle_rel = arc->last_angle - arc->bg_angle_start; + int16_t delta_angle = angle - last_angle_rel; + + /*Do not allow big jumps. + *It's mainly to avoid jumping to the opposite end if the "dead" range between min. and max. is crossed. + *Check which end was closer on the last valid press (arc->min_close) and prefer that end*/ + if(LV_ABS(delta_angle) > 280) { + if(arc->min_close) angle = 0; + else angle = deg_range; + } + else { + if(angle < deg_range / 2)arc->min_close = 1; + else arc->min_close = 0; + } + + /*Calculate the slew rate limited angle based on change rate (degrees/sec)*/ + delta_angle = angle - last_angle_rel; + uint32_t delta_tick = lv_tick_elaps(arc->last_tick); + int16_t delta_angle_max = (arc->chg_rate * delta_tick) / 1000; + + if(delta_angle > delta_angle_max) { + delta_angle = delta_angle_max; + } + else if(delta_angle < -delta_angle_max) { + delta_angle = -delta_angle_max; + } + + angle = last_angle_rel + delta_angle; /*Apply the limited angle change*/ + + /*Rounding for symmetry*/ + int32_t round = ((bg_end - arc->bg_angle_start) * 8) / (arc->max_value - arc->min_value); + round = (round + 4) >> 4; + angle += round; + + angle += arc->bg_angle_start; /*Make the angle absolute again*/ + + /*Set the new value*/ + int16_t old_value = arc->value; + int16_t new_value = lv_map(angle, arc->bg_angle_start, bg_end, arc->min_value, arc->max_value); + if(new_value != lv_arc_get_value(obj)) { + arc->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/ + lv_arc_set_value(obj, new_value); /*set_value caches the last_angle for the next iteration*/ + if(new_value != old_value) { + res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return; + } + } + + /*Don't let the elapsed time become too big while sitting on an end point*/ + if(new_value == arc->min_value || new_value == arc->max_value) { + arc->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/ + } + } + else if(code == LV_EVENT_RELEASED || code == LV_EVENT_PRESS_LOST) { + arc->dragging = false; + + /*Leave edit mode if released. (No need to wait for LONG_PRESS)*/ + lv_group_t * g = lv_obj_get_group(obj); + bool editing = lv_group_get_editing(g); + lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); + if(indev_type == LV_INDEV_TYPE_ENCODER) { + if(editing) lv_group_set_editing(g, false); + } + + } + else if(code == LV_EVENT_KEY) { + char c = *((char *)lv_event_get_param(e)); + + int16_t old_value = arc->value; + if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { + lv_arc_set_value(obj, lv_arc_get_value(obj) + 1); + } + else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { + lv_arc_set_value(obj, lv_arc_get_value(obj) - 1); + } + + if(old_value != arc->value) { + res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return; + } + } + else if(code == LV_EVENT_HIT_TEST) { + lv_hit_test_info_t * info = lv_event_get_param(e);; + + lv_point_t p; + lv_coord_t r; + get_center(obj, &p, &r); + + lv_coord_t ext_click_area = 0; + if(obj->spec_attr) ext_click_area = obj->spec_attr->ext_click_pad; + + lv_coord_t w = lv_obj_get_style_arc_width(obj, LV_PART_MAIN); + r -= w + ext_click_area; + + lv_area_t a; + /*Invalid if clicked inside*/ + lv_area_set(&a, p.x - r, p.y - r, p.x + r, p.y + r); + if(_lv_area_is_point_on(&a, info->point, LV_RADIUS_CIRCLE)) { + info->res = false; + return; + } + + /*Valid if no clicked outside*/ + lv_area_increase(&a, w + ext_click_area * 2, w + ext_click_area * 2); + info->res = _lv_area_is_point_on(&a, info->point, LV_RADIUS_CIRCLE); + } + else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { + lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + lv_coord_t bg_pad = LV_MAX4(bg_left, bg_right, bg_top, bg_bottom); + + lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); + lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); + lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); + lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); + lv_coord_t knob_pad = LV_MAX4(knob_left, knob_right, knob_top, knob_bottom) + 2; + + lv_coord_t * s = lv_event_get_param(e); + *s = LV_MAX(*s, knob_pad - bg_pad); + } + else if(code == LV_EVENT_DRAW_MAIN) { + lv_arc_draw(e); + } +} + +static void lv_arc_draw(lv_event_t * e) +{ + lv_obj_t * obj = lv_event_get_target(e); + lv_arc_t * arc = (lv_arc_t *)obj; + + const lv_area_t * clip_area = lv_event_get_param(e); + + lv_point_t center; + lv_coord_t arc_r; + get_center(obj, ¢er, &arc_r); + + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + + /*Draw the background arc*/ + lv_draw_arc_dsc_t arc_dsc; + if(arc_r > 0) { + lv_draw_arc_dsc_init(&arc_dsc); + lv_obj_init_draw_arc_dsc(obj, LV_PART_MAIN, &arc_dsc); + + part_draw_dsc.part = LV_PART_MAIN; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_ARC_DRAW_PART_BACKGROUND; + part_draw_dsc.p1 = ¢er; + part_draw_dsc.radius = arc_r; + part_draw_dsc.arc_dsc = &arc_dsc; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); + + lv_draw_arc(center.x, center.y, part_draw_dsc.radius, arc->bg_angle_start + arc->rotation, + arc->bg_angle_end + arc->rotation, clip_area, + &arc_dsc); + + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); + } + + /*make the indicator arc smaller or larger according to its greatest padding value*/ + lv_coord_t left_indic = lv_obj_get_style_pad_left(obj, LV_PART_INDICATOR); + lv_coord_t right_indic = lv_obj_get_style_pad_right(obj, LV_PART_INDICATOR); + lv_coord_t top_indic = lv_obj_get_style_pad_top(obj, LV_PART_INDICATOR); + lv_coord_t bottom_indic = lv_obj_get_style_pad_bottom(obj, LV_PART_INDICATOR); + lv_coord_t indic_r = arc_r - LV_MAX4(left_indic, right_indic, top_indic, bottom_indic); + + if(indic_r > 0) { + lv_draw_arc_dsc_init(&arc_dsc); + lv_obj_init_draw_arc_dsc(obj, LV_PART_INDICATOR, &arc_dsc); + + part_draw_dsc.part = LV_PART_INDICATOR; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_ARC_DRAW_PART_FOREGROUND; + part_draw_dsc.p1 = ¢er; + part_draw_dsc.radius = indic_r; + part_draw_dsc.arc_dsc = &arc_dsc; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); + + if(arc_dsc.width > part_draw_dsc.radius) arc_dsc.width = part_draw_dsc.radius; + lv_draw_arc(center.x, center.y, part_draw_dsc.radius, arc->indic_angle_start + arc->rotation, + arc->indic_angle_end + arc->rotation, clip_area, + &arc_dsc); + + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); + } + + lv_area_t knob_area; + get_knob_area(obj, ¢er, arc_r, &knob_area); + + lv_draw_rect_dsc_t knob_rect_dsc; + lv_draw_rect_dsc_init(&knob_rect_dsc); + lv_obj_init_draw_rect_dsc(obj, LV_PART_KNOB, &knob_rect_dsc); + + part_draw_dsc.part = LV_PART_KNOB; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_ARC_DRAW_PART_KNOB; + part_draw_dsc.draw_area = &knob_area; + part_draw_dsc.rect_dsc = &knob_rect_dsc; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); + + lv_draw_rect(&knob_area, clip_area, &knob_rect_dsc); + + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); +} + +static void inv_arc_area(lv_obj_t * obj, uint16_t start_angle, uint16_t end_angle, lv_part_t part) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_arc_t * arc = (lv_arc_t *)obj; + + if(start_angle == end_angle) return; + + if(start_angle > 360) start_angle -= 360; + if(end_angle > 360) end_angle -= 360; + + /*Skip this complicated invalidation if the arc is not visible*/ + if(lv_obj_is_visible(obj) == false) return; + + lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + lv_coord_t right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + lv_coord_t bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + lv_coord_t rout = (LV_MIN(lv_obj_get_width(obj) - left - right, lv_obj_get_height(obj) - top - bottom)) / 2; + lv_coord_t x = obj->coords.x1 + rout + left; + lv_coord_t y = obj->coords.y1 + rout + top; + lv_coord_t w = lv_obj_get_style_arc_width(obj, part); + lv_coord_t rounded = lv_obj_get_style_arc_rounded(obj, part); + + if(part == LV_PART_INDICATOR) { + lv_coord_t knob_extra_size = lv_obj_calculate_ext_draw_size(obj, LV_PART_KNOB); + + lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); + lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); + lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); + lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); + + knob_extra_size += LV_MAX4(knob_left, knob_right, knob_top, knob_bottom); + + w += knob_extra_size * 2 + 2; + rout += knob_extra_size + 2; + } + + start_angle += arc->rotation; + end_angle += arc->rotation; + + if(start_angle > 360) start_angle -= 360; + if(end_angle > 360) end_angle -= 360; + + lv_area_t inv_area; + lv_draw_arc_get_area(x, y, rout, start_angle, end_angle, w, rounded, &inv_area); + lv_obj_invalidate_area(obj, &inv_area); +} + +static void get_center(lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r) +{ + lv_coord_t left_bg = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + lv_coord_t right_bg = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + lv_coord_t top_bg = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + lv_coord_t bottom_bg = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + + lv_coord_t r = (LV_MIN(lv_obj_get_width(obj) - left_bg - right_bg, + lv_obj_get_height(obj) - top_bg - bottom_bg)) / 2; + + *arc_r = r; + center->x = obj->coords.x1 + r + left_bg; + center->y = obj->coords.y1 + r + top_bg; + + lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); + r -= indic_width; +} + +static void get_knob_area(lv_obj_t * obj, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_arc_t * arc = (lv_arc_t *)obj; + + lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); + lv_coord_t indic_width_half = indic_width / 2; + r -= indic_width_half; + + uint16_t angle = arc->rotation; + if(arc->type == LV_ARC_MODE_NORMAL) { + angle += arc->indic_angle_end; + } + else if(arc->type == LV_ARC_MODE_REVERSE) { + angle += arc->indic_angle_start; + } + else if(arc->type == LV_ARC_MODE_SYMMETRICAL) { + int32_t range_midpoint = (int32_t)(arc->min_value + arc->max_value) / 2; + if(arc->value < range_midpoint) angle += arc->indic_angle_start; + else angle += arc->indic_angle_end; + } + lv_coord_t knob_x = (r * lv_trigo_sin(angle + 90)) >> LV_TRIGO_SHIFT; + lv_coord_t knob_y = (r * lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT; + + lv_coord_t left_knob = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); + lv_coord_t right_knob = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); + lv_coord_t top_knob = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); + lv_coord_t bottom_knob = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); + + knob_area->x1 = center->x + knob_x - left_knob - indic_width_half; + knob_area->x2 = center->x + knob_x + right_knob + indic_width_half; + knob_area->y1 = center->y + knob_y - top_knob - indic_width_half; + knob_area->y2 = center->y + knob_y + bottom_knob + indic_width_half; +} + +/** + * Used internally to update arc angles after a value change + * @param arc pointer to an arc object + */ +static void value_update(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_arc_t * arc = (lv_arc_t *)obj; + + /*If the value is still not set to any value do not update*/ + if(arc->value == VALUE_UNSET) return; + + int16_t bg_midpoint, range_midpoint, bg_end = arc->bg_angle_end; + if(arc->bg_angle_end < arc->bg_angle_start) bg_end = arc->bg_angle_end + 360; + + int16_t angle; + switch(arc->type) { + case LV_ARC_MODE_SYMMETRICAL: + bg_midpoint = (arc->bg_angle_start + bg_end) / 2; + range_midpoint = (int32_t)(arc->min_value + arc->max_value) / 2; + + if(arc->value < range_midpoint) { + angle = lv_map(arc->value, arc->min_value, range_midpoint, arc->bg_angle_start, bg_midpoint); + lv_arc_set_start_angle(obj, angle); + lv_arc_set_end_angle(obj, bg_midpoint); + } + else { + angle = lv_map(arc->value, range_midpoint, arc->max_value, bg_midpoint, bg_end); + lv_arc_set_start_angle(obj, bg_midpoint); + lv_arc_set_end_angle(obj, angle); + } + break; + case LV_ARC_MODE_REVERSE: + angle = lv_map(arc->value, arc->min_value, arc->max_value, arc->bg_angle_start, bg_end); + lv_arc_set_angles(obj, angle, arc->bg_angle_end); + break; + case LV_ARC_MODE_NORMAL: + angle = lv_map(arc->value, arc->min_value, arc->max_value, arc->bg_angle_start, bg_end); + lv_arc_set_angles(obj, arc->bg_angle_start, angle); + break; + default: + LV_LOG_WARN("Invalid mode: %d", arc->type); + return; + } + arc->last_angle = angle; /*Cache angle for slew rate limiting*/ +} + +#endif diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_arc.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.h similarity index 59% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_arc.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.h index 6fbc9b761..db9b786a1 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_arc.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.h @@ -41,25 +41,35 @@ typedef struct { uint16_t indic_angle_end; uint16_t bg_angle_start; uint16_t bg_angle_end; - int16_t value; /*Current value of the arc*/ - int16_t min_value; /*Minimum value of the arc*/ - int16_t max_value; /*Maximum value of the arc*/ + int16_t value; /*Current value of the arc*/ + int16_t min_value; /*Minimum value of the arc*/ + int16_t max_value; /*Maximum value of the arc*/ uint16_t dragging : 1; uint16_t type : 2; - uint16_t min_close : 1; /*1: the last pressed angle was closer to minimum end*/ - uint16_t chg_rate; /*Drag angle rate of change of the arc (degrees/sec)*/ - uint32_t last_tick; /*Last dragging event timestamp of the arc*/ - int16_t last_angle; /*Last dragging angle of the arc*/ -}lv_arc_t; + uint16_t min_close : 1; /*1: the last pressed angle was closer to minimum end*/ + uint16_t chg_rate; /*Drag angle rate of change of the arc (degrees/sec)*/ + uint32_t last_tick; /*Last dragging event timestamp of the arc*/ + int16_t last_angle; /*Last dragging angle of the arc*/ +} lv_arc_t; extern const lv_obj_class_t lv_arc_class; +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_arc_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_ARC_DRAW_PART_BACKGROUND, /**< The background arc*/ + LV_ARC_DRAW_PART_FOREGROUND, /**< The foreground arc*/ + LV_ARC_DRAW_PART_KNOB, /**< The knob*/ +} lv_arc_draw_part_type_t; + /********************** * GLOBAL PROTOTYPES **********************/ /** - * Create a arc objects + * Create an arc object * @param par pointer to an object, it will be the parent of the new arc * @return pointer to the created arc */ @@ -75,81 +85,81 @@ lv_obj_t * lv_arc_create(lv_obj_t * parent); /** * Set the start angle of an arc. 0 deg: right, 90 bottom, etc. - * @param arc pointer to an arc object + * @param arc pointer to an arc object * @param start the start angle */ void lv_arc_set_start_angle(lv_obj_t * arc, uint16_t start); /** * Set the end angle of an arc. 0 deg: right, 90 bottom, etc. - * @param arc pointer to an arc object - * @param end the end angle + * @param arc pointer to an arc object + * @param end the end angle */ void lv_arc_set_end_angle(lv_obj_t * arc, uint16_t end); /** * Set the start and end angles - * @param arc pointer to an arc object + * @param arc pointer to an arc object * @param start the start angle - * @param end the end angle + * @param end the end angle */ void lv_arc_set_angles(lv_obj_t * arc, uint16_t start, uint16_t end); /** * Set the start angle of an arc background. 0 deg: right, 90 bottom, etc. - * @param arc pointer to an arc object + * @param arc pointer to an arc object * @param start the start angle */ void lv_arc_set_bg_start_angle(lv_obj_t * arc, uint16_t start); /** * Set the start angle of an arc background. 0 deg: right, 90 bottom etc. - * @param arc pointer to an arc object - * @param end the end angle + * @param arc pointer to an arc object + * @param end the end angle */ void lv_arc_set_bg_end_angle(lv_obj_t * arc, uint16_t end); /** * Set the start and end angles of the arc background - * @param arc pointer to an arc object + * @param arc pointer to an arc object * @param start the start angle - * @param end the end angle + * @param end the end angle */ void lv_arc_set_bg_angles(lv_obj_t * arc, uint16_t start, uint16_t end); /** * Set the rotation for the whole arc - * @param arc pointer to an arc object - * @param rotation rotation angle + * @param arc pointer to an arc object + * @param rotation rotation angle */ void lv_arc_set_rotation(lv_obj_t * arc, uint16_t rotation); /** * Set the type of arc. - * @param arc pointer to arc object - * @param mode arc's mode + * @param arc pointer to arc object + * @param mode arc's mode */ void lv_arc_set_mode(lv_obj_t * arc, lv_arc_mode_t type); /** * Set a new value on the arc - * @param arc pointer to a arc object + * @param arc pointer to an arc object * @param value new value */ void lv_arc_set_value(lv_obj_t * arc, int16_t value); /** - * Set minimum and the maximum values of a arc - * @param arc pointer to the arc object - * @param min minimum value - * @param max maximum value + * Set minimum and the maximum values of an arc + * @param arc pointer to the arc object + * @param min minimum value + * @param max maximum value */ void lv_arc_set_range(lv_obj_t * arc, int16_t min, int16_t max); /** - * Set a change rate to limit the speed how fast the arc should reache the pressed point. - * @param arc pointer to a arc object - * @param rate the change rate + * Set a change rate to limit the speed how fast the arc should reach the pressed point. + * @param arc pointer to an arc object + * @param rate the change rate */ void lv_arc_set_change_rate(lv_obj_t * arc, uint16_t rate); @@ -159,57 +169,57 @@ void lv_arc_set_change_rate(lv_obj_t * arc, uint16_t rate); /** * Get the start angle of an arc. - * @param arc pointer to an arc object - * @return the start angle [0..360] + * @param arc pointer to an arc object + * @return the start angle [0..360] */ uint16_t lv_arc_get_angle_start(lv_obj_t * obj); /** * Get the end angle of an arc. - * @param arc pointer to an arc object - * @return the end angle [0..360] + * @param arc pointer to an arc object + * @return the end angle [0..360] */ uint16_t lv_arc_get_angle_end(lv_obj_t * obj); /** * Get the start angle of an arc background. - * @param arc pointer to an arc object - * @return the start angle [0..360] + * @param arc pointer to an arc object + * @return the start angle [0..360] */ uint16_t lv_arc_get_bg_angle_start(lv_obj_t * obj); /** * Get the end angle of an arc background. - * @param arc pointer to an arc object - * @return the end angle [0..360] + * @param arc pointer to an arc object + * @return the end angle [0..360] */ uint16_t lv_arc_get_bg_angle_end(lv_obj_t * obj); /** - * Get the value of a arc - * @param arc pointer to a arc object - * @return the value of the arc + * Get the value of an arc + * @param arc pointer to an arc object + * @return the value of the arc */ int16_t lv_arc_get_value(const lv_obj_t * obj); /** - * Get the minimum value of a arc - * @param arc pointer to a arc object - * @return the minimum value of the arc + * Get the minimum value of an arc + * @param arc pointer to an arc object + * @return the minimum value of the arc */ int16_t lv_arc_get_min_value(const lv_obj_t * obj); /** - * Get the maximum value of a arc - * @param arc pointer to a arc object - * @return the maximum value of the arc + * Get the maximum value of an arc + * @param arc pointer to an arc object + * @return the maximum value of the arc */ int16_t lv_arc_get_max_value(const lv_obj_t * obj); /** * Get whether the arc is type or not. - * @param arc pointer to a arc object - * @return arc's mode + * @param arc pointer to an arc object + * @return arc's mode */ lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj); diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_bar.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_bar.c similarity index 93% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_bar.c rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_bar.c index 793be15ce..5037f4288 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_bar.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_bar.c @@ -19,7 +19,7 @@ *********************/ #define MY_CLASS &lv_bar_class -/** hor. pad and ver. pad cannot make the indicator smaller then this [px]*/ +/** hor. pad and ver. pad cannot make the indicator smaller than this [px]*/ #define LV_BAR_SIZE_MIN 4 #define LV_BAR_IS_ANIMATING(anim_struct) (((anim_struct).anim_state) != LV_BAR_ANIM_STATE_INV) @@ -77,7 +77,7 @@ const lv_obj_class_t lv_bar_class = { lv_obj_t * lv_bar_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -95,7 +95,7 @@ void lv_bar_set_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim) if(bar->cur_value == value) return; value = LV_CLAMP(bar->min_value, value, bar->max_value); - value = value < bar->start_value ? bar->start_value : value; /*Can't be smaller then the left value*/ + value = value < bar->start_value ? bar->start_value : value; /*Can't be smaller than the left value*/ if(bar->cur_value == value) return; lv_bar_set_value_with_anim(obj, value, &bar->cur_value, &bar->cur_value_anim, anim); @@ -108,7 +108,7 @@ void lv_bar_set_start_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim lv_bar_t * bar = (lv_bar_t *)obj; value = LV_CLAMP(bar->min_value, value, bar->max_value); - value = value > bar->cur_value ? bar->cur_value : value; /*Can't be greater then the right value*/ + value = value > bar->cur_value ? bar->cur_value : value; /*Can't be greater than the right value*/ if(bar->start_value == value) return; lv_bar_set_value_with_anim(obj, value, &bar->start_value, &bar->start_value_anim, anim); @@ -310,8 +310,7 @@ static void draw_indic(lv_event_t * e) anim_start_value_x += anim_start_value_start_x; } - else - { + else { anim_start_value_x = (int32_t)((int32_t)anim_length * (bar->start_value - bar->min_value)) / range; } @@ -325,8 +324,7 @@ static void draw_indic(lv_event_t * e) bar->cur_value_anim.anim_state) / LV_BAR_ANIM_STATE_END); } - else - { + else { anim_cur_value_x = (int32_t)((int32_t)anim_length * (bar->cur_value - bar->min_value)) / range; } @@ -382,13 +380,15 @@ static void draw_indic(lv_event_t * e) /*Do not draw a zero length indicator but at least call the draw part events*/ if(!sym && indic_length_calc(&bar->indic_area) <= 1) { - lv_obj_draw_part_dsc_t obj_draw_dsc; - lv_obj_draw_dsc_init(&obj_draw_dsc, clip_area); - obj_draw_dsc.part = LV_PART_INDICATOR; - obj_draw_dsc.draw_area = &bar->indic_area; + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + part_draw_dsc.part = LV_PART_INDICATOR; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_BAR_DRAW_PART_INDICATOR; + part_draw_dsc.draw_area = &bar->indic_area; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &obj_draw_dsc); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &obj_draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); return; } @@ -403,13 +403,15 @@ static void draw_indic(lv_event_t * e) lv_draw_rect_dsc_init(&draw_rect_dsc); lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &draw_rect_dsc); - lv_obj_draw_part_dsc_t obj_draw_dsc; - lv_obj_draw_dsc_init(&obj_draw_dsc, clip_area); - obj_draw_dsc.part = LV_PART_INDICATOR; - obj_draw_dsc.rect_dsc = &draw_rect_dsc; - obj_draw_dsc.draw_area = &bar->indic_area; + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + part_draw_dsc.part = LV_PART_INDICATOR; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_BAR_DRAW_PART_INDICATOR; + part_draw_dsc.rect_dsc = &draw_rect_dsc; + part_draw_dsc.draw_area = &bar->indic_area; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &obj_draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); /*Draw only the shadow if the indicator is long enough. *The radius of the bg and the indicator can make a strange shape where @@ -482,11 +484,13 @@ static void draw_indic(lv_event_t * e) lv_draw_rect(&bar->indic_area, clip_area, &draw_rect_dsc); #if LV_DRAW_COMPLEX + lv_draw_mask_free_param(&mask_indic_param); + lv_draw_mask_free_param(&mask_bg_param); lv_draw_mask_remove_id(mask_indic_id); lv_draw_mask_remove_id(mask_bg_id); #endif - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &obj_draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } static void lv_bar_event(const lv_obj_class_t * class_p, lv_event_t * e) @@ -520,10 +524,12 @@ static void lv_bar_event(const lv_obj_class_t * class_p, lv_event_t * e) if(pad < 0) { *s = LV_MAX(*s, -pad); } - } else if(code == LV_EVENT_PRESSED || code == LV_EVENT_RELEASED) { + } + else if(code == LV_EVENT_PRESSED || code == LV_EVENT_RELEASED) { lv_bar_t * bar = (lv_bar_t *)obj; lv_obj_invalidate_area(obj, &bar->indic_area); - } else if(code == LV_EVENT_DRAW_MAIN) { + } + else if(code == LV_EVENT_DRAW_MAIN) { draw_indic(e); } } @@ -554,7 +560,7 @@ static void lv_bar_set_value_with_anim(lv_obj_t * obj, int32_t new_value, int32_ { if(en == LV_ANIM_OFF) { *value_ptr = new_value; - lv_obj_invalidate((lv_obj_t*)obj); + lv_obj_invalidate((lv_obj_t *)obj); } else { /*No animation in progress -> simply set the values*/ diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_bar.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_bar.h similarity index 93% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_bar.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_bar.h index cb3f99d20..b839b1453 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_bar.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_bar.h @@ -54,10 +54,18 @@ typedef struct { _lv_bar_anim_t cur_value_anim; _lv_bar_anim_t start_value_anim; lv_bar_mode_t mode : 2; /**< Type of bar*/ -}lv_bar_t; +} lv_bar_t; extern const lv_obj_class_t lv_bar_class; +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_bar_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_BAR_DRAW_PART_INDICATOR, /**< The indicator*/ +} lv_bar_draw_part_type_t; + /********************** * GLOBAL PROTOTYPES **********************/ diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_btn.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_btn.c similarity index 98% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_btn.c rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_btn.c index 3605ccc7d..5676dc7a4 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_btn.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_btn.c @@ -48,7 +48,7 @@ const lv_obj_class_t lv_btn_class = { lv_obj_t * lv_btn_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_btn.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_btn.h similarity index 98% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_btn.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_btn.h index 8a5af5102..1d471f975 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_btn.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_btn.h @@ -28,7 +28,7 @@ extern "C" { typedef struct { lv_obj_t obj; -}lv_btn_t; +} lv_btn_t; extern const lv_obj_class_t lv_btn_class; diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_btnmatrix.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.c similarity index 86% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_btnmatrix.c rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.c index dd33ade13..0108a8ec5 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_btnmatrix.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.c @@ -43,14 +43,15 @@ static bool button_is_checked(lv_btnmatrix_ctrl_t ctrl_bits); static bool button_is_repeat_disabled(lv_btnmatrix_ctrl_t ctrl_bits); static bool button_is_inactive(lv_btnmatrix_ctrl_t ctrl_bits); static bool button_is_click_trig(lv_btnmatrix_ctrl_t ctrl_bits); +static bool button_is_popover(lv_btnmatrix_ctrl_t ctrl_bits); static bool button_is_checkable(lv_btnmatrix_ctrl_t ctrl_bits); static bool button_is_recolor(lv_btnmatrix_ctrl_t ctrl_bits); static bool button_get_checked(lv_btnmatrix_ctrl_t ctrl_bits); -static bool button_is_recolor(lv_btnmatrix_ctrl_t ctrl_bits); static uint16_t get_button_from_point(lv_obj_t * obj, lv_point_t * p); static void allocate_btn_areas_and_controls(const lv_obj_t * obj, const char ** map); static void invalidate_button_area(const lv_obj_t * obj, uint16_t btn_idx); static void make_one_button_checked(lv_obj_t * obj, uint16_t btn_idx); +static bool has_popovers_in_top_row(lv_obj_t * obj); /********************** * STATIC VARIABLES @@ -58,16 +59,16 @@ static void make_one_button_checked(lv_obj_t * obj, uint16_t btn_idx); static const char * lv_btnmatrix_def_map[] = {"Btn1", "Btn2", "Btn3", "\n", "Btn4", "Btn5", ""}; const lv_obj_class_t lv_btnmatrix_class = { - .constructor_cb = lv_btnmatrix_constructor, - .destructor_cb = lv_btnmatrix_destructor, - .event_cb = lv_btnmatrix_event, - .width_def = LV_DPI_DEF * 2, - .height_def = LV_DPI_DEF, - .instance_size = sizeof(lv_btnmatrix_t), - .editable = LV_OBJ_CLASS_EDITABLE_TRUE, - .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, - .base_class = &lv_obj_class - }; + .constructor_cb = lv_btnmatrix_constructor, + .destructor_cb = lv_btnmatrix_destructor, + .event_cb = lv_btnmatrix_event, + .width_def = LV_DPI_DEF * 2, + .height_def = LV_DPI_DEF, + .instance_size = sizeof(lv_btnmatrix_t), + .editable = LV_OBJ_CLASS_EDITABLE_TRUE, + .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, + .base_class = &lv_obj_class +}; /********************** * MACROS @@ -79,7 +80,7 @@ const lv_obj_class_t lv_btnmatrix_class = { lv_obj_t * lv_btnmatrix_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -94,7 +95,7 @@ void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]) LV_ASSERT_OBJ(obj, MY_CLASS); if(map == NULL) return; - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj;; + lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; /*Analyze the map and create the required number of buttons*/ allocate_btn_areas_and_controls(obj, map); @@ -111,15 +112,8 @@ void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]) lv_coord_t max_w = lv_obj_get_content_width(obj); lv_coord_t max_h = lv_obj_get_content_height(obj); - /*Count the lines to calculate button height*/ - uint8_t row_cnt = 1; - uint32_t i; - for(i = 0; map[i] && map[i][0] != '\0'; i++) { - if(strcmp(map[i], "\n") == 0) row_cnt++; - } - /*Calculate the position of each row*/ - lv_coord_t max_h_no_gap = max_h - (prow * (row_cnt - 1)); + lv_coord_t max_h_no_gap = max_h - (prow * (btnm->row_cnt - 1)); /*Count the units and the buttons in a line *(A button can be 1,2,3... unit wide)*/ @@ -129,7 +123,7 @@ void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]) /*Count the units and the buttons in a line*/ uint32_t row; - for(row = 0; row < row_cnt; row++) { + for(row = 0; row < btnm->row_cnt; row++) { uint16_t unit_cnt = 0; /*Number of units in a row*/ uint16_t btn_cnt = 0; /*Number of buttons in a row*/ /*Count the buttons and units in this row*/ @@ -144,8 +138,8 @@ void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]) continue; } - lv_coord_t row_y1 = ptop + (max_h_no_gap * row) / row_cnt + row * prow; - lv_coord_t row_y2 = ptop + (max_h_no_gap * (row + 1)) / row_cnt + row * prow - 1; + lv_coord_t row_y1 = ptop + (max_h_no_gap * row) / btnm->row_cnt + row * prow; + lv_coord_t row_y2 = ptop + (max_h_no_gap * (row + 1)) / btnm->row_cnt + row * prow - 1; /*Set the button size and positions*/ lv_coord_t max_w_no_gap = max_w - (pcol * (btn_cnt - 1)); @@ -180,6 +174,10 @@ void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]) map_row = &map_row[btn_cnt + 1]; /*Set the map to the next line*/ } + /*Popovers in the top row will draw outside the widget and the extended draw size depends on + *the row height which may have changed when setting the new map*/ + lv_obj_refresh_ext_draw_size(obj); + lv_obj_invalidate(obj); } @@ -220,9 +218,13 @@ void lv_btnmatrix_set_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctr btnm->ctrl_bits[btn_id] |= ctrl; invalidate_button_area(obj, btn_id); + + if (ctrl & LV_BTNMATRIX_CTRL_POPOVER) { + lv_obj_refresh_ext_draw_size(obj); + } } -void lv_btnmatrix_clear_btn_ctrl(const lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl) +void lv_btnmatrix_clear_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -232,6 +234,10 @@ void lv_btnmatrix_clear_btn_ctrl(const lv_obj_t * obj, uint16_t btn_id, lv_btnma btnm->ctrl_bits[btn_id] &= (~ctrl); invalidate_button_area(obj, btn_id); + + if (ctrl & LV_BTNMATRIX_CTRL_POPOVER) { + lv_obj_refresh_ext_draw_size(obj); + } } void lv_btnmatrix_set_btn_ctrl_all(lv_obj_t * obj, lv_btnmatrix_ctrl_t ctrl) @@ -331,7 +337,7 @@ bool lv_btnmatrix_has_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctr lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj;; if(btn_id >= btnm->btn_cnt) return false; - return (btnm->ctrl_bits[btn_id] & ctrl) ? true : false; + return ((btnm->ctrl_bits[btn_id] & ctrl) == ctrl) ? true : false; } bool lv_btnmatrix_get_one_checked(const lv_obj_t * obj) @@ -353,6 +359,7 @@ static void lv_btnmatrix_constructor(const lv_obj_class_t * class_p, lv_obj_t * LV_TRACE_OBJ_CREATE("begin"); lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; btnm->btn_cnt = 0; + btnm->row_cnt = 0; btnm->btn_id_sel = LV_BTNMATRIX_BTN_NONE; btnm->button_areas = NULL; btnm->ctrl_bits = NULL; @@ -361,7 +368,7 @@ static void lv_btnmatrix_constructor(const lv_obj_class_t * class_p, lv_obj_t * lv_btnmatrix_set_map(obj, lv_btnmatrix_def_map); - LV_TRACE_OBJ_CREATE("finshed"); + LV_TRACE_OBJ_CREATE("finished"); } static void lv_btnmatrix_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) @@ -373,7 +380,7 @@ static void lv_btnmatrix_destructor(const lv_obj_class_t * class_p, lv_obj_t * o lv_mem_free(btnm->ctrl_bits); btnm->button_areas = NULL; btnm->ctrl_bits = NULL; - LV_TRACE_OBJ_CREATE("finshed"); + LV_TRACE_OBJ_CREATE("finished"); } static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e) @@ -391,6 +398,15 @@ static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; lv_point_t p; + if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { + lv_coord_t * s = lv_event_get_param(e); + if (has_popovers_in_top_row(obj)) { + /*reserve one row worth of extra space to account for popovers in the top row*/ + *s = btnm->row_cnt > 0 ? lv_obj_get_content_height(obj) / btnm->row_cnt : 0; + } else { + *s = 0; + } + } if(code == LV_EVENT_STYLE_CHANGED) { lv_btnmatrix_set_map(obj, btnm->map_p); } @@ -419,6 +435,7 @@ static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e) if(btnm->btn_id_sel != LV_BTNMATRIX_BTN_NONE) { if(button_is_click_trig(btnm->ctrl_bits[btnm->btn_id_sel]) == false && + button_is_popover(btnm->ctrl_bits[btnm->btn_id_sel]) == false && button_is_inactive(btnm->ctrl_bits[btnm->btn_id_sel]) == false && button_is_hidden(btnm->ctrl_bits[btnm->btn_id_sel]) == false) { uint32_t b = btnm->btn_id_sel; @@ -451,7 +468,8 @@ static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e) button_is_hidden(btnm->ctrl_bits[btn_pr]) == false) { invalidate_button_area(obj, btn_pr); /*Send VALUE_CHANGED for the newly pressed button*/ - if(button_is_click_trig(btnm->ctrl_bits[btn_pr]) == false) { + if(button_is_click_trig(btnm->ctrl_bits[btn_pr]) == false && + button_is_popover(btnm->ctrl_bits[btnm->btn_id_sel]) == false) { uint32_t b = btn_pr; res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &b); if(res != LV_RES_OK) return; @@ -474,7 +492,8 @@ static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e) } - if(button_is_click_trig(btnm->ctrl_bits[btnm->btn_id_sel]) == true && + if((button_is_click_trig(btnm->ctrl_bits[btnm->btn_id_sel]) == true || + button_is_popover(btnm->ctrl_bits[btnm->btn_id_sel]) == true) && button_is_inactive(btnm->ctrl_bits[btnm->btn_id_sel]) == false && button_is_hidden(btnm->ctrl_bits[btnm->btn_id_sel]) == false) { uint32_t b = btnm->btn_id_sel; @@ -519,16 +538,19 @@ static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e) bool editing = lv_group_get_editing(lv_obj_get_group(obj)); /*Focus the first button if there is not selected button*/ if(btnm->btn_id_sel == LV_BTNMATRIX_BTN_NONE) { - if (indev_type == LV_INDEV_TYPE_KEYPAD || (indev_type == LV_INDEV_TYPE_ENCODER && editing)) { + if(indev_type == LV_INDEV_TYPE_KEYPAD || (indev_type == LV_INDEV_TYPE_ENCODER && editing)) { uint32_t b = 0; if(btnm->one_check) { - while(button_is_hidden(btnm->ctrl_bits[b]) || button_is_inactive(btnm->ctrl_bits[b]) || button_is_checked(btnm->ctrl_bits[b]) == false) b++; - } else { + while(button_is_hidden(btnm->ctrl_bits[b]) || button_is_inactive(btnm->ctrl_bits[b]) || + button_is_checked(btnm->ctrl_bits[b]) == false) b++; + } + else { while(button_is_hidden(btnm->ctrl_bits[b]) || button_is_inactive(btnm->ctrl_bits[b])) b++; } btnm->btn_id_sel = b; - } else { + } + else { btnm->btn_id_sel = LV_BTNMATRIX_BTN_NONE; } } @@ -620,7 +642,8 @@ static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e) } invalidate_button_area(obj, btnm->btn_id_sel); - } else if(code == LV_EVENT_DRAW_MAIN) { + } + else if(code == LV_EVENT_DRAW_MAIN) { draw_main(e); } @@ -649,7 +672,6 @@ static void draw_main(lv_event_t * e) lv_draw_rect_dsc_t draw_rect_dsc_def; lv_draw_label_dsc_t draw_label_dsc_def; - lv_state_t state_ori = obj->state; obj->state = LV_STATE_DEFAULT; obj->skip_trans = 1; @@ -670,11 +692,13 @@ static void draw_main(lv_event_t * e) char * txt_ap = lv_mem_buf_get(txt_ap_size); #endif - lv_obj_draw_part_dsc_t dsc; - lv_obj_draw_dsc_init(&dsc, clip_area); - dsc.part = LV_PART_ITEMS; - dsc.rect_dsc = &draw_rect_dsc_act; - dsc.label_dsc = &draw_label_dsc_act; + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + part_draw_dsc.part = LV_PART_ITEMS; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_BTNMATRIX_DRAW_PART_BTN; + part_draw_dsc.rect_dsc = &draw_rect_dsc_act; + part_draw_dsc.label_dsc = &draw_label_dsc_act; for(btn_i = 0; btn_i < btnm->btn_cnt; btn_i++, txt_i++) { /*Search the next valid text in the map*/ @@ -688,8 +712,9 @@ static void draw_main(lv_event_t * e) /*Get the state of the button*/ lv_state_t btn_state = LV_STATE_DEFAULT; if(button_get_checked(btnm->ctrl_bits[btn_i])) btn_state |= LV_STATE_CHECKED; + if(button_is_inactive(btnm->ctrl_bits[btn_i])) btn_state |= LV_STATE_DISABLED; - if(btn_i == btnm->btn_id_sel) { + else if(btn_i == btnm->btn_id_sel) { if(state_ori & LV_STATE_PRESSED) btn_state |= LV_STATE_PRESSED; if(state_ori & LV_STATE_FOCUSED) btn_state |= LV_STATE_FOCUSED; if(state_ori & LV_STATE_FOCUS_KEY) btn_state |= LV_STATE_FOCUS_KEY; @@ -725,9 +750,9 @@ static void draw_main(lv_event_t * e) else draw_label_dsc_act.flag &= ~LV_TEXT_FLAG_RECOLOR; - dsc.draw_area = &btn_area; - dsc.id = btn_i; - lv_event_send(obj,LV_EVENT_DRAW_PART_BEGIN, &dsc); + part_draw_dsc.draw_area = &btn_area; + part_draw_dsc.id = btn_i; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); /*Remove borders on the edges if `LV_BORDER_SIDE_INTERNAL`*/ if(draw_rect_dsc_act.border_side & LV_BORDER_SIDE_INTERNAL) { @@ -738,6 +763,13 @@ static void draw_main(lv_event_t * e) if(btn_area.y2 == obj->coords.y2 - pbottom) draw_rect_dsc_act.border_side &= ~LV_BORDER_SIDE_BOTTOM; } + lv_coord_t btn_height = lv_area_get_height(&btn_area); + + if ((btn_state & LV_STATE_PRESSED) && (btnm->ctrl_bits[btn_i] & LV_BTNMATRIX_CTRL_POPOVER)) { + /*Push up the upper boundary of the btn area to create the popover*/ + btn_area.y1 -= btn_height; + } + /*Draw the background*/ lv_draw_rect(&btn_area, clip_area, &draw_rect_dsc_act); @@ -757,17 +789,23 @@ static void draw_main(lv_event_t * e) #endif lv_point_t txt_size; lv_txt_get_size(&txt_size, txt, font, letter_space, - line_space, lv_area_get_width(&area_obj), draw_label_dsc_act.flag); + line_space, lv_area_get_width(&area_obj), draw_label_dsc_act.flag); btn_area.x1 += (lv_area_get_width(&btn_area) - txt_size.x) / 2; btn_area.y1 += (lv_area_get_height(&btn_area) - txt_size.y) / 2; btn_area.x2 = btn_area.x1 + txt_size.x; btn_area.y2 = btn_area.y1 + txt_size.y; + if ((btn_state & LV_STATE_PRESSED) && (btnm->ctrl_bits[btn_i] & LV_BTNMATRIX_CTRL_POPOVER)) { + /*Push up the button text into the popover*/ + btn_area.y1 -= btn_height / 2; + btn_area.y2 -= btn_height / 2; + } + /*Draw the text*/ lv_draw_label(&btn_area, clip_area, &draw_label_dsc_act, txt, NULL); - lv_event_send(obj,LV_EVENT_DRAW_PART_END, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } obj->skip_trans = 0; @@ -782,18 +820,20 @@ static void draw_main(lv_event_t * e) */ static void allocate_btn_areas_and_controls(const lv_obj_t * obj, const char ** map) { + lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; + btnm->row_cnt = 1; /*Count the buttons in the map*/ uint16_t btn_cnt = 0; uint16_t i = 0; while(map[i] && map[i][0] != '\0') { if(strcmp(map[i], "\n") != 0) { /*Do not count line breaks*/ btn_cnt++; + } else { + btnm->row_cnt++; } i++; } - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj;; - /*Do not allocate memory for the same amount of buttons*/ if(btn_cnt == btnm->btn_cnt) return; @@ -853,6 +893,11 @@ static bool button_is_click_trig(lv_btnmatrix_ctrl_t ctrl_bits) return (ctrl_bits & LV_BTNMATRIX_CTRL_CLICK_TRIG) ? true : false; } +static bool button_is_popover(lv_btnmatrix_ctrl_t ctrl_bits) +{ + return (ctrl_bits & LV_BTNMATRIX_CTRL_POPOVER) ? true : false; +} + static bool button_is_checkable(lv_btnmatrix_ctrl_t ctrl_bits) { return (ctrl_bits & LV_BTNMATRIX_CTRL_CHECKABLE) ? true : false; @@ -909,11 +954,11 @@ static uint16_t get_button_from_point(lv_obj_t * obj, lv_point_t * p) else btn_area.y1 += obj_cords.y1 - prow; if(btn_area.x2 >= w - pright - 2) btn_area.x2 += obj_cords.x1 + LV_MIN(pright, - BTN_EXTRA_CLICK_AREA_MAX); /*-2 for rounding error*/ + BTN_EXTRA_CLICK_AREA_MAX); /*-2 for rounding error*/ else btn_area.x2 += obj_cords.x1 + pcol; if(btn_area.y2 >= h - pbottom - 2) btn_area.y2 += obj_cords.y1 + LV_MIN(pbottom, - BTN_EXTRA_CLICK_AREA_MAX); /*-2 for rounding error*/ + BTN_EXTRA_CLICK_AREA_MAX); /*-2 for rounding error*/ else btn_area.y2 += obj_cords.y1 + prow; if(_lv_area_is_point_on(&btn_area, p, 0) != false) { @@ -938,7 +983,7 @@ static void invalidate_button_area(const lv_obj_t * obj, uint16_t btn_idx) lv_obj_get_coords(obj, &obj_area); /*The buttons might have outline and shadow so make the invalidation larger with the gaps between the buttons. - *It assumes that the outline or shadow is smaller then the gaps*/ + *It assumes that the outline or shadow is smaller than the gaps*/ lv_coord_t row_gap = lv_obj_get_style_pad_row(obj, LV_PART_MAIN); lv_coord_t col_gap = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); @@ -953,6 +998,11 @@ static void invalidate_button_area(const lv_obj_t * obj, uint16_t btn_idx) btn_area.x2 += obj_area.x1 + row_gap; btn_area.y2 += obj_area.y1 + col_gap; + if ((btn_idx == btnm->btn_id_sel) && (btnm->ctrl_bits[btn_idx] & LV_BTNMATRIX_CTRL_POPOVER)) { + /*Push up the upper boundary of the btn area to also invalidate the popover*/ + btn_area.y1 -= lv_area_get_height(&btn_area); + } + lv_obj_invalidate_area(obj, &btn_area); } @@ -972,4 +1022,30 @@ static void make_one_button_checked(lv_obj_t * obj, uint16_t btn_idx) if(was_toggled) lv_btnmatrix_set_btn_ctrl(obj, btn_idx, LV_BTNMATRIX_CTRL_CHECKED); } +/** + * Check if any of the buttons in the first row has the LV_BTNMATRIX_CTRL_POPOVER control flag set. + * @param obj Button matrix object + * @return true if at least one button has the flag, false otherwise + */ +static bool has_popovers_in_top_row(lv_obj_t * obj) +{ + lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; + + if (btnm->row_cnt <= 0) { + return false; + } + + const char ** map_row = btnm->map_p; + uint16_t btn_cnt = 0; + + while (map_row[btn_cnt] && strcmp(map_row[btn_cnt], "\n") != 0 && map_row[btn_cnt][0] != '\0') { + if (button_is_popover(btnm->ctrl_bits[btn_cnt])) { + return true; + } + btn_cnt++; + } + + return false; +} + #endif diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_btnmatrix.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.h similarity index 91% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_btnmatrix.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.h index c13493d2d..351bce31e 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_btnmatrix.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.h @@ -39,6 +39,7 @@ enum { LV_BTNMATRIX_CTRL_CHECKABLE = 0x0040, /**< The button can be toggled.*/ LV_BTNMATRIX_CTRL_CHECKED = 0x0080, /**< Button is currently toggled (e.g. checked).*/ LV_BTNMATRIX_CTRL_CLICK_TRIG = 0x0100, /**< 1: Send LV_EVENT_VALUE_CHANGE on CLICK, 0: Send LV_EVENT_VALUE_CHANGE on PRESS*/ + LV_BTNMATRIX_CTRL_POPOVER = 0x0200, /**< Show a popover when pressing this key*/ LV_BTNMATRIX_CTRL_RECOLOR = 0x1000, /**< Enable text recoloring with `#color`*/ _LV_BTNMATRIX_CTRL_RESERVED = 0x2000, /**< Reserved for later use*/ LV_BTNMATRIX_CTRL_CUSTOM_1 = 0x4000, /**< Custom free to use flag*/ @@ -47,7 +48,8 @@ enum { typedef uint16_t lv_btnmatrix_ctrl_t; -typedef bool (*lv_btnmatrix_btn_draw_cb_t)(lv_obj_t * btnm, uint32_t btn_id, const lv_area_t * draw_area, const lv_area_t * clip_area); +typedef bool (*lv_btnmatrix_btn_draw_cb_t)(lv_obj_t * btnm, uint32_t btn_id, const lv_area_t * draw_area, + const lv_area_t * clip_area); /*Data of button matrix*/ typedef struct { @@ -56,12 +58,21 @@ typedef struct { lv_area_t * button_areas; /*Array of areas of buttons*/ lv_btnmatrix_ctrl_t * ctrl_bits; /*Array of control bytes*/ uint16_t btn_cnt; /*Number of button in 'map_p'(Handled by the library)*/ + uint16_t row_cnt; /*Number of rows in 'map_p'(Handled by the library)*/ uint16_t btn_id_sel; /*Index of the active button (being pressed/released etc) or LV_BTNMATRIX_BTN_NONE*/ uint8_t one_check : 1; /*Single button toggled at once*/ } lv_btnmatrix_t; extern const lv_obj_class_t lv_btnmatrix_class; +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_btnmatrix_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_BTNMATRIX_DRAW_PART_BTN, /**< The rectangle and label of buttons*/ +} lv_btnmatrix_draw_part_type_t; + /********************** * GLOBAL PROTOTYPES **********************/ @@ -121,7 +132,7 @@ void lv_btnmatrix_set_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctr * @param btn_id 0 based index of the button to modify. (Not counting new lines) * @param ctrl OR-ed attributs. E.g. `LV_BTNMATRIX_CTRL_NO_REPEAT | LV_BTNMATRIX_CTRL_CHECKABLE` */ -void lv_btnmatrix_clear_btn_ctrl(const lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl); +void lv_btnmatrix_clear_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl); /** * Set attributes of all buttons of a button matrix @@ -151,10 +162,10 @@ void lv_btnmatrix_set_btn_width(lv_obj_t * obj, uint16_t btn_id, uint8_t width); /** * Make the button matrix like a selector widget (only one button may be checked at a time). - * `LV_BTNMATRIX_CTRL_CHECKABLE` must be enabled on the buttons to be selected useing + * `LV_BTNMATRIX_CTRL_CHECKABLE` must be enabled on the buttons to be selected using * `lv_btnmatrix_set_ctrl()` or `lv_btnmatrix_set_btn_ctrl_all()`. * @param obj pointer to a button matrix object - * @param en: whether "one check" mode is enabled + * @param en whether "one check" mode is enabled */ void lv_btnmatrix_set_one_checked(lv_obj_t * obj, bool en); @@ -201,7 +212,6 @@ bool lv_btnmatrix_has_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctr */ bool lv_btnmatrix_get_one_checked(const lv_obj_t * obj); - /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_canvas.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.c similarity index 84% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_canvas.c rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.c index 5101276fa..d5efc402d 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_canvas.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.c @@ -27,31 +27,14 @@ * STATIC PROTOTYPES **********************/ static void lv_canvas_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void set_set_px_cb(lv_disp_drv_t * disp_drv, lv_img_cf_t cf); - -static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, - lv_coord_t y, - lv_color_t color, lv_opa_t opa); - -static void set_px_cb_alpha1(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa); - -static void set_px_cb_alpha2(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa); - -static void set_px_cb_alpha4(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa); - -static void set_px_cb_alpha8(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa); - -static void set_px_alpha_generic(lv_img_dsc_t * d, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa); +static void lv_canvas_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); /********************** * STATIC VARIABLES **********************/ const lv_obj_class_t lv_canvas_class = { .constructor_cb = lv_canvas_constructor, + .destructor_cb = lv_canvas_destructor, .instance_size = sizeof(lv_canvas_t), .base_class = &lv_img_class }; @@ -66,7 +49,7 @@ const lv_obj_class_t lv_canvas_class = { lv_obj_t * lv_canvas_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -91,7 +74,7 @@ void lv_canvas_set_buffer(lv_obj_t * obj, void * buf, lv_coord_t w, lv_coord_t h lv_img_set_src(obj, &canvas->dsc); } -void lv_canvas_set_px(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_color_t c) +void lv_canvas_set_px_color(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_color_t c) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -101,6 +84,16 @@ void lv_canvas_set_px(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_color_t c) lv_obj_invalidate(obj); } +void lv_canvas_set_px_opa(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_opa_t opa) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_canvas_t * canvas = (lv_canvas_t *)obj; + + lv_img_buf_set_px_alpha(&canvas->dsc, x, y, opa); + lv_obj_invalidate(obj); +} + void lv_canvas_set_palette(lv_obj_t * obj, uint8_t id, lv_color_t c) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -595,7 +588,7 @@ void lv_canvas_draw_rect(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord disp.driver->hor_res = dsc->header.w; disp.driver->ver_res = dsc->header.h; - set_set_px_cb(disp.driver, dsc->header.cf); + lv_disp_drv_use_generic_set_px_cb(disp.driver, dsc->header.cf); /*Disable anti-aliasing if drawing with transparent color to chroma keyed canvas*/ lv_color_t ctransp = LV_COLOR_CHROMA_KEY; @@ -656,7 +649,7 @@ void lv_canvas_draw_text(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord disp.driver->hor_res = dsc->header.w; disp.driver->ver_res = dsc->header.h; - set_set_px_cb(disp.driver, dsc->header.cf); + lv_disp_drv_use_generic_set_px_cb(disp.driver, dsc->header.cf); lv_disp_t * refr_ori = _lv_refr_get_disp_refreshing(); _lv_refr_set_disp_refreshing(&disp); @@ -717,7 +710,7 @@ void lv_canvas_draw_img(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, const voi disp.driver->hor_res = dsc->header.w; disp.driver->ver_res = dsc->header.h; - set_set_px_cb(disp.driver, dsc->header.cf); + lv_disp_drv_use_generic_set_px_cb(disp.driver, dsc->header.cf); lv_disp_t * refr_ori = _lv_refr_get_disp_refreshing(); _lv_refr_set_disp_refreshing(&disp); @@ -764,7 +757,7 @@ void lv_canvas_draw_line(lv_obj_t * canvas, const lv_point_t points[], uint32_t disp.driver->hor_res = dsc->header.w; disp.driver->ver_res = dsc->header.h; - set_set_px_cb(disp.driver, dsc->header.cf); + lv_disp_drv_use_generic_set_px_cb(disp.driver, dsc->header.cf); /*Disable anti-aliasing if drawing with transparent color to chroma keyed canvas*/ lv_color_t ctransp = LV_COLOR_CHROMA_KEY; @@ -822,7 +815,7 @@ void lv_canvas_draw_polygon(lv_obj_t * canvas, const lv_point_t points[], uint32 disp.driver->hor_res = dsc->header.w; disp.driver->ver_res = dsc->header.h; - set_set_px_cb(disp.driver, dsc->header.cf); + lv_disp_drv_use_generic_set_px_cb(disp.driver, dsc->header.cf); /*Disable anti-aliasing if drawing with transparent color to chroma keyed canvas*/ lv_color_t ctransp = LV_COLOR_CHROMA_KEY; @@ -878,7 +871,7 @@ void lv_canvas_draw_arc(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_ disp.driver->hor_res = dsc->header.w; disp.driver->ver_res = dsc->header.h; - set_set_px_cb(disp.driver, dsc->header.cf); + lv_disp_drv_use_generic_set_px_cb(disp.driver, dsc->header.cf); /*Disable anti-aliasing if drawing with transparent color to chroma keyed canvas*/ lv_color_t ctransp = LV_COLOR_CHROMA_KEY; @@ -930,123 +923,13 @@ static void lv_canvas_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj LV_TRACE_OBJ_CREATE("finished"); } -static void set_set_px_cb(lv_disp_drv_t * disp_drv, lv_img_cf_t cf) +static void lv_canvas_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { - switch(cf) { - case LV_IMG_CF_TRUE_COLOR_ALPHA: - disp_drv->set_px_cb = set_px_true_color_alpha; - break; - case LV_IMG_CF_ALPHA_1BIT: - disp_drv->set_px_cb = set_px_cb_alpha1; - break; - case LV_IMG_CF_ALPHA_2BIT: - disp_drv->set_px_cb = set_px_cb_alpha2; - break; - case LV_IMG_CF_ALPHA_4BIT: - disp_drv->set_px_cb = set_px_cb_alpha4; - break; - case LV_IMG_CF_ALPHA_8BIT: - disp_drv->set_px_cb = set_px_cb_alpha8; - break; - default: - disp_drv->set_px_cb = NULL; - } -} + LV_UNUSED(class_p); + LV_TRACE_OBJ_CREATE("begin"); -static void set_px_cb_alpha1(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa) -{ - (void) disp_drv; /*Unused*/ - - if(opa <= LV_OPA_MIN) return; - lv_img_dsc_t d; - d.data = buf; - d.header.w = buf_w; - d.header.cf = LV_IMG_CF_ALPHA_1BIT; - - set_px_alpha_generic(&d, x, y, color, opa); -} - -static void set_px_cb_alpha2(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa) -{ - (void) disp_drv; /*Unused*/ - - if(opa <= LV_OPA_MIN) return; - lv_img_dsc_t d; - d.data = buf; - d.header.w = buf_w; - d.header.cf = LV_IMG_CF_ALPHA_2BIT; - - set_px_alpha_generic(&d, x, y, color, opa); -} - -static void set_px_cb_alpha4(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa) -{ - (void) disp_drv; /*Unused*/ - - if(opa <= LV_OPA_MIN) return; - lv_img_dsc_t d; - d.data = buf; - d.header.w = buf_w; - d.header.cf = LV_IMG_CF_ALPHA_4BIT; - - set_px_alpha_generic(&d, x, y, color, opa); -} - -static void set_px_cb_alpha8(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa) -{ - (void) disp_drv; /*Unused*/ - - if(opa <= LV_OPA_MIN) return; - lv_img_dsc_t d; - d.data = buf; - d.header.w = buf_w; - d.header.cf = LV_IMG_CF_ALPHA_8BIT; - - set_px_alpha_generic(&d, x, y, color, opa); -} - -static void set_px_alpha_generic(lv_img_dsc_t * d, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa) -{ - d->header.always_zero = 0; - d->header.h = 1; /*Doesn't matter*/ - - uint8_t br = lv_color_brightness(color); - if(opa < LV_OPA_MAX) { - uint8_t bg = lv_img_buf_get_px_alpha(d, x, y); - br = (uint16_t)((uint16_t)br * opa + (bg * (255 - opa))) >> 8; - } - - lv_img_buf_set_px_alpha(d, x, y, br); -} - -static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, - lv_coord_t y, - lv_color_t color, lv_opa_t opa) -{ - (void) disp_drv; /*Unused*/ - - if(opa <= LV_OPA_MIN) return; - lv_img_dsc_t d; - d.data = buf; - d.header.always_zero = 0; - d.header.h = 1; /*Doesn't matter*/; - d.header.w = buf_w; - d.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA; - - lv_color_t bg_color = lv_img_buf_get_px_color(&d, x, y, lv_color_black()); - lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&d, x, y); - - lv_opa_t res_opa; - lv_color_t res_color; - - lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &res_opa); - - lv_img_buf_set_px_alpha(&d, x, y, res_opa); - lv_img_buf_set_px_color(&d, x, y, res_color); + lv_canvas_t * canvas = (lv_canvas_t *)obj; + lv_img_cache_invalidate_src(&canvas->dsc); } #endif diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_canvas.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.h similarity index 93% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_canvas.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.h index bc0eadd1d..71f051614 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_canvas.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.h @@ -70,9 +70,27 @@ void lv_canvas_set_buffer(lv_obj_t * canvas, void * buf, lv_coord_t w, lv_coord_ * @param canvas * @param x x coordinate of the point to set * @param y x coordinate of the point to set - * @param c color of the point + * @param c color of the pixel */ -void lv_canvas_set_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c); +void lv_canvas_set_px_color(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c); + +/** + * DEPRECATED: added only for backward compatibility + */ +static inline void lv_canvas_set_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c) +{ + lv_canvas_set_px_color(canvas, x, y, c); +} + +/** + * Set the opacity of a pixel on the canvas + * @param canvas + * @param x x coordinate of the point to set + * @param y x coordinate of the point to set + * @param opa opacity of the pixel (0..255) + */ +void lv_canvas_set_px_opa(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_opa_t opa); + /** * Set the palette color of a canvas with index format. Valid only for `LV_IMG_CF_INDEXED1/2/4/8` diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_checkbox.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_checkbox.c similarity index 89% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_checkbox.c rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_checkbox.c index 651d14114..2128f2d13 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_checkbox.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_checkbox.c @@ -55,7 +55,7 @@ const lv_obj_class_t lv_checkbox_class = { lv_obj_t * lv_checkbox_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -85,6 +85,7 @@ void lv_checkbox_set_text(lv_obj_t * obj, const char * txt) cb->static_txt = 0; lv_obj_refresh_self_size(obj); + lv_obj_invalidate(obj); } void lv_checkbox_set_text_static(lv_obj_t * obj, const char * txt) @@ -93,10 +94,11 @@ void lv_checkbox_set_text_static(lv_obj_t * obj, const char * txt) if(!cb->static_txt) lv_mem_free(cb->txt); - cb->txt = (char*)txt; + cb->txt = (char *)txt; cb->static_txt = 1; lv_obj_refresh_self_size(obj); + lv_obj_invalidate(obj); } /*===================== @@ -154,10 +156,10 @@ static void lv_checkbox_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_event_code_t code = lv_event_get_code(e); lv_obj_t * obj = lv_event_get_target(e); - if (code == LV_EVENT_PRESSED || code == LV_EVENT_RELEASED) { - lv_obj_invalidate(obj); + if(code == LV_EVENT_PRESSED || code == LV_EVENT_RELEASED) { + lv_obj_invalidate(obj); } - else if (code == LV_EVENT_GET_SELF_SIZE) { + else if(code == LV_EVENT_GET_SELF_SIZE) { lv_point_t * p = lv_event_get_param(e); lv_checkbox_t * cb = (lv_checkbox_t *)obj; @@ -182,7 +184,7 @@ static void lv_checkbox_event(const lv_obj_class_t * class_p, lv_event_t * e) p->y = LV_MAX(marker_size.y, txt_size.y); } else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - lv_coord_t *s = lv_event_get_param(e); + lv_coord_t * s = lv_event_get_param(e); lv_coord_t m = lv_obj_calculate_ext_draw_size(obj, LV_PART_INDICATOR); *s = LV_MAX(*s, m); } @@ -192,7 +194,8 @@ static void lv_checkbox_event(const lv_obj_class_t * class_p, lv_event_t * e) if(res != LV_RES_OK) return; lv_obj_invalidate(obj); - } else if(code == LV_EVENT_DRAW_MAIN) { + } + else if(code == LV_EVENT_DRAW_MAIN) { lv_checkbox_draw(e); } } @@ -206,8 +209,9 @@ static void lv_checkbox_draw(lv_event_t * e) const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); lv_coord_t font_h = lv_font_get_line_height(font); - lv_coord_t bg_topp = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t bg_leftp = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + lv_coord_t bg_border = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + lv_coord_t bg_topp = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + bg_border; + lv_coord_t bg_leftp = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + bg_border; lv_coord_t bg_colp = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); lv_coord_t marker_leftp = lv_obj_get_style_pad_left(obj, LV_PART_INDICATOR); @@ -234,15 +238,17 @@ static void lv_checkbox_draw(lv_event_t * e) marker_area_transf.y1 -= transf_h; marker_area_transf.y2 += transf_h; - lv_obj_draw_part_dsc_t obj_draw_dsc; - lv_obj_draw_dsc_init(&obj_draw_dsc, clip_area); - obj_draw_dsc.rect_dsc = &indic_dsc; - obj_draw_dsc.draw_area = &marker_area_transf; - obj_draw_dsc.part = LV_PART_INDICATOR; + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + part_draw_dsc.rect_dsc = &indic_dsc; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_CHECKBOX_DRAW_PART_BOX; + part_draw_dsc.draw_area = &marker_area_transf; + part_draw_dsc.part = LV_PART_INDICATOR; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &obj_draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_rect(&marker_area_transf, clip_area, &indic_dsc); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &obj_draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_checkbox.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_checkbox.h similarity index 84% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_checkbox.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_checkbox.h index a1027a021..772f500d5 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_checkbox.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_checkbox.h @@ -29,11 +29,19 @@ extern "C" { typedef struct { lv_obj_t obj; char * txt; - uint32_t static_txt :1; -}lv_checkbox_t; + uint32_t static_txt : 1; +} lv_checkbox_t; extern const lv_obj_class_t lv_checkbox_class; +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_checkbox_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_CHECKBOX_DRAW_PART_BOX, /**< The tick box*/ +} lv_checkbox_draw_part_type_t; + /********************** * GLOBAL PROTOTYPES **********************/ @@ -61,7 +69,7 @@ void lv_checkbox_set_text(lv_obj_t * obj, const char * txt); * Set the text of a check box. `txt` must not be deallocated during the life * of this checkbox. * @param cb pointer to a check box - * @param txt the text of the check box. NULL to refresh with the current text. + * @param txt the text of the check box. */ void lv_checkbox_set_text_static(lv_obj_t * obj, const char * txt); diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_dropdown.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.c similarity index 90% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_dropdown.c rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.c index b5b9aa234..627bcf63e 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_dropdown.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.c @@ -49,8 +49,9 @@ static void draw_list(lv_event_t * e); static void draw_box(lv_obj_t * dropdown_obj, const lv_area_t * clip_area, uint16_t id, lv_state_t state); static void draw_box_label(lv_obj_t * dropdown_obj, const lv_area_t * clip_area, uint16_t id, lv_state_t state); +static lv_res_t btn_release_handler(lv_obj_t * obj); static lv_res_t list_release_handler(lv_obj_t * list_obj); -static void page_press_handler(lv_obj_t * page); +static void list_press_handler(lv_obj_t * page); static uint16_t get_id_on_point(lv_obj_t * dropdown_obj, lv_coord_t y); static void position_to_selected(lv_obj_t * obj); static lv_obj_t * get_label(const lv_obj_t * obj); @@ -89,7 +90,7 @@ const lv_obj_class_t lv_dropdownlist_class = { lv_obj_t * lv_dropdown_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(&lv_dropdown_class, parent); lv_obj_class_init_obj(obj); return obj; @@ -152,6 +153,9 @@ void lv_dropdown_set_options(lv_obj_t * obj, const char * options) /*Now the text is dynamically allocated*/ dropdown->static_txt = 0; + + lv_obj_invalidate(obj); + if(dropdown->list) lv_obj_invalidate(dropdown->list); } void lv_dropdown_set_options_static(lv_obj_t * obj, const char * options) @@ -178,6 +182,9 @@ void lv_dropdown_set_options_static(lv_obj_t * obj, const char * options) dropdown->static_txt = 1; dropdown->options = (char *)options; + + lv_obj_invalidate(obj); + if(dropdown->list) lv_obj_invalidate(dropdown->list); } void lv_dropdown_add_option(lv_obj_t * obj, const char * option, uint32_t pos) @@ -248,6 +255,7 @@ void lv_dropdown_add_option(lv_obj_t * obj, const char * option, uint32_t pos) dropdown->option_cnt++; lv_obj_invalidate(obj); + if(dropdown->list) lv_obj_invalidate(dropdown->list); } void lv_dropdown_clear_options(lv_obj_t * obj) @@ -264,6 +272,7 @@ void lv_dropdown_clear_options(lv_obj_t * obj) dropdown->option_cnt = 0; lv_obj_invalidate(obj); + if(dropdown->list) lv_obj_invalidate(dropdown->list); } void lv_dropdown_set_selected(lv_obj_t * obj, uint16_t sel_opt) @@ -335,7 +344,7 @@ const char * lv_dropdown_get_options(const lv_obj_t * obj) LV_ASSERT_OBJ(obj, MY_CLASS); lv_dropdown_t * dropdown = (lv_dropdown_t *)obj; - return dropdown->options; + return dropdown->options == NULL ? "" : dropdown->options; } uint16_t lv_dropdown_get_selected(const lv_obj_t * obj) @@ -373,7 +382,7 @@ void lv_dropdown_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf uint32_t c; for(c = 0; i < txt_len && dropdown->options[i] != '\n'; c++, i++) { if(buf_size && c >= buf_size - 1) { - LV_LOG_WARN("lv_dropdown_get_selected_str: the buffer was too small") + LV_LOG_WARN("lv_dropdown_get_selected_str: the buffer was too small"); break; } buf[c] = dropdown->options[i]; @@ -415,13 +424,16 @@ void lv_dropdown_open(lv_obj_t * dropdown_obj) if(dropdown->list == NULL) { lv_obj_t * list_obj = lv_dropdown_list_create(lv_obj_get_screen(dropdown_obj)); - ((lv_dropdown_list_t*) list_obj)->dropdown = dropdown_obj; + ((lv_dropdown_list_t *) list_obj)->dropdown = dropdown_obj; dropdown->list = list_obj; lv_obj_clear_flag(dropdown->list, LV_OBJ_FLAG_CLICK_FOCUSABLE); lv_obj_add_flag(dropdown->list, LV_OBJ_FLAG_IGNORE_LAYOUT); lv_obj_update_layout(dropdown->list); } + /*To allow styling the list*/ + lv_event_send(dropdown_obj, LV_EVENT_READY, NULL); + lv_obj_t * label = get_label(dropdown_obj); lv_label_set_text_static(label, dropdown->options); lv_obj_set_width(dropdown->list, LV_SIZE_CONTENT); @@ -489,23 +501,19 @@ void lv_dropdown_open(lv_obj_t * dropdown_obj) } } - lv_text_align_t align = lv_obj_get_style_text_align(label, LV_PART_MAIN); - if(align == LV_TEXT_ALIGN_AUTO) { - if(lv_obj_get_style_base_dir(label, LV_PART_MAIN) == LV_BASE_DIR_RTL) align = LV_TEXT_ALIGN_RIGHT; - else align = LV_TEXT_ALIGN_LEFT; - } + lv_text_align_t align = lv_obj_calculate_style_text_align(label, LV_PART_MAIN, dropdown->options); switch(align) { - default: - case LV_TEXT_ALIGN_LEFT: - lv_obj_set_x(label, 0); - break; - case LV_TEXT_ALIGN_RIGHT: - lv_obj_set_x(label, lv_obj_get_content_width(dropdown->list) - lv_obj_get_width(label)); - break; - case LV_TEXT_ALIGN_CENTER: - lv_obj_set_x(label, lv_obj_get_content_width(dropdown->list) / 2 - lv_obj_get_width(label) / 2); - break; + default: + case LV_TEXT_ALIGN_LEFT: + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 0, 0); + break; + case LV_TEXT_ALIGN_RIGHT: + lv_obj_align(label, LV_ALIGN_TOP_RIGHT, 0, 0); + break; + case LV_TEXT_ALIGN_CENTER: + lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); + break; } } @@ -517,6 +525,8 @@ void lv_dropdown_close(lv_obj_t * obj) dropdown->pr_opt_id = LV_DROPDOWN_PR_NONE; if(dropdown->list) lv_obj_del(dropdown->list); + + lv_event_send(obj, LV_EVENT_CANCEL, NULL); } /********************** @@ -525,7 +535,7 @@ void lv_dropdown_close(lv_obj_t * obj) static lv_obj_t * lv_dropdown_list_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(&lv_dropdownlist_class, parent); lv_obj_class_init_obj(obj); return obj; @@ -615,40 +625,22 @@ static void lv_dropdown_event(const lv_obj_class_t * class_p, lv_event_t * e) /*Encoders need special handling*/ if(indev_type == LV_INDEV_TYPE_ENCODER) { /*Open the list if editing*/ - if(editing) lv_dropdown_open(obj); + if(editing) { + lv_dropdown_open(obj); + } /*Close the list if navigating*/ - else + else { + dropdown->sel_opt_id = dropdown->sel_opt_id_orig; lv_dropdown_close(obj); + } } } else if(code == LV_EVENT_DEFOCUSED || code == LV_EVENT_LEAVE) { lv_dropdown_close(obj); } else if(code == LV_EVENT_RELEASED) { - lv_indev_t * indev = lv_indev_get_act(); - if(lv_indev_get_scroll_obj(indev) == NULL) { - if(dropdown->list) { - lv_dropdown_close(obj); - if(dropdown->sel_opt_id_orig != dropdown->sel_opt_id) { - dropdown->sel_opt_id_orig = dropdown->sel_opt_id; - uint32_t id = dropdown->sel_opt_id; /*Just to use uint32_t in event data*/ - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &id); - if(res != LV_RES_OK) return; - lv_obj_invalidate(obj); - } - lv_indev_type_t indev_type = lv_indev_get_type(indev); - if(indev_type == LV_INDEV_TYPE_ENCODER) { - lv_group_set_editing(lv_obj_get_group(obj), false); - } - } - else { - lv_dropdown_open(obj); - } - } - else { - dropdown->sel_opt_id = dropdown->sel_opt_id_orig; - lv_obj_invalidate(obj); - } + res = btn_release_handler(obj); + if(res != LV_RES_OK) return; } else if(code == LV_EVENT_STYLE_CHANGED) { lv_obj_refresh_self_size(obj); @@ -686,6 +678,15 @@ static void lv_dropdown_event(const lv_obj_class_t * class_p, lv_event_t * e) dropdown->sel_opt_id = dropdown->sel_opt_id_orig; lv_dropdown_close(obj); } + else if(c == LV_KEY_ENTER) { + /* Handle the ENTER key only if it was send by an other object. + * Do no process it if ENTER is sent by the dropdown becasue it's handled in LV_EVENT_RELEASED */ + lv_obj_t * indev_obj = lv_indev_get_obj_act(); + if(indev_obj != obj) { + res = btn_release_handler(obj); + if(res != LV_RES_OK) return; + } + } } else if(code == LV_EVENT_DRAW_MAIN) { draw_main(e); @@ -714,7 +715,7 @@ static void lv_dropdown_list_event(const lv_obj_class_t * class_p, lv_event_t * } } else if(code == LV_EVENT_PRESSED) { - page_press_handler(list); + list_press_handler(list); } else if(code == LV_EVENT_SCROLL_BEGIN) { dropdown->pr_opt_id = LV_DROPDOWN_PR_NONE; @@ -762,16 +763,19 @@ static void draw_main(lv_event_t * e) lv_coord_t symbol_h; if(symbol_type == LV_IMG_SRC_SYMBOL) { lv_point_t size; - lv_txt_get_size(&size, dropdown->symbol, symbol_dsc.font, symbol_dsc.letter_space, symbol_dsc.line_space, LV_COORD_MAX, symbol_dsc.flag); + lv_txt_get_size(&size, dropdown->symbol, symbol_dsc.font, symbol_dsc.letter_space, symbol_dsc.line_space, LV_COORD_MAX, + symbol_dsc.flag); symbol_w = size.x; symbol_h = size.y; - } else { + } + else { lv_img_header_t header; lv_res_t res = lv_img_decoder_get_info(dropdown->symbol, &header); if(res == LV_RES_OK) { symbol_w = header.w; symbol_h = header.h; - } else { + } + else { symbol_w = -1; symbol_h = -1; } @@ -781,7 +785,8 @@ static void draw_main(lv_event_t * e) if(symbol_to_left) { symbol_area.x1 = obj->coords.x1 + left; symbol_area.x2 = symbol_area.x1 + symbol_w - 1; - } else { + } + else { symbol_area.x1 = obj->coords.x2 - right - symbol_w; symbol_area.x2 = symbol_area.x1 + symbol_w - 1; } @@ -790,7 +795,8 @@ static void draw_main(lv_event_t * e) symbol_area.y1 = obj->coords.y1 + top; symbol_area.y2 = symbol_area.y1 + symbol_h - 1; lv_draw_label(&symbol_area, clip_area, &symbol_dsc, dropdown->symbol, NULL); - } else { + } + else { symbol_area.y1 = obj->coords.y1 + (lv_obj_get_height(obj) - symbol_h) / 2; symbol_area.y2 = symbol_area.y1 + symbol_h - 1; lv_draw_img_dsc_t img_dsc; @@ -808,7 +814,8 @@ static void draw_main(lv_event_t * e) lv_obj_init_draw_label_dsc(obj, LV_PART_MAIN, &label_dsc); lv_point_t size; - lv_txt_get_size(&size, opt_txt, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, LV_COORD_MAX, label_dsc.flag); + lv_txt_get_size(&size, opt_txt, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, LV_COORD_MAX, + label_dsc.flag); lv_area_t txt_area; txt_area.y1 = obj->coords.y1 + top; @@ -823,7 +830,8 @@ static void draw_main(lv_event_t * e) if(symbol_to_left) { txt_area.x1 = obj->coords.x2 - right - size.x; txt_area.x2 = txt_area.x1 + size.x; - } else { + } + else { txt_area.x1 = obj->coords.x1 + left; txt_area.x2 = txt_area.x1 + size.x; } @@ -855,13 +863,15 @@ static void draw_list(lv_event_t * e) if(dropdown->pr_opt_id == dropdown->sel_opt_id) { draw_box(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_CHECKED | LV_STATE_PRESSED); draw_box_label(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_CHECKED | LV_STATE_PRESSED); - } else { + } + else { draw_box(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_PRESSED); draw_box_label(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_PRESSED); draw_box(dropdown_obj, &clip_area_core, dropdown->sel_opt_id, LV_STATE_CHECKED); draw_box_label(dropdown_obj, &clip_area_core, dropdown->sel_opt_id, LV_STATE_CHECKED); } - } else { + } + else { draw_box(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_PRESSED); draw_box_label(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_PRESSED); } @@ -924,7 +934,8 @@ static void draw_box_label(lv_obj_t * dropdown_obj, const lv_area_t * clip_area, lv_draw_label_dsc_init(&label_dsc); lv_obj_init_draw_label_dsc(list_obj, LV_PART_SELECTED, &label_dsc); - label_dsc.line_space = lv_obj_get_style_text_line_space(list_obj, LV_PART_SELECTED); /*Line space should come from the list*/ + label_dsc.line_space = lv_obj_get_style_text_line_space(list_obj, + LV_PART_SELECTED); /*Line space should come from the list*/ lv_obj_t * label = get_label(dropdown_obj); if(label == NULL) return; @@ -949,6 +960,38 @@ static void draw_box_label(lv_obj_t * dropdown_obj, const lv_area_t * clip_area, list_obj->skip_trans = 0; } + +static lv_res_t btn_release_handler(lv_obj_t * obj) +{ + lv_dropdown_t * dropdown = (lv_dropdown_t *)obj; + lv_indev_t * indev = lv_indev_get_act(); + if(lv_indev_get_scroll_obj(indev) == NULL) { + if(dropdown->list) { + lv_dropdown_close(obj); + if(dropdown->sel_opt_id_orig != dropdown->sel_opt_id) { + dropdown->sel_opt_id_orig = dropdown->sel_opt_id; + lv_res_t res; + uint32_t id = dropdown->sel_opt_id; /*Just to use uint32_t in event data*/ + res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &id); + if(res != LV_RES_OK) return res; + lv_obj_invalidate(obj); + } + lv_indev_type_t indev_type = lv_indev_get_type(indev); + if(indev_type == LV_INDEV_TYPE_ENCODER) { + lv_group_set_editing(lv_obj_get_group(obj), false); + } + } + else { + lv_dropdown_open(obj); + } + } + else { + dropdown->sel_opt_id = dropdown->sel_opt_id_orig; + lv_obj_invalidate(obj); + } + return LV_RES_OK; +} + /** * Called when a drop down list is released to open it or set new option * @param list pointer to the drop down list's list @@ -956,7 +999,7 @@ static void draw_box_label(lv_obj_t * dropdown_obj, const lv_area_t * clip_area, */ static lv_res_t list_release_handler(lv_obj_t * list_obj) { - lv_dropdown_list_t * list = (lv_dropdown_list_t*) list_obj; + lv_dropdown_list_t * list = (lv_dropdown_list_t *) list_obj; lv_obj_t * dropdown_obj = list->dropdown; lv_dropdown_t * dropdown = (lv_dropdown_t *)dropdown_obj; @@ -990,9 +1033,9 @@ static lv_res_t list_release_handler(lv_obj_t * list_obj) return LV_RES_OK; } -static void page_press_handler(lv_obj_t * list_obj) +static void list_press_handler(lv_obj_t * list_obj) { - lv_dropdown_list_t * list = (lv_dropdown_list_t*) list_obj; + lv_dropdown_list_t * list = (lv_dropdown_list_t *) list_obj; lv_obj_t * dropdown_obj = list->dropdown; lv_dropdown_t * dropdown = (lv_dropdown_t *)dropdown_obj; diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_dropdown.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.h similarity index 95% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_dropdown.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.h index 9cf81a047..402a37ce5 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_dropdown.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.h @@ -45,15 +45,15 @@ typedef struct { uint16_t sel_opt_id; /**< Index of the currently selected option*/ uint16_t sel_opt_id_orig; /**< Store the original index on focus*/ uint16_t pr_opt_id; /**< Index of the currently pressed option*/ - lv_dir_t dir :4; /**< Direction in which the list should open*/ - uint8_t static_txt :1; /**< 1: Only a pointer is saved in `options`*/ - uint8_t selected_highlight:1; /**< 1: Make the selected option highlighted in the list*/ -}lv_dropdown_t; + lv_dir_t dir : 4; /**< Direction in which the list should open*/ + uint8_t static_txt : 1; /**< 1: Only a pointer is saved in `options`*/ + uint8_t selected_highlight: 1; /**< 1: Make the selected option highlighted in the list*/ +} lv_dropdown_t; typedef struct { - lv_obj_t obj; - lv_obj_t * dropdown; -}lv_dropdown_list_t; + lv_obj_t obj; + lv_obj_t * dropdown; +} lv_dropdown_list_t; extern const lv_obj_class_t lv_dropdown_class; extern const lv_obj_class_t lv_dropdownlist_class; @@ -78,7 +78,7 @@ lv_obj_t * lv_dropdown_create(lv_obj_t * parent); * If set to `NULL` the selected option's text will be displayed on the button. * If set to a specific text then that text will be shown regardless the selected option. * @param obj pointer to a drop-down list object - * @param txt the text as a string (Only it's pointer is saved) + * @param txt the text as a string (Only its pointer is saved) */ void lv_dropdown_set_text(lv_obj_t * obj, const char * txt); diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_img.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.c similarity index 81% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_img.c rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_img.c index 950a58769..126e8805b 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_img.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.c @@ -37,14 +37,14 @@ static void draw_img(lv_event_t * e); * STATIC VARIABLES **********************/ const lv_obj_class_t lv_img_class = { - .constructor_cb = lv_img_constructor, - .destructor_cb = lv_img_destructor, - .event_cb = lv_img_event, - .width_def = LV_SIZE_CONTENT, - .height_def = LV_SIZE_CONTENT, - .instance_size = sizeof(lv_img_t), - .base_class = &lv_obj_class - }; + .constructor_cb = lv_img_constructor, + .destructor_cb = lv_img_destructor, + .event_cb = lv_img_event, + .width_def = LV_SIZE_CONTENT, + .height_def = LV_SIZE_CONTENT, + .instance_size = sizeof(lv_img_t), + .base_class = &lv_obj_class +}; /********************** * MACROS @@ -56,7 +56,7 @@ const lv_obj_class_t lv_img_class = { lv_obj_t * lv_img_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -95,7 +95,7 @@ void lv_img_set_src(lv_obj_t * obj, const void * src) if(src_type == LV_IMG_SRC_UNKNOWN) { LV_LOG_WARN("lv_img_set_src: unknown image type"); if(img->src_type == LV_IMG_SRC_SYMBOL || img->src_type == LV_IMG_SRC_FILE) { - lv_mem_free((void*)img->src); + lv_mem_free((void *)img->src); } img->src = NULL; img->src_type = LV_IMG_SRC_UNKNOWN; @@ -109,7 +109,7 @@ void lv_img_set_src(lv_obj_t * obj, const void * src) if(src_type == LV_IMG_SRC_VARIABLE) { /*If memory was allocated because of the previous `src_type` then free it*/ if(img->src_type == LV_IMG_SRC_FILE || img->src_type == LV_IMG_SRC_SYMBOL) { - lv_mem_free((void*)img->src); + lv_mem_free((void *)img->src); } img->src = src; } @@ -129,7 +129,7 @@ void lv_img_set_src(lv_obj_t * obj, const void * src) strcpy(new_str, src); img->src = new_str; - if(old_src) lv_mem_free((void*)old_src); + if(old_src) lv_mem_free((void *)old_src); } } @@ -163,7 +163,7 @@ void lv_img_set_offset_x(lv_obj_t * obj, lv_coord_t x) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_img_t * img = (lv_img_t *)obj; + lv_img_t * img = (lv_img_t *)obj; x = x % img->w; @@ -175,7 +175,7 @@ void lv_img_set_offset_y(lv_obj_t * obj, lv_coord_t y) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_img_t * img = (lv_img_t *)obj; + lv_img_t * img = (lv_img_t *)obj; y = y % img->h; @@ -187,11 +187,11 @@ void lv_img_set_angle(lv_obj_t * obj, int16_t angle) { if(angle < 0 || angle >= 3600) angle = angle % 3600; - lv_img_t * img = (lv_img_t *)obj; + lv_img_t * img = (lv_img_t *)obj; if(angle == img->angle) return; lv_coord_t transf_zoom = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN); - transf_zoom = (transf_zoom * img->zoom) >> 8; + transf_zoom = ((int32_t)transf_zoom * img->zoom) >> 8; lv_coord_t transf_angle = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN); @@ -222,7 +222,7 @@ void lv_img_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) if(img->pivot.x == x && img->pivot.y == y) return; lv_coord_t transf_zoom = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN); - transf_zoom = (transf_zoom * img->zoom) >> 8; + transf_zoom = ((int32_t)transf_zoom * img->zoom) >> 8; lv_coord_t transf_angle = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN); transf_angle += img->angle; @@ -251,7 +251,7 @@ void lv_img_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) void lv_img_set_zoom(lv_obj_t * obj, uint16_t zoom) { - lv_img_t * img = (lv_img_t *)obj; + lv_img_t * img = (lv_img_t *)obj; if(zoom == img->zoom) return; if(zoom == 0) zoom = 1; @@ -264,7 +264,7 @@ void lv_img_set_zoom(lv_obj_t * obj, uint16_t zoom) lv_coord_t w = lv_obj_get_width(obj); lv_coord_t h = lv_obj_get_height(obj); lv_area_t a; - _lv_img_buf_get_transformed_area(&a, w, h, transf_angle, (transf_zoom * img->zoom) >> 8, &img->pivot); + _lv_img_buf_get_transformed_area(&a, w, h, transf_angle, ((int32_t)transf_zoom * img->zoom) >> 8, &img->pivot); a.x1 += obj->coords.x1 - 1; a.y1 += obj->coords.y1 - 1; a.x2 += obj->coords.x1 + 1; @@ -274,7 +274,7 @@ void lv_img_set_zoom(lv_obj_t * obj, uint16_t zoom) img->zoom = zoom; lv_obj_refresh_ext_draw_size(obj); - _lv_img_buf_get_transformed_area(&a, w, h, transf_angle, (transf_zoom * img->zoom) >> 8, &img->pivot); + _lv_img_buf_get_transformed_area(&a, w, h, transf_angle, ((int32_t)transf_zoom * img->zoom) >> 8, &img->pivot); a.x1 += obj->coords.x1 - 1; a.y1 += obj->coords.y1 - 1; a.x2 += obj->coords.x1 + 1; @@ -284,13 +284,23 @@ void lv_img_set_zoom(lv_obj_t * obj, uint16_t zoom) void lv_img_set_antialias(lv_obj_t * obj, bool antialias) { - lv_img_t * img = (lv_img_t *)obj; + lv_img_t * img = (lv_img_t *)obj; if(antialias == img->antialias) return; img->antialias = antialias; lv_obj_invalidate(obj); } +void lv_img_set_size_mode(lv_obj_t * obj, lv_img_size_mode_t mode) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_img_t * img = (lv_img_t *)obj; + if(mode == img->obj_size_mode) return; + + img->obj_size_mode = mode; + lv_obj_invalidate(obj); +} + /*===================== * Getter functions *====================*/ @@ -299,7 +309,7 @@ const void * lv_img_get_src(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_img_t * img = (lv_img_t *)obj; + lv_img_t * img = (lv_img_t *)obj; return img->src; } @@ -308,7 +318,7 @@ lv_coord_t lv_img_get_offset_x(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_img_t * img = (lv_img_t *)obj; + lv_img_t * img = (lv_img_t *)obj; return img->offset.x; } @@ -317,7 +327,7 @@ lv_coord_t lv_img_get_offset_y(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_img_t * img = (lv_img_t *)obj; + lv_img_t * img = (lv_img_t *)obj; return img->offset.y; } @@ -326,7 +336,7 @@ uint16_t lv_img_get_angle(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_img_t * img = (lv_img_t *)obj; + lv_img_t * img = (lv_img_t *)obj; return img->angle; } @@ -335,7 +345,7 @@ void lv_img_get_pivot(lv_obj_t * obj, lv_point_t * pivot) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_img_t * img = (lv_img_t *)obj; + lv_img_t * img = (lv_img_t *)obj; *pivot = img->pivot; } @@ -344,7 +354,7 @@ uint16_t lv_img_get_zoom(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_img_t * img = (lv_img_t *)obj; + lv_img_t * img = (lv_img_t *)obj; return img->zoom; } @@ -353,11 +363,18 @@ bool lv_img_get_antialias(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_img_t * img = (lv_img_t *)obj; + lv_img_t * img = (lv_img_t *)obj; return img->antialias ? true : false; } +lv_img_size_mode_t lv_img_get_size_mode(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_img_t * img = (lv_img_t *)obj; + return img->obj_size_mode; +} + /********************** * STATIC FUNCTIONS **********************/ @@ -381,6 +398,7 @@ static void lv_img_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) img->offset.y = 0; img->pivot.x = 0; img->pivot.y = 0; + img->obj_size_mode = LV_IMG_SIZE_MODE_VIRTUAL; lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICKABLE); lv_obj_add_flag(obj, LV_OBJ_FLAG_ADV_HITTEST); @@ -393,12 +411,30 @@ static void lv_img_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) LV_UNUSED(class_p); lv_img_t * img = (lv_img_t *)obj; if(img->src_type == LV_IMG_SRC_FILE || img->src_type == LV_IMG_SRC_SYMBOL) { - lv_mem_free((void*)img->src); + lv_mem_free((void *)img->src); img->src = NULL; img->src_type = LV_IMG_SRC_UNKNOWN; } } +static lv_point_t lv_img_get_transformed_size(lv_obj_t * obj) +{ + lv_img_t * img = (lv_img_t *)obj; + + int32_t zoom_final = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN); + zoom_final = (zoom_final * img->zoom) >> 8; + int32_t angle_final = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN); + angle_final += img->angle; + + lv_area_t area_transform; + _lv_img_buf_get_transformed_area(&area_transform, img->w, img->h, + angle_final, zoom_final, &img->pivot); + + return (lv_point_t) { + lv_area_get_width(&area_transform), lv_area_get_height(&area_transform) + }; +} + static void lv_img_event(const lv_obj_class_t * class_p, lv_event_t * e) { LV_UNUSED(class_p); @@ -419,7 +455,8 @@ static void lv_img_event(const lv_obj_class_t * class_p, lv_event_t * e) /*Refresh the file name to refresh the symbol text size*/ if(img->src_type == LV_IMG_SRC_SYMBOL) { lv_img_set_src(obj, img->src); - } else { + } + else { /*With transformation it might change*/ lv_obj_refresh_ext_draw_size(obj); } @@ -428,7 +465,7 @@ static void lv_img_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_coord_t * s = lv_event_get_param(e); lv_coord_t transf_zoom = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN); - transf_zoom = (transf_zoom * img->zoom) >> 8; + transf_zoom = ((int32_t)transf_zoom * img->zoom) >> 8; lv_coord_t transf_angle = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN); transf_angle += img->angle; @@ -455,9 +492,9 @@ static void lv_img_event(const lv_obj_class_t * class_p, lv_event_t * e) angle += img->angle; /*If the object is exactly image sized (not cropped, not mosaic) and transformed - *perform hit test on it's transformed area*/ + *perform hit test on its transformed area*/ if(img->w == lv_obj_get_width(obj) && img->h == lv_obj_get_height(obj) && - (zoom != LV_IMG_ZOOM_NONE || angle != 0 || img->pivot.x != img->w / 2 || img->pivot.y != img->h / 2)) { + (zoom != LV_IMG_ZOOM_NONE || angle != 0 || img->pivot.x != img->w / 2 || img->pivot.y != img->h / 2)) { lv_coord_t w = lv_obj_get_width(obj); lv_coord_t h = lv_obj_get_height(obj); @@ -477,9 +514,14 @@ static void lv_img_event(const lv_obj_class_t * class_p, lv_event_t * e) } } else if(code == LV_EVENT_GET_SELF_SIZE) { - lv_point_t * p = lv_event_get_param(e);; - p->x = img->w; - p->y = img->h; + lv_point_t * p = lv_event_get_param(e); + if(img->obj_size_mode == LV_IMG_SIZE_MODE_REAL) { + *p = lv_img_get_transformed_size(obj); + } + else { + p->x = img->w; + p->y = img->h; + } } else if(code == LV_EVENT_DRAW_MAIN || code == LV_EVENT_DRAW_POST || code == LV_EVENT_COVER_CHECK) { draw_img(e); @@ -564,14 +606,21 @@ static void draw_img(lv_event_t * e) bg_pivot.x = img->pivot.x + pleft; bg_pivot.y = img->pivot.y + ptop; lv_area_t bg_coords; - _lv_img_buf_get_transformed_area(&bg_coords, obj_w, obj_h, - angle_final, zoom_final, &bg_pivot); - /*Modify the coordinates to draw the background for the rotated and scaled coordinates*/ - bg_coords.x1 += obj->coords.x1; - bg_coords.y1 += obj->coords.y1; - bg_coords.x2 += obj->coords.x1; - bg_coords.y2 += obj->coords.y1; + if(img->obj_size_mode == LV_IMG_SIZE_MODE_REAL) { + /*Object size equals to transformed image size*/ + lv_obj_get_coords(obj, &bg_coords); + } + else { + _lv_img_buf_get_transformed_area(&bg_coords, obj_w, obj_h, + angle_final, zoom_final, &bg_pivot); + + /*Modify the coordinates to draw the background for the rotated and scaled coordinates*/ + bg_coords.x1 += obj->coords.x1; + bg_coords.y1 += obj->coords.y1; + bg_coords.x2 += obj->coords.x1; + bg_coords.y2 += obj->coords.y1; + } lv_area_t ori_coords; lv_area_copy(&ori_coords, &obj->coords); @@ -590,6 +639,20 @@ static void draw_img(lv_event_t * e) lv_area_t img_max_area; lv_area_copy(&img_max_area, &obj->coords); + + lv_point_t img_size_final = lv_img_get_transformed_size(obj); + + if(img->obj_size_mode == LV_IMG_SIZE_MODE_REAL) { + img_max_area.x1 -= ((img->w - img_size_final.x) + 1) / 2; + img_max_area.x2 -= ((img->w - img_size_final.x) + 1) / 2; + img_max_area.y1 -= ((img->h - img_size_final.y) + 1) / 2; + img_max_area.y2 -= ((img->h - img_size_final.y) + 1) / 2; + } + else { + img_max_area.x2 = img_max_area.x1 + lv_area_get_width(&bg_coords) - 1; + img_max_area.y2 = img_max_area.y1 + lv_area_get_height(&bg_coords) - 1; + } + img_max_area.x1 += pleft; img_max_area.y1 += ptop; img_max_area.x2 -= pright; @@ -619,12 +682,12 @@ static void draw_img(lv_event_t * e) if(coords_tmp.y1 > img_max_area.y1) coords_tmp.y1 -= img->h; coords_tmp.y2 = coords_tmp.y1 + img->h - 1; - for(; coords_tmp.y1 < img_max_area.y2; coords_tmp.y1 += img->h, coords_tmp.y2 += img->h) { + for(; coords_tmp.y1 < img_max_area.y2; coords_tmp.y1 += img_size_final.y, coords_tmp.y2 += img_size_final.y) { coords_tmp.x1 = img_max_area.x1 + img->offset.x; if(coords_tmp.x1 > img_max_area.x1) coords_tmp.x1 -= img->w; coords_tmp.x2 = coords_tmp.x1 + img->w - 1; - for(; coords_tmp.x1 < img_max_area.x2; coords_tmp.x1 += img->w, coords_tmp.x2 += img->w) { + for(; coords_tmp.x1 < img_max_area.x2; coords_tmp.x1 += img_size_final.x, coords_tmp.x2 += img_size_final.x) { lv_draw_img(&coords_tmp, &img_clip_area, img->src, &img_dsc); } } diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_img.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.h similarity index 82% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_img.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_img.h index f731eae91..cf96c717e 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_img.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.h @@ -28,7 +28,10 @@ extern "C" { /********************** * TYPEDEFS **********************/ -/*Data of image*/ + +/** + * Data of image + */ typedef struct { lv_obj_t obj; const void * src; /*Image source: Pointer to an array or a file or a symbol*/ @@ -41,10 +44,28 @@ typedef struct { uint8_t src_type : 2; /*See: lv_img_src_t*/ uint8_t cf : 5; /*Color format from `lv_img_color_format_t`*/ uint8_t antialias : 1; /*Apply anti-aliasing in transformations (rotate, zoom)*/ + uint8_t obj_size_mode: 2; /*Image size mode when image size and object size is different.*/ } lv_img_t; extern const lv_obj_class_t lv_img_class; +/** + * Image size mode, when image size and object size is different + */ +enum { + /** Zoom doesn't affect the coordinates of the object, + * however if zoomed in the image is drawn out of the its coordinates. + * The layout's won't change on zoom */ + LV_IMG_SIZE_MODE_VIRTUAL = 0, + + /** If the object size is set to SIZE_CONTENT, then object size equals zoomed image size. + * It causes layout recalculation. + * If the object size is set explicitly the the image will be cropped if zoomed in.*/ + LV_IMG_SIZE_MODE_REAL, +}; + +typedef uint8_t lv_img_size_mode_t; + /********************** * GLOBAL PROTOTYPES **********************/ @@ -117,12 +138,19 @@ void lv_img_set_zoom(lv_obj_t * obj, uint16_t zoom); /** * Enable/disable anti-aliasing for the transformations (rotate, zoom) or not. - * The qualitiy is better with anti-aliasing looks better but slower. + * The quality is better with anti-aliasing looks better but slower. * @param obj pointer to an image object * @param antialias true: anti-aliased; false: not anti-aliased */ void lv_img_set_antialias(lv_obj_t * obj, bool antialias); +/** + * Set the image object size mode. + * + * @param obj pointer to an image object + * @param mode the new size mode. + */ +void lv_img_set_size_mode(lv_obj_t * obj, lv_img_size_mode_t mode); /*===================== * Getter functions *====================*/ @@ -176,6 +204,13 @@ uint16_t lv_img_get_zoom(lv_obj_t * obj); */ bool lv_img_get_antialias(lv_obj_t * obj); +/** + * Get the size mode of the image + * @param obj pointer to an image object + * @return element of @ref lv_img_size_mode_t + */ +lv_img_size_mode_t lv_img_get_size_mode(lv_obj_t * obj); + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_label.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.c similarity index 93% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_label.c rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_label.c index c71b74ada..39161fb88 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_label.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.c @@ -72,7 +72,7 @@ const lv_obj_class_t lv_label_class = { lv_obj_t * lv_label_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -144,7 +144,7 @@ void lv_label_set_text(lv_obj_t * obj, const char * text) lv_label_refr_text(obj); } -LV_FORMAT_ATTRIBUTE(2, 3) void lv_label_set_text_fmt(lv_obj_t * obj, const char * fmt, ...) +void lv_label_set_text_fmt(lv_obj_t * obj, const char * fmt, ...) { LV_ASSERT_OBJ(obj, MY_CLASS); LV_ASSERT_NULL(fmt); @@ -238,8 +238,8 @@ void lv_label_set_text_sel_start(lv_obj_t * obj, uint32_t index) label->sel_start = index; lv_obj_invalidate(obj); #else - (void)obj; /*Unused*/ - (void)index; /*Unused*/ + LV_UNUSED(obj); /*Unused*/ + LV_UNUSED(index); /*Unused*/ #endif } @@ -252,8 +252,8 @@ void lv_label_set_text_sel_end(lv_obj_t * obj, uint32_t index) label->sel_end = index; lv_obj_invalidate(obj); #else - (void)obj; /*Unused*/ - (void)index; /*Unused*/ + LV_UNUSED(obj); /*Unused*/ + LV_UNUSED(index); /*Unused*/ #endif } @@ -288,12 +288,9 @@ void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t LV_ASSERT_OBJ(obj, MY_CLASS); LV_ASSERT_NULL(pos); + lv_label_t * label = (lv_label_t *)obj; const char * txt = lv_label_get_text(obj); - lv_text_align_t align = lv_obj_get_style_text_align(obj, LV_PART_MAIN); - if(align == LV_TEXT_ALIGN_AUTO) { - if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) align = LV_TEXT_ALIGN_RIGHT; - else align = LV_TEXT_ALIGN_LEFT; - } + lv_text_align_t align = lv_obj_calculate_style_text_align(obj, LV_PART_MAIN, txt); if(txt[0] == '\0') { pos->y = 0; @@ -314,7 +311,6 @@ void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t lv_area_t txt_coords; lv_obj_get_content_coords(obj, &txt_coords); - lv_label_t * label = (lv_label_t *)obj; uint32_t line_start = 0; uint32_t new_line_start = 0; lv_coord_t max_w = lv_area_get_width(&txt_coords); @@ -352,10 +348,13 @@ void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t const char * bidi_txt; uint32_t visual_byte_pos; #if LV_USE_BIDI + lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN); + if(base_dir == LV_BASE_DIR_AUTO) base_dir = _lv_bidi_detect_base_dir(txt); + char * mutable_bidi_txt = NULL; /*Handle Bidi*/ if(new_line_start == byte_id) { - visual_byte_pos = byte_id - line_start; + visual_byte_pos = base_dir == LV_BASE_DIR_RTL ? 0 : byte_id - line_start; bidi_txt = &txt[line_start]; } else { @@ -363,7 +362,7 @@ void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t bool is_rtl; uint32_t visual_char_pos = _lv_bidi_get_visual_pos(&txt[line_start], &mutable_bidi_txt, new_line_start - line_start, - lv_obj_get_style_base_dir(obj, LV_PART_MAIN), line_char_id, &is_rtl); + base_dir, line_char_id, &is_rtl); bidi_txt = mutable_bidi_txt; if(is_rtl) visual_char_pos++; @@ -427,11 +426,7 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in) if(label->expand != 0) flag |= LV_TEXT_FLAG_EXPAND; if(lv_obj_get_style_width(obj, LV_PART_MAIN) == LV_SIZE_CONTENT && !obj->w_layout) flag |= LV_TEXT_FLAG_FIT; - lv_text_align_t align = lv_obj_get_style_text_align(obj, LV_PART_MAIN); - if(align == LV_TEXT_ALIGN_AUTO) { - if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) align = LV_TEXT_ALIGN_RIGHT; - else align = LV_TEXT_ALIGN_LEFT; - } + lv_text_align_t align = lv_obj_calculate_style_text_align(obj, LV_PART_MAIN, label->text); /*Search the line of the index letter*/; while(txt[line_start] != '\0') { @@ -489,7 +484,7 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in) /*Handle the recolor command*/ if((flag & LV_TEXT_FLAG_RECOLOR) != 0) { if(_lv_txt_is_cmd(&cmd_state, bidi_txt[i]) != false) { - continue; /*Skip the letter is it is part of a command*/ + continue; /*Skip the letter if it is part of a command*/ } } @@ -509,7 +504,7 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in) #if LV_USE_BIDI /*Handle Bidi*/ uint32_t cid = _lv_txt_encoded_get_char_id(bidi_txt, i); - if(txt[line_start + cid] == '\0') { + if(txt[line_start + i] == '\0') { logical_pos = i; } else { @@ -518,7 +513,7 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in) txt_len, lv_obj_get_style_base_dir(obj, LV_PART_MAIN), cid, &is_rtl); if(is_rtl) logical_pos++; } - lv_mem_buf_release(bidi_txt); + lv_mem_buf_release(bidi_txt); #else logical_pos = _lv_txt_encoded_get_char_id(bidi_txt, i); #endif @@ -534,7 +529,7 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos) lv_area_t txt_coords; lv_obj_get_content_coords(obj, &txt_coords); const char * txt = lv_label_get_text(obj); - lv_label_t * label = (lv_label_t*)obj; + lv_label_t * label = (lv_label_t *)obj; uint32_t line_start = 0; uint32_t new_line_start = 0; lv_coord_t max_w = lv_area_get_width(&txt_coords); @@ -542,11 +537,7 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos) lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); lv_coord_t letter_height = lv_font_get_line_height(font); - lv_text_align_t align = lv_obj_get_style_text_align(obj, LV_PART_MAIN); - if(align == LV_TEXT_ALIGN_AUTO) { - if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) align = LV_TEXT_ALIGN_RIGHT; - else align = LV_TEXT_ALIGN_LEFT; - } + lv_text_align_t align = lv_obj_calculate_style_text_align(obj, LV_PART_MAIN, label->text); lv_coord_t y = 0; lv_text_flag_t flag = LV_TEXT_FLAG_NONE; @@ -595,7 +586,7 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos) /*Handle the recolor command*/ if((flag & LV_TEXT_FLAG_RECOLOR) != 0) { if(_lv_txt_is_cmd(&cmd_state, txt[i]) != false) { - continue; /*Skip the letter is it is part of a command*/ + continue; /*Skip the letter if it is part of a command*/ } } last_x = x; @@ -622,7 +613,7 @@ uint32_t lv_label_get_text_selection_start(const lv_obj_t * obj) return label->sel_start; #else - (void)obj; /*Unused*/ + LV_UNUSED(obj); /*Unused*/ return LV_LABEL_TEXT_SELECTION_OFF; #endif } @@ -635,7 +626,7 @@ uint32_t lv_label_get_text_selection_end(const lv_obj_t * obj) lv_label_t * label = (lv_label_t *)obj; return label->sel_end; #else - (void)obj; /*Unused*/ + LV_UNUSED(obj); /*Unused*/ return LV_LABEL_TEXT_SELECTION_OFF; #endif } @@ -668,18 +659,7 @@ void lv_label_ins_text(lv_obj_t * obj, uint32_t pos, const char * txt) pos = _lv_txt_get_encoded_length(label->text); } -#if LV_USE_BIDI - char * bidi_buf = lv_mem_buf_get(ins_len + 1); - LV_ASSERT_MALLOC(bidi_buf); - if(bidi_buf == NULL) return; - - _lv_bidi_process(txt, bidi_buf, lv_obj_get_style_base_dir(obj, LV_PART_MAIN)); - _lv_txt_ins(label->text, pos, bidi_buf); - - lv_mem_buf_release(bidi_buf); -#else _lv_txt_ins(label->text, pos, txt); -#endif lv_label_set_text(obj, NULL); } @@ -701,7 +681,6 @@ void lv_label_cut_text(lv_obj_t * obj, uint32_t pos, uint32_t cnt) lv_label_refr_text(obj); } - /********************** * STATIC FUNCTIONS **********************/ @@ -770,6 +749,15 @@ static void lv_label_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_label_revert_dots(obj); lv_label_refr_text(obj); } + else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { + /* Italic or other non-typical letters can be drawn of out of the object. + * It happens if box_w + ofs_x > adw_w in the glyph. + * To avoid this add some extra draw area. + * font_h / 4 is an empirical value. */ + const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); + lv_coord_t font_h = lv_font_get_line_height(font); + lv_event_set_ext_draw_size(e, font_h / 4); + } else if(code == LV_EVENT_SIZE_CHANGED) { lv_label_revert_dots(obj); lv_label_refr_text(obj); @@ -809,11 +797,6 @@ static void draw_main(lv_event_t * e) lv_area_t txt_coords; lv_obj_get_content_coords(obj, &txt_coords); - lv_text_align_t align = lv_obj_get_style_text_align(obj, LV_PART_MAIN); - if(align == LV_TEXT_ALIGN_AUTO) { - if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) align = LV_TEXT_ALIGN_RIGHT; - else align = LV_TEXT_ALIGN_LEFT; - } lv_text_flag_t flag = LV_TEXT_FLAG_NONE; if(label->recolor != 0) flag |= LV_TEXT_FLAG_RECOLOR; if(label->expand != 0) flag |= LV_TEXT_FLAG_EXPAND; @@ -827,6 +810,7 @@ static void draw_main(lv_event_t * e) label_draw_dsc.flag = flag; lv_obj_init_draw_label_dsc(obj, LV_PART_MAIN, &label_draw_dsc); + lv_bidi_calculate_align(&label_draw_dsc.align, &label_draw_dsc.bidi_dir, label->text); label_draw_dsc.sel_start = lv_label_get_text_selection_start(obj); label_draw_dsc.sel_end = lv_label_get_text_selection_end(obj); @@ -838,10 +822,10 @@ static void draw_main(lv_event_t * e) /* In SROLL and SROLL_CIRC mode the CENTER and RIGHT are pointless so remove them. * (In addition they will result misalignment is this case)*/ if((label->long_mode == LV_LABEL_LONG_SCROLL || label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) && - (align == LV_TEXT_ALIGN_CENTER || align == LV_TEXT_ALIGN_RIGHT)) { + (label_draw_dsc.align == LV_TEXT_ALIGN_CENTER || label_draw_dsc.align == LV_TEXT_ALIGN_RIGHT)) { lv_point_t size; lv_txt_get_size(&size, label->text, label_draw_dsc.font, label_draw_dsc.letter_space, label_draw_dsc.line_space, - LV_COORD_MAX, flag); + LV_COORD_MAX, flag); if(size.x > lv_area_get_width(&txt_coords)) { label_draw_dsc.align = LV_TEXT_ALIGN_LEFT; } @@ -866,14 +850,18 @@ static void draw_main(lv_event_t * e) txt_coords.y2 = obj->coords.y2; } - lv_draw_label(&txt_coords, &txt_clip, &label_draw_dsc, label->text, hint); + if(label->long_mode == LV_LABEL_LONG_SCROLL || label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) { + lv_draw_label(&txt_coords, &txt_clip, &label_draw_dsc, label->text, hint); + } else { + lv_draw_label(&txt_coords, clip_area, &label_draw_dsc, label->text, hint); + } if(label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) { lv_point_t size; lv_txt_get_size(&size, label->text, label_draw_dsc.font, label_draw_dsc.letter_space, label_draw_dsc.line_space, - LV_COORD_MAX, flag); + LV_COORD_MAX, flag); - /*Draw the text again on label to the original to make an circular effect */ + /*Draw the text again on label to the original to make a circular effect */ if(size.x > lv_area_get_width(&txt_coords)) { label_draw_dsc.ofs_x = label->offset.x + size.x + lv_font_get_glyph_width(label_draw_dsc.font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT; @@ -882,7 +870,7 @@ static void draw_main(lv_event_t * e) lv_draw_label(&txt_coords, &txt_clip, &label_draw_dsc, label->text, hint); } - /*Draw the text again below the original to make an circular effect */ + /*Draw the text again below the original to make a circular effect */ if(size.y > lv_area_get_height(&txt_coords)) { label_draw_dsc.ofs_x = label->offset.x; label_draw_dsc.ofs_y = label->offset.y + size.y + lv_font_get_line_height(label_draw_dsc.font); @@ -893,7 +881,7 @@ static void draw_main(lv_event_t * e) } /** - * Refresh the label with its text stored in its labelended data + * Refresh the label with its text stored in its extended data * @param label pointer to a label object */ static void lv_label_refr_text(lv_obj_t * obj) @@ -939,7 +927,7 @@ static void lv_label_refr_text(lv_obj_t * obj) int32_t start, end; lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN); - if (base_dir == LV_BASE_DIR_AUTO) + if(base_dir == LV_BASE_DIR_AUTO) base_dir = _lv_bidi_detect_base_dir(label->text); if(base_dir == LV_BASE_DIR_RTL) { @@ -1038,7 +1026,7 @@ static void lv_label_refr_text(lv_obj_t * obj) int32_t start, end; lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN); - if (base_dir == LV_BASE_DIR_AUTO) + if(base_dir == LV_BASE_DIR_AUTO) base_dir = _lv_bidi_detect_base_dir(label->text); if(base_dir == LV_BASE_DIR_RTL) { @@ -1131,10 +1119,13 @@ static void lv_label_refr_text(lv_obj_t * obj) /*Save letters under the dots and replace them with dots*/ uint32_t byte_id_ori = byte_id; uint32_t i; - uint8_t len = 0; + uint8_t len = 0; for(i = 0; i <= LV_LABEL_DOT_NUM; i++) { len += _lv_txt_encoded_size(&label->text[byte_id]); _lv_txt_encoded_next(label->text, &byte_id); + if (len > LV_LABEL_DOT_NUM || byte_id > txt_len) { + break; + } } if(lv_label_set_dot_tmp(obj, &label->text[byte_id_ori], len)) { diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_label.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.h similarity index 98% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_label.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_label.h index aac7d0b8c..b9a0e5013 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_label.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.h @@ -64,7 +64,8 @@ typedef struct { #endif #if LV_LABEL_TEXT_SELECTION - uint32_t sel_start; uint32_t sel_end; + uint32_t sel_start; + uint32_t sel_end; #endif lv_point_t offset; /*Text draw position offset*/ @@ -73,7 +74,7 @@ typedef struct { uint8_t recolor : 1; /*Enable in-line letter re-coloring*/ uint8_t expand : 1; /*Ignore real width (used by the library with LV_LABEL_LONG_SROLL)*/ uint8_t dot_tmp_alloc : 1; /*1: dot_tmp has been allocated;.0: dot_tmp directly holds up to 4 bytes of characters*/ -}lv_label_t; +} lv_label_t; extern const lv_obj_class_t lv_label_class; @@ -83,7 +84,7 @@ extern const lv_obj_class_t lv_label_class; /** * Create a label objects - * @param parent pointer to an object, it will be the parent of the new labely. + * @param parent pointer to an object, it will be the parent of the new label. * @return pointer to the created button */ lv_obj_t * lv_label_create(lv_obj_t * parent); @@ -109,7 +110,7 @@ void lv_label_set_text_fmt(lv_obj_t * obj, const char * fmt, ...) LV_FORMAT_ATTR /** * Set a static text. It will not be saved by the label so the 'text' variable - * has to be 'alive' while the label exist. + * has to be 'alive' while the label exists. * @param label pointer to a label object * @param text pointer to a text. NULL to refresh with the current text. */ diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_line.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_line.c similarity index 98% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_line.c rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_line.c index 016882986..e73e6e89e 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_line.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_line.c @@ -53,7 +53,7 @@ const lv_obj_class_t lv_line_class = { lv_obj_t * lv_line_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -159,7 +159,8 @@ static void lv_line_event(const lv_obj_class_t * class_p, lv_event_t * e) p->x = w; p->y = h; } - } else if(code == LV_EVENT_DRAW_MAIN) { + } + else if(code == LV_EVENT_DRAW_MAIN) { lv_line_t * line = (lv_line_t *)obj; const lv_area_t * clip_area = lv_event_get_param(e); diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_line.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_line.h similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_line.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_line.h diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_objx_templ.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_objx_templ.c similarity index 97% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_objx_templ.c rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_objx_templ.c index c7ef2a578..91565466a 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_objx_templ.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_objx_templ.c @@ -5,7 +5,7 @@ /** * TODO Remove these instructions - * Search an replace: templ -> object short name with lower case(e.g. btn, label etc) + * Search and replace: templ -> object short name with lower case(e.g. btn, label etc) * TEMPL -> object short name with upper case (e.g. BTN, LABEL etc.) * * You can remove the defined() clause from the #if statement below. This exists because diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_objx_templ.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_objx_templ.h similarity index 94% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_objx_templ.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_objx_templ.h index 9084f81c1..b7149bca8 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_objx_templ.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_objx_templ.h @@ -5,7 +5,7 @@ /** * TODO Remove these instructions - * Search an replace: templ -> object short name with lower case(e.g. btn, label etc) + * Search and replace: templ -> object short name with lower case(e.g. btn, label etc) * TEMPL -> object short name with upper case (e.g. BTN, LABEL etc.) * */ diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_roller.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.c similarity index 93% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_roller.c rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.c index 05bc450fd..fa558782d 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_roller.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.c @@ -46,21 +46,21 @@ static void set_y_anim(void * obj, int32_t v); * STATIC VARIABLES **********************/ const lv_obj_class_t lv_roller_class = { - .constructor_cb = lv_roller_constructor, - .event_cb = lv_roller_event, - .width_def = LV_SIZE_CONTENT, - .height_def = LV_DPI_DEF, - .instance_size = sizeof(lv_roller_t), - .editable = LV_OBJ_CLASS_EDITABLE_TRUE, - .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, - .base_class = &lv_obj_class + .constructor_cb = lv_roller_constructor, + .event_cb = lv_roller_event, + .width_def = LV_SIZE_CONTENT, + .height_def = LV_DPI_DEF, + .instance_size = sizeof(lv_roller_t), + .editable = LV_OBJ_CLASS_EDITABLE_TRUE, + .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, + .base_class = &lv_obj_class }; const lv_obj_class_t lv_roller_label_class = { - .event_cb = lv_roller_label_event, - .instance_size = sizeof(lv_label_t), - .base_class = &lv_label_class - }; + .event_cb = lv_roller_label_event, + .instance_size = sizeof(lv_label_t), + .base_class = &lv_label_class +}; /********************** * MACROS @@ -77,7 +77,7 @@ const lv_obj_class_t lv_roller_label_class = { */ lv_obj_t * lv_roller_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -98,7 +98,7 @@ void lv_roller_set_options(lv_obj_t * obj, const char * options, lv_roller_mode_ LV_ASSERT_OBJ(obj, MY_CLASS); LV_ASSERT_NULL(options); - lv_roller_t * roller = (lv_roller_t*)obj; + lv_roller_t * roller = (lv_roller_t *)obj; lv_obj_t * label = get_label(obj); roller->sel_opt_id = 0; @@ -157,7 +157,7 @@ void lv_roller_set_selected(lv_obj_t * obj, uint16_t sel_opt, lv_anim_enable_t a *if moving to the next option with an animation which was just deleted in the PRESS Call the ancestor's event handler *nothing will continue the animation.*/ - lv_roller_t * roller = (lv_roller_t*)obj; + lv_roller_t * roller = (lv_roller_t *)obj; /*In infinite mode interpret the new ID relative to the currently visible "page"*/ if(roller->mode == LV_ROLLER_MODE_INFINITE) { @@ -208,7 +208,7 @@ uint16_t lv_roller_get_selected(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_roller_t * roller = (lv_roller_t*)obj; + lv_roller_t * roller = (lv_roller_t *)obj; if(roller->mode == LV_ROLLER_MODE_INFINITE) { uint16_t real_id_cnt = roller->option_cnt / LV_ROLLER_INF_PAGES; return roller->sel_opt_id % real_id_cnt; @@ -228,7 +228,7 @@ void lv_roller_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_s { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_roller_t * roller = (lv_roller_t*)obj; + lv_roller_t * roller = (lv_roller_t *)obj; lv_obj_t * label = get_label(obj); uint32_t i; uint16_t line = 0; @@ -242,7 +242,7 @@ void lv_roller_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_s uint32_t c; for(c = 0; i < txt_len && opt_txt[i] != '\n'; c++, i++) { if(buf_size && c >= buf_size - 1) { - LV_LOG_WARN("lv_dropdown_get_selected_str: the buffer was too small") + LV_LOG_WARN("lv_dropdown_get_selected_str: the buffer was too small"); break; } buf[c] = opt_txt[i]; @@ -274,7 +274,7 @@ uint16_t lv_roller_get_option_cnt(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_roller_t * roller = (lv_roller_t*)obj; + lv_roller_t * roller = (lv_roller_t *)obj; if(roller->mode == LV_ROLLER_MODE_INFINITE) { return roller->option_cnt / LV_ROLLER_INF_PAGES; } @@ -291,7 +291,7 @@ uint16_t lv_roller_get_option_cnt(const lv_obj_t * obj) static void lv_roller_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { LV_UNUSED(class_p); - lv_roller_t * roller = (lv_roller_t*)obj; + lv_roller_t * roller = (lv_roller_t *)obj; roller->mode = LV_ROLLER_MODE_NORMAL; roller->option_cnt = 0; @@ -301,7 +301,7 @@ static void lv_roller_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN); - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * label = lv_obj_class_create_obj(&lv_roller_label_class, obj); lv_obj_class_init_obj(label); lv_roller_set_options(obj, "Option 1\nOption 2\nOption 3\nOption 4\nOption 5", LV_ROLLER_MODE_NORMAL); @@ -321,7 +321,7 @@ static void lv_roller_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_event_code_t code = lv_event_get_code(e); lv_obj_t * obj = lv_event_get_target(e); - lv_roller_t * roller = (lv_roller_t*)obj; + lv_roller_t * roller = (lv_roller_t *)obj; if(code == LV_EVENT_GET_SELF_SIZE) { lv_point_t * p = lv_event_get_param(e); @@ -478,12 +478,12 @@ static void draw_main(lv_event_t * e) /*Get the size of the "selected text"*/ lv_point_t res_p; lv_txt_get_size(&res_p, lv_label_get_text(label), label_dsc.font, label_dsc.letter_space, label_dsc.line_space, - lv_obj_get_width(obj), LV_TEXT_FLAG_EXPAND); + lv_obj_get_width(obj), LV_TEXT_FLAG_EXPAND); /*Move the selected label proportionally with the background label*/ lv_coord_t roller_h = lv_obj_get_height(obj); int32_t label_y_prop = label->coords.y1 - (roller_h / 2 + - obj->coords.y1); /*label offset from the middle line of the roller*/ + obj->coords.y1); /*label offset from the middle line of the roller*/ label_y_prop = (label_y_prop * 16384) / lv_obj_get_height( label); /*Proportional position from the middle line (upscaled by << 14)*/ @@ -575,25 +575,21 @@ static void refr_position(lv_obj_t * obj, lv_anim_enable_t anim_en) lv_obj_t * label = get_label(obj); if(label == NULL) return; - lv_text_align_t align = lv_obj_get_style_text_align(label, LV_PART_MAIN); - if(align == LV_TEXT_ALIGN_AUTO) { - if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) align = LV_TEXT_ALIGN_RIGHT; - else align = LV_TEXT_ALIGN_LEFT; - } + lv_text_align_t align = lv_obj_calculate_style_text_align(label, LV_PART_MAIN, lv_label_get_text(label)); switch(align) { - case LV_TEXT_ALIGN_CENTER: - lv_obj_set_x(label, (lv_obj_get_content_width(obj) - lv_obj_get_width(label)) / 2); - break; - case LV_TEXT_ALIGN_RIGHT: - lv_obj_set_x(label, lv_obj_get_content_width(obj) - lv_obj_get_width(label)); - break; - case LV_TEXT_ALIGN_LEFT: - lv_obj_set_x(label, 0); - break; + case LV_TEXT_ALIGN_CENTER: + lv_obj_set_x(label, (lv_obj_get_content_width(obj) - lv_obj_get_width(label)) / 2); + break; + case LV_TEXT_ALIGN_RIGHT: + lv_obj_set_x(label, lv_obj_get_content_width(obj) - lv_obj_get_width(label)); + break; + case LV_TEXT_ALIGN_LEFT: + lv_obj_set_x(label, 0); + break; } - lv_roller_t * roller = (lv_roller_t*)obj; + lv_roller_t * roller = (lv_roller_t *)obj; const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); lv_coord_t font_h = lv_font_get_line_height(font); @@ -635,7 +631,7 @@ static lv_res_t release_handler(lv_obj_t * obj) if(label == NULL) return LV_RES_OK; lv_indev_t * indev = lv_indev_get_act(); - lv_roller_t * roller = (lv_roller_t*)obj; + lv_roller_t * roller = (lv_roller_t *)obj; /*Leave edit mode once a new option is selected*/ lv_indev_type_t indev_type = lv_indev_get_type(indev); @@ -674,7 +670,8 @@ static lv_res_t release_handler(lv_obj_t * obj) if(letter == '\n' && i_prev != letter_i) new_opt++; i_prev = i; } - } else { + } + else { /*If dragged then align the list to have an element in the middle*/ const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); @@ -707,7 +704,7 @@ static lv_res_t release_handler(lv_obj_t * obj) */ static void inf_normalize(lv_obj_t * obj) { - lv_roller_t * roller = (lv_roller_t*)obj; + lv_roller_t * roller = (lv_roller_t *)obj; if(roller->mode == LV_ROLLER_MODE_INFINITE) { uint16_t real_id_cnt = roller->option_cnt / LV_ROLLER_INF_PAGES; diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_roller.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.h similarity index 91% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_roller.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.h index 24202734b..1520c4a57 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_roller.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.h @@ -37,13 +37,13 @@ enum { typedef uint8_t lv_roller_mode_t; typedef struct { - lv_obj_t obj; - uint16_t option_cnt; /**< Number of options*/ - uint16_t sel_opt_id; /**< Index of the current option*/ - uint16_t sel_opt_id_ori; /**< Store the original index on focus*/ - lv_roller_mode_t mode : 1; - uint32_t moved : 1; -}lv_roller_t; + lv_obj_t obj; + uint16_t option_cnt; /**< Number of options*/ + uint16_t sel_opt_id; /**< Index of the current option*/ + uint16_t sel_opt_id_ori; /**< Store the original index on focus*/ + lv_roller_mode_t mode : 1; + uint32_t moved : 1; +} lv_roller_t; extern const lv_obj_class_t lv_roller_class; diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_slider.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.c similarity index 92% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_slider.c rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.c index 327fbb2ef..79b43719f 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_slider.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.c @@ -58,7 +58,7 @@ const lv_obj_class_t lv_slider_class = { lv_obj_t * lv_slider_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -134,11 +134,11 @@ static void lv_slider_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_coord_t dist_left, dist_right; if(hor) { if((base_dir != LV_BASE_DIR_RTL && p.x > slider->right_knob_area.x2) || (base_dir == LV_BASE_DIR_RTL && - p.x < slider->right_knob_area.x1)) { + p.x < slider->right_knob_area.x1)) { slider->value_to_set = &slider->bar.cur_value; } else if((base_dir != LV_BASE_DIR_RTL && p.x < slider->left_knob_area.x1) || (base_dir == LV_BASE_DIR_RTL && - p.x > slider->left_knob_area.x2)) { + p.x > slider->left_knob_area.x2)) { slider->value_to_set = &slider->bar.start_value; } else { @@ -277,7 +277,7 @@ static void lv_slider_event(const lv_obj_class_t * class_p, lv_event_t * e) } else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); - lv_coord_t knob_right = lv_obj_get_style_pad_right(obj,LV_PART_KNOB); + lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); @@ -313,7 +313,8 @@ static void lv_slider_event(const lv_obj_class_t * class_p, lv_event_t * e) res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return; } - } else if(code == LV_EVENT_DRAW_MAIN) { + } + else if(code == LV_EVENT_DRAW_MAIN) { draw_knob(e); } } @@ -370,25 +371,28 @@ static void draw_knob(lv_event_t * e) position_knob(obj, &knob_area, knob_size, hor); lv_area_copy(&slider->right_knob_area, &knob_area); - lv_obj_draw_part_dsc_t dsc; - lv_obj_draw_dsc_init(&dsc, clip_area); - dsc.part = LV_PART_KNOB; - dsc.id = 0; - dsc.draw_area = &slider->right_knob_area; - dsc.rect_dsc = &knob_rect_dsc; + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, clip_area); + part_draw_dsc.part = LV_PART_KNOB; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_SLIDER_DRAW_PART_KNOB; + part_draw_dsc.id = 0; + part_draw_dsc.draw_area = &slider->right_knob_area; + part_draw_dsc.rect_dsc = &knob_rect_dsc; if(lv_slider_get_mode(obj) != LV_SLIDER_MODE_RANGE) { - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_rect(&slider->right_knob_area, clip_area, &knob_rect_dsc); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &dsc); - } else { - /*Save the draw dsc. because it can be modified in the event*/ + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); + } + else { + /*Save the draw part_draw_dsc. because it can be modified in the event*/ lv_draw_rect_dsc_t knob_rect_dsc_tmp; lv_memcpy(&knob_rect_dsc_tmp, &knob_rect_dsc, sizeof(lv_draw_rect_dsc_t)); - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_rect(&slider->right_knob_area, clip_area, &knob_rect_dsc); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); /*Draw a second knob for the start_value side*/ if(hor) { @@ -401,13 +405,14 @@ static void draw_knob(lv_event_t * e) lv_area_copy(&slider->left_knob_area, &knob_area); lv_memcpy(&knob_rect_dsc, &knob_rect_dsc_tmp, sizeof(lv_draw_rect_dsc_t)); - dsc.draw_area = &slider->left_knob_area; - dsc.rect_dsc = &knob_rect_dsc; - dsc.id = 1; + part_draw_dsc.type = LV_SLIDER_DRAW_PART_KNOB_LEFT; + part_draw_dsc.draw_area = &slider->left_knob_area; + part_draw_dsc.rect_dsc = &knob_rect_dsc; + part_draw_dsc.id = 1; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_rect(&slider->left_knob_area, clip_area, &knob_rect_dsc); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } } diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_slider.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.h similarity index 92% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_slider.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.h index 2cf44d4c1..28b7543db 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_slider.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.h @@ -47,10 +47,19 @@ typedef struct { int32_t * value_to_set; /*Which bar value to set*/ uint8_t dragging : 1; /*1: the slider is being dragged*/ uint8_t left_knob_focus : 1; /*1: with encoder now the right knob can be adjusted*/ -}lv_slider_t; +} lv_slider_t; extern const lv_obj_class_t lv_slider_class; +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_slider_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_SLIDER_DRAW_PART_KNOB, /**< The main (right) knob's rectangle*/ + LV_SLIDER_DRAW_PART_KNOB_LEFT, /**< The left knob's rectangle*/ +} lv_slider_draw_part_type_t; + /********************** * GLOBAL PROTOTYPES **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_switch.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_switch.c new file mode 100644 index 000000000..7bc89512c --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_switch.c @@ -0,0 +1,282 @@ +/** + * @file lv_sw.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_switch.h" + +#if LV_USE_SWITCH != 0 + +#include "../misc/lv_assert.h" +#include "../misc/lv_math.h" +#include "../misc/lv_anim.h" +#include "../core/lv_indev.h" +#include "../core/lv_disp.h" +#include "lv_img.h" + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_switch_class + +#define LV_SWITCH_IS_ANIMATING(sw) (((sw)->anim_state) != LV_SWITCH_ANIM_STATE_INV) + +/** Switch animation start value. (Not the real value of the switch just indicates process animation)*/ +#define LV_SWITCH_ANIM_STATE_START 0 + +/** Switch animation end value. (Not the real value of the switch just indicates process animation)*/ +#define LV_SWITCH_ANIM_STATE_END 256 + +/** Mark no animation is in progress*/ +#define LV_SWITCH_ANIM_STATE_INV -1 + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_switch_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_switch_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_switch_event(const lv_obj_class_t * class_p, lv_event_t * e); +static void draw_main(lv_event_t * e); + +static void lv_switch_anim_exec_cb(void * sw, int32_t value); +static void lv_switch_trigger_anim(lv_obj_t * obj); +static void lv_switch_anim_ready(lv_anim_t * a); +/********************** + * STATIC VARIABLES + **********************/ +const lv_obj_class_t lv_switch_class = { + .constructor_cb = lv_switch_constructor, + .destructor_cb = lv_switch_destructor, + .event_cb = lv_switch_event, + .width_def = (4 * LV_DPI_DEF) / 10, + .height_def = (4 * LV_DPI_DEF) / 17, + .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, + .instance_size = sizeof(lv_switch_t), + .base_class = &lv_obj_class +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_switch_create(lv_obj_t * parent) +{ + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + return obj; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_switch_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + LV_TRACE_OBJ_CREATE("begin"); + + lv_switch_t * sw = (lv_switch_t *)obj; + + sw->anim_state = LV_SWITCH_ANIM_STATE_INV; + + lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_add_flag(obj, LV_OBJ_FLAG_CHECKABLE); + lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS); + + LV_TRACE_OBJ_CREATE("finished"); +} + +static void lv_switch_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + lv_switch_t * sw = (lv_switch_t *)obj; + + lv_anim_del(sw, NULL); +} + +static void lv_switch_event(const lv_obj_class_t * class_p, lv_event_t * e) +{ + LV_UNUSED(class_p); + + lv_res_t res; + + /*Call the ancestor's event handler*/ + res = lv_obj_event_base(MY_CLASS, e); + if(res != LV_RES_OK) return; + + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * obj = lv_event_get_target(e); + + if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { + lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); + lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); + lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); + lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); + + /*The smaller size is the knob diameter*/ + lv_coord_t knob_size = LV_MAX4(knob_left, knob_right, knob_bottom, knob_top); + knob_size += 2; /*For rounding error*/ + knob_size += lv_obj_calculate_ext_draw_size(obj, LV_PART_KNOB); + + lv_coord_t * s = lv_event_get_param(e); + *s = LV_MAX(*s, knob_size); + *s = LV_MAX(*s, lv_obj_calculate_ext_draw_size(obj, LV_PART_INDICATOR)); + } + else if(code == LV_EVENT_VALUE_CHANGED) { + lv_switch_trigger_anim(obj); + lv_obj_invalidate(obj); + } + else if(code == LV_EVENT_DRAW_MAIN) { + draw_main(e); + } +} + +static void draw_main(lv_event_t * e) +{ + lv_obj_t * obj = lv_event_get_target(e); + lv_switch_t * sw = (lv_switch_t *)obj; + + const lv_area_t * clip_area = lv_event_get_param(e); + lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN); + + /*Calculate the indicator area*/ + lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + + /*Draw the indicator*/ + /*Respect the background's padding*/ + lv_area_t indic_area; + lv_area_copy(&indic_area, &obj->coords); + indic_area.x1 += bg_left; + indic_area.x2 -= bg_right; + indic_area.y1 += bg_top; + indic_area.y2 -= bg_bottom; + + lv_draw_rect_dsc_t draw_indic_dsc; + lv_draw_rect_dsc_init(&draw_indic_dsc); + lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &draw_indic_dsc); + lv_draw_rect(&indic_area, clip_area, &draw_indic_dsc); + + /*Draw the knob*/ + lv_coord_t objh = lv_obj_get_height(obj); + lv_coord_t knob_size = objh; + lv_area_t knob_area; + + lv_coord_t anim_length = obj->coords.x2 - bg_right - obj->coords.x1 - bg_left - knob_size; + + lv_coord_t anim_value_x; + + bool chk = lv_obj_get_state(obj) & LV_STATE_CHECKED; + + if(LV_SWITCH_IS_ANIMATING(sw)) { + /* Use the animation's coordinate */ + anim_value_x = (anim_length * sw->anim_state) / LV_SWITCH_ANIM_STATE_END; + } + else { + /* Use LV_STATE_CHECKED to decide the coordinate */ + anim_value_x = chk ? anim_length : 0; + } + + if(base_dir == LV_BASE_DIR_RTL) { + anim_value_x = anim_length - anim_value_x; + } + + knob_area.x1 = obj->coords.x1 + bg_left + anim_value_x; + knob_area.x2 = knob_area.x1 + knob_size; + + knob_area.y1 = obj->coords.y1 + bg_top; + knob_area.y2 = obj->coords.y2 - bg_bottom; + + lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); + lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); + lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); + lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); + + /*Apply the paddings on the knob area*/ + knob_area.x1 -= knob_left; + knob_area.x2 += knob_right; + knob_area.y1 -= knob_top; + knob_area.y2 += knob_bottom; + + lv_draw_rect_dsc_t knob_rect_dsc; + lv_draw_rect_dsc_init(&knob_rect_dsc); + lv_obj_init_draw_rect_dsc(obj, LV_PART_KNOB, &knob_rect_dsc); + + lv_draw_rect(&knob_area, clip_area, &knob_rect_dsc); +} + +static void lv_switch_anim_exec_cb(void * var, int32_t value) +{ + lv_switch_t * sw = var; + sw->anim_state = value; + lv_obj_invalidate((lv_obj_t *)sw); +} + +/** + * Resets the switch's animation state to "no animation in progress". + */ +static void lv_switch_anim_ready(lv_anim_t * a) +{ + lv_switch_t * sw = a->var; + sw->anim_state = LV_SWITCH_ANIM_STATE_INV; + lv_obj_invalidate((lv_obj_t *)sw); +} + +/** + * Starts an animation for the switch knob. if the anim_time style property is greater than 0 + * @param obj the switch to animate + */ +static void lv_switch_trigger_anim(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_switch_t * sw = (lv_switch_t *)obj; + + uint32_t anim_dur_full = lv_obj_get_style_anim_time(obj, LV_PART_MAIN); + + if(anim_dur_full > 0) { + bool chk = lv_obj_get_state(obj) & LV_STATE_CHECKED; + int32_t anim_start; + int32_t anim_end; + /*No animation in progress -> simply set the values*/ + if(sw->anim_state == LV_SWITCH_ANIM_STATE_INV) { + anim_start = chk ? LV_SWITCH_ANIM_STATE_START : LV_SWITCH_ANIM_STATE_END; + anim_end = chk ? LV_SWITCH_ANIM_STATE_END : LV_SWITCH_ANIM_STATE_START; + } + /*Animation in progress. Start from the animation end value*/ + else { + anim_start = sw->anim_state; + anim_end = chk ? LV_SWITCH_ANIM_STATE_END : LV_SWITCH_ANIM_STATE_START; + } + /*Calculate actual animation duration*/ + uint32_t anim_dur = (anim_dur_full * LV_ABS(anim_start - anim_end)) / LV_SWITCH_ANIM_STATE_END; + + /*Stop the previous animation if it exists*/ + lv_anim_del(sw, NULL); + + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, sw); + lv_anim_set_exec_cb(&a, lv_switch_anim_exec_cb); + lv_anim_set_values(&a, anim_start, anim_end); + lv_anim_set_ready_cb(&a, lv_switch_anim_ready); + lv_anim_set_time(&a, anim_dur); + lv_anim_start(&a); + } +} + + +#endif diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_switch.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_switch.h similarity index 85% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_switch.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_switch.h index 8ff92afb9..7d573f2af 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_switch.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_switch.h @@ -17,11 +17,6 @@ extern "C" { #if LV_USE_SWITCH != 0 -/*Testing of dependencies*/ -#if LV_USE_SLIDER == 0 -#error "lv_switch: lv_slider is required. Enable it in lv_conf.h (LV_USE_SLIDER 1)" -#endif - #include "../core/lv_obj.h" /********************* @@ -34,7 +29,8 @@ extern "C" { typedef struct { lv_obj_t obj; -}lv_switch_t; + int32_t anim_state; +} lv_switch_t; extern const lv_obj_class_t lv_switch_class; diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_table.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_table.c similarity index 92% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_table.c rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_table.c index 283540cf5..a07c3249b 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_table.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_table.c @@ -63,7 +63,7 @@ const lv_obj_class_t lv_table_class = { lv_obj_t * lv_table_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -131,7 +131,7 @@ void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, con lv_table_cell_ctrl_t ctrl = 0; /*Save the control byte*/ - if(table->cell_data[cell]) ctrl= table->cell_data[cell][0]; + if(table->cell_data[cell]) ctrl = table->cell_data[cell][0]; va_list ap, ap2; va_start(ap, fmt); @@ -191,7 +191,7 @@ void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, con const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_ITEMS); lv_coord_t h = get_row_height(obj, row, font, letter_space, line_space, - cell_left, cell_right, cell_top, cell_bottom); + cell_left, cell_right, cell_top, cell_bottom); lv_coord_t minh = lv_obj_get_style_min_height(obj, LV_PART_ITEMS); @@ -251,13 +251,13 @@ void lv_table_set_col_cnt(lv_obj_t * obj, uint16_t col_cnt) /*Free the unused cells*/ if(old_col_cnt > col_cnt) { - uint16_t old_cell_cnt = old_col_cnt * table->row_cnt; - uint32_t new_cell_cnt = table->col_cnt * table->row_cnt; - uint32_t i; - for(i = new_cell_cnt; i < old_cell_cnt; i++) { - lv_mem_free(table->cell_data[i]); - } - } + uint16_t old_cell_cnt = old_col_cnt * table->row_cnt; + uint32_t new_cell_cnt = table->col_cnt * table->row_cnt; + uint32_t i; + for(i = new_cell_cnt; i < old_cell_cnt; i++) { + lv_mem_free(table->cell_data[i]); + } + } char ** new_cell_data = lv_mem_alloc(table->row_cnt * table->col_cnt * sizeof(char *)); LV_ASSERT_MALLOC(new_cell_data); @@ -282,7 +282,8 @@ void lv_table_set_col_cnt(lv_obj_t * obj, uint16_t col_cnt) old_col_start = row * old_col_cnt; new_col_start = row * col_cnt; - lv_memcpy_small(&new_cell_data[new_col_start], &table->cell_data[old_col_start], sizeof(new_cell_data[0]) * min_col_cnt); + lv_memcpy_small(&new_cell_data[new_col_start], &table->cell_data[old_col_start], + sizeof(new_cell_data[0]) * min_col_cnt); } lv_mem_free(table->cell_data); @@ -491,8 +492,8 @@ static void lv_table_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_coord_t h = 0; for(i = 0; i < table->row_cnt; i++) h += table->row_h[i]; - p->x = w; - p->y = h; + p->x = w - 1; + p->y = h - 1; } else if(code == LV_EVENT_PRESSED || code == LV_EVENT_PRESSING) { uint16_t col; @@ -502,8 +503,8 @@ static void lv_table_event(const lv_obj_class_t * class_p, lv_event_t * e) if(pr_res == LV_RES_OK && (table->col_act != col || table->row_act != row)) { table->col_act = col; table->row_act = row; + lv_obj_invalidate(obj); } - lv_obj_invalidate(obj); } else if(code == LV_EVENT_RELEASED) { lv_obj_invalidate(obj); @@ -522,7 +523,8 @@ static void lv_table_event(const lv_obj_class_t * class_p, lv_event_t * e) } else if(code == LV_EVENT_FOCUSED) { lv_obj_invalidate(obj); - } else if(code == LV_EVENT_KEY) { + } + else if(code == LV_EVENT_KEY) { int32_t c = *((int32_t *)lv_event_get_param(e)); int32_t col = table->col_act; int32_t row = table->row_act; @@ -546,21 +548,25 @@ static void lv_table_event(const lv_obj_class_t * class_p, lv_event_t * e) if(row < table->row_cnt - 1) { col = 0; row++; - } else { + } + else { col = table->col_cnt - 1; } - } else if (col < 0) { + } + else if(col < 0) { if(row != 0) { col = table->col_cnt - 1; row--; - } else { + } + else { col = 0; } } if(row >= table->row_cnt) { row = table->row_cnt - 1; - } else if(row < 0) { + } + else if(row < 0) { row = 0; } @@ -572,7 +578,8 @@ static void lv_table_event(const lv_obj_class_t * class_p, lv_event_t * e) res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return; } - } else if(code == LV_EVENT_DRAW_MAIN) { + } + else if(code == LV_EVENT_DRAW_MAIN) { draw_main(e); } } @@ -582,13 +589,16 @@ static void draw_main(lv_event_t * e) { lv_obj_t * obj = lv_event_get_target(e); lv_table_t * table = (lv_table_t *)obj; - const lv_area_t * clip_area = lv_event_get_param(e); + const lv_area_t * clip_area_ori = lv_event_get_param(e); + lv_area_t clip_area; + if(!_lv_area_intersect(&clip_area, &obj->coords, clip_area_ori)) return; lv_point_t txt_size; lv_area_t cell_area; lv_area_t txt_area; lv_text_flag_t txt_flags; + lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); @@ -618,16 +628,18 @@ static void draw_main(lv_event_t * e) uint16_t row; uint16_t cell = 0; - cell_area.y2 = obj->coords.y1 + bg_top - 1 - lv_obj_get_scroll_y(obj) ; + cell_area.y2 = obj->coords.y1 + bg_top - 1 - lv_obj_get_scroll_y(obj) + border_width; lv_coord_t scroll_x = lv_obj_get_scroll_x(obj) ; bool rtl = lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false; /*Handle custom drawer*/ - lv_obj_draw_part_dsc_t dsc; - lv_obj_draw_dsc_init(&dsc, clip_area); - dsc.part = LV_PART_ITEMS; - dsc.rect_dsc = &rect_dsc_act; - dsc.label_dsc = &label_dsc_act; + lv_obj_draw_part_dsc_t part_draw_dsc; + lv_obj_draw_dsc_init(&part_draw_dsc, &clip_area); + part_draw_dsc.part = LV_PART_ITEMS; + part_draw_dsc.class_p = MY_CLASS; + part_draw_dsc.type = LV_TABLE_DRAW_PART_CELL; + part_draw_dsc.rect_dsc = &rect_dsc_act; + part_draw_dsc.label_dsc = &label_dsc_act; for(row = 0; row < table->row_cnt; row++) { lv_coord_t h_row = table->row_h[row]; @@ -635,10 +647,10 @@ static void draw_main(lv_event_t * e) cell_area.y1 = cell_area.y2 + 1; cell_area.y2 = cell_area.y1 + h_row - 1; - if(cell_area.y1 > clip_area->y2) return; + if(cell_area.y1 > clip_area.y2) return; - if(rtl) cell_area.x1 = obj->coords.x2 - bg_right - 1 - scroll_x; - else cell_area.x2 = obj->coords.x1 + bg_left - 1 - scroll_x; + if(rtl) cell_area.x1 = obj->coords.x2 - bg_right - 1 - scroll_x - border_width; + else cell_area.x2 = obj->coords.x1 + bg_left - 1 - scroll_x + border_width; for(col = 0; col < table->col_cnt; col++) { lv_table_cell_ctrl_t ctrl = 0; @@ -670,7 +682,7 @@ static void draw_main(lv_event_t * e) } } - if(cell_area.y2 < clip_area->y1) { + if(cell_area.y2 < clip_area.y1) { cell += col_merge + 1; col += col_merge; continue; @@ -689,7 +701,7 @@ static void draw_main(lv_event_t * e) cell_area_border.x2 += rect_dsc_def.border_width / 2 + (rect_dsc_def.border_width & 0x1); } if((rect_dsc_def.border_side & LV_BORDER_SIDE_BOTTOM) && - cell_area_border.y2 < obj->coords.y2 - bg_bottom - 1) { + cell_area_border.y2 < obj->coords.y2 - bg_bottom - 1) { cell_area_border.y2 += rect_dsc_def.border_width / 2 + (rect_dsc_def.border_width & 0x1); } @@ -718,11 +730,11 @@ static void draw_main(lv_event_t * e) obj->skip_trans = 0; } - dsc.draw_area = &cell_area_border; - dsc.id = row * table->col_cnt + col; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &dsc); + part_draw_dsc.draw_area = &cell_area_border; + part_draw_dsc.id = row * table->col_cnt + col; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_rect(&cell_area_border, clip_area, &rect_dsc_act); + lv_draw_rect(&cell_area_border, &clip_area, &rect_dsc_act); if(table->cell_data[cell]) { txt_area.x1 = cell_area.x1 + cell_left; @@ -736,8 +748,8 @@ static void draw_main(lv_event_t * e) else txt_flags = LV_TEXT_FLAG_NONE; lv_txt_get_size(&txt_size, table->cell_data[cell] + 1, label_dsc_def.font, - label_dsc_act.letter_space, label_dsc_act.line_space, - lv_area_get_width(&txt_area), txt_flags); + label_dsc_act.letter_space, label_dsc_act.line_space, + lv_area_get_width(&txt_area), txt_flags); /*Align the content to the middle if not cropped*/ if(!crop) { @@ -747,13 +759,13 @@ static void draw_main(lv_event_t * e) lv_area_t label_mask; bool label_mask_ok; - label_mask_ok = _lv_area_intersect(&label_mask, clip_area, &cell_area); + label_mask_ok = _lv_area_intersect(&label_mask, &clip_area, &cell_area); if(label_mask_ok) { lv_draw_label(&txt_area, &label_mask, &label_dsc_act, table->cell_data[cell] + 1, NULL); } } - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); cell += col_merge + 1; col += col_merge; @@ -781,7 +793,7 @@ static void refr_size(lv_obj_t * obj, uint32_t strat_row) for(i = strat_row; i < table->row_cnt; i++) { table->row_h[i] = get_row_height(obj, i, font, letter_space, line_space, - cell_left, cell_right, cell_top, cell_bottom); + cell_left, cell_right, cell_top, cell_bottom); table->row_h[i] = LV_CLAMP(minh, table->row_h[i], maxh); } @@ -827,14 +839,14 @@ static lv_coord_t get_row_height(lv_obj_t * obj, uint16_t row_id, const lv_font_ /*With text crop assume 1 line*/ if(ctrl & LV_TABLE_CELL_CTRL_TEXT_CROP) { h_max = LV_MAX(lv_font_get_line_height(font) + cell_top + cell_bottom, - h_max); + h_max); } /*Without text crop calculate the height of the text in the cell*/ else { txt_w -= cell_left + cell_right; lv_txt_get_size(&txt_size, table->cell_data[cell] + 1, font, - letter_space, line_space, txt_w, LV_TEXT_FLAG_NONE); + letter_space, line_space, txt_w, LV_TEXT_FLAG_NONE); h_max = LV_MAX(txt_size.y + cell_top + cell_bottom, h_max); cell += col_merge; @@ -848,7 +860,7 @@ static lv_coord_t get_row_height(lv_obj_t * obj, uint16_t row_id, const lv_font_ static lv_res_t get_pressed_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col) { - lv_table_t * table = (lv_table_t *)obj; + lv_table_t * table = (lv_table_t *)obj; lv_indev_type_t type = lv_indev_get_type(lv_indev_get_act()); if(type != LV_INDEV_TYPE_POINTER && type != LV_INDEV_TYPE_BUTTON) { diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_table.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_table.h similarity index 96% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_table.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_table.h index cd87e19b7..910627087 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_table.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_table.h @@ -60,6 +60,14 @@ typedef struct { extern const lv_obj_class_t lv_table_class; +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_table_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_TABLE_DRAW_PART_CELL, /**< A cell*/ +} lv_table_draw_part_type_t; + /********************** * GLOBAL PROTOTYPES **********************/ diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_textarea.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.c similarity index 87% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_textarea.c rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.c index 0bcbefdf5..6be921b50 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_textarea.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.c @@ -45,6 +45,7 @@ static void lv_textarea_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void lv_textarea_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void lv_textarea_event(const lv_obj_class_t * class_p, lv_event_t * e); +static void label_event_cb(lv_event_t * e); static void cursor_blink_anim_cb(void * obj, int32_t show); static void pwd_char_hider_anim(void * obj, int32_t x); static void pwd_char_hider_anim_ready(lv_anim_t * a); @@ -83,7 +84,7 @@ static const char * ta_insert_replace; lv_obj_t * lv_textarea_create(lv_obj_t * parent) { - LV_LOG_INFO("begin") + LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; @@ -97,7 +98,7 @@ void lv_textarea_add_char(lv_obj_t * obj, uint32_t c) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; const char * letter_buf; @@ -172,7 +173,7 @@ void lv_textarea_add_text(lv_obj_t * obj, const char * txt) LV_ASSERT_OBJ(obj, MY_CLASS); LV_ASSERT_NULL(txt); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; if(ta->pwd_mode != 0) pwd_char_hider(obj); /*Make sure all the current text contains only '*'*/ @@ -233,7 +234,7 @@ void lv_textarea_del_char(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; uint32_t cur_pos = ta->cursor.pos; if(cur_pos == 0) return; @@ -247,6 +248,7 @@ void lv_textarea_del_char(lv_obj_t * obj) /*Delete a character*/ _lv_txt_cut(label_txt, ta->cursor.pos - 1, 1); + /*Refresh the label*/ lv_label_set_text(ta->label, label_txt); lv_textarea_clear_selection(obj); @@ -258,8 +260,7 @@ void lv_textarea_del_char(lv_obj_t * obj) } if(ta->pwd_mode != 0) { - uint32_t byte_pos = _lv_txt_encoded_get_byte_id(ta->pwd_tmp, ta->cursor.pos - 1); - _lv_txt_cut(ta->pwd_tmp, ta->cursor.pos - 1, _lv_txt_encoded_size(&ta->pwd_tmp[byte_pos])); + _lv_txt_cut(ta->pwd_tmp, ta->cursor.pos - 1, 1); ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, strlen(ta->pwd_tmp) + 1); LV_ASSERT_MALLOC(ta->pwd_tmp); @@ -291,7 +292,7 @@ void lv_textarea_set_text(lv_obj_t * obj, const char * txt) LV_ASSERT_OBJ(obj, MY_CLASS); LV_ASSERT_NULL(txt); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; /*Clear the existing selection*/ lv_textarea_clear_selection(obj); @@ -351,7 +352,7 @@ void lv_textarea_set_placeholder_text(lv_obj_t * obj, const char * txt) LV_ASSERT_OBJ(obj, MY_CLASS); LV_ASSERT_NULL(txt); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; size_t txt_len = strlen(txt); @@ -386,7 +387,7 @@ void lv_textarea_set_cursor_pos(lv_obj_t * obj, int32_t pos) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; if((uint32_t)ta->cursor.pos == (uint32_t)pos) return; uint32_t len = _lv_txt_get_encoded_length(lv_label_get_text(ta->label)); @@ -398,27 +399,24 @@ void lv_textarea_set_cursor_pos(lv_obj_t * obj, int32_t pos) ta->cursor.pos = pos; /*Position the label to make the cursor visible*/ - lv_point_t cur_pos; - const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_area_t label_cords; - lv_area_t ta_cords; - lv_label_get_letter_pos(ta->label, pos, &cur_pos); - lv_obj_get_coords(obj, &ta_cords); - lv_obj_get_coords(ta->label, &label_cords); + lv_obj_update_layout(obj); - /*The text area needs to have it's final size to see if the cursor is out of the area or not*/ - lv_obj_update_layout(obj); + lv_point_t cur_pos; + const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); + lv_label_get_letter_pos(ta->label, pos, &cur_pos); - /*Check the top*/ - lv_coord_t font_h = lv_font_get_line_height(font); - if(cur_pos.y < lv_obj_get_scroll_top(obj)) { - lv_obj_scroll_to_y(obj, cur_pos.y, LV_ANIM_ON); - } - /*Check the bottom*/ - lv_coord_t h = lv_obj_get_content_height(obj); - if(cur_pos.y + font_h - lv_obj_get_scroll_top(obj) > h) { - lv_obj_scroll_to_y(obj, cur_pos.y - h + font_h, LV_ANIM_ON); - } + /*The text area needs to have it's final size to see if the cursor is out of the area or not*/ + + /*Check the top*/ + lv_coord_t font_h = lv_font_get_line_height(font); + if(cur_pos.y < lv_obj_get_scroll_top(obj)) { + lv_obj_scroll_to_y(obj, cur_pos.y, LV_ANIM_ON); + } + /*Check the bottom*/ + lv_coord_t h = lv_obj_get_content_height(obj); + if(cur_pos.y + font_h - lv_obj_get_scroll_top(obj) > h) { + lv_obj_scroll_to_y(obj, cur_pos.y - h + font_h, LV_ANIM_ON); + } /*Check the left*/ if(cur_pos.x < lv_obj_get_scroll_left(obj)) { @@ -449,7 +447,7 @@ void lv_textarea_set_password_mode(lv_obj_t * obj, bool en) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; if(ta->pwd_mode == en) return; ta->pwd_mode = en == false ? 0 : 1; @@ -482,12 +480,13 @@ void lv_textarea_set_one_line(lv_obj_t * obj, bool en) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; if(ta->one_line == en) return; if(en) { ta->one_line = 1; lv_obj_set_width(ta->label, LV_SIZE_CONTENT); + lv_obj_set_style_min_width(ta->label, lv_pct(100), 0); lv_obj_set_height(obj, LV_SIZE_CONTENT); lv_obj_scroll_to(obj, 0, 0, LV_ANIM_OFF); @@ -495,6 +494,7 @@ void lv_textarea_set_one_line(lv_obj_t * obj, bool en) else { ta->one_line = 0; lv_obj_set_width(ta->label, lv_pct(100)); + lv_obj_set_style_min_width(ta->label, 0, 0); lv_obj_remove_local_style_prop(obj, LV_STYLE_HEIGHT, LV_PART_MAIN); lv_obj_scroll_to(obj, 0, 0, LV_ANIM_OFF); } @@ -504,7 +504,7 @@ void lv_textarea_set_accepted_chars(lv_obj_t * obj, const char * list) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; ta->accepted_chars = list; } @@ -513,7 +513,7 @@ void lv_textarea_set_max_length(lv_obj_t * obj, uint32_t num) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; ta->max_length = num; } @@ -531,14 +531,14 @@ void lv_textarea_set_text_selection(lv_obj_t * obj, bool en) LV_ASSERT_OBJ(obj, MY_CLASS); #if LV_LABEL_TEXT_SELECTION - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; ta->text_sel_en = en; if(!en) lv_textarea_clear_selection(obj); #else - (void)obj; /*Unused*/ - (void)en; /*Unused*/ + LV_UNUSED(obj); /*Unused*/ + LV_UNUSED(en); /*Unused*/ #endif } @@ -552,19 +552,20 @@ void lv_textarea_set_password_show_time(lv_obj_t * obj, uint16_t time) void lv_textarea_set_align(lv_obj_t * obj, lv_text_align_t align) { + LV_LOG_WARN("Deprecated: use the normal text_align style property instead"); lv_obj_set_style_text_align(obj, align, 0); switch(align) { - default: - case LV_TEXT_ALIGN_LEFT: - lv_obj_align(lv_textarea_get_label(obj), LV_ALIGN_TOP_LEFT, 0, 0); - break; - case LV_TEXT_ALIGN_RIGHT: - lv_obj_align(lv_textarea_get_label(obj), LV_ALIGN_TOP_RIGHT, 0, 0); - break; - case LV_TEXT_ALIGN_CENTER: - lv_obj_align(lv_textarea_get_label(obj), LV_ALIGN_TOP_MID, 0, 0); - break; + default: + case LV_TEXT_ALIGN_LEFT: + lv_obj_align(lv_textarea_get_label(obj), LV_ALIGN_TOP_LEFT, 0, 0); + break; + case LV_TEXT_ALIGN_RIGHT: + lv_obj_align(lv_textarea_get_label(obj), LV_ALIGN_TOP_RIGHT, 0, 0); + break; + case LV_TEXT_ALIGN_CENTER: + lv_obj_align(lv_textarea_get_label(obj), LV_ALIGN_TOP_MID, 0, 0); + break; } } @@ -576,7 +577,7 @@ const char * lv_textarea_get_text(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; const char * txt; if(ta->pwd_mode == 0) { @@ -593,7 +594,7 @@ const char * lv_textarea_get_placeholder_text(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; if(ta->placeholder_txt) return ta->placeholder_txt; else return ""; } @@ -602,7 +603,7 @@ lv_obj_t * lv_textarea_get_label(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; return ta->label; } @@ -610,7 +611,7 @@ uint32_t lv_textarea_get_cursor_pos(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; return ta->cursor.pos; } @@ -618,7 +619,7 @@ bool lv_textarea_get_cursor_click_pos(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; return ta->cursor.click_pos ? true : false; } @@ -626,7 +627,7 @@ bool lv_textarea_get_password_mode(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; return ta->pwd_mode == 0 ? false : true; } @@ -634,7 +635,7 @@ bool lv_textarea_get_one_line(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; return ta->one_line == 0 ? false : true; } @@ -642,7 +643,7 @@ const char * lv_textarea_get_accepted_chars(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; return ta->accepted_chars; } @@ -651,7 +652,7 @@ uint32_t lv_textarea_get_max_length(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; return ta->max_length; } @@ -660,17 +661,17 @@ bool lv_textarea_text_is_selected(const lv_obj_t * obj) LV_ASSERT_OBJ(obj, MY_CLASS); #if LV_LABEL_TEXT_SELECTION - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; - if((lv_label_get_text_selection_start(ta->label) == LV_DRAW_LABEL_NO_TXT_SEL || - lv_label_get_text_selection_end(ta->label) == LV_DRAW_LABEL_NO_TXT_SEL)) { + if((lv_label_get_text_selection_start(ta->label) != LV_DRAW_LABEL_NO_TXT_SEL || + lv_label_get_text_selection_end(ta->label) != LV_DRAW_LABEL_NO_TXT_SEL)) { return true; } else { return false; } #else - (void)obj; /*Unused*/ + LV_UNUSED(obj); /*Unused*/ return false; #endif } @@ -680,10 +681,10 @@ bool lv_textarea_get_text_selection(lv_obj_t * obj) LV_ASSERT_OBJ(obj, MY_CLASS); #if LV_LABEL_TEXT_SELECTION - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; return ta->text_sel_en; #else - (void)obj; /*Unused*/ + LV_UNUSED(obj); /*Unused*/ return false; #endif } @@ -692,7 +693,7 @@ uint16_t lv_textarea_get_password_show_time(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; return ta->pwd_show_time; } @@ -706,7 +707,7 @@ void lv_textarea_clear_selection(lv_obj_t * obj) LV_ASSERT_OBJ(obj, MY_CLASS); #if LV_LABEL_TEXT_SELECTION - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; if(lv_label_get_text_selection_start(ta->label) != LV_DRAW_LABEL_NO_TXT_SEL || lv_label_get_text_selection_end(ta->label) != LV_DRAW_LABEL_NO_TXT_SEL) { @@ -714,7 +715,7 @@ void lv_textarea_clear_selection(lv_obj_t * obj) lv_label_set_text_sel_end(ta->label, LV_DRAW_LABEL_NO_TXT_SEL); } #else - (void)obj; /*Unused*/ + LV_UNUSED(obj); /*Unused*/ #endif } @@ -742,7 +743,7 @@ void lv_textarea_cursor_down(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; lv_point_t pos; /*Get the position of the current letter*/ @@ -771,7 +772,7 @@ void lv_textarea_cursor_up(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; lv_point_t pos; /*Get the position of the current letter*/ @@ -808,7 +809,8 @@ static void lv_textarea_constructor(const lv_obj_class_t * class_p, lv_obj_t * o ta->accepted_chars = NULL; ta->max_length = 0; ta->cursor.show = 1; - ta->cursor.pos = 1; /*It will be set to zero later (with zero value lv_textarea_set_cursor_pos(obj, 0); woldn't do anything as there is no difference)*/ + /*It will be set to zero later (with zero value lv_textarea_set_cursor_pos(obj, 0); woldn't do anything as there is no difference)*/ + ta->cursor.pos = 1; ta->cursor.click_pos = 1; ta->cursor.valid_x = 0; ta->one_line = 0; @@ -821,6 +823,7 @@ static void lv_textarea_constructor(const lv_obj_class_t * class_p, lv_obj_t * o ta->label = lv_label_create(obj); lv_obj_set_width(ta->label, lv_pct(100)); lv_label_set_text(ta->label, ""); + lv_obj_add_event_cb(ta->label, label_event_cb, LV_EVENT_ALL, NULL); lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS); lv_textarea_set_cursor_pos(obj, 0); @@ -855,27 +858,10 @@ static void lv_textarea_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_event_code_t code = lv_event_get_code(e); lv_obj_t * obj = lv_event_get_target(e); - lv_textarea_t * ta = (lv_textarea_t *)obj; - if(code == LV_EVENT_STYLE_CHANGED) { - if(ta->label) { - lv_label_set_text(ta->label, NULL); - refr_cursor_area(obj); - start_cursor_blink(obj); - } - } - else if(code == LV_EVENT_FOCUSED) { + if(code == LV_EVENT_FOCUSED) { start_cursor_blink(obj); } - else if(code == LV_EVENT_SIZE_CHANGED) { - /*Set the label width according to the text area width*/ - if(ta->label) { - lv_obj_set_pos(ta->label, 0, 0); - lv_label_set_text(ta->label, NULL); /*Refresh the label*/ - - refr_cursor_area(obj); - } - } else if(code == LV_EVENT_KEY) { uint32_t c = *((uint32_t *)lv_event_get_param(e)); /*uint32_t because can be UTF-8*/ if(c == LV_KEY_RIGHT) @@ -912,6 +898,21 @@ static void lv_textarea_event(const lv_obj_class_t * class_p, lv_event_t * e) } } +static void label_event_cb(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * label = lv_event_get_target(e); + lv_obj_t * ta = lv_obj_get_parent(label); + + if(code == LV_EVENT_STYLE_CHANGED || code == LV_EVENT_SIZE_CHANGED) { + lv_label_set_text(label, NULL); + refr_cursor_area(ta); + start_cursor_blink(ta); + } +} + + + /** * Called to blink the cursor * @param ta pointer to a text area @@ -919,7 +920,7 @@ static void lv_textarea_event(const lv_obj_class_t * class_p, lv_event_t * e) */ static void cursor_blink_anim_cb(void * obj, int32_t show) { - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; if(show != ta->cursor.show) { ta->cursor.show = show == 0 ? 0 : 1; lv_area_t area_tmp; @@ -961,7 +962,7 @@ static void pwd_char_hider_anim_ready(lv_anim_t * a) */ static void pwd_char_hider(lv_obj_t * obj) { - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; if(ta->pwd_mode != 0) { char * txt = lv_label_get_text(ta->label); int32_t enc_len = _lv_txt_get_encoded_length(txt); @@ -999,10 +1000,10 @@ static void pwd_char_hider(lv_obj_t * obj) */ static bool char_is_accepted(lv_obj_t * obj, uint32_t c) { - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; /*If no restriction accept it*/ - if(ta->accepted_chars == NULL && ta->max_length == 0) return true; + if((ta->accepted_chars == NULL || ta->accepted_chars[0] == '\0') && ta->max_length == 0) return true; /*Too many characters?*/ if(ta->max_length > 0 && _lv_txt_get_encoded_length(lv_textarea_get_text(obj)) >= ta->max_length) { @@ -1032,7 +1033,8 @@ static void start_cursor_blink(lv_obj_t * obj) if(blink_time == 0) { lv_anim_del(obj, cursor_blink_anim_cb); ta->cursor.show = 1; - } else { + } + else { lv_anim_t a; lv_anim_init(&a); lv_anim_set_var(&a, ta); @@ -1076,14 +1078,11 @@ static void refr_cursor_area(lv_obj_t * obj) lv_point_t letter_pos; lv_label_get_letter_pos(ta->label, cur_pos, &letter_pos); - lv_text_align_t align = lv_obj_get_style_text_align(ta->label, LV_PART_MAIN); - if(align == LV_TEXT_ALIGN_AUTO) { - if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) align = LV_TEXT_ALIGN_RIGHT; - else align = LV_TEXT_ALIGN_LEFT; - } + lv_text_align_t align = lv_obj_calculate_style_text_align(ta->label, LV_PART_MAIN, lv_label_get_text(ta->label)); /*If the cursor is out of the text (most right) draw it to the next line*/ - if(letter_pos.x + ta->label->coords.x1 + letter_w > ta->label->coords.x2 && ta->one_line == 0 && align != LV_TEXT_ALIGN_RIGHT) { + if(letter_pos.x + ta->label->coords.x1 + letter_w > ta->label->coords.x2 && ta->one_line == 0 && + align != LV_TEXT_ALIGN_RIGHT) { letter_pos.x = 0; letter_pos.y += letter_h + line_space; @@ -1104,10 +1103,11 @@ static void refr_cursor_area(lv_obj_t * obj) ta->cursor.txt_byte_pos = byte_pos; /*Calculate the cursor according to its type*/ - lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_CURSOR); - lv_coord_t bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_CURSOR); - lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_CURSOR); - lv_coord_t right = lv_obj_get_style_pad_right(obj, LV_PART_CURSOR); + lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_CURSOR); + lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_CURSOR) + border_width; + lv_coord_t bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_CURSOR) + border_width; + lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_CURSOR) + border_width; + lv_coord_t right = lv_obj_get_style_pad_right(obj, LV_PART_CURSOR) + border_width; lv_area_t cur_area; cur_area.x1 = letter_pos.x - left; @@ -1141,7 +1141,7 @@ static void update_cursor_position_on_click(lv_event_t * e) lv_event_code_t code = lv_event_get_code(e); lv_obj_t * obj = lv_event_get_target(e); - lv_textarea_t * ta = (lv_textarea_t *)obj; + lv_textarea_t * ta = (lv_textarea_t *)obj; if(ta->cursor.click_pos == 0) return; if(lv_indev_get_type(click_source) == LV_INDEV_TYPE_KEYPAD || @@ -1253,7 +1253,7 @@ static void update_cursor_position_on_click(lv_event_t * e) static lv_res_t insert_handler(lv_obj_t * obj, const char * txt) { ta_insert_replace = NULL; - lv_event_send(obj, LV_EVENT_INSERT, (char*)txt); + lv_event_send(obj, LV_EVENT_INSERT, (char *)txt); if(ta_insert_replace) { if(ta_insert_replace[0] == '\0') return LV_RES_INV; /*Drop this text*/ @@ -1309,6 +1309,7 @@ static void draw_cursor(lv_event_t * e) lv_area_t cur_area; lv_area_copy(&cur_area, &ta->cursor.area); + cur_area.x1 += ta->label->coords.x1; cur_area.y1 += ta->label->coords.y1; cur_area.x2 += ta->label->coords.x1; @@ -1316,19 +1317,23 @@ static void draw_cursor(lv_event_t * e) lv_draw_rect(&cur_area, clip_area, &cur_dsc); + lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_CURSOR); + lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_CURSOR) + border_width; + lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_CURSOR) + border_width; char letter_buf[8] = {0}; lv_memcpy(letter_buf, &txt[ta->cursor.txt_byte_pos], _lv_txt_encoded_size(&txt[ta->cursor.txt_byte_pos])); - if(cur_dsc.bg_opa == LV_OPA_COVER) { - lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_CURSOR); - lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_CURSOR); - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_CURSOR); - cur_area.x1 += left + border_width; - cur_area.y1 += top + border_width; + cur_area.x1 += left; + cur_area.y1 += top; - lv_draw_label_dsc_t cur_label_dsc; - lv_draw_label_dsc_init(&cur_label_dsc); - lv_obj_init_draw_label_dsc(obj, LV_PART_CURSOR, &cur_label_dsc); + /*Draw the letter over the cursor only if + *the cursor has background or the letter has different color than the original. + *Else the original letter is drawn twice which makes it look bolder*/ + lv_color_t label_color = lv_obj_get_style_text_color(ta->label, 0); + lv_draw_label_dsc_t cur_label_dsc; + lv_draw_label_dsc_init(&cur_label_dsc); + lv_obj_init_draw_label_dsc(obj, LV_PART_CURSOR, &cur_label_dsc); + if(cur_dsc.bg_opa > LV_OPA_MIN || cur_label_dsc.color.full != label_color.full) { lv_draw_label(&cur_area, clip_area, &cur_label_dsc, letter_buf, NULL); } } diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_textarea.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.h similarity index 99% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_textarea.h rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.h index 0964416d4..2ab48f0ab 100644 --- a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_textarea.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.h @@ -199,6 +199,7 @@ void lv_textarea_set_text_selection(lv_obj_t * obj, bool en); void lv_textarea_set_password_show_time(lv_obj_t * obj, uint16_t time); /** + * Deprecated: use the normal text_align style property instead * Set the label's alignment. * It sets where the label is aligned (in one line mode it can be smaller than the text area) * and how the lines of the area align in case of multiline text area diff --git a/lib/libesp32_lvgl/LVGL8/src/widgets/lv_widgets.mk b/lib/libesp32_lvgl/lvgl/src/widgets/lv_widgets.mk similarity index 100% rename from lib/libesp32_lvgl/LVGL8/src/widgets/lv_widgets.mk rename to lib/libesp32_lvgl/lvgl/src/widgets/lv_widgets.mk diff --git a/pio-tools/add_c_flags.py b/pio-tools/add_c_flags.py new file mode 100644 index 000000000..0c39e777f --- /dev/null +++ b/pio-tools/add_c_flags.py @@ -0,0 +1,4 @@ +Import("env") + +# General options that are passed to the C compiler (C only; not C++). +env.Append(CFLAGS=["-Wno-discarded-qualifiers", "-Wno-implicit-function-declaration"]) diff --git a/pio-tools/name-firmware.py b/pio-tools/name-firmware.py index b49def236..dcb1e9d30 100644 --- a/pio-tools/name-firmware.py +++ b/pio-tools/name-firmware.py @@ -14,6 +14,12 @@ def bin_map_copy(source, target, env): map_file = tasmotapiolib.get_final_map_path(env) bin_file = tasmotapiolib.get_final_bin_path(env) + if env["PIOPLATFORM"] == "espressif32": + factory_tmp = pathlib.Path(firsttarget).with_suffix("") + factory = factory_tmp.with_suffix(factory_tmp.suffix + ".factory.bin") + one_bin_tmp = pathlib.Path(bin_file).with_suffix("") + one_bin_file = one_bin_tmp.with_suffix(one_bin_tmp.suffix + ".factory.bin") + # check if new target files exist and remove if necessary for f in [map_file, bin_file]: if f.is_file(): @@ -22,6 +28,7 @@ def bin_map_copy(source, target, env): # copy firmware.bin and map to final destination shutil.copy(firsttarget, bin_file) shutil.move(tasmotapiolib.get_source_map_path(env), map_file) - + if env["PIOPLATFORM"] == "espressif32": + shutil.copy(factory, one_bin_file) env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", bin_map_copy) diff --git a/pio-tools/obj-dump.py b/pio-tools/obj-dump.py index 91bc3de58..359c76a80 100644 --- a/pio-tools/obj-dump.py +++ b/pio-tools/obj-dump.py @@ -3,7 +3,18 @@ Import('env') def obj_dump_after_elf(source, target, env): + platform = env.PioPlatform() + board = env.BoardConfig() + mcu = board.get("build.mcu", "esp32") + print("Create firmware.asm") - env.Execute("xtensa-lx106-elf-objdump "+ "-D " + str(target[0]) + " > "+ "${PROGNAME}.asm") - + if mcu == "esp8266": + env.Execute("xtensa-lx106-elf-objdump "+ "-D -C " + str(target[0]) + " > "+ "$BUILD_DIR/${PROGNAME}.asm") + if mcu == "esp32": + env.Execute("xtensa-esp32-elf-objdump "+ "-D -C " + str(target[0]) + " > "+ "$BUILD_DIR/${PROGNAME}.asm") + if mcu == "esp32s2": + env.Execute("xtensa-esp32s2-elf-objdump "+ "-D -C " + str(target[0]) + " > "+ "$BUILD_DIR/${PROGNAME}.asm") + if mcu == "esp32c3": + env.Execute("riscv32-esp-elf-objdump "+ "-D -C " + str(target[0]) + " > "+ "$BUILD_DIR/${PROGNAME}.asm") + env.AddPostAction("$BUILD_DIR/${PROGNAME}.elf", [obj_dump_after_elf]) diff --git a/pio-tools/post_esp32.py b/pio-tools/post_esp32.py new file mode 100644 index 000000000..662d011d8 --- /dev/null +++ b/pio-tools/post_esp32.py @@ -0,0 +1,65 @@ +# From: https://github.com/letscontrolit/ESPEasy/blob/mega/tools/pio/post_esp32.py +# Thanks TD-er :) + +# Combines separate bin files with their respective offsets into a single file +# This single file must then be flashed to an ESP32 node with 0 offset. +# +# Original implementation: Bartłomiej Zimoń (@uzi18) +# +# Special thanks to @Jason2866 for helping debug flashing to >4MB flash +# Thanks @jesserockz (esphome) for adapting to use esptool.py with merge_bin +# +# Typical layout of the generated file: +# Offset | File +# - 0x1000 | ~\.platformio\packages\framework-arduinoespressif32\tools\sdk\esp32\bin\bootloader_dout_40m.bin +# - 0x8000 | ~\Tasmota\.pio\build\\partitions.bin +# - 0xe000 | ~\.platformio\packages\framework-arduinoespressif32\tools\partitions\boot_app0.bin +# - 0x10000 | ~\Tasmota\.pio\build\/firmware.bin + +Import("env") + +platform = env.PioPlatform() + +import sys +from os.path import join + +sys.path.append(join(platform.get_package_dir("tool-esptoolpy"))) +import esptool + +def esp32_create_combined_bin(source, target, env): + #print("Generating combined binary for serial flashing") + + # The offset from begin of the file where the app0 partition starts + # This is defined in the partition .csv file + app_offset = 0x10000 + + new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.factory.bin") + sections = env.subst(env.get("FLASH_EXTRA_IMAGES")) + firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin") + chip = env.get("BOARD_MCU") + flash_size = env.BoardConfig().get("upload.flash_size") + cmd = [ + "--chip", + chip, + "merge_bin", + "-o", + new_file_name, + "--flash_size", + flash_size, + ] + + print(" Offset | File") + for section in sections: + sect_adr, sect_file = section.split(" ", 1) + print(f" - {sect_adr} | {sect_file}") + cmd += [sect_adr, sect_file] + + print(f" - {hex(app_offset)} | {firmware_name}") + cmd += [hex(app_offset), firmware_name] + + #print('Using esptool.py arguments: %s' % ' '.join(cmd)) + + esptool.main(cmd) + + +env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_create_combined_bin) diff --git a/platformio.ini b/platformio.ini index fdb0e328a..6b77f47c1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -23,6 +23,7 @@ extra_configs = platformio_tasmota32.ini platformio_tasmota_env.ini platformio_tasmota_env32.ini platformio_override.ini + platformio_tasmota_cenv.ini [common] platform = ${core.platform} @@ -38,7 +39,7 @@ monitor_port = COM5 ; *** Upload Serial reset method for Wemos and NodeMCU upload_resetmethod = nodemcu upload_port = COM5 -extra_scripts = ${scripts_defaults.extra_scripts} +extra_scripts = ${esp_defaults.extra_scripts} lib_ldf_mode = chain lib_compat_mode = strict shared_libdeps_dir = lib @@ -70,6 +71,7 @@ extra_scripts = pio-tools/strip-floats.py pio-tools/download_fs.py [esp_defaults] +extra_scripts = ${scripts_defaults.extra_scripts} ; *** remove undesired all warnings build_unflags = -Wall ; -mtarget-align @@ -106,9 +108,8 @@ build_flags = ${esp_defaults.build_flags} [core] ; *** Esp8266 Tasmota modified Arduino core based on core 2.7.4. Added Backport for PWM selection -platform = espressif8266 @ 2.6.3 -platform_packages = tasmota/framework-arduinoespressif8266 @ ~2.7.4 - platformio/tool-esptoolpy @ ~1.30100 +platform = https://github.com/tasmota/platform-espressif8266/releases/download/v2.7.4.9/platform-espressif8266-2.7.4.9.zip +platform_packages = build_unflags = ${esp_defaults.build_unflags} build_flags = ${esp82xx_defaults.build_flags} ; *** Use ONE of the two PWM variants. Tasmota default is Locked PWM diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 3bbbc9f44..e22ad911b 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -11,7 +11,6 @@ [platformio] ; For best Gitpod performance remove the ";" in the next line. Needed Platformio files are cached and installed at first run ;core_dir = .platformio -extra_configs = platformio_tasmota_cenv.ini ; *** Build/upload environment default_envs = @@ -42,8 +41,9 @@ default_envs = [env] ; Activate Development core by removing ";" the next lines ;platform = https://github.com/platformio/platform-espressif8266.git -;platform_packages = ${common.platform_packages} -; framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git +;platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git +; mcspr/toolchain-xtensa @ ~5.100300.211127 +; platformio/tool-esptoolpy @ ~1.30100 ;build_unflags = ${common.build_unflags} ; -Wswitch-unreachable ;build_flags = ${common.build_flags} @@ -64,7 +64,7 @@ board = ${common.board} ;monitor_speed = 115200 ; *** Serial port used for erasing/flashing the ESP82xx ;upload_port = COM5 -extra_scripts = ${scripts_defaults.extra_scripts} +extra_scripts = ${esp_defaults.extra_scripts} ; pio-tools/obj-dump.py lib_ldf_mode = ${common.lib_ldf_mode} lib_compat_mode = ${common.lib_compat_mode} @@ -90,12 +90,12 @@ lib_extra_dirs = ${library.lib_extra_dirs} [env:tasmota32_base] ; *** Uncomment next line ";" to enable development Tasmota Arduino version ESP32 -;platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/525/framework-arduinoespressif32-release_v4.4-7cac8278e.tar.gz +;platform = https://github.com/Jason2866/platform-espressif32/releases/download/v2.0.2.1/platform-espressif32-2.0.2.1.zip build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} ; Build variant ESP32 4M Flash, Tasmota 1856k Code/OTA, 320k LITTLEFS (default) -board = esp32_4M +;board = esp32_4M ; Build variant ESP32 8M Flash, Tasmota 2944k Code/OTA, 2112k LITTLEFS ;board = esp32_8M ; Build variant ESP32 16M Flash, Tasmota 2944k Code/OTA, 10M LITTLEFS @@ -108,9 +108,8 @@ monitor_speed = 115200 upload_port = COM4 ;upload_speed = 115200 upload_resetmethod = ${common.upload_resetmethod} -extra_scripts = ${common.extra_scripts} -lib_ldf_mode = ${common.lib_ldf_mode} -lib_compat_mode = ${common.lib_compat_mode} +extra_scripts = ${esp32_defaults.extra_scripts} +; pio-tools/obj-dump.py lib_ignore = ESP32 Azure IoT Arduino ESP32 Async UDP diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 575f9d160..a27266b38 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -7,11 +7,13 @@ build_unflags = ${esp_defaults.build_unflags} -Wincompatible-pointer-types -Wnonnull-compare -fexceptions + -fno-lto -Wpointer-arith build_flags = ${esp_defaults.build_flags} -Wno-switch-unreachable -Wno-stringop-overflow -fno-exceptions + -flto -DBUFFER_LENGTH=128 -DHTTP_UPLOAD_BUFLEN=2048 -DMQTT_MAX_PACKET_SIZE=1200 @@ -30,16 +32,20 @@ build_flags = ${esp_defaults.build_flags} -include "esp32x_fixes.h" ; wrappers for the crash-recorder -Wl,--wrap=panicHandler -Wl,--wrap=xt_unhandled_exception + -Wl,--wrap=_Z11analogWritehi ; `analogWrite(unsigned char, int)` use the Tasmota version of analogWrite for deeper integration and phase control +extra_scripts = pre:pio-tools/add_c_flags.py + post:pio-tools/post_esp32.py + ${esp_defaults.extra_scripts} [core32] -platform = https://github.com/tasmota/platform-espressif32/releases/download/v3.4.1/Tasmota-platform-espressif32.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.2/platform-tasmota-espressif32-2.0.2.zip platform_packages = build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} [core32solo1] -platform = https://github.com/tasmota/platform-espressif32/releases/download/v3.4.1/Tasmota-platform-espressif32.zip -platform_packages = framework-arduinoespressif32 @ https://github.com/tasmota/arduino-esp32/releases/download/2.0.1.1/framework-arduinoespressif32-solo1-release_IDF4.4.tar.gz +platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.2solo1/platform-tasmota-espressif32-2.0.2solo1.zip +platform_packages = build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} diff --git a/platformio_tasmota_cenv_sample.ini b/platformio_tasmota_cenv_sample.ini index ea5114455..798c58bab 100644 --- a/platformio_tasmota_cenv_sample.ini +++ b/platformio_tasmota_cenv_sample.ini @@ -1,15 +1,3 @@ -;*** Beta Tasmota version for ESP32-S2 -[env:tasmota32s2] -extends = env:tasmota32_base -board = esp32s2 -build_flags = ${env:tasmota32_base.build_flags} -D FIRMWARE_TASMOTA32 -lib_ignore = - ESP8266Audio - ESP8266SAM - TTGO TWatch Library - NimBLE-Arduino - epdiy - [env:tasmota-rangeextender] build_flags = ${env.build_flags} -D FIRMWARE_RANGE_EXTENDER @@ -36,27 +24,31 @@ extends = env:tasmota32_base build_type = debug build_unflags = ${env:tasmota32_base.build_unflags} build_flags = ${env:tasmota32_base.build_flags} +monitor_filters = esp32_exception_decoder ; -Wstack-usage=300 ; *** JTAG Debug version, needs esp-prog or FT2232H or FT232H ; *** Install howto for Windows https://community.platformio.org/t/esp32-pio-unified-debugger/4541/20 [env:tasmota32-ocd] -;build_type = debug +build_type = debug extends = env:tasmota32_base debug_tool = esp-prog upload_protocol = esp-prog debug_init_break = tbreak setup build_unflags = ${env:tasmota32_base.build_unflags} build_flags = ${env:tasmota32_base.build_flags} +monitor_filters = esp32_exception_decoder ; *** JTAG Debug version, needs esp-prog or FT2232H or FT232H [env:tasmota32solo1-ocd] -;build_type = debug -extends = env:tasmota32_base +build_type = debug +extends = env:tasmota32solo1 +platform = ${core32solo1.platform} platform_packages = ${core32solo1.platform_packages} board = esp32_solo1_4M debug_tool = esp-prog upload_protocol = esp-prog debug_init_break = tbreak setup -build_unflags = ${env:tasmota32_base.build_unflags} -build_flags = ${env:tasmota32_base.build_flags} +build_unflags = ${core32solo1.build_unflags} +build_flags = ${core32solo1.build_flags} +monitor_filters = esp32_exception_decoder diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index 68d4b17e4..e2ce02124 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -68,6 +68,12 @@ build_flags = ${env.build_flags} -DUSE_ZIGBEE -DUSE_CCLOADER -DUSE_U board = esp8266_4M2M board_build.f_cpu = 160000000L +[env:tasmota3] +platform = espressif8266 +platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git + mcspr/toolchain-xtensa @ ~5.100300.211127 + platformio/tool-esptoolpy @ ~1.30100 + [env:tasmota-AF] build_flags = ${env.build_flags} -DMY_LANGUAGE=af_AF diff --git a/platformio_tasmota_env32.ini b/platformio_tasmota_env32.ini index 380fac213..f623f135d 100644 --- a/platformio_tasmota_env32.ini +++ b/platformio_tasmota_env32.ini @@ -8,7 +8,7 @@ board = esp32_4M monitor_speed = 115200 upload_port = ${common.upload_port} upload_resetmethod = ${common.upload_resetmethod} -extra_scripts = ${common.extra_scripts} +extra_scripts = ${esp32_defaults.extra_scripts} build_unflags = ${core32.build_unflags} build_flags = ${core32.build_flags} lib_ldf_mode = ${common.lib_ldf_mode} @@ -49,24 +49,26 @@ build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_TASMOTA32 [env:tasmota32solo1] extends = env:tasmota32_base +board = esp32_solo1_4M +platform = ${core32solo1.platform} platform_packages = ${core32solo1.platform_packages} -build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_TASMOTA32 +build_flags = ${core32solo1.build_flags} -DFIRMWARE_TASMOTA32 [env:tasmota32-webcam] extends = env:tasmota32_base board = esp32-cam build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_WEBCAM -lib_extra_dirs = lib/libesp32 +lib_extra_dirs = lib/lib_ssl, lib/libesp32 [env:tasmota32-odroidgo] extends = env:tasmota32_base board = esp32-odroid -build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_ODROID_GO -DUSE_UNIVERSAL_DISPLAY -DUSE_AUTOCONF +build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_ODROID_GO -DUSE_UNIVERSAL_DISPLAY [env:tasmota32-core2] extends = env:tasmota32_base board = esp32-m5core2 -build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_M5STACK_CORE2 -DUSE_UNIVERSAL_DISPLAY -DUSE_AUTOCONF +build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_M5STACK_CORE2 -DUSE_UNIVERSAL_DISPLAY lib_extra_dirs = lib/libesp32, lib/libesp32_lvgl, lib/lib_basic, lib/lib_i2c, lib/lib_rf, lib/lib_div, lib/lib_ssl, lib/lib_display, lib/lib_audio [env:tasmota32-bluetooth] @@ -77,32 +79,42 @@ lib_extra_dirs = lib/libesp32, lib/libesp32_div, lib/lib_basic, lib/lib [env:tasmota32-display] extends = env:tasmota32_base build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_DISPLAYS -lib_extra_dirs = lib/libesp32, lib/lib_basic, lib/lib_display +lib_extra_dirs = lib/libesp32, lib/lib_basic, lib/lib_display, lib/lib_ssl [env:tasmota32-lvgl] extends = env:tasmota32_base -build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_LVGL -DUSE_AUTOCONF +build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_LVGL board_build.f_cpu = 160000000L lib_extra_dirs = lib/libesp32, lib/libesp32_lvgl, lib/lib_basic, lib/lib_i2c, lib/lib_rf, lib/lib_div, lib/lib_ssl, lib/lib_display [env:tasmota32-ir] extends = env:tasmota32_base build_flags = ${env:tasmota32_base.build_flags} -DUSE_IR_REMOTE_FULL -DFIRMWARE_IR -lib_extra_dirs = lib/libesp32, lib/lib_basic +lib_extra_dirs = lib/libesp32, lib/lib_basic, lib/lib_ssl [env:tasmota32c3] extends = env:tasmota32_base board = esp32c3 build_unflags = ${env:tasmota32_base.build_unflags} + -flto -mtarget-align build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_TASMOTA32 + -fno-lto lib_ignore = - ESP8266Audio - ESP8266SAM TTGO TWatch Library Micro-RTSP epdiy +[env:tasmota32s2] +extends = env:tasmota32_base +board = esp32s2 +build_flags = ${env:tasmota32_base.build_flags} -D FIRMWARE_TASMOTA32 +lib_ignore = + TTGO TWatch Library + NimBLE-Arduino + Micro-RTSP + epdiy + [env:tasmota32-AF] extends = env:tasmota32_base build_flags = ${env:tasmota32_base.build_flags} -DMY_LANGUAGE=af_AF -DFIRMWARE_TASMOTA32 diff --git a/tasmota/berry/drivers/i2c_axp192_M5StackCore2.be b/tasmota/berry/drivers/i2c_axp192_M5StackCore2.be index 79e6ee7f6..212fc8e32 100644 --- a/tasmota/berry/drivers/i2c_axp192_M5StackCore2.be +++ b/tasmota/berry/drivers/i2c_axp192_M5StackCore2.be @@ -67,9 +67,9 @@ class AXP192_M5Stack_Core2 : AXP192 # Reset LCD Controller self.set_lcd_reset(false) - self.get_tasmota().delay(100) # wait for 100ms + tasmota.delay(100) # wait for 100ms self.set_lcd_reset(true) - self.get_tasmota().delay(100) # wait for 100ms + tasmota.delay(100) # wait for 100ms # bus power mode_output self.set_buf_power_mode(false) diff --git a/tasmota/berry/include/be_gpio_defines.h b/tasmota/berry/include/be_gpio_defines.h index 73f37825e..8906f90a0 100644 --- a/tasmota/berry/include/be_gpio_defines.h +++ b/tasmota/berry/include/be_gpio_defines.h @@ -2,7 +2,7 @@ * Generated code, don't edit *******************************************************************/ -const be_constint_t lv_gpio_constants[] = { +const be_const_member_t lv_gpio_constants[] = { { "A4988_DIR", (int32_t) GPIO_A4988_DIR }, { "A4988_ENA", (int32_t) GPIO_A4988_ENA }, @@ -14,6 +14,7 @@ const be_constint_t lv_gpio_constants[] = { { "ADC_INPUT", (int32_t) GPIO_ADC_INPUT }, { "ADC_JOY", (int32_t) GPIO_ADC_JOY }, { "ADC_LIGHT", (int32_t) GPIO_ADC_LIGHT }, + { "ADC_MQ", (int32_t) GPIO_ADC_MQ }, { "ADC_PH", (int32_t) GPIO_ADC_PH }, { "ADC_RANGE", (int32_t) GPIO_ADC_RANGE }, { "ADC_TEMP", (int32_t) GPIO_ADC_TEMP }, diff --git a/tasmota/berry/internal/gpio.be b/tasmota/berry/internal/gpio.be index 3c589a046..a1816dfc7 100644 --- a/tasmota/berry/internal/gpio.be +++ b/tasmota/berry/internal/gpio.be @@ -254,3 +254,4 @@ gpio.TFMINIPLUS_RX = 235 gpio.ZEROCROSS = 236 gpio.HALLEFFECT = 237 gpio.SENSOR_END = 238 +gpio.ADC_MQ = 239 diff --git a/tasmota/berry/lvgl_examples/lvgl_demo.be b/tasmota/berry/lvgl_examples/lvgl_demo.be index 3aa1bc292..7e5754e5f 100644 --- a/tasmota/berry/lvgl_examples/lvgl_demo.be +++ b/tasmota/berry/lvgl_examples/lvgl_demo.be @@ -26,8 +26,8 @@ stat_line.refr_size() stat_line.refr_pos() # new in LVGL8 #- display wifi strength indicator icon (for professionals ;) -# -wifi_icon = lv_wifi_arcs_icon(stat_line) # the widget takes care of positioning and driver stuff -clock_icon = lv_clock_icon(stat_line) +wifi_icon = lv.wifi_arcs_icon(stat_line) # the widget takes care of positioning and driver stuff +clock_icon = lv.clock_icon(stat_line) #- create a style for the buttons -# btn_style = lv.style() diff --git a/tasmota/berry/lvgl_examples/robotocondensed_latin1.tapp b/tasmota/berry/lvgl_examples/robotocondensed_latin1.tapp new file mode 100644 index 000000000..bf714bc6e Binary files /dev/null and b/tasmota/berry/lvgl_examples/robotocondensed_latin1.tapp differ diff --git a/tasmota/berry/lvgl_examples/test_grid.be b/tasmota/berry/lvgl_examples/test_grid.be new file mode 100644 index 000000000..54022fdc8 --- /dev/null +++ b/tasmota/berry/lvgl_examples/test_grid.be @@ -0,0 +1,83 @@ +# demo of gird layout + +lv.start() + +var col_dsc = lv.coord_arr([90, 90, 90, lv.GRID_TEMPLATE_LAST]) +var row_dsc = lv.coord_arr([15, 15, 15, lv.GRID_TEMPLATE_LAST]) +var scr = lv.scr_act() + +var cont = lv.obj(scr) + +cont.set_grid_dsc_array(col_dsc, row_dsc) +# replaces +# cont.set_style_grid_column_dsc_array(col_dsc, 0) +# cont.set_style_grid_row_dsc_array(row_dsc, 0) +# cont.set_layout(lv.LAYOUT_GRID) +cont.set_size(320, 240) +cont.center() + +var zone_name = 0 +var zone_mode = 1 +var zone_power = 2 +var zone_until = 3 + +var z1col = 0 +var z2col = 1 +var z3col = 2 + +# Zone Name + +var lbl_z1_name = lv.label(cont) +var lbl_z2_name = lv.label(cont) +var lbl_z3_name = lv.label(cont) + +lbl_z1_name.set_grid_cell(lv.GRID_ALIGN_CENTER, z1col, 1, lv.GRID_ALIGN_STRETCH, zone_name, 1) +lbl_z1_name.set_text("HTG 1") +lbl_z1_name.center() + +lbl_z2_name.set_grid_cell(lv.GRID_ALIGN_CENTER, z2col, 1, lv.GRID_ALIGN_STRETCH, zone_name, 1) +lbl_z2_name.set_text("HTG 2") +lbl_z2_name.center() + +lbl_z3_name.set_grid_cell(lv.GRID_ALIGN_CENTER, z3col, 1, lv.GRID_ALIGN_STRETCH, zone_name, 1) +lbl_z3_name.set_text("HTG 1") +lbl_z3_name.center() + +# Zone Mode + +var lbl_z1_mode = lv.label(cont) +var lbl_z2_mode = lv.label(cont) +var lbl_z3_mode = lv.label(cont) + +lbl_z1_mode.set_grid_cell(lv.GRID_ALIGN_CENTER, z1col, 1, lv.GRID_ALIGN_STRETCH, zone_mode, 1) +lbl_z1_mode.set_text("Auto") +lbl_z1_mode.center() + +lbl_z2_mode.set_grid_cell(lv.GRID_ALIGN_CENTER, z2col, 1, lv.GRID_ALIGN_STRETCH, zone_mode, 1) +lbl_z2_mode.set_text("Allday") +lbl_z2_mode.center() + +lbl_z3_mode.set_grid_cell(lv.GRID_ALIGN_CENTER, z3col, 1, lv.GRID_ALIGN_STRETCH, zone_mode, 1) +lbl_z3_mode.set_text("Auto") +lbl_z3_mode.center() + +# Zone Power + +var lbl_z1_power = lv.label(cont) +var lbl_z2_power = lv.label(cont) +var lbl_z3_power = lv.label(cont) + +lbl_z1_power.set_grid_cell(lv.GRID_ALIGN_CENTER, z1col, 1, lv.GRID_ALIGN_STRETCH, zone_power, 1) +lbl_z1_power.set_recolor(True) +lbl_z1_power.set_text("#ff0000 Off# Until") +lbl_z1_power.center() + +lbl_z2_power.set_grid_cell(lv.GRID_ALIGN_CENTER, z2col, 1, lv.GRID_ALIGN_STRETCH, zone_power, 1) +lbl_z2_power.set_recolor(True) +lbl_z2_power.set_text("#0000ff On# Until") +lbl_z2_power.center() + +lbl_z3_power.set_grid_cell(lv.GRID_ALIGN_CENTER, z3col, 1, lv.GRID_ALIGN_STRETCH, zone_power, 1) +lbl_z3_power.set_recolor(True) +lbl_z3_power.set_text("#ff0000 Off# Until") +lbl_z3_power.center() \ No newline at end of file diff --git a/tasmota/berry/lvgl_examples/widget_test.be b/tasmota/berry/lvgl_examples/widget_test.be index 06060d1c5..3fa2ee7e8 100644 --- a/tasmota/berry/lvgl_examples/widget_test.be +++ b/tasmota/berry/lvgl_examples/widget_test.be @@ -23,9 +23,10 @@ def eventcb(class_p, e) print(string.format("> event class_p=0x%08X event=%s obj=%s code=%i", class_p, str(event), str(obj), event_code)) end -var cb_ctor = tasmota.gen_cb(ctorcb) -var cb_dtor = tasmota.gen_cb(dtorcb) -var cb_event = tasmota.gen_cb(eventcb) +import cb +var cb_ctor = cb.gen_cb(ctorcb) +var cb_dtor = cb.gen_cb(dtorcb) +var cb_event = cb.gen_cb(eventcb) # static void lv_img_event(const lv_obj_class_t * class_p, lv_event_t * e) diff --git a/tasmota/berry/modules/DisplayCalibrate.tapp b/tasmota/berry/modules/DisplayCalibrate.tapp new file mode 100644 index 000000000..7a8b80e72 Binary files /dev/null and b/tasmota/berry/modules/DisplayCalibrate.tapp differ diff --git a/tasmota/berry/modules/partition.be b/tasmota/berry/modules/partition.be index db9773424..50bd00bd8 100644 --- a/tasmota/berry/modules/partition.be +++ b/tasmota/berry/modules/partition.be @@ -1,77 +1,27 @@ -#------------------------------------------------------------- - - Parser for ESP32 partition - - - -------------------------------------------------------------# -partition = module('partition') +####################################################################### +# Partition manager for ESP32 - ESP32C3 - ESP32S2 +# +# use : `import partition` +# +# Provides low-level objects and a Web UI +####################################################################### -import flash -import string -import webserver +var partition = module('partition') -#- remove trailing NULL chars from a buffer before converting to string -# -#- Berry strings can contain NULL, but this messes up C-Berry interface -# -def remove_trailing_zeroes(b) - while size(b) > 0 - if b.get(size(b)-1,1) == 0 - b.resize(size(b)-1) - else - break - end - end - return b -end - - -#------------------------------------------------------------- - - Simple CRC32 imple - - - - adapted from Python https://rosettacode.org/wiki/CRC-32#Python - -------------------------------------------------------------# -def crc32_create_table() - var a = [] - for i:0..255 - var k = i - for j:0..7 - if k & 1 - k = (k >> 1) & 0x7FFFFFFF - k ^= 0xedb88320 - else - k = (k >> 1) & 0x7FFFFFFF - end - end - a.push(k) - end - return a -end - -var crc32_table = crc32_create_table() - -def crc32_update(buf, crc) - crc ^= 0xffffffff - for k:0..size(buf)-1 - crc = (crc >> 8 & 0x00FFFFFF) ^ crc32_table[(crc & 0xff) ^ buf[k]] - end - return crc ^ 0xffffffff -end - -#- crc32 for ota_seq as 32 bits unsigned, with init vector -1 -# -def crc32_ota_seq(seq) - return crc32_update(bytes().add(seq, 4), 0xFFFFFFFF) -end - -#------------------------------------------------------------- - - Class for a partition table entry - - - typedef struct { - uint16_t magic; - uint8_t type; - uint8_t subtype; - uint32_t offset; - uint32_t size; - uint8_t label[16]; - uint32_t flags; - } esp_partition_info_t_simplified; - -------------------------------------------------------------# +####################################################################### +# Class for a partition table entry +# +# typedef struct { +# uint16_t magic; +# uint8_t type; +# uint8_t subtype; +# uint32_t offset; +# uint32_t size; +# uint8_t label[16]; +# uint32_t flags; +# } esp_partition_info_t_simplified; +# +####################################################################### class Partition_info var type var subtype @@ -80,8 +30,19 @@ class Partition_info var label var flags + #- remove trailing NULL chars from a buffer before converting to string -# + #- Berry strings can contain NULL, but this messes up C-Berry interface -# + static def remove_trailing_zeroes(b) + while size(b) > 0 + if b[-1] == 0 b.resize(size(b)-1) + else break end + end + return b + end + + # def init(raw) - if raw == nil || !issubclass(bytes, raw) + if raw == nil || !issubclass(bytes, raw) # no payload, empty partition information self.type = 0 self.subtype = 0 self.start = 0 @@ -91,7 +52,7 @@ class Partition_info return end - #- parse -# + #- we have a payload, parse it -# var magic = raw.get(0,2) if magic == 0x50AA #- partition entry -# @@ -99,11 +60,12 @@ class Partition_info self.subtype = raw.get(3,1) self.start = raw.get(4,4) self.size = raw.get(8,4) - self.label = remove_trailing_zeroes(raw[12..27]).asstring() + self.label = self.remove_trailing_zeroes(raw[12..27]).asstring() self.flags = raw.get(28,4) elif magic == 0xEBEB #- MD5 -# else + import string raise "internal_error", string.format("invalid magic number %02X", magic) end @@ -127,6 +89,7 @@ class Partition_info # get the actual image size give of the partition # returns -1 if the partition is not an app ota partition def get_image_size() + import flash if self.is_ota() == nil return -1 end try var addr = self.start @@ -153,7 +116,7 @@ class Partition_info return total_size except .. as e, m - print(string.format("BRY: Exception> '%s' - %s", e, m)) + print("BRY: Exception> '" + e + "' - " + m) return -1 end end @@ -206,7 +169,7 @@ class Partition_info end end - +partition.Partition_info = Partition_info #------------------------------------------------------------- - OTA Data @@ -244,6 +207,45 @@ class Partition_otadata var seq0 #- ota_seq of first block -# var seq1 #- ota_seq of second block -# + #------------------------------------------------------------- + - Simple CRC32 imple + - + - adapted from Python https://rosettacode.org/wiki/CRC-32#Python + -------------------------------------------------------------# + static def crc32_create_table() + var a = [] + for i:0..255 + var k = i + for j:0..7 + if k & 1 + k = (k >> 1) & 0x7FFFFFFF + k ^= 0xedb88320 + else + k = (k >> 1) & 0x7FFFFFFF + end + end + a.push(k) + end + return a + end + static crc32_table = Partition_otadata.crc32_create_table() + + static def crc32_update(buf, crc) + crc ^= 0xffffffff + for k:0..size(buf)-1 + crc = (crc >> 8 & 0x00FFFFFF) ^ Partition_otadata.crc32_table[(crc & 0xff) ^ buf[k]] + end + return crc ^ 0xffffffff + end + + #- crc32 for ota_seq as 32 bits unsigned, with init vector -1 -# + static def crc32_ota_seq(seq) + return Partition_otadata.crc32_update(bytes().add(seq, 4), 0xFFFFFFFF) + end + + #---------------------------------------------------------------------# + # Rest of the class + #---------------------------------------------------------------------# def init(maxota, offset) self.maxota = maxota if self.maxota == nil self.maxota = 1 end @@ -258,6 +260,7 @@ class Partition_otadata self.maxota = n end + # change the active OTA partition def set_active(n) var seq_max = 0 #- current highest seq number -# var block_act = 0 #- block number containing the highest seq number -# @@ -286,17 +289,17 @@ class Partition_otadata end self._validate() end - end - #- load otadata -# + #- load otadata from SPI Flash -# def load() + import flash var otadata0 = flash.read(0xE000, 32) var otadata1 = flash.read(0xF000, 32) self.seq0 = otadata0.get(0, 4) #- ota_seq for block 1 -# self.seq1 = otadata1.get(0, 4) #- ota_seq for block 2 -# - var valid0 = otadata0.get(28, 4) == crc32_ota_seq(self.seq0) #- is CRC32 valid? -# - var valid1 = otadata1.get(28, 4) == crc32_ota_seq(self.seq1) #- is CRC32 valid? -# + var valid0 = otadata0.get(28, 4) == self.crc32_ota_seq(self.seq0) #- is CRC32 valid? -# + var valid1 = otadata1.get(28, 4) == self.crc32_ota_seq(self.seq1) #- is CRC32 valid? -# if !valid0 self.seq0 = nil end if !valid1 self.seq1 = nil end @@ -314,7 +317,9 @@ class Partition_otadata end end + # Save partition information to SPI Flash def save() + import flash #- check the block number to save, 0 or 1. Choose the highest ota_seq -# var block_to_save = -1 #- invalid -# var seq_to_save = -1 #- invalid value -# @@ -337,19 +342,21 @@ class Partition_otadata var bytes_to_save = bytes() bytes_to_save.add(seq_to_save, 4) bytes_to_save += bytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") - bytes_to_save.add(crc32_ota_seq(seq_to_save), 4) + bytes_to_save.add(self.crc32_ota_seq(seq_to_save), 4) #- erase flash area and write -# flash.erase(offset_to_save, 0x1000) flash.write(offset_to_save, bytes_to_save) end + # Produce a human-readable representation of the object with relevant information def tostring() + import string return string.format("", - self.active_otadata, self.seq0, self.seq1, self.maxota) + self.active_otadata, self.seq0, self.seq1, self.maxota) end - end +partition.Partition_otadata = Partition_otadata #------------------------------------------------------------- - Class for a partition table entry @@ -367,8 +374,9 @@ class Partition self.load_otadata() end + # Load partition information from SPI Flash def load() - #- load partition table from flash -# + import flash self.raw = flash.read(0x8000,0x1000) end @@ -466,6 +474,7 @@ class Partition #- write back to flash -# def save() + import flash var b = self.tobytes() #- erase flash area and write -# flash.erase(0x8000, 0x1000) @@ -476,6 +485,7 @@ class Partition #- invalidate SPIFFS partition to force format at next boot -# #- we simply erase the first byte of the first 2 blocks in the SPIFFS partition -# def invalidate_spiffs() + import flash #- we expect the SPIFFS partition to be the last one -# var spiffs = self.slots[-1] if !spiffs.is_spiffs() raise 'value_error', 'No SPIFFS partition found' end @@ -485,21 +495,21 @@ class Partition flash.write(spiffs.start + 0x1000, b) #- block #1 -# end end +partition.Partition = Partition - -#------------------------------------------------------------- - - Parser manager for ESP32 - - - -------------------------------------------------------------# - -class Partition_manager : Driver - - def init() - end +################################################################################# +# Partition_manager_UI +# +# WebUI for the partition manager +################################################################################# +class Partition_manager_UI + static app_size_max = 1984 # Max OTA size (4096 - 64) / 2 rounded to lowest 64KB + static app_size_min = 896 # Min OTA size - let's set it at a safe 896KB for minimal Tasmota32 with TLS # create a method for adding a button to the main menu # the button 'Partition Manager' redirects to '/part_mgr?' def web_add_button() + import webserver webserver.content_send( "") end @@ -508,6 +518,8 @@ class Partition_manager : Driver # Show a single OTA Partition #- ---------------------------------------------------------------------- -# def page_show_partition(slot, active, ota_num) + import webserver + import string #- define `bdis` style for gray disabled buttons -# webserver.content_send("
") webserver.content_send(string.format(" %s%s", @@ -515,6 +527,7 @@ class Partition_manager : Driver webserver.content_send(string.format("

Partition size: %i KB

", slot.size / 1024)) var used = slot.get_image_size() + if used > slot.size slot.used = -1 end # we may have a leftover of a previous firmware but the slot shrank - in this case the slot is inknown if used >= 0 webserver.content_send(string.format("

Used: %i KB

", used / 1024)) webserver.content_send(string.format("

Free: %i KB

", (slot.size - used) / 1024)) @@ -522,7 +535,7 @@ class Partition_manager : Driver webserver.content_send("

Used: unknwon

") webserver.content_send("

Free: unknwon

") end - if !active && used >= 0 + if !active && used > 0 webserver.content_send("

") webserver.content_send("") @@ -547,6 +560,8 @@ class Partition_manager : Driver # Show a single OTA Partition #- ---------------------------------------------------------------------- -# def page_show_spiffs(slot, free_mem) + import webserver + import string webserver.content_send(string.format("
 %s", slot.start / 0x1000, slot.label)) @@ -586,9 +601,11 @@ class Partition_manager : Driver end #- ---------------------------------------------------------------------- -# - #- Display the Re-partition section + #- Display the Re-partition section - both OTA different sizes #- ---------------------------------------------------------------------- -# - def page_show_repartition(p) + def page_show_repartition_asym(p) + import webserver + import string if p.get_active() != 0 webserver.content_send("

Re-partition can be done only if 'app0' is active.

") else @@ -596,23 +613,40 @@ class Partition_manager : Driver var app0 = p.get_ota_slot(0) var app0_size_kb = ((app0.size / 1024 + 63) / 64) * 64 # rounded to upper 64kb var app0_used_kb = (((app0.get_image_size()) / 1024 / 64) + 1) * 64 - var flash_size_kb = tasmota.memory()['flash'] - var app_size_max = 1984 # Max OTA size (4096 - 64) / 2 rounded to lowest 64KB - webserver.content_send("

Resize app Partitions

") - webserver.content_send(string.format("

Min: %i KB

", app0_used_kb)) - webserver.content_send(string.format("

Max: %i KB

", app_size_max)) - webserver.content_send("

New: (multiple of 64 KB)

") + var app1 = p.get_ota_slot(1) + var app1_size_kb = ((app1.size / 1024 + 63) / 64) * 64 # rounded to upper 64kb + # var app1_used_kb = (((app1.get_image_size()) / 1024 / 64) + 1) * 64 # we don't actually need it + + var flash_size_kb = tasmota.memory()['flash'] + + webserver.content_send("

Resize app Partitions.
It is highly recommended to set
both partition with the same size.
SPIFFS is adjusted accordinlgy.

") + webserver.content_send("") - webserver.content_send(string.format("", app0_used_kb, app_size_max, app0_size_kb)) + + webserver.content_send("

app0:

") + webserver.content_send(string.format("

Min: %i KB

", app0_used_kb)) + webserver.content_send(string.format("

Max: %i KB

", self.app_size_max)) + webserver.content_send("

New: (multiple of 64 KB)

") + webserver.content_send(string.format("", app0_used_kb, self.app_size_max, app0_size_kb)) + + webserver.content_send("

app1:

") + webserver.content_send(string.format("

Min: %i KB

", self.app_size_min)) + webserver.content_send(string.format("

Max: %i KB

", self.app_size_max)) + webserver.content_send("

New: (multiple of 64 KB)

") + webserver.content_send(string.format("", self.app_size_min, self.app_size_max, app1_size_kb)) + webserver.content_send("

") end end - - #- this method displays the web page -# + ####################################################################### + # Display the complete page + ####################################################################### def page_part_mgr() + import webserver + import string if !webserver.check_privileged_access() return nil end var p = partition.Partition() @@ -626,24 +660,28 @@ class Partition_manager : Driver webserver.content_send("

") webserver.content_send("
 Re-partition

") - self.page_show_repartition(p) + self.page_show_repartition_asym(p) webserver.content_send("

") - webserver.content_button(webserver.BUTTON_MANAGEMENT) #- button back to management page -# webserver.content_stop() #- end of web page -# end - #- ---------------------------------------------------------------------- -# - #- this is the controller, called using POST and changing parameters - #- ---------------------------------------------------------------------- -# + ####################################################################### + # Web Controller, called by POST to `/part_mgr` + ####################################################################### def page_part_ctl() + import webserver + import string if !webserver.check_privileged_access() return nil end #- check that the partition is valid -# var p = partition.Partition() try + #---------------------------------------------------------------------# + # Switch OTA partition from one to another + #---------------------------------------------------------------------# if webserver.has_arg("ota") #- OTA switch partition -# var ota_target = int(webserver.arg("ota")) @@ -661,6 +699,10 @@ class Partition_manager : Driver #- and force restart -# webserver.redirect("/?rst=") + + #---------------------------------------------------------------------# + # Resize the SPIFFS partition, generally to extend it to full free size + #---------------------------------------------------------------------# elif webserver.has_arg("spiffs_size") #- SPIFFS size change -# var spiffs_size_kb = int(webserver.arg("spiffs_size")) @@ -683,6 +725,9 @@ class Partition_manager : Driver #- and force restart -# webserver.redirect("/?rst=") + #---------------------------------------------------------------------# + # Repartition symmetrical OTA with a new SPIFFS size + #---------------------------------------------------------------------# elif webserver.has_arg("repartition") if p.get_active() != 0 raise "value_error", "Can't repartition unless active partition is app0" end #- complete repartition -# @@ -700,11 +745,10 @@ class Partition_manager : Driver var app0_size_kb = ((app0.size / 1024 + 63) / 64) * 64 # rounded to upper 64kb var app0_used_kb = (((app0.get_image_size()) / 1024 / 64) + 1) * 64 var flash_size_kb = tasmota.memory()['flash'] - var app_size_max = 1984 # Max OTA size (4096 - 64) / 2 rounded to lowest 64KB var part_size_kb = int(webserver.arg("repartition")) - if part_size_kb < app0_used_kb || part_size_kb > app_size_max - raise "value_error", string.printf("Invalid partition size %i KB, should be between %i and %i", part_size_kb, app0_used_kb, app_size_max) + if part_size_kb < app0_used_kb || part_size_kb > self.app_size_max + raise "value_error", string.printf("Invalid partition size %i KB, should be between %i and %i", part_size_kb, app0_used_kb, self.app_size_max) end if part_size_kb == app0_size_kb raise "value_error", "No change to partition size, abort" end @@ -722,6 +766,54 @@ class Partition_manager : Driver p.invalidate_spiffs() # erase SPIFFS or data is corrupt #- and force restart -# webserver.redirect("/?rst=") + + #---------------------------------------------------------------------# + # Repartition OTA with a new SPIFFS size + #---------------------------------------------------------------------# + elif webserver.has_arg("app0") && webserver.has_arg("app1") + if p.get_active() != 0 raise "value_error", "Can't repartition unless active partition is app0" end + #- complete repartition -# + var app0 = p.get_ota_slot(0) + var app1 = p.get_ota_slot(1) + var spiffs = p.slots[-1] + + if !spiffs.is_spiffs() raise 'internal_error', 'No SPIFFS partition found' end + if app0 == nil || app1 == nil + raise "internal_error", "Unable to find partitions app0 and app1" + end + if p.ota_max() != 1 + raise "internal_error", "There are more than 2 OTA partition, abort" + end + var app0_size_kb = ((app0.size / 1024 + 63) / 64) * 64 # rounded to upper 64kb + var app0_used_kb = (((app0.get_image_size()) / 1024 / 64) + 1) * 64 + var app1_size_kb = ((app1.size / 1024 + 63) / 64) * 64 # rounded to upper 64kb + var flash_size_kb = tasmota.memory()['flash'] + + var part0_size_kb = int(webserver.arg("app0")) + if part0_size_kb < app0_used_kb || part0_size_kb > self.app_size_max + raise "value_error", string.printf("Invalid partition size app%i %i KB, should be between %i and %i", 0, part0_size_kb, app0_used_kb, self.app_size_max) + end + var part1_size_kb = int(webserver.arg("app1")) + if part1_size_kb < self.app_size_min || part1_size_kb > self.app_size_max + raise "value_error", string.printf("Invalid partition size app%i %i KB, should be between %i and %i", 1, part1_size_kb, self.app_size_min, self.app_size_max) + end + if part0_size_kb == app0_size_kb && part1_size_kb == app1_size_kb raise "value_error", "No change to partition sizes, abort" end + + #- all good, proceed -# + # resize app0 + app0.size = part0_size_kb * 1024 + # change app1 + app1.start = app0.start + app0.size + app1.size = part1_size_kb * 1024 + # change spiffs + spiffs.start = app1.start + app1.size + spiffs.size = flash_size_kb * 1024 - spiffs.start + + p.save() + p.invalidate_spiffs() # erase SPIFFS or data is corrupt + #- and force restart -# + webserver.redirect("/?rst=") + #---------------------------------------------------------------------# else raise "value_error", "Unknown command" end @@ -744,20 +836,22 @@ class Partition_manager : Driver #- ---------------------------------------------------------------------- -# #- this is called at Tasmota start-up, as soon as Wifi/Eth is up and web server running -# def web_add_handler() + import webserver #- we need to register a closure, not just a function, that captures the current instance -# webserver.on("/part_mgr", / -> self.page_part_mgr(), webserver.HTTP_GET) webserver.on("/part_mgr", / -> self.page_part_ctl(), webserver.HTTP_POST) end - end +partition.Partition_manager_UI = Partition_manager_UI + #- create and register driver in Tasmota -# -var partition_manager = Partition_manager() -tasmota.add_driver(partition_manager) -## can be removed if put in 'autoexec.bat' -partition_manager.web_add_handler() - -partition.Partition = Partition +if tasmota + var partition_manager_ui = partition.Partition_manager_UI() + tasmota.add_driver(partition_manager_ui) + ## can be removed if put in 'autoexec.bat' + partition_manager_ui.web_add_handler() +end return partition diff --git a/tasmota/berry/modules/partition.bec b/tasmota/berry/modules/partition.bec deleted file mode 100644 index 8a2f56cd3..000000000 Binary files a/tasmota/berry/modules/partition.bec and /dev/null differ diff --git a/tasmota/berry/modules/ts_calibrate/autoexec.be b/tasmota/berry/modules/ts_calibrate/autoexec.be new file mode 100644 index 000000000..2663f2edf --- /dev/null +++ b/tasmota/berry/modules/ts_calibrate/autoexec.be @@ -0,0 +1,18 @@ +# register the command 'DisplayCalibrate' +# +# load the module in memory only when the command is first used +# +var wd = tasmota.wd # capture value of the first run +tasmota.add_cmd("DisplayCalibrate", + def () + import sys + var path = sys.path() + + path.push(wd) + import ts_calibrate + path.pop() + + tasmota.set_timer(0, /-> ts_calibrate.start()) + tasmota.resp_cmnd_done() + end +) diff --git a/tasmota/berry/modules/ts_calibrate/ts_calibrate.be b/tasmota/berry/modules/ts_calibrate/ts_calibrate.be new file mode 100644 index 000000000..8435c2199 --- /dev/null +++ b/tasmota/berry/modules/ts_calibrate/ts_calibrate.be @@ -0,0 +1,322 @@ +# TouchScreen calibration +var ts_calibrate = module("ts_calibrate") + +ts_calibrate.init = def (m) + class TS_Calibrate + var l1, l2 # LVGL lines used to draw a cross + var p1, p2, p3, p4 # points needs to be kept in memory across calls + var pt_arr1, pt_arr2 + var f20 # font Montserrat 20 + var scr_orig # original screen + var scr_ts # screen used for calibration + var hres, vres + var instr_label # label for instructions + # + var raw_pts # 4x raw points for 4 corners + var raw_pts_weight # weight for current corner, used for an aveage measure + # + var state_closure # closure to call at next iteration + var state_corner # which corner are we now tracking + # + var m_line # display.ini parsed, array of 2 string (before and after :M line) + + static msg_prefix = "Touch Screen calibration\n" + static msg_touch = "Press the center of\n" + static msg_corners = [ "upper left cross", "upper right cross", "lower left cross", "lower right cross" ] + static msg_ok = "Calibration successful\nRestarting in 5 seconds" + static msg_nok = "Calibration failed\nPlease try again" + + static round = def (v) return int(v + 0.5) end + + def init() + end + + def start() + self.state_corner= -1 # no corner being tracked yet + self.m_line = nil + + # check display.ini to see if touchscreen is present with ':M' line in display.ini + self.m_line = self.load_m_line() + if !self.m_line + tasmota.log("TS : Abort, no touchscreen ':M' line present in 'display.ini'", 2) + return + end + + lv.start() + + # check if `DisplayRotate` is set to zero + var display_rotate_ret = tasmota.cmd("DisplayRotate") + if display_rotate_ret != nil && display_rotate_ret["DisplayRotate"] != 0 + tasmota.log("TS : Calibration requires 'DisplayRotate 0'") + return + end + + self.raw_pts = [ lv.point(), lv.point(), lv.point(), lv.point() ] + + self.scr_orig = lv.scr_act() # save the current screen to restore it later + self.f20 = lv.montserrat_font(20) # load embedded Montserrat 20 + self.hres = lv.get_hor_res() + self.vres = lv.get_ver_res() + + self.scr_ts = lv.obj(0) # create a new temporary screen for the calibration + lv.scr_load(self.scr_ts) + + self.instr_label = lv.label(self.scr_ts) + self.instr_label.center() + if self.f20 != nil self.instr_label.set_style_text_font(self.f20, lv.PART_MAIN | lv.STATE_DEFAULT) end + self.instr_label.set_text(self.msg_prefix) + + self.l1 = lv.line(self.scr_ts) + self.l2 = lv.line(self.scr_ts) + self.l1.set_style_line_width(2, lv.PART_MAIN | lv.STATE_DEFAULT) + self.l2.set_style_line_width(2, lv.PART_MAIN | lv.STATE_DEFAULT) + + self.p1 = lv.point() + self.p2 = lv.point() + self.p3 = lv.point() + self.p4 = lv.point() + + # register ourselves as driver + tasmota.add_driver(self) + + # start calibrate in 2 seconds + tasmota.set_timer(2000, /-> self.do_next_corner()) + end + + def do_cross_n(n) + self.state_corner = n + self.raw_pts_weight = 0 # reset weight (for average of measures) + + if n == 0 self.draw_cross(20,20,30) + elif n == 1 self.draw_cross(self.hres - 20, 20, 30) + elif n == 2 self.draw_cross(20, self.vres - 20, 30) + else self.draw_cross(self.hres - 20, self.vres - 20, 30) + end + # set message + self.instr_label.set_text(self.msg_prefix + self.msg_touch + self.msg_corners[n]) + end + + # remove and restore previous state + def del() + lv.scr_load(self.scr_orig) # restore previous screen + self.scr_ts.del() # delete all objects + tasmota.remove_driver(self) + end + + # draw cross + def draw_cross(x, y, size) + var sz2 = size / 2 + self.p1.x = x - sz2 + self.p1.y = y + self.p2.x = x + sz2 + self.p2.y = y + + self.pt_arr1 = lv.lv_point_arr([self.p1, self.p2]) + self.l1.set_points(self.pt_arr1, 2) + + self.p3.x = x + self.p3.y = y - sz2 + self.p4.x = x + self.p4.y = y + sz2 + + self.pt_arr2 = lv.lv_point_arr([self.p3, self.p4]) + self.l2.set_points(self.pt_arr2, 2) + end + + def every_50ms() + # + if self.state_closure self.state_closure() end + end + + def track_touch_screen() + var tracking = lv.get_ts_calibration() + if tracking.state + # screen is pressed, compute an average of all previous measures + self.raw_pts[self.state_corner].x = (self.raw_pts[self.state_corner].x * self.raw_pts_weight + tracking.raw_x) / (self.raw_pts_weight + 1) + self.raw_pts[self.state_corner].y = (self.raw_pts[self.state_corner].y * self.raw_pts_weight + tracking.raw_y) / (self.raw_pts_weight + 1) + self.raw_pts_weight += 1 # we now have 1 more measure + else + # screen is not pressed anymore + if (self.raw_pts_weight >= 3) + self.state_closure = nil # stop tracking + tasmota.set_timer(0, /-> self.do_next_corner()) # defer to next corner + + end # we need at least 3 succesful measures do consider complete + end + end + + def do_next_corner() + # start the measure of the next corner + self.state_corner += 1 + if self.state_corner <= 3 + self.do_cross_n(self.state_corner) + self.state_closure = /-> self.track_touch_screen() + else + # finished + self.l1.del() + self.l2.del() + self.finish() + end + end + + # All values are computed and correct, log results and store to 'display.ini' + def finish() + # calibration is finished, do the housekeeping + import string + var p0x = real(self.raw_pts[0].x) + var p0y = real(self.raw_pts[0].y) + var p1x = real(self.raw_pts[1].x) + var p1y = real(self.raw_pts[1].y) + var p2x = real(self.raw_pts[2].x) + var p2y = real(self.raw_pts[2].y) + var p3x = real(self.raw_pts[3].x) + var p3y = real(self.raw_pts[3].y) + tasmota.log(string.format("TS : Calibration (%i,%i) - (%i,%i) - (%i,%i) - (%i,%i)", + int(p0x), int(p0y), int(p1x), int(p1y), int(p2x), int(p2y), int(p3x), int(p3y)) + , 2) + var m_line = self.calc_geometry(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y, self.hres, self.vres, 20) + var ok = false + if m_line + ok = self.update_display_ini(m_line) + end + if ok + self.instr_label.set_text(self.msg_prefix + self.msg_ok) + else + self.instr_label.set_text(self.msg_prefix + self.msg_nok) + end + tasmota.set_timer(3000, /->self.cleanup(ok)) + end + + # cleanup display, remove any widgets created + def cleanup(restart) + self.del() + + if (restart) + tasmota.cmd("Restart 1") + end + end + + # Find 'display.ini' file either in root folder or in autoconf file + # and check that it contains a line ':M*' + # Returns an array of 2 strings (before and after :M line) + # or 'nil' if not found + def load_m_line() + try + import re + import path + + # try display.ini at root + var disp_ini + if path.exists("display.ini") + var disp_f = open("display.ini") + disp_ini = disp_f.read() + disp_f.close() + elif autoconf.get_current_module_path() && path.exists(autoconf.get_current_module_path() + "#display.ini") + var disp_f = open(autoconf.get_current_module_path() + "#display.ini") + disp_ini = disp_f.read() + disp_f.close() + else + return nil + end + + # look for ":M" line + var sp = re.split(":M.*?\n", disp_ini) + if size(sp) == 2 + return sp # found + end + except .. as e, m + tasmota.log("TS : Couldn't open 'display.ini': "+str(e)+" '"+str(m)+"'") + end + return nil + end + + # try to update 'display.ini' if present in file-system + def update_display_ini(m_line) + try + + # found + var disp_ini = self.m_line[0] + str(m_line) + "\n" + self.m_line[1] + + # write back file + var disp_f = open("display.ini", "w") + disp_f.write(disp_ini) + disp_f.close() + tasmota.log("TS : Successfully updated 'display.ini'", 2) + return true + except .. as e, m + tasmota.log("TS : Error updating 'display.ini': "+str(e)+" '"+str(m)+"'") + end + return false + end + + def calc_geometry(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y, hres, vres, padding) + import math + import string + + tasmota.log(string.format("TS : Geometry (%i,%i) (%i,%i) (%i,%i) (%i,%i) - %ix%i pad %i", + int(p0x), int(p0y), + int(p1x), int(p1y), + int(p2x), int(p2y), + int(p3x), int(p3y), + int(hres), int(vres), int(padding) + ), 3) + + var vec_01_x = p1x - p0x + var vec_01_y = p1y - p0y + var norm_01 = math.sqrt(vec_01_x * vec_01_x + vec_01_y * vec_01_y) + + var vec_02_x = p2x - p0x + var vec_02_y = p2y - p0y + var norm_02 = math.sqrt(vec_01_x * vec_01_x + vec_01_y * vec_01_y) + + var scalar_01_02 = vec_01_x * vec_02_x + vec_01_y * vec_02_y + var cos_th_01_02 = math.abs(scalar_01_02) / norm_01 / norm_02 + + tasmota.log("cos_th_01_02=" + str(cos_th_01_02), 4) + + if (cos_th_01_02 > 0.05) + tasmota.log("TS : Wrong geometry - bad angle. Try again.", 2) + return nil + end + + # Now check the center is valid + var center_03_x = (p0x + p3x) / 2 + var center_03_y = (p0y + p3y) / 2 + var center_12_x = (p1x + p2x) / 2 + var center_12_y = (p1y + p2y) / 2 + var norm_delta_centers = ((center_12_x - center_03_x) * (center_12_x - center_03_x) + (center_12_y - center_03_y) * (center_12_y - center_03_y)) / norm_01 / norm_02 + tasmota.log("norm_delta_centers=" + str(norm_delta_centers), 4) + + if (norm_delta_centers > 0.02) + tasmota.log("TS : Wrong geometry - bad center. Try again", 2) + return nil + end + + var xmin = (p0x + p2x) / 2 + var xmax = (p1x + p3x) / 2 + var ymin = (p0y + p1y) / 2 + var ymax = (p2y + p3y) / 2 + tasmota.log("raw xmin=" + str(xmin) + " xmax=" + str(xmax) + " ymin=" + str(ymin) + " ymax=" + str(ymax), 4) + + var range_x = xmax - xmin + var range_y = ymax - ymin + + tasmota.log("range_x=" + str(range_x) + " range_y=" + str(range_y), 4) + var extend_x = (range_x / (hres - 2*padding) * hres - range_x) / 2 + var extend_y = (range_y / (vres - 2*padding) * vres - range_y) / 2 + + xmin -= extend_x + xmax += extend_x + ymin -= extend_y + ymax += extend_y + tasmota.log("final xmin=" + str(xmin) + " xmax=" + str(xmax) + " ymin=" + str(ymin) + " ymax=" + str(ymax), 4) + + var M_string = string.format(":M,%i,%i,%i,%i", int(xmin), int(xmax), int(ymin), int(ymax)) + tasmota.log(string.format("TS : Add this to display.ini '%s'", M_string)) + return M_string + end + end + return TS_Calibrate() +end + +return ts_calibrate diff --git a/tasmota/html_compressed/HTTP_HEADER1_ES6.h b/tasmota/html_compressed/HTTP_HEADER1_ES6.h index d95dc2499..662e6bdce 100644 --- a/tasmota/html_compressed/HTTP_HEADER1_ES6.h +++ b/tasmota/html_compressed/HTTP_HEADER1_ES6.h @@ -2,21 +2,32 @@ // compressed by tools/unishox/compress-html-uncompressed.py ///////////////////////////////////////////////////////////////////// -const size_t HTTP_HEADER1_SIZE = 371; +const size_t HTTP_HEADER1_SIZE = 685; const char HTTP_HEADER1_COMPRESSED[] PROGMEM = "\x3D\x0F\xE1\x10\x98\x1D\x19\x0C\x64\x85\x50\xD0\x8F\xC3\xD0\x55\x0D\x09\x05\x7C" "\x3C\x7C\x3D\x87\xD7\x8F\x62\x0C\x2B\xF7\x8F\x87\xB0\xF6\x1F\x87\xA0\xA7\x62\x1F" "\x87\xA0\xD7\x56\x83\x15\x7F\xF3\xA3\xE1\xF6\x2E\x8C\x1D\x67\x3E\x7D\x90\x21\x52" "\xEB\x1A\xCF\x87\xB0\xCF\x58\xF8\xCC\xFD\x1E\xC4\x1E\x75\x3E\xA3\xE1\xEC\x1F\xD1" "\x28\x51\xF0\x46\x67\xA1\xB3\xAC\x7F\x44\xA1\x47\x56\xF6\xD6\xD8\x47\x5F\x83\xB0" "\x99\xF0\xE4\x3A\x88\x5F\x9F\xCE\xBF\x07\x61\x58\xE0\x99\xF3\xB0\xF6\x1D\x87\xE1" - "\xE9\x5B\x41\x33\xF0\xFA\xF2\x3A\xD1\xF5\xE3\xD0\xEC\x04\x19\x67\xA7\x83\xFE\x8C" - "\xA3\xF0\xCE\xFE\x8D\x87\xCE\x16\x10\x47\x50\x54\x75\x56\x1D\x54\x30\xEA\x18\x19" - "\xF0\xFB\x3E\xCF\x0C\x71\xF3\xC7\xC3\xF0\x4C\x0C\x58\xD7\xD4\x74\x1E\x74\x4C\x26" - "\x35\xF5\x10\xE3\x22\xD1\x0E\xEF\x8E\xF1\xE0\xD5\xE0\x48\xBA\x6A\x16\xFE\x64\x5E" - "\x61\x30\xEB\x3E\x77\x7C\x77\x8F\x1E\x18\x7C\xD3\xE1\xF8\xC7\x1D\xDD\x3B\xC7\x4A" - "\x32\x18\xCF\x87\x74\x11\xA4\x1F\x0F\x87\xDD\x33\x65\x1F\x67\x68\xFB\x19\x7E\xF0" - "\xFE\x7C\x43\xEC\xF3\x04\x19\xC7\x78\xF0\x3E\x11\xF0\xC1\xF0\xFC\x1F\xDE\x13\x07" - "\xCE\x96\x20\x84\xCC\xDF\x51\x05\xBE\xA7\xCF\xE7\x74\xFB\x0B\x2C\x43\xEC\xEA\x30" - "\x77\x8F\x06"; + "\xE8\x16\xF1\xA2\xFB\x08\xF8\x7B\x34\x3C\xE3\xD8\x85\x7D\x98\x3E\x1E\xC1\x2E\xAC" + "\xF3\xD1\xB6\x3C\xCE\xC3\x61\xD7\xA1\xE7\x1E\x07\x5F\x99\xCE\xC3\xA8\x88\xAE\xEC" + "\x75\xDB\xB6\x3A\xC3\xBB\x77\x66\xA0\xC8\x7C\xAC\xAC\xAC\xAC\x8C\x0F\x15\x95\x95" + "\x90\x63\xC4\x57\x77\x66\xAB\xBB\xBD\xB2\x37\xA0\x11\x32\x04\x29\x46\xF5\xE3\xB0" + "\xEC\x3B\x0E\xC2\xB2\x18\x73\x4E\xC2\x1C\x76\xC8\x51\xCE\x22\x36\x1C\xA3\xB0\x85" + "\x1C\xF9\x1A\x1C\x44\x66\x73\x09\x91\xB7\x87\x1D\xB2\x14\x2C\x43\x94\x76\x10\xA3" + "\x9E\x2E\x10\xCC\xE6\x13\x39\xB6\x43\x8E\xD9\x18\x1A\x46\xD1\xA7\x60\xA2\x1A\x68" + "\x6C\x33\x39\x84\x46\xD1\xE2\x36\x8E\x3B\x64\x28\xB0\x33\x94\x76\x10\xA3\x9A\x76" + "\xC8\x43\x33\x98\x46\x08\x61\x0C\x1C\x76\xC8\x51\xCD\x2E\x39\x47\x61\x0A\x3B\x08" + "\x43\x88\x8C\xCE\x61\x18\x39\xA7\x61\x0E\x3B\x64\xCA\xCA\xCB\x0E\x61\x13\x2B\x2B" + "\x21\x05\x90\xE2\xB2\xB2\xB3\x9E\x21\xE2\x35\x02\x5C\xC0\x5B\xB8\x0A\x17\x0F\x61" + "\xF8\x7A\x56\xD0\x4C\xFC\x3E\xBC\x8E\xB4\x7D\x78\xF4\x3B\x01\x06\x59\xE9\xE0\xFF" + "\xA3\x28\xFC\x33\xBF\xA3\x61\xF3\x85\x84\x11\xD4\x15\x1D\x55\x87\x55\x0C\x3A\x86" + "\x06\x7C\x3E\xCF\xB3\xC3\x1C\x7C\xF1\xF0\xFC\x13\x03\x16\x35\xF5\x1D\x07\x9D\x13" + "\x09\x8D\x7D\x44\x38\xC8\xB4\x43\xBB\xE3\xBC\x78\x35\x78\x12\x2E\x9A\x85\xBF\x99" + "\x17\x98\x4C\x3A\xCF\x9D\xDF\x1D\xE3\xC7\x86\x1F\x34\xF8\x7E\x31\xC7\x77\x4E\xF1" + "\xD2\x8C\x86\x33\xE1\xDD\x04\x69\x07\xC3\xE1\xF7\x4C\xD9\x47\xD9\xDA\x3E\xC6\x5F" + "\xBC\x3F\x9F\x10\xFB\x3C\xC1\x06\x71\xDE\x3C\x0F\x84\x7C\x30\x7C\x3F\x07\xF7\x84" + "\xC1\xF3\xA5\x88\x21\x33\x37\xD4\x41\x6F\xA9\xF3\xF9\xDD\x3E\xC2\xCB\x10\xFB\x3A" + "\x8C\x1D\xE3\xC1"; #define HTTP_HEADER1 Decompress(HTTP_HEADER1_COMPRESSED,HTTP_HEADER1_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_compressed/HTTP_HEADER1_NOES6.h b/tasmota/html_compressed/HTTP_HEADER1_NOES6.h index fae966b15..85c977688 100644 --- a/tasmota/html_compressed/HTTP_HEADER1_NOES6.h +++ b/tasmota/html_compressed/HTTP_HEADER1_NOES6.h @@ -2,21 +2,32 @@ // compressed by tools/unishox/compress-html-uncompressed.py ///////////////////////////////////////////////////////////////////// -const size_t HTTP_HEADER1_SIZE = 425; +const size_t HTTP_HEADER1_SIZE = 739; const char HTTP_HEADER1_COMPRESSED[] PROGMEM = "\x3D\x0F\xE1\x10\x98\x1D\x19\x0C\x64\x85\x50\xD0\x8F\xC3\xD0\x55\x0D\x09\x05\x7C" "\x3C\x7C\x3D\x87\xD7\x8F\x62\x0C\x2B\xF7\x8F\x87\xB0\xF6\x1F\x87\xA0\xA7\x62\x1F" "\x87\xA0\xD7\x56\x83\x15\x7F\xF3\xA3\xE1\xF6\x2E\x8C\x1D\x67\x3E\x7D\x90\x21\x52" "\xEB\x1A\xCF\x87\xB0\xCF\x58\xF8\xCC\xFD\x1E\xC4\x1E\x75\x3E\xA3\xE1\xEC\x1F\xD1" "\x28\x51\xF0\x46\x67\xA1\xB3\xAC\x7F\x44\xA1\x47\x56\xF6\xD6\xD8\x47\x5F\x83\xB0" "\x99\xF0\xE4\x3A\x88\x5F\x9F\xCE\xBF\x07\x61\x58\xE0\x99\xF3\xB0\xF6\x1D\x87\xE1" - "\xE9\x5B\x41\x33\xF0\xFA\xF2\x3A\xD1\xF5\xE3\xD0\xEC\x04\x19\x67\xA7\x83\xFE\x8C" - "\xA3\xF0\xCE\xFE\x8D\x87\xCE\x16\x10\x47\x50\x54\x75\x56\x1D\x54\x30\xEA\x18\x19" - "\xF0\xFB\x3E\xCF\x06\x05\xF0\x75\xB9\xC9\x8E\x3B\xBE\x3B\xC7\xB7\xEE\x85\xFF\x90" - "\x98\x18\xB1\xAF\xA8\xE8\x3C\xE8\x98\x4C\x6B\xEA\x21\xC6\x45\xA2\x1D\xDF\x1D\xE3" - "\xC1\xEE\x04\x4C\x38\xD5\xE0\x4F\xC3\x8D\x42\xDF\xCC\x8B\xCC\x26\x1D\x67\xC1\x27" - "\x0D\xF0\xC3\xBB\xA7\x78\xF6\xB1\xC7\x77\x4E\xF1\xD2\x8C\x86\x33\xE1\xDD\x04\x69" - "\x07\xC3\xE1\xF7\x4C\xD9\x47\xD9\xDA\x3E\xC6\x5F\xBC\x3F\x9F\x10\xFB\x3C\xC1\x06" - "\x70\x23\xE3\xE3\xE1\x1D\xD3\x07\x78\xF6\x8F\xEF\x09\x83\xE7\x4B\x10\x42\x66\x6F" - "\xA8\x82\xDF\x53\xE7\xF3\xBA\x7D\x85\x96\x21\xF6\x75\x18\x3B\xC7\x83\xDC"; + "\xE8\x16\xF1\xA2\xFB\x08\xF8\x7B\x34\x3C\xE3\xD8\x85\x7D\x98\x3E\x1E\xC1\x2E\xAC" + "\xF3\xD1\xB6\x3C\xCE\xC3\x61\xD7\xA1\xE7\x1E\x07\x5F\x99\xCE\xC3\xA8\x88\xAE\xEC" + "\x75\xDB\xB6\x3A\xC3\xBB\x77\x66\xA0\xC8\x7C\xAC\xAC\xAC\xAC\x8C\x0F\x15\x95\x95" + "\x90\x63\xC4\x57\x77\x66\xAB\xBB\xBD\xB2\x37\xA0\x11\x32\x04\x29\x46\xF5\xE3\xB0" + "\xEC\x3B\x0E\xC2\xB2\x18\x73\x4E\xC2\x1C\x76\xC8\x51\xCE\x22\x36\x1C\xA3\xB0\x85" + "\x1C\xF9\x1A\x1C\x44\x66\x73\x09\x91\xB7\x87\x1D\xB2\x14\x2C\x43\x94\x76\x10\xA3" + "\x9E\x2E\x10\xCC\xE6\x13\x39\xB6\x43\x8E\xD9\x18\x1A\x46\xD1\xA7\x60\xA2\x1A\x68" + "\x6C\x33\x39\x84\x46\xD1\xE2\x36\x8E\x3B\x64\x28\xB0\x33\x94\x76\x10\xA3\x9A\x76" + "\xC8\x43\x33\x98\x46\x08\x61\x0C\x1C\x76\xC8\x51\xCD\x2E\x39\x47\x61\x0A\x3B\x08" + "\x43\x88\x8C\xCE\x61\x18\x39\xA7\x61\x0E\x3B\x64\xCA\xCA\xCB\x0E\x61\x13\x2B\x2B" + "\x21\x05\x90\xE2\xB2\xB2\xB3\x9E\x21\xE2\x35\x02\x5C\xC0\x5B\xB8\x0A\x17\x0F\x61" + "\xF8\x7A\x56\xD0\x4C\xFC\x3E\xBC\x8E\xB4\x7D\x78\xF4\x3B\x01\x06\x59\xE9\xE0\xFF" + "\xA3\x28\xFC\x33\xBF\xA3\x61\xF3\x85\x84\x11\xD4\x15\x1D\x55\x87\x55\x0C\x3A\x86" + "\x06\x7C\x3E\xCF\xB3\xC1\x81\x7C\x1D\x6E\x72\x63\x8E\xEF\x8E\xF1\xED\xFB\xA1\x7F" + "\xE4\x26\x06\x2C\x6B\xEA\x3A\x0F\x3A\x26\x13\x1A\xFA\x88\x71\x91\x68\x87\x77\xC7" + "\x78\xF0\x7B\x81\x13\x0E\x35\x78\x13\xF0\xE3\x50\xB7\xF3\x22\xF3\x09\x87\x59\xF0" + "\x49\xC3\x7C\x30\xEE\xE9\xDE\x3D\xAC\x71\xDD\xD3\xBC\x74\xA3\x21\x8C\xF8\x77\x41" + "\x1A\x41\xF0\xF8\x7D\xD3\x36\x51\xF6\x76\x8F\xB1\x97\xEF\x0F\xE7\xC4\x3E\xCF\x30" + "\x41\x9C\x08\xF8\xF8\xF8\x47\x74\xC1\xDE\x3D\xA3\xFB\xC2\x60\xF9\xD2\xC4\x10\x99" + "\x9B\xEA\x20\xB7\xD4\xF9\xFC\xEE\x9F\x61\x65\x88\x7D\x9D\x46\x0E\xF1\xE0\xF7\x1B"; #define HTTP_HEADER1 Decompress(HTTP_HEADER1_COMPRESSED,HTTP_HEADER1_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_compressed/HTTP_SCRIPT_ROOT_WEB_DISPLAY.h b/tasmota/html_compressed/HTTP_SCRIPT_ROOT_WEB_DISPLAY.h index 5955e2b0e..a7fc25354 100644 --- a/tasmota/html_compressed/HTTP_SCRIPT_ROOT_WEB_DISPLAY.h +++ b/tasmota/html_compressed/HTTP_SCRIPT_ROOT_WEB_DISPLAY.h @@ -2,7 +2,7 @@ // compressed by tools/unishox/compress-html-uncompressed.py ///////////////////////////////////////////////////////////////////// -const size_t HTTP_SCRIPT_ROOT_SIZE = 779; +const size_t HTTP_SCRIPT_ROOT_SIZE = 880; const char HTTP_SCRIPT_ROOT_COMPRESSED[] PROGMEM = "\x33\xBF\xAF\x98\xF0\xA3\xE1\xC8\x75\x11\x8A\x3C\x18\x17\xC1\xD6\xE7\x20\xAC\xEE" "\x8C\x3B\xC7\xB6\xCF\x83\x0F\xF1\xFE\x3E\xCF\xB3\xC0\x61\x3B\xF9\x56\x8D\x78\x2E" "\x8E\xE9\x8A\x3B\xC0\x93\x34\x2A\x2B\x3B\xC7\x8D\x30\x77\x4D\x87\xF0\xF9\xC2\xC2" @@ -24,7 +24,9 @@ const char HTTP_SCRIPT_ROOT_COMPRESSED[] PROGMEM = "\x33\xBF\xAF\x98\xF0\xA3\xE1 "\xDC\x40\x89\xCB\x2F\x99\x9D\x9D\xD1\x97\xF3\xAB\x4C\xEF\xE7\x78\xF6\x85\x67\x74" "\xFB\x3F\x5E\x33\x3E\x1F\x67\x6F\x4C\xEF\xE7\x6C\xFB\x3F\x67\xD9\xDB\x19\x7F\x3B" "\xC7\x80\x46\xC3\x74\x12\x30\xD0\x41\xE6\xE0\xF0\x0A\x78\xA7\xCC\x78\x51\xF0\xE3" - "\x20\x46\xC6\xC6\x7C\xEE\x98\x3B\xC7\xB7\x4C\x1D\xD3\x07\x78\xF6\x82\x67\x0B\xA0" - "\x99\xC3\xF8\x28\x70\xCA\x08\x5A\x79\xEE\x61\x79\x82\xF6\x40\x08\x7A\xF9\xEE"; + "\x20\x4A\xC6\xE8\x13\x71\xC1\x97\xF4\x7C\x43\x2F\xE7\x4F\x05\xA1\xB3\xBA\x71\x9D" + "\x47\x72\x8E\xF1\xDC\x3B\x64\x08\xD3\x8E\x59\xDE\x20\x60\xBA\x08\xCF\x9D\xD3\x07" + "\x78\xF6\xE9\x83\xBA\x60\xEF\x1E\xD0\x4C\xE3\x08\x13\x38\xE4\x05\x0E\x32\x81\x0B" + "\x74\x3D\xCC\x2F\x30\x5E\xC8\x01\x0F\x5F\x3D\xC6"; #define HTTP_SCRIPT_ROOT Decompress(HTTP_SCRIPT_ROOT_COMPRESSED,HTTP_SCRIPT_ROOT_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_uncompressed/HTTP_HEADER1_ES6.h b/tasmota/html_uncompressed/HTTP_HEADER1_ES6.h index d89b93352..35b38ead0 100644 --- a/tasmota/html_uncompressed/HTTP_HEADER1_ES6.h +++ b/tasmota/html_uncompressed/HTTP_HEADER1_ES6.h @@ -3,6 +3,7 @@ const char HTTP_HEADER1[] PROGMEM = "" "" "" + "" "%s - %s" ""; +void ScriptFullWebpage1(void) { + ScriptFullWebpage(1); +} +void ScriptFullWebpage2(void) { + ScriptFullWebpage(2); +} +void ScriptFullWebpage3(void) { + ScriptFullWebpage(3); +} +void ScriptFullWebpage4(void) { + ScriptFullWebpage(4); +} -void ScriptFullWebpage(void) { - uint32_t fullpage_refresh=10000; +void ScriptFullWebpage(uint8_t page) { + uint32_t fullpage_refresh = 10000; if (!HttpCheckPriviledgedAccess()) { return; } String stmp = Webserver->uri(); @@ -7149,7 +7673,7 @@ void ScriptFullWebpage(void) { Script_Check_HTML_Setvars(); } WSContentBegin(200, CT_HTML); - ScriptWebShow('w'); + ScriptWebShow('w', page); WSContentEnd(); //Serial.printf("fwp update sv %s\n",stmp.c_str() ); return; //goto redraw; @@ -7163,19 +7687,18 @@ void ScriptFullWebpage(void) { } WSContentBegin(200, CT_HTML); - const char *title = "Full Screen"; - WSContentSend_P(HTTP_SCRIPT_FULLPAGE1, SettingsText(SET_DEVICENAME), title, fullpage_refresh); + WSContentSend_P(HTTP_HEADER1, PSTR(D_HTML_LANGUAGE), SettingsText(SET_DEVICENAME), PSTR("Full Screen")); + WSContentSend_P(HTTP_SCRIPT_FULLPAGE1, page , fullpage_refresh); WSContentSend_P(HTTP_SCRIPT_FULLPAGE2, fullpage_refresh); //WSContentSend_P(PSTR("
")); //WSContentSendStyle(); - WSContentSend_P(PSTR("
")); - ScriptWebShow('w'); + ScriptWebShow('w', page); WSContentSend_P(PSTR("
")); - ScriptWebShow('x'); + ScriptWebShow('x', page); WSContentStop(); } @@ -7214,7 +7737,9 @@ void Script_Check_HTML_Setvars(void) { //toLog(cmdbuf); execute_script(cmdbuf); - Run_Scripter(">E", 2, 0); + //Run_Scripter(">E", 2, 0); + if (glob_script_mem.event_script) Run_Scripter(glob_script_mem.event_script, 0, 0); + } } @@ -7243,20 +7768,23 @@ const char SCRIPT_MSG_SLIDER[] PROGMEM = "
"; const char SCRIPT_MSG_CHKBOX[] PROGMEM = - "
"; + "%s"; const char SCRIPT_MSG_PULLDOWNa[] PROGMEM = - "
"; const char SCRIPT_MSG_PULLDOWNb[] PROGMEM = ""; const char SCRIPT_MSG_PULLDOWNc[] PROGMEM = - "
"; + ""; const char SCRIPT_MSG_TEXTINP[] PROGMEM = - "
"; + "%s"; + +const char SCRIPT_MSG_TEXTINP_U[] PROGMEM = + "%s"; const char SCRIPT_MSG_NUMINP[] PROGMEM = - "
"; + "%s"; #ifdef USE_GOOGLE_CHARTS @@ -7307,7 +7835,7 @@ const char SCRIPT_MSG_GOPT2[] PROGMEM = "showRowNumber:true,sort:'disable',allowHtml:true,width:'100%%',height:'100%%',cssClassNames:cssc"; const char SCRIPT_MSG_GOPT3[] PROGMEM = -"title:'%s',isStacked:false,vAxes:{0:{maxValue:%d},1:{maxValue:%d}},series:{0:{targetAxisIndex:0},1:{targetAxisIndex:1}}%s"; +"title:'%s',isStacked:false,vAxes:{0:{maxValue:%s},1:{maxValue:%s}},series:{0:{targetAxisIndex:0},1:{targetAxisIndex:1}}%s"; const char SCRIPT_MSG_GOPT4[] PROGMEM = //"hAxis:{minValue:new Date(0,1,1,0,0),maxValue:new Date(0,1,2,0,0),format:'HH:mm'}"; @@ -7317,7 +7845,7 @@ const char SCRIPT_MSG_GOPT5[] PROGMEM = "new Date(0,0,0,%d,%d)"; const char SCRIPT_MSG_GOPT6[] PROGMEM = -"title:'%s',isStacked:false,vAxis:{viewWindow:{min:%d,max:%d}}%s"; +"title:'%s',isStacked:false,vAxis:{viewWindow:{min:%s,max:%s}}%s"; const char SCRIPT_MSG_GTE1[] PROGMEM = "'%s'"; @@ -7338,15 +7866,15 @@ uint16 entries = 0; uint16_t cipos = 0; uint8_t anum = 0; - while (anum> 2 %d\n",len); - if (fa && len>=entries) { + if (fa && len >= entries) { if (!entries) { entries = len; } @@ -7395,6 +7923,32 @@ char *gc_send_labels(char *lp,uint32_t anum) { return lp; } +const char *GC_type(uint8_t type) { + switch (type) { + case 'l': + return PSTR("LineChart"); + case 'b': + return PSTR("BarChart"); + case 'p': + return PSTR("PieChart"); + case 'g': + return PSTR("Gauge"); + case 't': + return PSTR("Table"); + case 'T': + return PSTR("Timeline"); + case 'h': + return PSTR("Histogram"); + case 'c': + return PSTR("ColumnChart"); + case 'C': + return PSTR("ComboChart"); + default: + return PSTR("*"); + } +} + + #endif // USE_GOOGLE_CHARTS void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen) { @@ -7408,42 +7962,67 @@ uint32_t cnt; nbuf[cnt] = 0; } -void ScriptWebShow(char mc) { - uint8_t web_script; - glob_script_mem.web_mode = mc; - if (mc=='w' || mc=='x') { - if (mc=='x') { - mc='$'; - } - web_script = Run_Scripter(">w", -2, 0); +#define WSO_NOCENTER 1 +#define WSO_NODIV 2 +#define WSO_FORCEPLAIN 4 +#define WSO_STOP_DIV 0x80 + +void WCS_DIV(uint8_t flag) { + if (flag & WSO_NODIV) return; + if (flag & WSO_STOP_DIV) { + WSContentSend_PD(SCRIPT_MSG_BUT_STOP); } else { - web_script = Run_Scripter(">W", -2, 0); + WSContentSend_PD(SCRIPT_MSG_BUT_START); + } +} + + +uint8_t specopt; +uint8_t chartindex; +uint8_t google_libs; +#ifdef USE_GOOGLE_CHARTS +char gs_ctype; +#endif + +void ScriptWebShow(char mc, uint8_t page) { + float cv_max = 0; + float cv_inc = 0; + float *cv_count = 0; + char *cv_ptr; + + //uint8_t web_script; + glob_script_mem.web_mode = mc; + if (mc == 'w' || mc == 'x') { + if (mc == 'x') { + mc = '$'; + } + glob_script_mem.section_ptr = glob_script_mem.web_pages[page]; + } else { + glob_script_mem.section_ptr = glob_script_mem.web_pages[0]; } - if (web_script==99) { - char tmp[256]; - uint8_t optflg = 0; - uint8_t chartindex = 1; - uint8_t google_libs = 0; + if (glob_script_mem.section_ptr) { + + chartindex = 1; + google_libs = 0; char *lp = glob_script_mem.section_ptr + 2; - if (mc=='w') { + if (mc == 'w') { while (*lp) { - if (*lp=='\n') break; + if (*lp == '\n') break; lp++; } } - char *cv_ptr; - float cv_max=0; - float cv_inc=0; - float *cv_count=0; + + specopt = 0; while (lp) { - while (*lp==SCRIPT_EOL) { + while (*lp == SCRIPT_EOL) { lp++; } if (!*lp || *lp=='#' || *lp=='>') { break; } - if (*lp!=';') { + if (*lp != ';') { + // send this line to web SCRIPT_SKIP_SPACES if (!strncmp(lp, "%for ", 5)) { @@ -7451,7 +8030,7 @@ void ScriptWebShow(char mc) { struct T_INDEX ind; uint8_t vtype; lp = isvar(lp + 5, &vtype, &ind, 0, 0, 0); - if ((vtype!=VAR_NV) && (vtype&STYPE)==0) { + if ((vtype != VAR_NV) && (vtype&STYPE) == 0) { uint16_t index = glob_script_mem.type[ind.index].index; cv_count = &glob_script_mem.fvars[index]; SCRIPT_SKIP_SPACES @@ -7461,7 +8040,7 @@ void ScriptWebShow(char mc) { SCRIPT_SKIP_SPACES lp = GetNumericArgument(lp , OPER_EQU, &cv_inc, 0); cv_ptr = lp; - goto nextwebline; + //goto nextwebline; } else { continue; } @@ -7469,557 +8048,716 @@ void ScriptWebShow(char mc) { if (cv_count) { // for next loop *cv_count += cv_inc; - if (*cv_count<=cv_max) { + if (*cv_count <= cv_max) { lp = cv_ptr; } else { cv_count = 0; - goto nextwebline; + //goto nextwebline; } } else { - goto nextwebline; + //goto nextwebline; } } else if (!strncmp(lp, "%=#", 3)) { // subroutine + uint8_t sflg = specopt; + specopt = WSO_FORCEPLAIN; lp = scripter_sub(lp + 1, 0); - goto nextwebline; - } - - Replace_Cmd_Vars(lp, 1, tmp, sizeof(tmp)); - char *lin = tmp; - if ((!mc && (*lin!='$')) || (mc=='w' && (*lin!='$'))) { - /*if (!mc || mc=='w') { - if (*lin=='$') { - lin++; - if (!strncmp(lin,"gc(", 3)) { - goto exgc; - } - }*/ - // normal web section - if (*lin=='@') { - lin++; - optflg = 1; - } else { - optflg = 0; - } - // check for input elements - if (!strncmp(lin, "sl(", 3)) { - // insert slider sl(min max var left mid right) - char *lp = lin; - float min; - lp = GetNumericArgument(lp + 3, OPER_EQU, &min, 0); - SCRIPT_SKIP_SPACES - // arg2 - float max; - lp = GetNumericArgument(lp, OPER_EQU, &max, 0); - SCRIPT_SKIP_SPACES - float val; - char *slp = lp; - lp = GetNumericArgument(lp, OPER_EQU, &val, 0); - SCRIPT_SKIP_SPACES - - char vname[16]; - ScriptGetVarname(vname, slp, sizeof(vname)); - - char left[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, left, 0); - SCRIPT_SKIP_SPACES - char mid[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, mid, 0); - SCRIPT_SKIP_SPACES - char right[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, right, 0); - SCRIPT_SKIP_SPACES - - WSContentSend_PD(SCRIPT_MSG_SLIDER, left,mid, right, (uint32_t)min, (uint32_t)max, (uint32_t)val, vname); - - } else if (!strncmp(lin, "ck(", 3)) { - char *lp = lin + 3; - char *slp = lp; - float val; - lp = GetNumericArgument(lp, OPER_EQU, &val, 0); - SCRIPT_SKIP_SPACES - - char vname[16]; - ScriptGetVarname(vname, slp, sizeof(vname)); - - char label[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, label, 0); - const char *cp; - uint8_t uval; - if (val>0) { - cp = "checked='checked'"; - uval = 0; - } else { - cp = ""; - uval = 1; - } - WSContentSend_PD(SCRIPT_MSG_CHKBOX, label, (char*)cp, uval, vname); - } else if (!strncmp(lin, "pd(", 3)) { - // pull down - char *lp = lin + 3; - char *slp = lp; - float val; - lp = GetNumericArgument(lp, OPER_EQU, &val, 0); - SCRIPT_SKIP_SPACES - - char vname[16]; - ScriptGetVarname(vname, slp, sizeof(vname)); - - SCRIPT_SKIP_SPACES - char pulabel[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, pulabel, 0); - - WSContentSend_PD(SCRIPT_MSG_PULLDOWNa, vname, pulabel, 1, vname, vname); - - // get pu labels - uint8_t index = 1; - while (*lp) { - SCRIPT_SKIP_SPACES - lp = GetStringArgument(lp, OPER_EQU, pulabel, 0); - char *cp; - if (val == index) { - cp = (char*)"selected"; - } else { - cp = (char*)""; - } - WSContentSend_PD(SCRIPT_MSG_PULLDOWNb, cp, index, pulabel); - SCRIPT_SKIP_SPACES - if (*lp == ')') { - lp++; - break; - } - index++; - } - WSContentSend_PD(SCRIPT_MSG_PULLDOWNc); - } else if (!strncmp(lin, "bu(", 3)) { - char *lp = lin + 3; - uint8_t bcnt = 0; - char *found = lin; - while (bcnt<4) { - found = strstr(found, "bu("); - if (!found) break; - found += 3; - bcnt++; - } - uint8_t proz = 100 / bcnt; - if (!optflg && bcnt>1) proz -= 2; - if (optflg) WSContentSend_PD(SCRIPT_MSG_BUT_START_TBL); - else WSContentSend_PD(SCRIPT_MSG_BUT_START); - for (uint32_t cnt = 0; cnt < bcnt; cnt++) { - float val; - char *slp = lp; - lp = GetNumericArgument(lp, OPER_EQU, &val, 0); - SCRIPT_SKIP_SPACES - - char vname[16]; - ScriptGetVarname(vname, slp, sizeof(vname)); - - SCRIPT_SKIP_SPACES - char ontxt[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, ontxt, 0); - SCRIPT_SKIP_SPACES - char offtxt[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, offtxt, 0); - - char *cp; - uint8_t uval; - if (val>0) { - cp = ontxt; - uval = 0; - } else { - cp = offtxt; - uval = 1; - } - if (bcnt>1 && cnt==bcnt-1) { - if (!optflg) proz += 2; - } - if (!optflg) { - WSContentSend_PD(SCRIPT_MSG_BUTTONa, proz, uval, vname, cp); - } else { - WSContentSend_PD(SCRIPT_MSG_BUTTONa_TBL, proz, uval, vname, cp); - } - if (bcnt>1 && cnt%s"), lin); - } else { - WSContentSend_PD(PSTR("{s}%s{e}"), lin); - } - } - } - // end standard web interface + specopt = sflg; + //goto nextwebline; } else { - // main section interface - if (*lin==mc) { - -#ifdef USE_GOOGLE_CHARTS - lin++; -exgc: - char *lp; - if (!strncmp(lin, "gc(", 3)) { - // get google table - lp = lin + 3; - SCRIPT_SKIP_SPACES - const char *type; - const char *func; - char options[312]; - uint8_t nanum = MAX_GARRAY; - uint8_t y2f = 0; - uint8_t tonly = 0; - char ctype; - ctype = *lp; - lp++; - if (!(google_libs & GLIBS_MAIN)) { - google_libs |= GLIBS_MAIN; - WSContentSend_PD(SCRIPT_MSG_GTABLE); - } - switch (ctype) { - case 'l': - type = PSTR("LineChart"); - break; - case 'b': - type = PSTR("BarChart"); - break; - case 'p': - type = PSTR("PieChart"); - break; - case 'g': - type = PSTR("Gauge"); - if (!(google_libs & GLIBS_GAUGE)) { - google_libs |= GLIBS_GAUGE; - WSContentSend_PD(SCRIPT_MSG_GAUGE); - } - break; - case 't': - type = PSTR("Table"); - if (!(google_libs & GLIBS_TABLE)) { - google_libs |= GLIBS_TABLE; - WSContentSend_PD(SCRIPT_MSG_TABLE); - } - break; - case 'T': - type = PSTR("Timeline"); - if (!(google_libs & GLIBS_TIMELINE)) { - google_libs |= GLIBS_TIMELINE; - WSContentSend_PD(SCRIPT_MSG_TIMELINE); - } - break; - case 'h': - type = PSTR("Histogram"); - break; - case 'c': - type = PSTR("ColumnChart"); - break; - case 'C': - type = PSTR("ComboChart"); - break; - case 'e': - WSContentSend_PD(SCRIPT_MSG_GTABLEbx, type, chartindex); - chartindex++; - goto nextwebline; - break; - default: - // error - goto nextwebline; - break; - } - if (ctype=='l' && *lp=='f') { - lp++; - func = PSTR(",curveType:'function'"); - } else { - func = ""; - } - if (*lp=='2') { - lp++; - nanum = 2; - y2f = 1; - } - if (*lp=='t') { - lp++; - tonly = 1; - } - SCRIPT_SKIP_SPACES - - //Serial.printf("type %d\n",ctype); - - float *arrays[MAX_GARRAY]; - uint8_t anum = 0; - uint16_t entries = 0; - uint16_t ipos = 0; - lp = gc_get_arrays(lp, &arrays[0], &anum, &entries, &ipos); - - if (anum>nanum) { - goto nextwebline; - } - // we know how many arrays and the number of entries - //Serial.printf("arrays %d\n",anum); - //Serial.printf("entries %d\n",entries); - if (ctype=='T') { - if (anum && !(entries & 1)) { - WSContentSend_PD(SCRIPT_MSG_GTABLEa); - char label[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, label, 0); - SCRIPT_SKIP_SPACES - char lab2[SCRIPT_MAXSSIZE]; - lab2[0] = 0; - if (*lp!=')') { - lp = GetStringArgument(lp, OPER_EQU, lab2, 0); - WSContentSend_PD(SCRIPT_MSG_GTABLEe); - } else { - WSContentSend_PD(SCRIPT_MSG_GTABLEd); - } - - for (uint32_t ind = 0; ind < anum; ind++) { - char lbl[16]; - float *fp = arrays[ind]; - GetTextIndexed(lbl, sizeof(lbl), ind, label); - char lbl2[16]; - if (lab2[0]) { - GetTextIndexed(lbl2, sizeof(lbl2), ind, lab2); - } - uint32_t ventries = 0; - for (uint32_t cnt = 0; cnt < entries; cnt += 2) { - if (fp[cnt]!=0 && fp[cnt+1]!=0) { - ventries+=2; - } else { - break; - } - } - - for (uint32_t cnt = 0; cnt < ventries; cnt += 2) { - WSContentSend_PD("['%s',",lbl); - if (lab2[0]) { - WSContentSend_PD("'%s',",lbl2); - } - uint32_t time = fp[cnt]; - WSContentSend_PD(SCRIPT_MSG_GOPT5, time / 60, time % 60); - WSContentSend_PD(","); - time = fp[cnt + 1]; - WSContentSend_PD(SCRIPT_MSG_GOPT5, time / 60, time % 60); - WSContentSend_PD("]"); - if (cnt < ventries - 2) { WSContentSend_PD(","); } - } - if (ind < anum - 1) { - if (ventries) { - WSContentSend_PD(","); - } - } - } - snprintf_P(options,sizeof(options), SCRIPT_MSG_GOPT4); - } - } else { - // we need to fetch the labels now - WSContentSend_PD(SCRIPT_MSG_GTABLEa); - lp = gc_send_labels(lp, anum); - - // now we have to export the values - // fetch label part only once in combo string - char label[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, label, 0); - SCRIPT_SKIP_SPACES - - int16_t divflg = 1; - int16_t todflg = -1; - if (!strncmp(label, "cnt", 3)) { - char *cp = &label[3]; - //todflg=atoi(&label[3]); - todflg = strtol(cp, &cp, 10); - if (todflg >= entries) todflg = entries - 1; - if (todflg < 0) todflg = 0; - if (*cp=='/') { - cp++; - divflg = strtol(cp, &cp, 10); - } - } else { - char *lp = label; - if (!strncmp(label, "wdh:", 4)) { - // one week hours - todflg = -2; - lp += 4; - } - uint16 segments = 1; - for (uint32_t cnt = 0; cnt < strlen(lp); cnt++) { - if (lp[cnt]=='|') { - segments++; - } - } - divflg = entries / segments; - } - - uint32_t aind = ipos; - if (aind>=entries) aind = entries - 1; - for (uint32_t cnt = 0; cnt < entries; cnt++) { - WSContentSend_PD("['"); - char lbl[16]; - if (todflg>=0) { - sprintf(lbl, "%d:%02d", todflg / divflg, (todflg % divflg) * (60 / divflg) ); - todflg++; - if (todflg >= entries) { - todflg = 0; - } - } else { - if (todflg==-1) { - GetTextIndexed(lbl, sizeof(lbl), aind / divflg, label); - } else { - // day,hours,mins - GetTextIndexed(lbl, sizeof(lbl), aind / divflg, label + 4); - sprintf(lbl, "%s-%02d", lbl, aind % divflg); - } - } - WSContentSend_PD(lbl); - WSContentSend_PD("',"); - for (uint32_t ind = 0; ind < anum; ind++) { - char acbuff[32]; - float *fp = arrays[ind]; - f2char(fp[aind], glob_script_mem.script_dprec, glob_script_mem.script_lzero, acbuff); - WSContentSend_PD("%s", acbuff); - if (ind=entries) { - aind = 0; - } - } - // table complete - if (tonly) { - WSContentSend_PD("]);"); - goto nextwebline; - } - // get header - char header[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, header, 0); - SCRIPT_SKIP_SPACES - - switch (ctype) { - case 't': - snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT2); - break; - default: - snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT1, header); - break; - } - // check for 2 axis option - if (y2f) { - // 2 y axes variant - SCRIPT_SKIP_SPACES - float max1; - lp = GetNumericArgument(lp, OPER_EQU, &max1, 0); - SCRIPT_SKIP_SPACES - float max2; - lp = GetNumericArgument(lp, OPER_EQU, &max2, 0); - SCRIPT_SKIP_SPACES - snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT3, header, (uint32_t)max1, (uint32_t)max2, func); - } else { - SCRIPT_SKIP_SPACES - if (ctype!='g') { - if (*lp!=')') { - float max1; - lp = GetNumericArgument(lp, OPER_EQU, &max1, 0); - SCRIPT_SKIP_SPACES - float max2; - lp = GetNumericArgument(lp, OPER_EQU, &max2, 0); - SCRIPT_SKIP_SPACES - snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT6, header, (uint32_t)max1, (uint32_t)max2, func); - } - } - } - - if (ctype=='g') { - float yellowFrom; - lp = GetNumericArgument(lp, OPER_EQU, &yellowFrom, 0); - SCRIPT_SKIP_SPACES - float redFrom; - lp = GetNumericArgument(lp, OPER_EQU, &redFrom, 0); - SCRIPT_SKIP_SPACES - float maxValue; - lp = GetNumericArgument(lp, OPER_EQU, &maxValue, 0); - SCRIPT_SKIP_SPACES - float redTo = maxValue; - float yellowTo = redFrom; - snprintf_P(options, sizeof(options), SCRIPT_MSG_GAUGEOPT, (uint32_t)maxValue, (uint32_t)redFrom, (uint32_t)redTo, - (uint32_t)yellowFrom, (uint32_t)yellowTo); - } - } - WSContentSend_PD(SCRIPT_MSG_GTABLEb, options); - WSContentSend_PD(SCRIPT_MSG_GTABLEbx, type, chartindex); - chartindex++; - } else { - WSContentSend_PD(PSTR("%s"), lin); - } -#else - lin++; - WSContentSend_PD(PSTR("%s"), lin); - } else { - // WSContentSend_PD(PSTR("%s"),lin); -#endif //USE_GOOGLE_CHARTS - } + web_send_line(mc, lp); } - } nextwebline: - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; + if (*lp == SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } } } } } + +char *web_send_line(char mc, char *lp1) { +char tmp[256]; +char center[10]; +uint8_t optflg = 0; +const char *gc_str; + + Replace_Cmd_Vars(lp1, 1, tmp, sizeof(tmp)); + + char *lin = tmp; + if ((!mc && (*lin != '$')) || (mc == 'w' && (*lin != '$'))) { + // normal web section + if (*lin == '@') { + lin++; + optflg = 1; + } else { + optflg = 0; + } + + if (specopt & WSO_NOCENTER) { + center[0] = 0; + } else { + strcpy_P(center, PSTR("
")); + } + + if (!strncmp(lin, "so(", 3)) { + // set options + char *lp = lin; + float var; + lp = GetNumericArgument(lp + 3, OPER_EQU, &var, 0); + SCRIPT_SKIP_SPACES + lp++; + specopt = var; + // bit 0 = center mode + if (specopt & WSO_NOCENTER) { + center[0] = 0; + } else { + strcpy_P(center, PSTR("
")); + } + } else if (!strncmp(lin, "sl(", 3)) { + // insert slider sl(min max var left mid right) + char *lp = lin; + float min; + lp = GetNumericArgument(lp + 3, OPER_EQU, &min, 0); + SCRIPT_SKIP_SPACES + // arg2 + float max; + lp = GetNumericArgument(lp, OPER_EQU, &max, 0); + SCRIPT_SKIP_SPACES + float val; + char *slp = lp; + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); + SCRIPT_SKIP_SPACES + + char vname[16]; + ScriptGetVarname(vname, slp, sizeof(vname)); + + char left[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, left, 0); + SCRIPT_SKIP_SPACES + char mid[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, mid, 0); + SCRIPT_SKIP_SPACES + char right[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, right, 0); + SCRIPT_SKIP_SPACES + + WSContentSend_PD(SCRIPT_MSG_SLIDER, left,mid, right, (uint32_t)min, (uint32_t)max, (uint32_t)val, vname); + lp++; + + } else if (!strncmp(lin, "ck(", 3)) { + char *lp = lin + 3; + char *slp = lp; + float val; + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); + SCRIPT_SKIP_SPACES + + char vname[16]; + ScriptGetVarname(vname, slp, sizeof(vname)); + + char label[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, label, 0); + const char *cp; + uint8_t uval; + if (val>0) { + cp = "checked='checked'"; + uval = 0; + } else { + cp = ""; + uval = 1; + } + WCS_DIV(specopt); + WSContentSend_PD(SCRIPT_MSG_CHKBOX, center, label, (char*)cp, uval, vname); + WCS_DIV(specopt | WSO_STOP_DIV); + lp++; + } else if (!strncmp(lin, "pd(", 3)) { + // pull down + char *lp = lin + 3; + char *slp = lp; + float val; + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); + SCRIPT_SKIP_SPACES + + char vname[16]; + ScriptGetVarname(vname, slp, sizeof(vname)); + + SCRIPT_SKIP_SPACES + char pulabel[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, pulabel, 0); + SCRIPT_SKIP_SPACES + + glob_script_mem.glob_error = 0; + uint16_t tsiz = 200; + float fvar; + char *slp1 = lp; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + if (!glob_script_mem.glob_error) { + tsiz = fvar; + } else { + lp = slp1; + } + WCS_DIV(specopt); + WSContentSend_PD(SCRIPT_MSG_PULLDOWNa, center, vname, pulabel, tsiz, 1, vname, vname); + + // get pu labels + uint8_t index = 1; + while (*lp) { + SCRIPT_SKIP_SPACES + lp = GetStringArgument(lp, OPER_EQU, pulabel, 0); + if (index == 1 && pulabel[0] == '#') { + // number range + char *cp = &pulabel[1]; + uint8_t from = strtol(cp, &cp, 10); + uint8_t to = from; + if (*cp == '-') { + cp++; + to = strtol(cp, &cp, 10); + } + for (uint32_t cnt = from; cnt <= to; cnt++) { + sprintf(pulabel, "%d", cnt); + if (val == index) { + cp = (char*)"selected"; + } else { + cp = (char*)""; + } + WSContentSend_PD(SCRIPT_MSG_PULLDOWNb, cp, index, pulabel); + index++; + } + break; + } + + char *cp; + if (val == index) { + cp = (char*)"selected"; + } else { + cp = (char*)""; + } + WSContentSend_PD(SCRIPT_MSG_PULLDOWNb, cp, index, pulabel); + SCRIPT_SKIP_SPACES + if (*lp == ')') { + lp++; + break; + } + index++; + } + WSContentSend_PD(SCRIPT_MSG_PULLDOWNc); + WCS_DIV(specopt | WSO_STOP_DIV); + } else if (!strncmp(lin, "bu(", 3)) { + char *lp = lin + 3; + uint8_t bcnt = 0; + char *found = lin; + while (bcnt<4) { + found = strstr(found, "bu("); + if (!found) break; + found += 3; + bcnt++; + } + uint8_t proz = 100 / bcnt; + if (!optflg && bcnt>1) proz -= 2; + if (optflg) WSContentSend_PD(SCRIPT_MSG_BUT_START_TBL); + else WSContentSend_PD(SCRIPT_MSG_BUT_START); + for (uint32_t cnt = 0; cnt < bcnt; cnt++) { + float val; + char *slp = lp; + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); + SCRIPT_SKIP_SPACES + + char vname[16]; + ScriptGetVarname(vname, slp, sizeof(vname)); + + SCRIPT_SKIP_SPACES + char ontxt[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, ontxt, 0); + SCRIPT_SKIP_SPACES + char offtxt[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, offtxt, 0); + + char *cp; + uint8_t uval; + if (val>0) { + cp = ontxt; + uval = 0; + } else { + cp = offtxt; + uval = 1; + } + if (bcnt > 1 && cnt == bcnt - 1) { + if (!optflg) proz += 2; + } + if (!optflg) { + WSContentSend_PD(SCRIPT_MSG_BUTTONa, proz, uval, vname, cp); + } else { + WSContentSend_PD(SCRIPT_MSG_BUTTONa_TBL, proz, uval, vname, cp); + } + if (bcnt > 1 && cnt < bcnt - 1) { + if (!optflg) WSContentSend_PD(SCRIPT_MSG_BUTTONb, 2); + } + lp += 4; + } + if (optflg) WSContentSend_PD(SCRIPT_MSG_BUT_STOP_TBL); + else WSContentSend_PD(SCRIPT_MSG_BUT_STOP); + + } else if (!strncmp(lin, "tm(", 3)) { + // time only HH:MM + float val; + char *lp = lin + 3; + char *slp = lp; + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); + SCRIPT_SKIP_SPACES + char vname[16]; + ScriptGetVarname(vname, slp, sizeof(vname)); + SCRIPT_SKIP_SPACES + char label[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, label, 0); + SCRIPT_SKIP_SPACES + uint16_t tsiz = 70; + if (*lp != ')') { + float fvar; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + tsiz = fvar; + } + lp++; + char vstr[16]; + uint32_t tv = val; + sprintf_P(vstr,PSTR("%02d:%02d"),tv / 100, tv % 100); + const char *type = PSTR("time"); + const char *min = PSTR("00:00"); + const char *max = PSTR("23:59"); + const char *styp = PSTR("sivat"); + WCS_DIV(specopt); + WSContentSend_PD(SCRIPT_MSG_TEXTINP_U, center, label, type, vstr, min, max, tsiz, styp, vname); + WCS_DIV(specopt | WSO_STOP_DIV); + } else if (!strncmp(lin, "tx(", 3)) { + // text + char *lp = lin + 3; + char *slp = lp; + char str[SCRIPT_MAXSSIZE]; + lp = ForceStringVar(lp, str); + SCRIPT_SKIP_SPACES + char label[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, label, 0); + char vname[16]; + ScriptGetVarname(vname, slp, sizeof(vname)); + SCRIPT_SKIP_SPACES + + uint16_t tsiz = 200; + if (*lp != ')') { + glob_script_mem.glob_error = 0; + float fvar; + char *slp1 = lp; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + SCRIPT_SKIP_SPACES + if (!glob_script_mem.glob_error) { + tsiz = fvar; + } else { + lp = slp1; + } + + if (*lp != ')') { + char type[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, type, 0); + SCRIPT_SKIP_SPACES + // also requires min max values + char min[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, min, 0); + SCRIPT_SKIP_SPACES + char max[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, max, 0); + SCRIPT_SKIP_SPACES + WCS_DIV(specopt); + const char *styp = PSTR("siva"); + WSContentSend_PD(SCRIPT_MSG_TEXTINP_U, center, label, type, str, min, max, tsiz, styp, vname); + WCS_DIV(specopt | WSO_STOP_DIV); + } else { + WCS_DIV(specopt); + WSContentSend_PD(SCRIPT_MSG_TEXTINP, center, label, str, tsiz, vname); + WCS_DIV(specopt | WSO_STOP_DIV); + } + } else { + WCS_DIV(specopt); + WSContentSend_PD(SCRIPT_MSG_TEXTINP, center, label, str, tsiz, vname); + WCS_DIV(specopt | WSO_STOP_DIV); + } + lp++; + //goto restart; + + } else if (!strncmp(lin, "nm(", 3)) { + char *lp = lin; + float min; + lp = GetNumericArgument(lp + 3, OPER_EQU, &min, 0); + SCRIPT_SKIP_SPACES + float max; + lp = GetNumericArgument(lp, OPER_EQU, &max, 0); + SCRIPT_SKIP_SPACES + float step; + lp = GetNumericArgument(lp, OPER_EQU, &step, 0); + SCRIPT_SKIP_SPACES + float val; + char *slp = lp; + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); + SCRIPT_SKIP_SPACES + char vname[16]; + ScriptGetVarname(vname, slp, sizeof(vname)); + + char label[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, label, 0); + SCRIPT_SKIP_SPACES + uint16_t tsiz = 200; + uint8_t dprec = 1; + if (*lp != ')') { + float val; + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); + SCRIPT_SKIP_SPACES + tsiz = val; + if (*lp != ')') { + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); + dprec = val; + } + } + + char vstr[16],minstr[16],maxstr[16],stepstr[16]; + dtostrfd(val, dprec, vstr); + dtostrfd(min, dprec, minstr); + dtostrfd(max, dprec, maxstr); + dtostrfd(step, dprec, stepstr); + WCS_DIV(specopt); + WSContentSend_PD(SCRIPT_MSG_NUMINP, center, label, minstr, maxstr, stepstr, vstr, tsiz, vname); + WCS_DIV(specopt | WSO_STOP_DIV); + lp++; + + } else { + if (mc == 'w' || (specopt & WSO_FORCEPLAIN)) { + WSContentSend_PD(PSTR("%s"), lin); + } else { + if (optflg) { + WSContentSend_PD(PSTR("
%s
"), lin); + } else { + WSContentSend_PD(PSTR("{s}%s{e}"), lin); + } + } + } + // end standard web interface + } else { + // main section interface + if (*lin == mc) { + +#ifdef USE_GOOGLE_CHARTS + lin++; +exgc: + char *lp; + if (!strncmp(lin, "gc(", 3)) { + // get google table + lp = lin + 3; + SCRIPT_SKIP_SPACES + + const char *func; + char options[312]; + uint8_t nanum = MAX_GARRAY; + uint8_t y2f = 0; + uint8_t tonly = 0; + char type = *lp; + if (type != 'e') { + gs_ctype = type; + } + lp++; + if (!(google_libs & GLIBS_MAIN)) { + google_libs |= GLIBS_MAIN; + WSContentSend_PD(SCRIPT_MSG_GTABLE); + } + + gc_str = GC_type(gs_ctype); + + switch (gs_ctype) { + case 'g': + if (!(google_libs & GLIBS_GAUGE)) { + google_libs |= GLIBS_GAUGE; + WSContentSend_PD(SCRIPT_MSG_GAUGE); + } + break; + case 't': + if (!(google_libs & GLIBS_TABLE)) { + google_libs |= GLIBS_TABLE; + WSContentSend_PD(SCRIPT_MSG_TABLE); + } + break; + case 'T': + if (!(google_libs & GLIBS_TIMELINE)) { + google_libs |= GLIBS_TIMELINE; + WSContentSend_PD(SCRIPT_MSG_TIMELINE); + } + break; + } + if (type == 'e') { + WSContentSend_PD(SCRIPT_MSG_GTABLEbx, gc_str, chartindex); + chartindex++; + return lp1; + } + + + if (gs_ctype=='l' && *lp=='f') { + lp++; + func = PSTR(",curveType:'function'"); + } else { + func = ""; + } + if (*lp=='2') { + lp++; + nanum = 2; + y2f = 1; + } + if (*lp=='t') { + lp++; + tonly = 1; + } + SCRIPT_SKIP_SPACES + + //Serial.printf("type %d\n",ctype); + + float *arrays[MAX_GARRAY]; + uint8_t anum = 0; + uint16_t entries = 0; + uint16_t ipos = 0; + lp = gc_get_arrays(lp, &arrays[0], &anum, &entries, &ipos); + + if (anum>nanum) { + return lp1; + //goto nextwebline; + } + // we know how many arrays and the number of entries + //Serial.printf("arrays %d\n",anum); + //Serial.printf("entries %d\n",entries); + if (gs_ctype=='T') { + if (anum && !(entries & 1)) { + WSContentSend_PD(SCRIPT_MSG_GTABLEa); + char label[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, label, 0); + SCRIPT_SKIP_SPACES + char lab2[SCRIPT_MAXSSIZE]; + lab2[0] = 0; + if (*lp!=')') { + lp = GetStringArgument(lp, OPER_EQU, lab2, 0); + WSContentSend_PD(SCRIPT_MSG_GTABLEe); + } else { + WSContentSend_PD(SCRIPT_MSG_GTABLEd); + } + + for (uint32_t ind = 0; ind < anum; ind++) { + char lbl[16]; + float *fp = arrays[ind]; + GetTextIndexed(lbl, sizeof(lbl), ind, label); + char lbl2[16]; + if (lab2[0]) { + GetTextIndexed(lbl2, sizeof(lbl2), ind, lab2); + } + uint32_t ventries = 0; + for (uint32_t cnt = 0; cnt < entries; cnt += 2) { + if (fp[cnt]!=0 && fp[cnt+1]!=0) { + ventries+=2; + } else { + break; + } + } + + for (uint32_t cnt = 0; cnt < ventries; cnt += 2) { + WSContentSend_PD("['%s',",lbl); + if (lab2[0]) { + WSContentSend_PD("'%s',",lbl2); + } + uint32_t time = fp[cnt]; + WSContentSend_PD(SCRIPT_MSG_GOPT5, time / 60, time % 60); + WSContentSend_PD(","); + time = fp[cnt + 1]; + WSContentSend_PD(SCRIPT_MSG_GOPT5, time / 60, time % 60); + WSContentSend_PD("]"); + if (cnt < ventries - 2) { WSContentSend_PD(","); } + } + if (ind < anum - 1) { + if (ventries) { + WSContentSend_PD(","); + } + } + } + snprintf_P(options,sizeof(options), SCRIPT_MSG_GOPT4); + } + } else { + // we need to fetch the labels now + WSContentSend_PD(SCRIPT_MSG_GTABLEa); + lp = gc_send_labels(lp, anum); + + // now we have to export the values + // fetch label part only once in combo string + char label[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, label, 0); + SCRIPT_SKIP_SPACES + + uint8_t asflg = 1; + if (label[0] == '&') { + strcpy(label, &label[1]); + asflg = 0; + } + + int16_t divflg = 1; + int16_t todflg = -1; + if (!strncmp(label, "cnt", 3)) { + char *cp = &label[3]; + //todflg=atoi(&label[3]); + todflg = strtol(cp, &cp, 10); + if (todflg >= entries) todflg = entries - 1; + if (todflg < 0) todflg = 0; + if (*cp=='/') { + cp++; + divflg = strtol(cp, &cp, 10); + } + } else { + char *lp = label; + if (!strncmp(label, "wdh:", 4)) { + // one week hours + todflg = -2; + lp += 4; + } + uint16 segments = 1; + for (uint32_t cnt = 0; cnt < strlen(lp); cnt++) { + if (lp[cnt] == '|') { + segments++; + } + } + divflg = entries / segments; + } + + uint32_t aind = ipos; + if (aind >= entries) aind = entries - 1; + for (uint32_t cnt = 0; cnt < entries; cnt++) { + WSContentSend_PD("['"); + char lbl[16]; + if (todflg >= 0) { + sprintf(lbl, "%d:%02d", todflg / divflg, (todflg % divflg) * (60 / divflg) ); + todflg++; + if (todflg >= entries) { + todflg = 0; + } + } else { + if (todflg == -1) { + GetTextIndexed(lbl, sizeof(lbl), aind / divflg, label); + } else { + // day,hours,mins + GetTextIndexed(lbl, sizeof(lbl), aind / divflg, label + 4); + sprintf(lbl, "%s-%02d", lbl, aind % divflg); + } + } + WSContentSend_PD(lbl); + WSContentSend_PD("',"); + for (uint32_t ind = 0; ind < anum; ind++) { + char acbuff[32]; + float *fp = arrays[ind]; + float fval; + if (asflg) { + fval = fp[aind]; + } else { + fval = fp[cnt]; + } + f2char(fval, glob_script_mem.script_dprec, glob_script_mem.script_lzero, acbuff); + WSContentSend_PD("%s", acbuff); + if (ind < anum - 1) { WSContentSend_PD(","); } + } + WSContentSend_PD("]"); + if (cnt < entries - 1) { WSContentSend_PD(","); } + aind++; + if (aind >= entries) { + aind = 0; + } + } + // table complete + if (tonly) { + WSContentSend_PD("]);"); + return lp1; + //goto nextwebline; + } + // get header + char header[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, header, 0); + SCRIPT_SKIP_SPACES + + switch (gs_ctype) { + case 't': + snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT2); + break; + default: + snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT1, header); + break; + } + // check for 2 axis option + if (y2f) { + // 2 y axes variant + SCRIPT_SKIP_SPACES + float max1; + lp = GetNumericArgument(lp, OPER_EQU, &max1, 0); + SCRIPT_SKIP_SPACES + float max2; + lp = GetNumericArgument(lp, OPER_EQU, &max2, 0); + SCRIPT_SKIP_SPACES + char maxstr1[16]; + dtostrfd(max1, 3, maxstr1); + char maxstr2[16]; + dtostrfd(max2, 3, maxstr2); + //snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT3, header, (uint32_t)max1, (uint32_t)max2, func); + snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT3, header, maxstr1, maxstr2, func); + } else { + SCRIPT_SKIP_SPACES + if (gs_ctype!='g') { + if (*lp!=')') { + float max1; + lp = GetNumericArgument(lp, OPER_EQU, &max1, 0); + SCRIPT_SKIP_SPACES + float max2; + lp = GetNumericArgument(lp, OPER_EQU, &max2, 0); + SCRIPT_SKIP_SPACES + char maxstr1[16]; + dtostrfd(max1, 3, maxstr1); + char maxstr2[16]; + dtostrfd(max2, 3, maxstr2); + //nprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT6, header, (uint32_t)max1, (uint32_t)max2, func); + snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT6, header, maxstr1, maxstr2, func); + } + } + } + + if (gs_ctype=='g') { + float yellowFrom; + lp = GetNumericArgument(lp, OPER_EQU, &yellowFrom, 0); + SCRIPT_SKIP_SPACES + float redFrom; + lp = GetNumericArgument(lp, OPER_EQU, &redFrom, 0); + SCRIPT_SKIP_SPACES + float maxValue; + lp = GetNumericArgument(lp, OPER_EQU, &maxValue, 0); + SCRIPT_SKIP_SPACES + float redTo = maxValue; + float yellowTo = redFrom; + snprintf_P(options, sizeof(options), SCRIPT_MSG_GAUGEOPT, (uint32_t)maxValue, (uint32_t)redFrom, (uint32_t)redTo, + (uint32_t)yellowFrom, (uint32_t)yellowTo); + } + } + WSContentSend_PD(SCRIPT_MSG_GTABLEb, options); + WSContentSend_PD(SCRIPT_MSG_GTABLEbx, gc_str, chartindex); + chartindex++; + } else { + WSContentSend_PD(PSTR("%s"), lin); + } +#else + lin++; + WSContentSend_PD(PSTR("%s"), lin); + } else { + // WSContentSend_PD(PSTR("%s"),lin); +#endif //USE_GOOGLE_CHARTS + } + } + return lp1; +} + #endif //USE_SCRIPT_WEB_DISPLAY @@ -8095,7 +8833,10 @@ void ScriptJsonAppend(void) { bool RulesProcessEvent(const char *json_event) { - if (bitRead(Settings->rule_enabled, 0)) Run_Scripter(">E", 2, json_event); + if (bitRead(Settings->rule_enabled, 0)) { + //Run_Scripter(">E", 2, json_event); + if (glob_script_mem.event_script) Run_Scripter(glob_script_mem.event_script, 0, json_event); + } return true; } @@ -8106,11 +8847,10 @@ bool RulesProcessEvent(const char *json_event) { #define STASK_STACK 8192-2048 #endif -#if 1 - struct ESP32_Task { uint16_t task_timer; TaskHandle_t task_t; + char *tstart; } esp32_tasks[2]; @@ -8123,25 +8863,28 @@ void script_task1(void *arg) { //time=esp32_tasks[0].task_timer-time; //if (timerule_enabled, 0)) { - Run_Scripter(">t1", 3, 0); + if (esp32_tasks[0].tstart) Run_Scripter(esp32_tasks[0].tstart, 0, 0); + } + if (esp32_tasks[0].task_timer) { + delay(esp32_tasks[0].task_timer); + } else { + esp32_tasks[0].task_t = 0; + vTaskDelete( NULL ); } } } void script_task2(void *arg) { - //uint32_t lastms=millis(); - //uint32_t time; while (1) { - //time=millis()-lastms; - //lastms=millis(); - //time=esp32_tasks[1].task_timer-time; - //if (timerule_enabled, 0)) { - Run_Scripter(">t2", 3, 0); + if (esp32_tasks[1].tstart) Run_Scripter(esp32_tasks[1].tstart, 0, 0); + } + if (esp32_tasks[1].task_timer) { + delay(esp32_tasks[1].task_timer); + } else { + esp32_tasks[1].task_t = 0; + vTaskDelete( NULL ); } } } @@ -8157,49 +8900,23 @@ uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, int32_ esp32_tasks[num].task_t = 0; } if (prio >= 0) { - res = xTaskCreatePinnedToCore(script_task1, num==0?"T1":"T2", STASK_STACK, NULL, prio, &esp32_tasks[num].task_t, core); + char *sp = 0; esp32_tasks[num].task_timer = time; + if (!num) { + if (Run_Scripter(">t1", -3, 0) == 99) { + sp = glob_script_mem.section_ptr + 2; + res = xTaskCreatePinnedToCore(script_task1, "T1", STASK_STACK, NULL, prio, &esp32_tasks[num].task_t, core); + } + } else { + if (Run_Scripter(">t2", -3, 0) == 99) { + sp = glob_script_mem.section_ptr + 2; + res = xTaskCreatePinnedToCore(script_task2, "T2", STASK_STACK, NULL, prio, &esp32_tasks[num].task_t, core); + } + } + esp32_tasks[num].tstart = sp; } return res; } -#else - -uint16_t task_timer1; -uint16_t task_timer2; -TaskHandle_t task_t1; -TaskHandle_t task_t2; - -void script_task1(void *arg) { - while (1) { - delay(task_timer1); - Run_Scripter(">t1", 3, 0); - } -} - -void script_task2(void *arg) { - while (1) { - delay(task_timer2); - Run_Scripter(">t2", 3, 0); - } -} - -uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, int32_t prio) { - //return 0; - BaseType_t res = 0; - if (core > 1) { core = 1; } - if (num == 1) { - if (task_t1) { vTaskDelete(task_t1); } - res = xTaskCreatePinnedToCore(script_task1, "T1", STASK_STACK, NULL, prio, &task_t1, core); - task_timer1 = time; - } else { - if (task_t2) { vTaskDelete(task_t2); } - res = xTaskCreatePinnedToCore(script_task2, "T2", STASK_STACK, NULL, prio, &task_t2, core); - task_timer2 = time; - } - return res; -} -#endif - #endif // USE_SCRIPT_TASK #endif // ESP32 @@ -8210,11 +8927,18 @@ int32_t url2file(uint8_t fref, char *url) { WiFiClient http_client; HTTPClient http; int32_t httpCode = 0; - char hbuff[128]; - strcpy(hbuff, "http://"); - strcat(hbuff, url); - http.begin(http_client, UrlEncode(hbuff)); - httpCode = http.GET(); + String weburl = "http://"+UrlEncode(url); + //for (uint32_t retry = 0; retry < 15; retry++) { + http.begin(http_client, weburl); + delay(100); + httpCode = http.GET(); + //if (httpCode > 0) { + // break; + //} + //} + if (httpCode < 0) { + AddLog(LOG_LEVEL_INFO,PSTR("HTTP error %d = %s"), httpCode, http.errorToString(httpCode).c_str()); + } if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) { WiFiClient *stream = http.getStreamPtr(); int32_t len = http.getSize(); @@ -8288,7 +9012,9 @@ int32_t http_req(char *host, char *request) { // AddLog(LOG_LEVEL_INFO, PSTR("JSON %s"), wd_jstr); // TasmotaGlobal.mqtt_data = wd_jstr; - Run_Scripter(">E", 2, ResponseData()); + //Run_Scripter(">E", 2, ResponseData()); + if (glob_script_mem.event_script) Run_Scripter(glob_script_mem.event_script, 0, ResponseData()); + glob_script_mem.glob_error = 0; #endif @@ -8314,12 +9040,12 @@ String authCookie = ""; // get tesla powerwall info page json string uint32_t call2https(const char *host, const char *path) { - if (TasmotaGlobal.global_state.wifi_down) return 1; + //if (TasmotaGlobal.global_state.wifi_down) return 1; uint32_t status = 0; #ifdef TESLA_POWERWALL - authCookie = powerwall.getAuthCookie(); - return 0; +// authCookie = powerwall.getAuthCookie(); +// return 0; #endif #ifdef ESP32 @@ -8353,12 +9079,15 @@ uint32_t call2https(const char *host, const char *path) { } #endif + + AddLog(LOG_LEVEL_INFO,PSTR(">>> host %s"),host); + uint32_t retry = 0; - while ((!httpsClient->connect(host, 443)) && (retry < 5)) { + while ((!httpsClient->connect(host, 443)) && (retry < 10)) { delay(100); retry++; } - if (retry == 5) { + if (retry == 10) { return 2; } AddLog(LOG_LEVEL_INFO,PSTR("connected")); @@ -8865,6 +9594,37 @@ int32_t retval = 0; #endif +#ifdef SCRIPT_FULL_WEBPAGE +void script_add_subpage(uint8_t num) { + //uint8_t web_script = Run_Scripter(code, -strlen(code), 0); + if (glob_script_mem.web_pages[num]) { + char bname[48]; + cpy2lf(bname, sizeof(bname), glob_script_mem.web_pages[num] + 3); + + void (*wptr)(void); + + char id[8]; + switch (num) { + case 1: + wptr = ScriptFullWebpage1; + break; + case 2: + wptr = ScriptFullWebpage2; + break; + case 3: + wptr = ScriptFullWebpage3; + break; + case 4: + wptr = ScriptFullWebpage4; + break; + } + sprintf_P(id, PSTR("/sfd%1d"), num); + Webserver->on(id, wptr); + WSContentSend_PD(HTTP_WEB_FULL_DISPLAY, num, bname); + } +} +#endif // SCRIPT_FULL_WEBPAGE + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -8931,13 +9691,13 @@ bool Xdrv10(uint8_t function) if (EEP_INIT(EEP_SCRIPT_SIZE)) { // found 32kb eeprom, char *script; - if (EEP_SCRIPT_SIZE!=SPECIAL_EEPMODE_SIZE) { + if (EEP_SCRIPT_SIZE != SPECIAL_EEPMODE_SIZE) { script = (char*)calloc(EEP_SCRIPT_SIZE + 4, 1); if (!script) break; glob_script_mem.script_ram = script; glob_script_mem.script_size = EEP_SCRIPT_SIZE; EEP_READ(0, EEP_SCRIPT_SIZE, script); - if (*script==0xff) { + if (*script == 0xff) { memset(script, EEP_SCRIPT_SIZE, 0); } script[EEP_SCRIPT_SIZE - 1] = 0; @@ -8946,7 +9706,7 @@ bool Xdrv10(uint8_t function) ucs = (uint8_t*)calloc(SPI_FLASH_SEC_SIZE + 4, 1); if (!ucs) break; alt_eeprom_readBytes(0, SPI_FLASH_SEC_SIZE, ucs); - if (*ucs==0xff) { + if (*ucs == 0xff) { memset(ucs, SPI_FLASH_SEC_SIZE, 0); } ucs[SPI_FLASH_SEC_SIZE - 1] = 0; @@ -9027,7 +9787,9 @@ bool Xdrv10(uint8_t function) //case FUNC_INIT: if (bitRead(Settings->rule_enabled, 0)) { Run_Scripter(">B\n", 3, 0); - glob_script_mem.fast_script = Run_Scripter(">F", -2, 0); + if (Run_Scripter(">F", -2, 0) == 99) {glob_script_mem.fast_script = glob_script_mem.section_ptr + 2;} else {glob_script_mem.fast_script = 0;} + if (Run_Scripter(">E", -2, 0) == 99) {glob_script_mem.event_script = glob_script_mem.section_ptr + 2;} else {glob_script_mem.event_script = 0;} + script_set_web_pages(); #if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) Script_Check_Hue(0); #endif //USE_SCRIPT_HUE @@ -9048,7 +9810,8 @@ bool Xdrv10(uint8_t function) if (bitRead(Settings->rule_enabled, 0)) Run_Scripter(">P", 2, 0); #else if (bitRead(Settings->rule_enabled, 0)) { - Run_Scripter(">E", 2, 0); + //Run_Scripter(">E", 2, 0); + if (glob_script_mem.event_script) Run_Scripter(glob_script_mem.event_script, 0, 0); result = glob_script_mem.event_handeled; } #endif //SCRIPT_POWER_SECTION @@ -9059,10 +9822,12 @@ bool Xdrv10(uint8_t function) if (!strncmp_P(ResponseData(), PSTR("{\"Status"), 8)) { Run_Scripter(">U", 2, ResponseData()); } else { - Run_Scripter(">E", 2, ResponseData()); + //Run_Scripter(">E", 2, ResponseData()); + if (glob_script_mem.event_script) Run_Scripter(glob_script_mem.event_script, 0, ResponseData()); } #else - Run_Scripter(">E", 2, ResponseData()); + //Run_Scripter(">E", 2, ResponseData()); + if (glob_script_mem.event_script) Run_Scripter(glob_script_mem.event_script, 0, ResponseData()); #endif result = glob_script_mem.event_handeled; @@ -9086,15 +9851,12 @@ bool Xdrv10(uint8_t function) #ifdef USE_SCRIPT_WEB_DISPLAY case FUNC_WEB_ADD_MAIN_BUTTON: if (bitRead(Settings->rule_enabled, 0)) { - ScriptWebShow('$'); + ScriptWebShow('$', 0); #ifdef SCRIPT_FULL_WEBPAGE - uint8_t web_script = Run_Scripter(">w", -2, 0); - if (web_script==99) { - char bname[48]; - cpy2lf(bname, sizeof(bname), glob_script_mem.section_ptr + 3); - WSContentSend_PD(HTTP_WEB_FULL_DISPLAY, bname); - Webserver->on("/sfd", ScriptFullWebpage); - } + script_add_subpage(1); + script_add_subpage(2); + script_add_subpage(3); + script_add_subpage(4); #endif // SCRIPT_FULL_WEBPAGE #ifdef USE_UFILESYS @@ -9130,7 +9892,7 @@ bool Xdrv10(uint8_t function) #ifdef USE_SCRIPT_WEB_DISPLAY case FUNC_WEB_SENSOR: if (bitRead(Settings->rule_enabled, 0)) { - ScriptWebShow(0); + ScriptWebShow(0, 0); } break; #endif //USE_SCRIPT_WEB_DISPLAY diff --git a/tasmota/xdrv_12_discovery.ino b/tasmota/xdrv_12_discovery.ino index da92495d5..112df2387 100644 --- a/tasmota/xdrv_12_discovery.ino +++ b/tasmota/xdrv_12_discovery.ino @@ -48,10 +48,12 @@ void TasDiscoverMessage(void) { } bool TuyaMod = false; +#ifdef USE_TUYA_MCU + TuyaMod = IsModuleTuya(); +#endif bool iFanMod = false; #ifdef ESP8266 - if ((TUYA_DIMMER == TasmotaGlobal.module_type) || (SK03_TUYA == TasmotaGlobal.module_type)) { TuyaMod = true; }; - if ((SONOFF_IFAN02 == TasmotaGlobal.module_type) || (SONOFF_IFAN03 == TasmotaGlobal.module_type)) { iFanMod = true; }; + iFanMod = ((SONOFF_IFAN02 == TasmotaGlobal.module_type) || (SONOFF_IFAN03 == TasmotaGlobal.module_type)); #endif // ESP8266 ResponseAppend_P(PSTR("]," // Friendly Names (end) diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index a686531f6..0aa67c753 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -39,7 +39,7 @@ const char kHAssJsonSensorDevCla[] PROGMEM = "dev_cla\":\"power|dev_cla\":\"battery|dev_cla\":\"current|ic\":\"mdi:leak|ic\":\"mdi:current-ac|dev_cla\":\"humidity|dev_cla\":\"illuminance|" "ic\":\"mdi:cup-water|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|" "dev_cla\":\"pm1|dev_cla\":\"pm25|dev_cla\":\"pm10|dev_cla\":\"power_factor|dev_cla\":\"power|ic\":\"mdi:progress-clock|" - "dev_cla\":\"power|dev_cla\":\"energy|dev_cla\":\"energy|dev_cla\":\"voltage|ic\":\"mdi:scale|dev_cla\":\"energy|" + "dev_cla\":\"power|dev_cla\":\"energy|dev_cla\":\"energy\",\"stat_cla\":\"total_increasing|dev_cla\":\"voltage|ic\":\"mdi:scale|dev_cla\":\"energy|" "dev_cla\":\"carbon_dioxide|dev_cla\":\"carbon_dioxide|dev_class\":\"volatile_organic_compounds|" "ic\":\"mdi:palette|ic\":\"mdi:palette|ic\":\"mdi:palette|ic\":\"mdi:temperature-kelvin|ic\":\"mdi:ruler|dev_cla\":\"illuminance|"; @@ -215,10 +215,12 @@ void HassDiscoverMessage(void) { } bool TuyaMod = false; +#ifdef USE_TUYA_MCU + TuyaMod = IsModuleTuya(); +#endif bool iFanMod = false; #ifdef ESP8266 - if ((TUYA_DIMMER == TasmotaGlobal.module_type) || (SK03_TUYA == TasmotaGlobal.module_type)) { TuyaMod = true; }; - if ((SONOFF_IFAN02 == TasmotaGlobal.module_type) || (SONOFF_IFAN03 == TasmotaGlobal.module_type)) { iFanMod = true; }; + iFanMod = ((SONOFF_IFAN02 == TasmotaGlobal.module_type) || (SONOFF_IFAN03 == TasmotaGlobal.module_type)); #endif // ESP8266 ResponseAppend_P(PSTR("]," // Friendly Names (end) @@ -456,12 +458,14 @@ void HAssAnnounceRelayLight(void) uint8_t TuyaDim = 0; power_t shutter_mask = 0; - #ifdef ESP8266 - if (PWM_DIMMER == TasmotaGlobal.module_type ) { PwmMod = true; } // - if (SONOFF_IFAN02 == TasmotaGlobal.module_type || SONOFF_IFAN03 == TasmotaGlobal.module_type) { FanMod = true; } - if (SONOFF_DUAL == TasmotaGlobal.module_type) { valid_relay = 2; } - if (TUYA_DIMMER == TasmotaGlobal.module_type || SK03_TUYA == TasmotaGlobal.module_type) { TuyaMod = true; } - #endif //ESP8266 +#ifdef ESP8266 + PwmMod = (PWM_DIMMER == TasmotaGlobal.module_type); + FanMod = (SONOFF_IFAN02 == TasmotaGlobal.module_type || SONOFF_IFAN03 == TasmotaGlobal.module_type); + if (SONOFF_DUAL == TasmotaGlobal.module_type) { valid_relay = 2; } +#endif //ESP8266 +#ifdef USE_TUYA_MCU + TuyaMod = IsModuleTuya(); +#endif #ifdef USE_LIGHT // If there is a special Light to be enabled and managed with SetOption68 or SetOption37 >= 128, Discovery calculates the maximum number of entities to be generated in advance @@ -1026,8 +1030,7 @@ void HAssAnnounceShutters(void) } else { snprintf_P(stemp1, sizeof(stemp1), PSTR("%s"), SettingsText(SET_FRIENDLYNAME1 + i)); } - GetTopic_P(stemp2, TELE, TasmotaGlobal.mqtt_topic, D_RSLT_STATE); - Response_P(HASS_DISCOVER_BASE, stemp1, stemp2); + Response_P(PSTR("{\"name\":\"%s\""), stemp1); GetTopic_P(stemp1, TELE, TasmotaGlobal.mqtt_topic, S_LWT); TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, stemp1); @@ -1038,10 +1041,12 @@ void HAssAnnounceShutters(void) GetTopic_P(stemp1, STAT, TasmotaGlobal.mqtt_topic, PSTR("SHUTTER")); GetTopic_P(stemp2, CMND, TasmotaGlobal.mqtt_topic, PSTR("ShutterPosition")); TryResponseAppend_P(HASS_DISCOVER_SHUTTER_POS, stemp1, i + 1, stemp2, i + 1); - - GetTopic_P(stemp1, CMND, TasmotaGlobal.mqtt_topic, PSTR("ShutterTilt")); - TryResponseAppend_P(HASS_DISCOVER_SHUTTER_TILT, stemp1, i + 1, Settings->shutter_tilt_config[3][i], Settings->shutter_tilt_config[4][i]); - + + if (Settings->shutter_tilt_config[3][i] != Settings->shutter_tilt_config[4][i]) { + GetTopic_P(stemp1, CMND, TasmotaGlobal.mqtt_topic, PSTR("ShutterTilt")); + TryResponseAppend_P(HASS_DISCOVER_SHUTTER_TILT, stemp1, i + 1, Settings->shutter_tilt_config[3][i], Settings->shutter_tilt_config[4][i]); + } + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId()); TryResponseAppend_P(PSTR("}")); } else { diff --git a/tasmota/xdrv_15_pca9685.ino b/tasmota/xdrv_15_pca9685.ino index 48eae7f1f..9f6cee154 100644 --- a/tasmota/xdrv_15_pca9685.ino +++ b/tasmota/xdrv_15_pca9685.ino @@ -39,6 +39,7 @@ #define USE_PCA9685_FREQ 50 #endif +bool pca9685_inverted = false; // invert PWM for open-collector load bool pca9685_detected = false; uint16_t pca9685_freq = USE_PCA9685_FREQ; uint16_t pca9685_pin_pwm_value[16]; @@ -64,13 +65,22 @@ void PCA9685_Reset(void) { I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x80); PCA9685_SetPWMfreq(USE_PCA9685_FREQ); + pca9685_inverted = false; for (uint32_t pin=0;pin<16;pin++) { - PCA9685_SetPWM(pin,0,false); - pca9685_pin_pwm_value[pin] = 0; + PCA9685_SetPWM(pin,0,pca9685_inverted); + pca9685_pin_pwm_value[pin] = PCA9685_GetPWMvalue(0, pca9685_inverted); } Response_P(PSTR("{\"PCA9685\":{\"RESET\":\"OK\"}}")); } +uint16_t PCA9685_GetPWMvalue(uint16_t pwm, bool inverted) { + uint16_t pwm_val = pwm; + if (inverted) { + pwm_val = 4096-pwm; + } + return pwm_val; +} + void PCA9685_SetPWMfreq(double freq) { /* 7.3.5 from datasheet @@ -100,12 +110,13 @@ void PCA9685_SetPWM_Reg(uint8_t pin, uint16_t on, uint16_t off) { } void PCA9685_SetPWM(uint8_t pin, uint16_t pwm, bool inverted) { - if (4096 == pwm) { + uint16_t pwm_val = PCA9685_GetPWMvalue(pwm, inverted); + if (4096 == pwm_val) { PCA9685_SetPWM_Reg(pin, 4096, 0); // Special use additional bit causes channel to turn on completely without PWM } else { - PCA9685_SetPWM_Reg(pin, 0, pwm); + PCA9685_SetPWM_Reg(pin, 0, pwm_val); } - pca9685_pin_pwm_value[pin] = pwm; + pca9685_pin_pwm_value[pin] = pwm_val; } bool PCA9685_Command(void) @@ -130,6 +141,16 @@ bool PCA9685_Command(void) if (!strcmp(ArgV(argument, 1),"STATUS")) { PCA9685_OutputTelemetry(false); return serviced; } + if (!strcmp(ArgV(argument, 1),"INVERT")) { + if (paramcount > 1) { + pca9685_inverted = (1 == atoi(ArgV(argument, 2))); + Response_P(PSTR("{\"PCA9685\":{\"INVERT\":%i, \"Result\":\"OK\"}}"), pca9685_inverted?1:0); + return serviced; + } else { // No parameter was given for invert, so we return current setting + Response_P(PSTR("{\"PCA9685\":{\"INVERT\":%i}}"), pca9685_inverted?1:0); + return serviced; + } + } if (!strcmp(ArgV(argument, 1),"PWMF")) { if (paramcount > 1) { uint16_t new_freq = atoi(ArgV(argument, 2)); @@ -148,20 +169,20 @@ bool PCA9685_Command(void) uint8_t pin = atoi(ArgV(argument, 2)); if (paramcount > 2) { if (!strcmp(ArgV(argument, 3), "ON")) { - PCA9685_SetPWM(pin, 4096, false); + PCA9685_SetPWM(pin, 4096, pca9685_inverted); Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,4096); serviced = true; return serviced; } if (!strcmp(ArgV(argument, 3), "OFF")) { - PCA9685_SetPWM(pin, 0, false); + PCA9685_SetPWM(pin, 0, pca9685_inverted); Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,0); serviced = true; return serviced; } uint16_t pwm = atoi(ArgV(argument, 3)); - if ((pin >= 0 && pin <= 15) && (pwm >= 0 && pwm <= 4096)) { - PCA9685_SetPWM(pin, pwm, false); + if ((pin >= 0 && pin <= 15 || pin==61) && (pwm >= 0 && pwm <= 4096)) { + PCA9685_SetPWM(pin, pwm, pca9685_inverted); Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,pwm); serviced = true; return serviced; @@ -175,8 +196,10 @@ bool PCA9685_Command(void) void PCA9685_OutputTelemetry(bool telemetry) { ResponseTime_P(PSTR(",\"PCA9685\":{\"PWM_FREQ\":%i,"),pca9685_freq); + ResponseAppend_P(PSTR("\"INVERT\":%i,"), pca9685_inverted?1:0); for (uint32_t pin=0;pin<16;pin++) { - ResponseAppend_P(PSTR("\"PWM%i\":%i,"),pin,pca9685_pin_pwm_value[pin]); + uint16_t pwm_val = PCA9685_GetPWMvalue(pca9685_pin_pwm_value[pin], pca9685_inverted); // return logical (possibly inverted) pwm value + ResponseAppend_P(PSTR("\"PWM%i\":%i,"),pin,pwm_val); } ResponseAppend_P(PSTR("\"END\":1}}")); if (telemetry) { diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index 250c28b21..3c550424f 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -81,6 +81,7 @@ struct TUYA { bool send_success_next_second = false; // Second command success in low power mode uint32_t ignore_dimmer_cmd_timeout = 0; // Time until which received dimmer commands should be ignored bool ignore_tuyareceived = false; // When a modeset changes ignore stat + bool active; } Tuya; #define D_JSON_TUYA_MCU_RECEIVED "TuyaReceived" @@ -109,9 +110,16 @@ void (* const TuyaCommand[])(void) PROGMEM = { /*********************************************************************************************\ * Web Interface \*********************************************************************************************/ -bool IsModuleTuya(void) -{ - return ((TUYA_DIMMER == TasmotaGlobal.module_type) || (SK03_TUYA == TasmotaGlobal.module_type)); + +bool IsModuleTuya(void) { + bool is_tuya = Tuya.active; +//#ifdef ESP8266 + // This is not a Tuya driven device. It uses a Tuya provided ESP8266. Why it was here is a mystery to me. +// if (SK03_TUYA == TasmotaGlobal.module_type) { +// is_tuya = true; +// } +//#endif + return is_tuya; } bool AsModuleTuyaMS(void) // ModeSet Layout @@ -123,6 +131,7 @@ bool TuyaModeSet(void) // ModeSet Status { return Tuya.ModeSet; } + /*********************************************************************************************\ * Web Interface \*********************************************************************************************/ @@ -1055,8 +1064,10 @@ void TuyaNormalPowerModePacketProcess(void) * API Functions \*********************************************************************************************/ -bool TuyaModuleSelected(void) -{ +bool TuyaModuleSelected(void) { +#ifdef ESP8266 + if (TUYA_DIMMER != TasmotaGlobal.module_type) { return false; } + if (!PinUsed(GPIO_TUYA_RX) || !PinUsed(GPIO_TUYA_TX)) { // fallback to hardware-serial if not explicitly selected SetPin(1, AGPIO(GPIO_TUYA_TX)); SetPin(3, AGPIO(GPIO_TUYA_RX)); @@ -1064,6 +1075,8 @@ bool TuyaModuleSelected(void) Settings->my_gp.io[3] = AGPIO(GPIO_TUYA_RX); TasmotaGlobal.restart_flag = 2; } +#endif + if (!PinUsed(GPIO_TUYA_RX) || !PinUsed(GPIO_TUYA_TX)) { return false; } if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) == 0 && TUYA_DIMMER_ID > 0) { TuyaAddMcuFunc(TUYA_MCU_FUNC_DIMMER, TUYA_DIMMER_ID); @@ -1119,8 +1132,7 @@ bool TuyaModuleSelected(void) return true; } -void TuyaInit(void) -{ +void TuyaInit(void) { int baudrate = 9600; if (Settings->flag4.tuyamcu_baudrate) { baudrate = 115200; } // SetOption97 - Set Baud rate for TuyaMCU serial communication (0 = 9600 or 1 = 115200) @@ -1134,10 +1146,12 @@ void TuyaInit(void) Tuya.ignore_topic_timeout = millis() + 1000; // suppress /STAT topic for 1000ms to avoid data overflow AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: Request MCU configuration at %d bps"), baudrate); - + Tuya.heartbeat_timer = 0; // init heartbeat timer when dimmer init is done + return; } + free(Tuya.buffer); } - Tuya.heartbeat_timer = 0; // init heartbeat timer when dimmer init is done + Tuya.active = false; } void TuyaSerialInput(void) @@ -1332,33 +1346,6 @@ void TuyaSetTime(void) { } #endif //USE_TUYA_TIME -#ifdef USE_ENERGY_SENSOR - -/*********************************************************************************************\ - * Energy Interface -\*********************************************************************************************/ - -bool Xnrg32(uint8_t function) -{ - bool result = false; - - if (TUYA_DIMMER == TasmotaGlobal.module_type) { - if (FUNC_PRE_INIT == function) { - if (TuyaGetDpId(TUYA_MCU_FUNC_POWER) != 0 || TuyaGetDpId(TUYA_MCU_FUNC_POWER_COMBINED) != 0) { - if (TuyaGetDpId(TUYA_MCU_FUNC_CURRENT) == 0 && TuyaGetDpId(TUYA_MCU_FUNC_POWER_COMBINED) == 0) { - Energy.current_available = false; - } - if (TuyaGetDpId(TUYA_MCU_FUNC_VOLTAGE) == 0 && TuyaGetDpId(TUYA_MCU_FUNC_POWER_COMBINED) == 0) { - Energy.voltage_available = false; - } - TasmotaGlobal.energy_driver = XNRG_32; - } - } - } - return result; -} -#endif // USE_ENERGY_SENSOR - /*********************************************************************************************\ * Sensors \*********************************************************************************************/ @@ -1442,31 +1429,70 @@ void TuyaSensorsShow(bool json) #endif // USE_WEBSERVER } } - #ifdef USE_WEBSERVER +#ifdef USE_WEBSERVER if (AsModuleTuyaMS()) { WSContentSend_P(PSTR("{s}" D_JSON_IRHVAC_MODE "{m}%d{e}"), Tuya.ModeSet); } - #endif // USE_WEBSERVER +#endif // USE_WEBSERVER if (RootName) { ResponseJsonEnd();} } +#ifdef USE_WEBSERVER + +void TuyaAddButton(void) { + if (AsModuleTuyaMS()) { + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("
")); + char stemp[33]; + snprintf_P(stemp, sizeof(stemp), PSTR("" D_JSON_IRHVAC_MODE "")); + WSContentSend_P(HTTP_DEVICE_CONTROL, 26, TasmotaGlobal.devices_present + 1, + (strlen(SettingsText(SET_BUTTON1 + TasmotaGlobal.devices_present))) ? SettingsText(SET_BUTTON1 + TasmotaGlobal.devices_present) : stemp, ""); + WSContentSend_P(PSTR("")); + } +} + +#endif // USE_WEBSERVER + /*********************************************************************************************\ * Interface \*********************************************************************************************/ -bool Xdrv16(uint8_t function) +#ifdef USE_ENERGY_SENSOR + +bool Xnrg32(uint8_t function) { bool result = false; - if (TUYA_DIMMER == TasmotaGlobal.module_type) { + if (Tuya.active) { + if (FUNC_PRE_INIT == function) { + if (TuyaGetDpId(TUYA_MCU_FUNC_POWER) != 0 || TuyaGetDpId(TUYA_MCU_FUNC_POWER_COMBINED) != 0) { + if (TuyaGetDpId(TUYA_MCU_FUNC_CURRENT) == 0 && TuyaGetDpId(TUYA_MCU_FUNC_POWER_COMBINED) == 0) { + Energy.current_available = false; + } + if (TuyaGetDpId(TUYA_MCU_FUNC_VOLTAGE) == 0 && TuyaGetDpId(TUYA_MCU_FUNC_POWER_COMBINED) == 0) { + Energy.voltage_available = false; + } + TasmotaGlobal.energy_driver = XNRG_32; + } + } + } + return result; +} +#endif // USE_ENERGY_SENSOR + +bool Xdrv16(uint8_t function) { + bool result = false; + + if (FUNC_MODULE_INIT == function) { + result = TuyaModuleSelected(); + Tuya.active = result; + } + else if (Tuya.active) { switch (function) { case FUNC_LOOP: if (TuyaSerial) { TuyaSerialInput(); } break; - case FUNC_MODULE_INIT: - result = TuyaModuleSelected(); - break; case FUNC_PRE_INIT: TuyaInit(); break; @@ -1507,6 +1533,9 @@ bool Xdrv16(uint8_t function) TuyaSensorsShow(1); break; #ifdef USE_WEBSERVER + case FUNC_WEB_ADD_MAIN_BUTTON: + TuyaAddButton(); + break; case FUNC_WEB_SENSOR: TuyaSensorsShow(0); break; diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index f86b6d7e6..34af5420a 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -205,17 +205,17 @@ void HueRespondToMSearch(void) String uuid = HueUuid(); snprintf_P(response + len, sizeof(response) - len, msg[HUE_RESP_ST1], uuid.c_str()); - PortUdp.write(response); + PortUdp.write((const uint8_t*)response, strlen(response)); PortUdp.endPacket(); // AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_UPNP "UDP resp=%s"), response); snprintf_P(response + len, sizeof(response) - len, msg[HUE_RESP_ST2], uuid.c_str(), uuid.c_str()); - PortUdp.write(response); + PortUdp.write((const uint8_t*)response, strlen(response)); PortUdp.endPacket(); // AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_UPNP "UDP resp=%s"), response); snprintf_P(response + len, sizeof(response) - len, msg[HUE_RESP_ST3], uuid.c_str()); - PortUdp.write(response); + PortUdp.write((const uint8_t*)response, strlen(response)); PortUdp.endPacket(); // AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_UPNP "UDP resp=%s"), response); @@ -676,7 +676,7 @@ void HueGlobalConfig(String *path) { CheckHue(&response, appending); #endif // USE_LIGHT #ifdef USE_ZIGBEE - ZigbeeCheckHue(&response, appending); + ZigbeeCheckHue(response, &appending); #endif // USE_ZIGBEE response += F("},\"groups\":{},\"schedules\":{},\"config\":"); HueConfigResponse(&response); @@ -914,42 +914,44 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { } #endif // USE_LIGHT -void HueLights(String *path) +void HueLights(String *path_req) { /* * http://tasmota/api/username/lights/1/state?1={"on":true,"hue":56100,"sat":254,"bri":254,"alert":"none","transitiontime":40} */ String response; - int code = 200; + int32_t code = 200; uint8_t device = 1; uint32_t device_id; // the raw device_id used by Hue emulation uint8_t maxhue = (TasmotaGlobal.devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : TasmotaGlobal.devices_present; + path_req->remove(0,path_req->indexOf(F("/lights"))); // Remove until /lights + String path(*path_req); - path->remove(0,path->indexOf(F("/lights"))); // Remove until /lights - if (path->endsWith(F("/lights"))) { // Got /lights + if (path.endsWith(F("/lights"))) { // Got /lights response = F("{"); bool appending = false; #ifdef USE_LIGHT CheckHue(&response, appending); #endif // USE_LIGHT #ifdef USE_ZIGBEE - ZigbeeCheckHue(&response, appending); + ZigbeeCheckHue(response, &appending); #endif // USE_ZIGBEE #ifdef USE_SCRIPT_HUE Script_Check_Hue(&response); #endif response += F("}"); } - else if (path->endsWith(F("/state"))) { // Got ID/state - path->remove(0,8); // Remove /lights/ - path->remove(path->indexOf(F("/state"))); // Remove /state - device_id = atoi(path->c_str()); + else if (path.endsWith(F("/state"))) { // Got ID/state + path.remove(0,8); // Remove /lights/ + path.remove(path.indexOf(F("/state"))); // Remove /state + device_id = atoi(path.c_str()); device = DecodeLightId(device_id); #ifdef USE_ZIGBEE uint16_t shortaddr; device = DecodeLightId(device_id, &shortaddr); if (shortaddr) { - return ZigbeeHandleHue(shortaddr, device_id, response); + code = ZigbeeHandleHue(shortaddr, device_id, response); + goto exit; } #endif // USE_ZIGBEE @@ -965,16 +967,16 @@ void HueLights(String *path) #endif // USE_LIGHT } - else if(path->indexOf(F("/lights/")) >= 0) { // Got /lights/ID - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("/lights path=%s"), path->c_str()); - path->remove(0,8); // Remove /lights/ - device_id = atoi(path->c_str()); + else if(path.indexOf(F("/lights/")) >= 0) { // Got /lights/ID + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("/lights path=%s"), path.c_str()); + path.remove(0,8); // Remove /lights/ + device_id = atoi(path.c_str()); device = DecodeLightId(device_id); #ifdef USE_ZIGBEE uint16_t shortaddr; device = DecodeLightId(device_id, &shortaddr); if (shortaddr) { - ZigbeeHueStatus(&response, shortaddr); + code = ZigbeeHueStatus(&response, shortaddr); goto exit; } #endif // USE_ZIGBEE @@ -1000,6 +1002,14 @@ void HueLights(String *path) code = 406; } exit: + if (code < 0) { + response = F("{\"error\":{\"type\":"); + response += -code; + response += F(",\"address\":\""); + response += *path_req; + response += F("\",\"description\":\"\"}}"); + code = 200; + } AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); WSSend(code, CT_APP_JSON, response); } @@ -1011,7 +1021,7 @@ void HueGroups(String *path) */ String response(F("{}")); uint8_t maxhue = (TasmotaGlobal.devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : TasmotaGlobal.devices_present; - //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " HueGroups (%s)"), path->c_str()); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " HueGroups (%s)"), path.c_str()); if (path->endsWith(F("/0"))) { UnishoxStrings msg(HUE_LIGHTS); diff --git a/tasmota/xdrv_21_wemo.ino b/tasmota/xdrv_21_wemo.ino index 926192cc7..f0521aeea4 100644 --- a/tasmota/xdrv_21_wemo.ino +++ b/tasmota/xdrv_21_wemo.ino @@ -67,7 +67,7 @@ void WemoRespondToMSearch(int echo_type) } char response[400]; snprintf_P(response, sizeof(response), WEMO_MSEARCH, WiFi.localIP().toString().c_str(), type, WemoUuid().c_str(), type); - PortUdp.write(response); + PortUdp.write((uint8_t*)response, strlen(response)); PortUdp.endPacket(); snprintf_P(message, sizeof(message), PSTR(D_RESPONSE_SENT)); } else { diff --git a/tasmota/xdrv_21_wemo_multi.ino b/tasmota/xdrv_21_wemo_multi.ino index e2e12c6b3..145e3e8c5 100644 --- a/tasmota/xdrv_21_wemo_multi.ino +++ b/tasmota/xdrv_21_wemo_multi.ino @@ -291,7 +291,7 @@ public: } char response[400]; snprintf_P(response, sizeof(response), WEMO_MSEARCH, WiFi.localIP().toString().c_str(), _localPort, type, WemoUuid().c_str(), type); - PortUdp.write(response); + PortUdp.write((const uint8_t*)response, strlen(response)); PortUdp.endPacket(); // AddLog(LOG_LEVEL_DEBUG, PSTR("WMO: Sending packet device %d: %s"), _deviceId, response); diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index 23004f9db..9ae8114f7 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -823,7 +823,7 @@ public: // If light, returns the number of channels, or 0xFF if unknown int8_t getLightChannels(void) const { const Z_Data_Light & light = data.find(0); - if (&light != nullptr) { + if (&light != &z_data_unk) { return light.getConfig(); } else { return -1; diff --git a/tasmota/xdrv_23_zigbee_2a_devices_impl.ino b/tasmota/xdrv_23_zigbee_2a_devices_impl.ino index 543916efa..77027fc91 100644 --- a/tasmota/xdrv_23_zigbee_2a_devices_impl.ino +++ b/tasmota/xdrv_23_zigbee_2a_devices_impl.ino @@ -744,7 +744,7 @@ void Z_Device::jsonLightState(Z_attribute_list & attr_list) const { if (validPower()) { attr_list.addAttributePMEM(PSTR("Power")).setUInt(getPower()); } int32_t light_mode = -1; const Z_Data_Light & light = data.find(0); - if (&light != nullptr) { + if (&light != &z_data_unk) { if (light.validConfig()) { light_mode = light.getConfig(); } @@ -912,12 +912,12 @@ void Z_Device::setPower(bool power_on, uint8_t ep) { bool Z_Device::validPower(uint8_t ep) const { const Z_Data_OnOff & onoff = data.find(ep); - return (&onoff != nullptr); + return (&onoff != &z_data_unk); } bool Z_Device::getPower(uint8_t ep) const { const Z_Data_OnOff & onoff = data.find(ep); - if (&onoff != nullptr) return onoff.getPower(); + if (&onoff != &z_data_unk) return onoff.getPower(); return false; } diff --git a/tasmota/xdrv_23_zigbee_3_hue.ino b/tasmota/xdrv_23_zigbee_3_hue.ino index 01b7a5fda..ff3b637c1 100644 --- a/tasmota/xdrv_23_zigbee_3_hue.ino +++ b/tasmota/xdrv_23_zigbee_3_hue.ino @@ -42,7 +42,7 @@ void HueLightStatus1Zigbee(uint16_t shortaddr, uint8_t local_light_subtype, Stri const Z_Device & device = zigbee_devices.findShortAddr(shortaddr); const Z_Data_Light & light = device.data.find(); - if (&light != nullptr) { + if (&light != &z_data_unk) { bri = light.getDimmer(); colormode = light.getColorMode(); sat = light.getSat(); @@ -112,13 +112,19 @@ void HueLightStatus2Zigbee(uint16_t shortaddr, String *response) free(buf); } -void ZigbeeHueStatus(String * response, uint16_t shortaddr) { - *response += F("{\"state\":"); - HueLightStatus1Zigbee(shortaddr, zigbee_devices.getHueBulbtype(shortaddr), response); - HueLightStatus2Zigbee(shortaddr, response); +int32_t ZigbeeHueStatus(String * response, uint16_t shortaddr) { + int8_t bulbtype = zigbee_devices.getHueBulbtype(shortaddr); + if (bulbtype >= 0) { // respond only if eligible + *response += F("{\"state\":"); + HueLightStatus1Zigbee(shortaddr, zigbee_devices.getHueBulbtype(shortaddr), response); + HueLightStatus2Zigbee(shortaddr, response); + return 200; + } else { + return -3; + } } -void ZigbeeCheckHue(String * response, bool &appending) { +void ZigbeeCheckHue(String & response, bool * appending) { uint32_t zigbee_num = zigbee_devices.devicesSize(); for (uint32_t i = 0; i < zigbee_num; i++) { uint16_t shortaddr = zigbee_devices.devicesAt(i).shortaddr; @@ -126,13 +132,13 @@ void ZigbeeCheckHue(String * response, bool &appending) { if (bulbtype >= 0) { // this bulb is advertized - if (appending) { *response += ","; } - *response += "\""; - *response += EncodeLightId(0, shortaddr); - *response += F("\":{\"state\":"); - HueLightStatus1Zigbee(shortaddr, bulbtype, response); // TODO - HueLightStatus2Zigbee(shortaddr, response); - appending = true; + if (*appending) { response += ","; } + response += "\""; + response += EncodeLightId(0, shortaddr); + response += F("\":{\"state\":"); + HueLightStatus1Zigbee(shortaddr, bulbtype, &response); // TODO + HueLightStatus2Zigbee(shortaddr, &response); + *appending = true; } } } @@ -223,16 +229,20 @@ void ZigbeeHueHS(uint16_t shortaddr, uint16_t hue, uint8_t sat) { light.setHue(hue); } -void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) { +int32_t ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) { uint8_t bri, sat; uint16_t ct, hue; int code = 200; + int8_t bulbtype = zigbee_devices.getHueBulbtype(shortaddr); + if (bulbtype < 0) { // respond only if eligible + response = F("{}"); + return 200; + } + bool resp = false; // is the response non null (add comma between parameters) bool on = false; - uint8_t bulbtype = zigbee_devices.getHueBulbtype(shortaddr); - const size_t buf_size = 100; char * buf = (char*) malloc(buf_size); UnishoxStrings msg(HUE_LIGHTS); @@ -368,10 +378,8 @@ void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) { else { response = msg[HUE_ERROR_JSON]; } - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); - WSSend(code, CT_APP_JSON, response); - free(buf); + return 200; } #endif // USE_WEBSERVER && USE_EMULATION && USE_EMULATION_HUE diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index f2d3334eb..805297380 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -1353,7 +1353,7 @@ void ZCLFrame::computeSyntheticAttributes(Z_attribute_list& attr_list) { uint8_t brightness = 255; if (device.valid()) { const Z_Data_Light & light = device.data.find(_srcendpoint); - if ((&light != nullptr) && (light.validDimmer())) { + if ((&light != &z_data_unk) && (light.validDimmer())) { // Dimmer has a valid value brightness = changeUIntScale(light.getDimmer(), 0, 254, 0, 255); // range is 0..255 } diff --git a/tasmota/xdrv_23_zigbee_A_impl.ino b/tasmota/xdrv_23_zigbee_A_impl.ino index 5f2e412a4..41ee70119 100644 --- a/tasmota/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/xdrv_23_zigbee_A_impl.ino @@ -59,7 +59,7 @@ void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZbInfo, &CmndZbForget, &CmndZbSave, &CmndZbName, &CmndZbBind, &CmndZbUnbind, &CmndZbPing, &CmndZbModelId, &CmndZbLight, &CmndZbOccupancy, - &CmndZbRestore, &CmndZbBindState, &CmndZbMap, CmndZbLeave, + &CmndZbRestore, &CmndZbBindState, &CmndZbMap, &CmndZbLeave, &CmndZbConfig, &CmndZbData, &CmndZbScan, }; diff --git a/tasmota/xdrv_24_buzzer.ino b/tasmota/xdrv_24_buzzer.ino index 377c2fee6..d7b8ef0f3 100644 --- a/tasmota/xdrv_24_buzzer.ino +++ b/tasmota/xdrv_24_buzzer.ino @@ -51,11 +51,11 @@ void BuzzerSet(uint32_t state) { static uint8_t last_state = 0; if (last_state != state) { #ifdef ESP32 - analogAttach(Pin(GPIO_BUZZER), 7); + if (analogAttach(Pin(GPIO_BUZZER))) #endif // ESP32 - // Set 50% duty cycle for frequency output - // Set 0% (or 100% for inverted PWM) duty cycle which turns off frequency output either way - analogWrite(Pin(GPIO_BUZZER), (state) ? Settings->pwm_range / 2 : 0); // set duty cycle for frequency output + // Set 50% duty cycle for frequency output + // Set 0% (or 100% for inverted PWM) duty cycle which turns off frequency output either way + analogWrite(Pin(GPIO_BUZZER), (state) ? Settings->pwm_range / 2 : 0); // set duty cycle for frequency output last_state = state; } } else { diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 198fbb9c1..d731bdd21 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -476,6 +476,7 @@ void ShutterPowerOff(uint8_t i) { AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Stop %d. Mode %d, time:%d"), i+1,Shutter[i].switch_mode, Shutter[i].time); // fix log to indicate correct shutter number ShutterDecellerateForStop(i); + uint8_t cur_relay = Settings->shutter_startrelay[i] + (Shutter[i].direction == 1 ? 0 : (uint8_t)(ShutterGlobal.position_mode == SHT_TIME)) ; if (Shutter[i].direction !=0) { Shutter[i].direction = 0; } @@ -493,7 +494,6 @@ void ShutterPowerOff(uint8_t i) } break; case SHT_PULSE: - uint8_t cur_relay = Settings->shutter_startrelay[i] + (Shutter[i].direction == 1 ? 0 : (uint8_t)(ShutterGlobal.position_mode == SHT_TIME)) ; // we have a momentary switch here. Needs additional pulse on same relay after the end if ((SRC_PULSETIMER == TasmotaGlobal.last_source || SRC_SHUTTER == TasmotaGlobal.last_source || SRC_WEBGUI == TasmotaGlobal.last_source)) { ExecuteCommandPowerShutter(cur_relay, 1, SRC_SHUTTER); diff --git a/tasmota/xdrv_29_deepsleep.ino b/tasmota/xdrv_29_deepsleep.ino index ac0478ee5..f93506410 100644 --- a/tasmota/xdrv_29_deepsleep.ino +++ b/tasmota/xdrv_29_deepsleep.ino @@ -95,7 +95,7 @@ void DeepSleepPrepare(void) if ((RtcSettings.nextwakeup == 0) || (RtcSettings.deepsleep_slip < 9000) || (RtcSettings.deepsleep_slip > 11000) || - (RtcSettings.nextwakeup > (UtcTime() + Settings->deepsleep))) { + (RtcSettings.nextwakeup > (LocalTime() + Settings->deepsleep))) { AddLog(LOG_LEVEL_ERROR, PSTR("DSL: Reset wrong settings wakeup: %ld, slip %ld"), RtcSettings.nextwakeup, RtcSettings.deepsleep_slip ); RtcSettings.nextwakeup = 0; RtcSettings.deepsleep_slip = 10000; @@ -103,13 +103,13 @@ void DeepSleepPrepare(void) // Timeslip in 0.1 seconds between the real wakeup and the calculated wakeup // Because deepsleep is in second and timeslip in 0.1 sec the compare always check if the slip is in the 10% range - int16_t timeslip = (int16_t)(RtcSettings.nextwakeup + millis() / 1000 - UtcTime()) * 10; + int16_t timeslip = (int16_t)(RtcSettings.nextwakeup + millis() / 1000 - LocalTime()) * 10; // Allow 10% of deepsleep error to count as valid deepsleep; expecting 3-4% // if more then 10% timeslip = 0 == non valid wakeup; maybe manual timeslip = (timeslip < -(int32_t)Settings->deepsleep) ? 0 : (timeslip > (int32_t)Settings->deepsleep) ? 0 : 1; if (timeslip) { - RtcSettings.deepsleep_slip = (Settings->deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / tmax((Settings->deepsleep - (millis() / 1000)),5); + RtcSettings.deepsleep_slip = (Settings->deepsleep + RtcSettings.nextwakeup - LocalTime()) * RtcSettings.deepsleep_slip / tmax((Settings->deepsleep - (millis() / 1000)),5); // Avoid crazy numbers. Again maximum 10% deviation. RtcSettings.deepsleep_slip = tmin(tmax(RtcSettings.deepsleep_slip, 9000), 11000); RtcSettings.nextwakeup += Settings->deepsleep; @@ -117,15 +117,15 @@ void DeepSleepPrepare(void) // It may happen that wakeup in just <5 seconds in future // In this case also add deepsleep to nextwakeup - if (RtcSettings.nextwakeup <= (UtcTime() - DEEPSLEEP_MIN_TIME)) { + if (RtcSettings.nextwakeup <= (LocalTime() - DEEPSLEEP_MIN_TIME)) { // ensure nextwakeup is at least in the future - RtcSettings.nextwakeup += (((UtcTime() + DEEPSLEEP_MIN_TIME - RtcSettings.nextwakeup) / Settings->deepsleep) + 1) * Settings->deepsleep; + RtcSettings.nextwakeup += (((LocalTime() + DEEPSLEEP_MIN_TIME - RtcSettings.nextwakeup) / Settings->deepsleep) + 1) * Settings->deepsleep; } - String dt = GetDT(RtcSettings.nextwakeup + LocalTime() - UtcTime()); // 2017-03-07T11:08:02 + String dt = GetDT(RtcSettings.nextwakeup); // 2017-03-07T11:08:02 // Limit sleeptime to DEEPSLEEP_MAX_CYCLE - // uint32_t deepsleep_sleeptime = DEEPSLEEP_MAX_CYCLE < (RtcSettings.nextwakeup - UtcTime()) ? (uint32_t)DEEPSLEEP_MAX_CYCLE : RtcSettings.nextwakeup - UtcTime(); - deepsleep_sleeptime = tmin((uint32_t)DEEPSLEEP_MAX_CYCLE ,RtcSettings.nextwakeup - UtcTime()); + // uint32_t deepsleep_sleeptime = DEEPSLEEP_MAX_CYCLE < (RtcSettings.nextwakeup - LocalTime()) ? (uint32_t)DEEPSLEEP_MAX_CYCLE : RtcSettings.nextwakeup - LocalTime(); + deepsleep_sleeptime = tmin((uint32_t)DEEPSLEEP_MAX_CYCLE ,RtcSettings.nextwakeup - LocalTime()); // stat/tasmota/DEEPSLEEP = {"DeepSleep":{"Time":"2019-11-12T21:33:45","Epoch":1573590825}} Response_P(PSTR("{\"" D_PRFX_DEEPSLEEP "\":{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%d}}"), (char*)dt.c_str(), RtcSettings.nextwakeup); @@ -140,7 +140,7 @@ void DeepSleepStart(void) AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Sleeping")); // Won't show in GUI WifiShutdown(); - RtcSettings.ultradeepsleep = RtcSettings.nextwakeup - UtcTime(); + RtcSettings.ultradeepsleep = RtcSettings.nextwakeup - LocalTime(); RtcSettingsSave(); RtcRebootReset(); #ifdef ESP8266 diff --git a/tasmota/xdrv_31_tasmota_client.ino b/tasmota/xdrv_31_tasmota_client.ino index 6301393d7..d47f39b43 100644 --- a/tasmota/xdrv_31_tasmota_client.ino +++ b/tasmota/xdrv_31_tasmota_client.ino @@ -52,7 +52,7 @@ #define CMND_END 0xFD #define CMND_FEATURES 0x01 -#define CMND_JSON 0x02 +#define CMND_GET_JSON 0x02 #define CMND_FUNC_EVERY_SECOND 0x03 #define CMND_FUNC_EVERY_100_MSECOND 0x04 #define CMND_CLIENT_SEND 0x05 @@ -438,7 +438,7 @@ bool TasmotaClient_Available(void) { void TasmotaClient_Show(void) { if ((TClient.type) && (TClientSettings.features.func_json_append)) { - TasmotaClient_sendCmnd(CMND_JSON, 0); + TasmotaClient_sendCmnd(CMND_GET_JSON, 0); char buffer[100]; uint8_t len = TasmotaClient_receiveData(buffer, sizeof(buffer) -1); diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino index aad092643..4c1c9d067 100644 --- a/tasmota/xdrv_35_pwm_dimmer.ino +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -29,6 +29,9 @@ * https://www.amazon.com/dp/B07K67D43J * https://www.amazon.com/dp/B07TTGFWFM * +* Template for Linkind device +* {"NAME":"ESP32-Linkind","GPIO":[6213,8448,0,0,640,0,0,0,0,288,0,0,0,0,0,0,0,608,0,0,0,544,0,0,0,0,0,0,33,32,0,0,0,0,0,0],"FLAG":0,"BASE":1} +* \*********************************************************************************************/ #define XDRV_35 35 @@ -126,7 +129,11 @@ void PWMModulePreInit(void) device_group_count = button_count; // If no relay or PWM is defined, all buttons control remote devices. - if (!PinUsed(GPIO_REL1) && !PinUsed(GPIO_PWM1)) { + if (!PinUsed(GPIO_REL1) && !PinUsed(GPIO_PWM1) +#ifdef USE_I2C + && !PinUsed(GPIO_I2C_SCL) +#endif // USE_I2C + ) { first_device_group_is_local = false; // Back out the changes made in the light module under the assumtion we have a relay or PWM. @@ -165,13 +172,16 @@ void PWMDimmerSetBrightnessLeds(int32_t bri) bri = ((bri == -2 && Settings->flag4.led_timeout) || !Light.power ? 0 : light_state.getBri()); if (!bri || !Settings->flag4.led_timeout) led_timeout_seconds = 0; } - uint32_t step = 256 / (leds + 1); // Turn the LED's on/off. - uint32_t level = 0; + uint32_t step = 256 / (leds + 1); + int32_t level = 0; + if (TasmotaGlobal.gpio_optiona.linkind_support) { + step = 256 / leds; + level = -step; + } led = -1; mask = 0; - uint16_t pwm_led_bri = 0; for (uint32_t count = 0; count < leds; count++) { level += step; for (;;) { @@ -180,8 +190,12 @@ void PWMDimmerSetBrightnessLeds(int32_t bri) if (!mask) mask = 1; if (Settings->ledmask & mask) break; } - pwm_led_bri = changeUIntScale((bri > level ? bri - level : 0), 0, step, 0, Settings->pwm_range); - analogWrite(Pin(GPIO_LED1, led), bitRead(TasmotaGlobal.led_inverted, led) ? Settings->pwm_range - pwm_led_bri : pwm_led_bri); + if (TasmotaGlobal.gpio_optiona.linkind_support) { + SetLedPowerIdx(led, bri > level); + } else { + uint16_t pwm_led_bri = changeUIntScale((bri > level ? bri - level : 0), 0, step, 0, Settings->pwm_range); + analogWrite(Pin(GPIO_LED1, led), bitRead(TasmotaGlobal.led_inverted, led) ? Settings->pwm_range - pwm_led_bri : pwm_led_bri); + } } } } @@ -450,15 +464,13 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed) if (invert_power_button_bri_direction) { invert_power_button_bri_direction = false; #ifdef USE_PWM_DIMMER_REMOTE - if (active_remote_pwm_dimmer) + if (active_remote_pwm_dimmer) { active_remote_pwm_dimmer->power_button_increases_bri ^= 1; - else + } else #endif // USE_PWM_DIMMER_REMOTE power_button_increases_bri ^= 1; -#ifdef USE_PWM_DIMMER_REMOTE dgr_item = DGR_ITEM_FLAGS; state_updated = true; -#endif // USE_PWM_DIMMER_REMOTE } } @@ -842,7 +854,8 @@ bool Xdrv35(uint8_t function) } // If hold time has arrived and no rule is enabled that handles the button hold, handle it. - else if (button_hold_time[button_index] <= now) { + else if ((int32_t)(now - button_hold_time[button_index]) >= 0) { + #ifdef USE_RULES Response_P(PSTR("{\"Button%u\":{\"State\":3}}"), button_index + 1); Rules.no_execute = true; @@ -896,7 +909,8 @@ bool Xdrv35(uint8_t function) case FUNC_ANY_KEY: { uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; // 0 = Off, 1 = On, 2 = Toggle, 3 = Hold, 10,11,12,13 and 14 for Button Multipress - if ((state == 2 || state == 10) && ignore_any_key_time < millis()) { + if ((state == 2 || state == 10) && (int32_t)(millis() - ignore_any_key_time) > 0) { + uint32_t button_index = (XdrvMailbox.payload & 0xFF) - 1; button_unprocessed[button_index] = false; PWMDimmerHandleButton(button_index, false); diff --git a/tasmota/xdrv_39_thermostat.ino b/tasmota/xdrv_39_thermostat.ino index 414cb358b..26620394a 100644 --- a/tasmota/xdrv_39_thermostat.ino +++ b/tasmota/xdrv_39_thermostat.ino @@ -1334,7 +1334,7 @@ uint8_t ThermostatGetDutyCycle(uint8_t ctr_output) if ( (Thermostat[ctr_output].status.controller_mode == CTR_PI) || ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) &&(Thermostat[ctr_output].status.phase_hybrid_ctr == CTR_HYBRID_PI))) { - value = Thermostat[ctr_output].time_total_pi / Thermostat[ctr_output].time_pi_cycle; + value = 100*Thermostat[ctr_output].time_total_pi / ((uint32_t)60*(uint32_t)Thermostat[ctr_output].time_pi_cycle); } else if ( (Thermostat[ctr_output].status.controller_mode == CTR_RAMP_UP) || ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) diff --git a/tasmota/xdrv_42_i2s_audio.ino b/tasmota/xdrv_42_i2s_audio.ino index c7b0c460b..c87d763da 100644 --- a/tasmota/xdrv_42_i2s_audio.ino +++ b/tasmota/xdrv_42_i2s_audio.ino @@ -320,7 +320,11 @@ uint32_t SpeakerMic(uint8_t spkr) { i2s_driver_uninstall(Speak_I2S_NUMBER); if (spkr==MODE_SPK) { - out = new AudioOutputI2S(); + #ifdef USE_I2S_NO_DAC + out = new AudioOutputI2SNoDAC(); + #else + out = new AudioOutputI2S(0, 1); + #endif out->SetPinout(DAC_IIS_BCK, DAC_IIS_WS, DAC_IIS_DOUT); out->SetGain(((float)is2_volume/100.0)*4.0); out->stop(); diff --git a/tasmota/xdrv_44_miel_hvac.ino b/tasmota/xdrv_44_miel_hvac.ino index 66e034fec..e5f37fbc1 100644 --- a/tasmota/xdrv_44_miel_hvac.ino +++ b/tasmota/xdrv_44_miel_hvac.ino @@ -42,7 +42,7 @@ #include /* from hvac */ -bool temp_type = false; +bool temp_type = false; struct miel_hvac_header { uint8_t start; @@ -713,7 +713,7 @@ miel_hvac_cmnd_settemp(void) if (XdrvMailbox.data_len == 0) return; - + degc = strtof(XdrvMailbox.data, nullptr); if (degc < MIEL_HVAC_UPDATE_TEMP_MIN || degc > MIEL_HVAC_UPDATE_TEMP_MAX) { @@ -1069,7 +1069,7 @@ miel_hvac_pre_init(void) sc->sc_serial = new TasmotaSerial(Pin(GPIO_MIEL_HVAC_RX), Pin(GPIO_MIEL_HVAC_TX), 2); - if (!sc->sc_serial->begin(baudrate, 2)) { + if (!sc->sc_serial->begin(baudrate, SERIAL_8E1)) { AddLog(LOG_LEVEL_ERROR, PSTR(MIEL_HVAC_LOGNAME ": unable to begin serial " "(baudrate %d)"), baudrate); @@ -1207,7 +1207,7 @@ miel_hvac_connect(struct miel_hvac_softc *sc) return; } - serial->begin(baudrate, 2); + serial->begin(baudrate, SERIAL_8E1); if (serial->hardwareSerial()) SetSerial(baudrate, TS_SERIAL_8E1); } diff --git a/tasmota/xdrv_50_filesystem.ino b/tasmota/xdrv_50_filesystem.ino index 8a0ed1d16..828028827 100644 --- a/tasmota/xdrv_50_filesystem.ino +++ b/tasmota/xdrv_50_filesystem.ino @@ -287,16 +287,40 @@ bool TfsFileExists(const char *fname){ bool TfsSaveFile(const char *fname, const uint8_t *buf, uint32_t len) { if (!ffs_type) { return false; } - +#ifdef USE_WEBCAM + WcInterrupt(0); // Stop stream if active to fix TG1WDT_SYS_RESET +#endif + bool result = false; File file = ffsp->open(fname, "w"); if (!file) { AddLog(LOG_LEVEL_INFO, PSTR("TFS: Save failed")); - return false; + } else { + // This will timeout on ESP32-webcam + // But now solved with WcInterrupt(0) in support_esp.ino + file.write(buf, len); + /* + // This will still timeout on ESP32-webcam when wcresolution 10 + uint32_t count = len / 512; + uint32_t chunk = len / count; + for (uint32_t i = 0; i < count; i++) { + file.write(buf + (i * chunk), chunk); + // do actually wait a little to allow ESP32 tasks to tick + // fixes task timeout in ESP32Solo1 style unicore code and webcam. + delay(10); + OsWatchLoop(); + } + uint32_t left = len % count; + if (left) { + file.write(buf + (count * chunk), left); + } + */ + file.close(); + result = true; } - - file.write(buf, len); - file.close(); - return true; +#ifdef USE_WEBCAM + WcInterrupt(1); +#endif + return result; } bool TfsInitFile(const char *fname, uint32_t len, uint8_t init_value) { @@ -324,6 +348,11 @@ bool TfsLoadFile(const char *fname, uint8_t *buf, uint32_t len) { AddLog(LOG_LEVEL_INFO, PSTR("TFS: File '%s' not found"), fname +1); // Skip leading slash return false; } + + size_t flen = file.size(); + if (len > flen){ + len = flen; + } file.read(buf, len); file.close(); @@ -954,15 +983,15 @@ void UfsEditor(void) { char fname[UFS_FILENAME_SIZE]; UfsFilename(fname, fname_input); // Trim spaces and add slash - AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: UfsEditor: file=%s, ffs_type=%d, TfsFileExist=%d"), fname, ffs_type, TfsFileExists(fname)); + AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: UfsEditor: file=%s, ffs_type=%d, TfsFileExist=%d"), fname, ffs_type, dfsp->exists(fname)); WSContentStart_P(PSTR(D_EDIT_FILE)); WSContentSendStyle(); char *bfname = fname +1; WSContentSend_P(HTTP_EDITOR_FORM_START, bfname); // Skip leading slash - if (ffs_type && TfsFileExists(fname)) { - File fp = ffsp->open(fname, "r"); + if (ffs_type && dfsp->exists(fname)) { + File fp = dfsp->open(fname, "r"); if (!fp) { AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: UfsEditor: file open failed")); WSContentSend_P(D_NEW_FILE); @@ -1015,14 +1044,14 @@ void UfsEditorUpload(void) { } String content = Webserver->arg("content"); - if (!ffsp) { + if (!dfsp) { Web.upload_error = 1; AddLog(LOG_LEVEL_ERROR, PSTR("UFS: UfsEditor: 507: no storage available")); WSSend(507, CT_PLAIN, F("507: no storage available")); return; } - File fp = ffsp->open(fname, "w"); + File fp = dfsp->open(fname, "w"); if (!fp) { Web.upload_error = 1; AddLog(LOG_LEVEL_ERROR, PSTR("UFS: UfsEditor: 400: invalid file name '%s'"), fname); diff --git a/tasmota/xdrv_52_0_berry_struct.ino b/tasmota/xdrv_52_0_berry_struct.ino index fe09b3c84..760358ab0 100644 --- a/tasmota/xdrv_52_0_berry_struct.ino +++ b/tasmota/xdrv_52_0_berry_struct.ino @@ -23,6 +23,7 @@ #include #include +#include "be_mapping.h" #include "re1.5.h" /*********************************************************************************************\ diff --git a/tasmota/xdrv_52_1_berry_native.ino b/tasmota/xdrv_52_1_berry_native.ino index 970d26c48..b0809c8d3 100644 --- a/tasmota/xdrv_52_1_berry_native.ino +++ b/tasmota/xdrv_52_1_berry_native.ino @@ -26,27 +26,17 @@ const char kTypeError[] PROGMEM = "type_error"; const char kInternalError[] PROGMEM = "intenal_error"; -extern "C" { - - /*********************************************************************************************\ - * Support for Berry int constants - * as virtual members - \*********************************************************************************************/ - typedef struct be_constint_t { - const char * name; - int32_t value; - } be_constint_t; - -} - /*********************************************************************************************\ * LVGL top level virtual members * * Responds to virtual constants \*********************************************************************************************/ extern "C" { - // Clear all elements on the stack - void be_pop_all(bvm *vm) { + #include "be_vm.h" + // Call error handler and pop all from stack + void be_error_pop_all(bvm *vm); + void be_error_pop_all(bvm *vm) { + if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_PCALL_ERROR); be_pop(vm, be_top(vm)); // clear Berry stack } @@ -54,7 +44,7 @@ extern "C" { #include "be_debug.h" void be_dumpstack(bvm *vm) { int32_t top = be_top(vm); - AddLog(LOG_LEVEL_INFO, "BRY: top=%d", top); + AddLog(LOG_LEVEL_DEBUG, "BRY: top=%d", top); be_tracestack(vm); for (uint32_t i = 1; i <= top; i++) { const char * tname = be_typename(vm, i); @@ -73,65 +63,6 @@ extern "C" { return v; } - // variant of be_raise with string format - [[ noreturn ]] void be_raisef(bvm *vm, const char *except, const char *msg, ...) { - // To save stack space support logging for max text length of 128 characters - char log_data[128]; - - va_list arg; - va_start(arg, msg); - uint32_t len = ext_vsnprintf_P(log_data, sizeof(log_data)-3, msg, arg); - va_end(arg); - if (len+3 > sizeof(log_data)) { strcat(log_data, "..."); } // Actual data is more - be_raise(vm, except, log_data); - } - - static void map_insert_int(bvm *vm, const char *key, int value) - { - be_pushstring(vm, key); - be_pushint(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); - } - static void map_insert_bool(bvm *vm, const char *key, bool value) - { - be_pushstring(vm, key); - be_pushbool(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); - } - // if value == NAN, ignore - static void map_insert_float(bvm *vm, const char *key, float value) - { - if (!isnan(value)) { - be_pushstring(vm, key); - be_pushreal(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); - } - } - static void map_insert_str(bvm *vm, const char *key, const char *value) - { - be_pushstring(vm, key); - be_pushstring(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); - } - static void map_insert_list_uint8(bvm *vm, const char *key, const uint8_t *value, size_t size) - { - be_pushstring(vm, key); - - be_newobject(vm, "list"); - for (uint32_t i=0; i < size; i++) { - be_pushint(vm, value[i]); - be_data_push(vm, -2); - be_pop(vm, 1); - } - be_pop(vm, 1); // now list is on top - - be_data_insert(vm, -3); // insert into map, key/value - be_pop(vm, 2); // pop both key and value - } int32_t member_find(bvm *vm, const char *key, int32_t default_value) { int32_t ret = default_value; if (be_getmember(vm, -1, key)) { @@ -168,390 +99,6 @@ extern "C" { be_call(vm, 2); // call wirn 2 parameters (implicit instance and key) be_pop(vm, 2); // pop 2 arguments and return value } - - // create an object from the pointer and a class name - // on return, instance is pushed on the stack - void lv_create_object(bvm *vm, const char * class_name, void * ptr); - void lv_create_object(bvm *vm, const char * class_name, void * ptr) { - if (ptr == nullptr) { - be_throw(vm, BE_MALLOC_FAIL); - } - - be_getglobal(vm, class_name); // stack = class - be_call(vm, 0); // instanciate, stack = instance - be_getmember(vm, -1, "init"); // stack = instance, init_func - be_pushvalue(vm, -2); // stack = instance, init_func, instance - be_pushcomptr(vm, ptr); // stack = instance, init_func, instance, ptr - be_call(vm, 2); // stack = instance, ret, instance, ptr - be_pop(vm, 3); // stack = instance - } - - extern void berry_log_C(const char * berry_buf, ...); - // Create a class given a global name or a name within a module - // Case 1: (no dot in name) `lv_wifi_bars` will look for a global variable `lv_wifi_bars` - // Case 2: (dot in name) `lvgl.lv_obj` will import `lvgl` and look for `lv_obj` within this module - // returns true if successful and result is top of stack, or false if not found and `nil` is at top of stack - bbool be_find_class(bvm *vm, const char * cl_name); - bbool be_find_class(bvm *vm, const char * cl_name) { - char *saveptr; - bbool ret = false; - - if (cl_name == NULL) { - be_pushnil(vm); - return ret; - } - // berry_log_C(">> be_find_class %s", cl_name); - char cl_name_buf[strlen(cl_name)+1]; - strcpy(cl_name_buf, cl_name); - - char * prefix = strtok_r(cl_name_buf, ".", &saveptr); - char * suffix = strtok_r(NULL, ".", &saveptr); - if (suffix) { - // berry_log_C(">> be_find_class %s - %s", prefix, suffix); - be_getmodule(vm, prefix); - ret = be_getmember(vm, -1, suffix); - // berry_log_C(">> be_find_class ret=%i", ret); - be_remove(vm, -2); - } else { - ret = be_getglobal(vm, prefix); - } - return ret; - } -} - -/*********************************************************************************************\ - * Binary search for dynamic attributes - * - * Names need to be sorted -\*********************************************************************************************/ -// binary search within an array of sorted strings -// the first 4 bytes are a pointer to a string -// returns 0..total_elements-1 or -1 if not found -// -// This version skips the first character of the string if it's not a letter, -// the first character is used to indicate the type of the value associated to the key -extern "C" { - int32_t bin_search(const char * needle, const void * table, size_t elt_size, size_t total_elements); - int32_t bin_search(const char * needle, const void * table, size_t elt_size, size_t total_elements) { - int32_t low = 0; - int32_t high = total_elements - 1; - int32_t mid = (low + high) / 2; - // start a dissect - while (low <= high) { - const char * elt = *(const char **) ( ((uint8_t*)table) + mid * elt_size ); - char first_char = elt[0]; - if ( !(first_char >= 'a' && first_char <='z') && !(first_char >= 'A' && first_char <='Z') ) { - elt++; // skip first char - } - int32_t comp = strcmp(needle, elt); - if (comp < 0) { - high = mid - 1; - } else if (comp > 0) { - low = mid + 1; - } else { - break; - } - mid = (low + high) / 2; - } - if (low <= high) { - return mid; - } else { - return -1; - } - } -} - -/*********************************************************************************************\ - * Generalized callbacks - * - * Warning, the following expect all parameters to be 32 bits wide -\*********************************************************************************************/ - -extern "C" { - - /*********************************************************************************************\ - * Callback structures - * - * We allow 4 parameters, or 3 if method (first arg is `self`) - * This could be extended if needed - \*********************************************************************************************/ - typedef int32_t (*berry_callback_t)(int32_t v0, int32_t v1, int32_t v2, int32_t v3); - - extern void BerryDumpErrorAndClear(bvm *vm, bool berry_console); - - /*********************************************************************************************\ - * Callback structures - * - * We allow 4 parameters, or 3 if method (first arg is `self`) - * This could be extended if needed - \*********************************************************************************************/ - int32_t call_berry_cb(int32_t num, int32_t v0, int32_t v1, int32_t v2, int32_t v3) { - // call berry cb dispatcher - int32_t ret = 0; - // get the 'tasmota' object (global) and call 'cb_dispatch' - be_getglobal(berry.vm, PSTR("tasmota")); - if (!be_isnil(berry.vm, -1)) { - be_getmethod(berry.vm, -1, PSTR("cb_dispatch")); - - if (!be_isnil(berry.vm, -1)) { - be_pushvalue(berry.vm, -2); // add instance as first arg - // push all args as ints (may be revised) - be_pushint(berry.vm, num); - be_pushint(berry.vm, v0); - be_pushint(berry.vm, v1); - be_pushint(berry.vm, v2); - be_pushint(berry.vm, v3); - - ret = be_pcall(berry.vm, 6); // 5 arguments - if (ret != 0) { - BerryDumpErrorAndClear(berry.vm, false); // log in Tasmota console only - be_pop_all(berry.vm); // clear Berry stack - return 0; - } - be_pop(berry.vm, 6); - - if (be_isint(berry.vm, -1) || be_isnil(berry.vm, -1)) { // sanity check - if (be_isint(berry.vm, -1)) { - ret = be_toint(berry.vm, -1); - } - // All good, we can proceed - be_pop(berry.vm, 2); // remove tasmota instance and result - return ret; - } - } - be_pop(berry.vm, 1); - } - be_pop(berry.vm, 1); - AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_BERRY "can't call 'tasmota.cb_dispatch'")); - return 0; - } - - #define BERRY_CB(n) int32_t berry_cb_##n(int32_t v0, int32_t v1, int32_t v2, int32_t v3) { return call_berry_cb(n, v0, v1, v2, v3); } - // list the callbacks - BERRY_CB(0); - BERRY_CB(1); - BERRY_CB(2); - BERRY_CB(3); - BERRY_CB(4); - BERRY_CB(5); - BERRY_CB(6); - BERRY_CB(7); - BERRY_CB(8); - BERRY_CB(9); - BERRY_CB(10); - BERRY_CB(11); - BERRY_CB(12); - BERRY_CB(13); - BERRY_CB(14); - BERRY_CB(15); - BERRY_CB(16); - BERRY_CB(17); - BERRY_CB(18); - BERRY_CB(19); - - // array of callbacks - berry_callback_t berry_callback_array[] { - berry_cb_0, - berry_cb_1, - berry_cb_2, - berry_cb_3, - berry_cb_4, - berry_cb_5, - berry_cb_6, - berry_cb_7, - berry_cb_8, - berry_cb_9, - berry_cb_10, - berry_cb_11, - berry_cb_12, - berry_cb_13, - berry_cb_14, - berry_cb_15, - berry_cb_16, - berry_cb_17, - berry_cb_18, - berry_cb_19, - }; -} - -/*********************************************************************************************\ - * Automatically parse Berry stack and call the C function accordingly - * - * This function takes the n incoming arguments and pushes them as arguments - * on the stack for the C function: - * - be_int -> int32_t - * - be_bool -> int32_t with value 0/1 - * - be_string -> const char * - * - be_instance -> gets the member "_p" and pushes as void* - * - * This works because C silently ignores any unwanted arguments. - * There is a strong requirements that all ints and pointers are 32 bits. - * Float is not supported but could be added. Double cannot be supported because they are 64 bits - * - * Optional argument: - * - return_type: the C function return value is int32_t and is converted to the - * relevant Berry object depending on this char: - * '' (default): nil, no value - * 'i' be_int - * 'b' be_bool - * 's' be_str - * - * - arg_type: optionally check the types of input arguments, or throw an error - * string of argument types, '+' marks optional arguments - * '.' don't care - * 'i' be_int - * 'b' be_bool - * 's' be_string - * 'c' C callback - * 'lv_obj' be_instance of type or subtype - * '^lv_event_cb' callback of a named class - will call `_lvgl.gen_cb(arg_type, closure, self, lv native pointer)` and expects a callback address in return - * - * Ex: "oii+s" takes 3 mandatory arguments (obj_instance, int, int) and an optional fourth one [,string] -\*********************************************************************************************/ -// general form of lv_obj_t* function, up to 4 parameters -// We can only send 32 bits arguments (no 64 bits nor double) and we expect pointers to be 32 bits - -#define LVBE_LVGL_GLOB "_lvgl" -#define LVBE_LVGL_CB_GEN "gen_cb" - -// read a single value at stack position idx, convert to int. -// if object instance, get `_p` member and convert it recursively -int32_t be_convert_single_elt(bvm *vm, int32_t idx, const char * arg_type = nullptr, int32_t lv_obj_cb = 0) { - int32_t ret = 0; - char provided_type = 0; - idx = be_absindex(vm, idx); // make sure we have an absolute index - - // berry_log_C(">> 0 idx=%i arg_type=%s", idx, arg_type ? arg_type : "NULL"); - if (arg_type == nullptr) { arg_type = "."; } // if no type provided, replace with wildchar - size_t arg_type_len = strlen(arg_type); - - // handle callbacks first, since a wrong parameter will always yield to a crash - if (arg_type_len > 1 && arg_type[0] == '^') { // it is a callback - arg_type++; // skip first character - if (be_isclosure(vm, idx)) { - be_getglobal(vm, LVBE_LVGL_GLOB); - be_getmethod(vm, -1, LVBE_LVGL_CB_GEN); - be_pushvalue(vm, -2); - be_remove(vm, -3); // stack contains method + instance - be_pushstring(vm, arg_type); - be_pushvalue(vm, idx); - be_pushvalue(vm, 1); - be_pushint(vm, lv_obj_cb); - be_call(vm, 5); - const void * func = be_tocomptr(vm, -6); - be_pop(vm, 6); - - // berry_log_C("func=%p", func); - return (int32_t) func; - } else { - be_raise(vm, kTypeError, "Closure expected for callback type"); - } - } - - // first convert the value to int32 - if (be_isint(vm, idx)) { ret = be_toint(vm, idx); provided_type = 'i'; } - else if (be_isbool(vm, idx)) { ret = be_tobool(vm, idx); provided_type = 'b'; } - else if (be_isstring(vm, idx)) { ret = (int32_t) be_tostring(vm, idx); provided_type = 's'; } - else if (be_iscomptr(vm, idx)) { ret = (int32_t) be_tocomptr(vm, idx); provided_type = 'c'; } - - // check if simple type was a match - if (provided_type) { - bool type_ok = false; - type_ok = (arg_type[0] == '.'); // any type is accepted - type_ok = type_ok || (arg_type[0] == provided_type); // or type is a match - type_ok = type_ok || (ret == 0 && arg_type_len != 1); // or NULL is accepted for an instance - - if (!type_ok) { - berry_log_C("Unexpected argument type '%c', expected '%s'", provided_type, arg_type); - } - return ret; - } - - // non-simple type - if (be_isinstance(vm, idx)) { - // check if the instance is a subclass of `bytes()`` - be_getbuiltin(vm, "bytes"); // add "list" class - if (be_isderived(vm, idx)) { - be_pop(vm, 1); - be_getmember(vm, idx, "_buffer"); - be_pushvalue(vm, idx); - be_call(vm, 1); - int32_t ret = (int32_t) be_tocomptr(vm, -2); - be_pop(vm, 2); - return ret; - } else { - be_pop(vm, 1); - be_getmember(vm, idx, "_p"); - int32_t ret = be_convert_single_elt(vm, -1, nullptr); // recurse - be_pop(vm, 1); - - if (arg_type_len > 1) { - // Check type - be_classof(vm, idx); - bool class_found = be_find_class(vm, arg_type); - // Stack: class_of_idx, class_of_target (or nil) - if (class_found) { - if (!be_isderived(vm, -2)) { - berry_log_C("Unexpected class type '%s', expected '%s'", be_classname(vm, idx), arg_type); - } - } else { - berry_log_C("Unable to find class '%s' (%d)", arg_type, arg_type_len); - } - be_pop(vm, 2); - } else if (arg_type[0] != '.') { - berry_log_C("Unexpected instance type '%s', expected '%s'", be_classname(vm, idx), arg_type); - } - - return ret; - } - } else { - be_raise(vm, kTypeError, nullptr); - } - - return ret; -} - -extern "C" { - - /*********************************************************************************************\ - * Generalized virtual members for modules - * - * Takes a pointer to be_constint_t array and size - * Returns true if a match was found. In such case the result is on Berry stack - * - * Encoding depend on prefix (which is skipped when matching names): - * 1. `COLOR_WHITE` int value - * 3. `$SYMBOL_OK"` string pointer - * 4. `&seg7_font` comptr - \*********************************************************************************************/ - bool be_module_member(bvm *vm, const be_constint_t * definitions, size_t def_len); - bool be_module_member(bvm *vm, const be_constint_t * definitions, size_t def_len) { - int32_t argc = be_top(vm); // Get the number of arguments - if (argc == 1 && be_isstring(vm, 1)) { - const char * needle = be_tostring(vm, 1); - int32_t idx; - - idx = bin_search(needle, &definitions[0].name, sizeof(definitions[0]), def_len); - if (idx >= 0) { - // we did have a match - const char * key = definitions[idx].name; - switch (key[0]) { - // switch depending on the first char of the key, indicating the type - case '$': // string - be_pushstring(vm, (const char*) definitions[idx].value); - break; - case '&': // native function - be_pushntvfunction(vm, (bntvfunc) definitions[idx].value); - break; - default: // int - be_pushint(vm, definitions[idx].value); - break; - } - return true; - } - } - return false; - } } /*********************************************************************************************\ @@ -563,7 +110,6 @@ void BrTimeoutStart(void) { if (0 == berry.timeout) { berry.timeout = 1; // rare case when value accidentally computes to zero } - } void BrTimeoutYield(void) { diff --git a/tasmota/xdrv_52_3_berry_MI32.ino b/tasmota/xdrv_52_3_berry_MI32.ino new file mode 100644 index 000000000..a2f03fe21 --- /dev/null +++ b/tasmota/xdrv_52_3_berry_MI32.ino @@ -0,0 +1,234 @@ +/* + xdrv_52_3_berry_MI32.ino - Berry scripting language, native functions + + Copyright (C) 2021 Christian Baars & Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry + + This program 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 . +*/ + + +#ifdef USE_BERRY + +#include + +#if defined(USE_MI_ESP32) && !defined(USE_BLE_ESP32) + +/*********************************************************************************************\ + * Native functions mapped to Berry functions + * + * +\*********************************************************************************************/ +extern "C" { + +/******************************************************************** +** MI32 - sensor specific functions +********************************************************************/ + + extern uint32_t MI32numberOfDevices(); + extern const char * MI32getDeviceName(uint32_t slot); + extern void MI32setBatteryForSlot(uint32_t slot, uint8_t value); + extern void MI32setHumidityForSlot(uint32_t slot, float value); + extern void MI32setTemperatureForSlot(uint32_t slot, float value); + extern uint8_t * MI32getDeviceMAC(uint32_t slot); + + int be_MI32_devices(bvm *vm); + int be_MI32_devices(bvm *vm) { + uint32_t devices = MI32numberOfDevices(); + be_pushint(vm, devices); + be_return(vm); + } + + int be_MI32_set_bat(bvm *vm); + int be_MI32_set_bat(bvm *vm){ + int32_t argc = be_top(vm); // Get the number of arguments + if (argc == 3 && be_isint(vm, 2) && be_isint(vm, 3)) { + uint32_t slot = be_toint(vm, 2); + int32_t bat_val = be_toint(vm, 3); + MI32setBatteryForSlot(slot,bat_val); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + int be_MI32_get_name(bvm *vm); + int be_MI32_get_name(bvm *vm){ + int32_t argc = be_top(vm); // Get the number of arguments + if (argc == 2 && be_isint(vm, 2)) { + uint32_t slot = be_toint(vm, 2); + const char * name = MI32getDeviceName(slot); + be_pushstring(vm,name); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + int be_MI32_get_MAC(bvm *vm); + int be_MI32_get_MAC(bvm *vm){ + int32_t argc = be_top(vm); // Get the number of arguments + if (argc == 2 && be_isint(vm, 2)) { + uint32_t slot = be_toint(vm, 2); + uint8_t *buffer = MI32getDeviceMAC(slot); + size_t len = 6; + if(buffer != NULL) { + be_pushbytes(vm,buffer,len); + be_return(vm); // Return + } + } + be_raise(vm, kTypeError, nullptr); + } + + int be_MI32_set_hum(bvm *vm); + int be_MI32_set_hum(bvm *vm){ + int32_t argc = be_top(vm); // Get the number of arguments + if (argc == 3 && be_isint(vm, 2) && be_isreal(vm, 3)) { + uint32_t slot = be_toint(vm, 2); + float hum_val = be_toreal(vm, 3); + MI32setHumidityForSlot(slot,hum_val); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + int be_MI32_set_temp(bvm *vm); + int be_MI32_set_temp(bvm *vm){ + int32_t argc = be_top(vm); // Get the number of arguments + if (argc == 3 && be_isint(vm, 2) && be_isreal(vm, 3)) { + uint32_t slot = be_toint(vm, 2); + float temp_val = be_toreal(vm, 3); + MI32setTemperatureForSlot(slot,temp_val); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + +/******************************************************************** +** BLE - generic BLE functions +********************************************************************/ + extern void MI32setBerryAdvCB(void* function, uint8_t *buffer); + extern void MI32setBerryConnCB(void* function, uint8_t *buffer); + extern bool MI32runBerryConnection(uint8_t operation); + extern bool MI32setBerryCtxSvc(const char *Svc); + extern bool MI32setBerryCtxChr(const char *Chr); + extern bool MI32setBerryCtxMAC(uint8_t *MAC, uint8_t type); + + + int be_BLE_reg_conn_cb(bvm *vm); + int be_BLE_reg_conn_cb(bvm *vm){ + int32_t argc = be_top(vm); // Get the number of arguments + if (argc == 3 && be_iscomptr(vm, 2)) { + void* cb = be_tocomptr(vm, 2); + size_t len; + uint8_t * buf = (uint8_t*)be_tobytes(vm, 3, &len); + MI32setBerryConnCB(cb,buf); + be_return(vm); + } + be_raise(vm, kTypeError, nullptr); + } + + int be_BLE_reg_adv_cb(bvm *vm); + int be_BLE_reg_adv_cb(bvm *vm){ + int32_t argc = be_top(vm); // Get the number of arguments + if (argc == 3 && be_iscomptr(vm, 2)) { + void* cb = be_tocomptr(vm, 2); + size_t len; + uint8_t * buf = (uint8_t*)be_tobytes(vm, 3, &len); + MI32setBerryAdvCB(cb,buf); + be_return(vm); // Return + } + else if(argc == 2 && be_isint(vm, 2)){ + if(be_toint(vm, 2) == 0){ + MI32setBerryAdvCB(NULL,NULL); + be_return(vm); // Return + } + } + be_raise(vm, kTypeError, nullptr); + } + + int be_BLE_set_MAC(bvm *vm); + int be_BLE_set_MAC(bvm *vm){ + int32_t argc = be_top(vm); // Get the number of arguments + if (argc > 1 && be_isbytes(vm, 2)) { + size_t len = 6; + uint8_t type = 0; + if(argc == 3 && be_isint(vm, 3)){ + type = be_toint(vm,3); + } + if (MI32setBerryCtxMAC((uint8_t*)be_tobytes(vm, 2, &len),type)) be_return(vm); + } + be_raise(vm, kTypeError, nullptr); + } + + int be_BLE_set_service(bvm *vm); + int be_BLE_set_service(bvm *vm){ + int32_t argc = be_top(vm); // Get the number of arguments + if (argc == 2 && be_isstring(vm, 2)) { + if (MI32setBerryCtxSvc(be_tostring(vm, 2))) be_return(vm); + } + be_raise(vm, kTypeError, nullptr); + } + + int be_BLE_set_characteristic(bvm *vm); + int be_BLE_set_characteristic(bvm *vm){ + int32_t argc = be_top(vm); // Get the number of arguments + if (argc == 2 && be_isstring(vm, 2)) { + if (MI32setBerryCtxChr(be_tostring(vm, 2))) be_return(vm); + } + be_raise(vm, kTypeError, nullptr); + } + + int be_BLE_run(bvm *vm); + int be_BLE_run(bvm *vm){ + int32_t argc = be_top(vm); // Get the number of arguments + if (argc == 2 && be_isint(vm, 2)) { + if (MI32runBerryConnection(be_toint(vm, 2))) be_return(vm); + } + be_raise(vm, kTypeError, nullptr); + } +} //extern "C" + + +#endif // USE_MI_ESP32 + +#endif // USE_BERRY + +/* +BLE.set_svc +BLE.set_chr + +BLE.set_MAC +BLE.run(op) +be_BLE_op: +1 read +2 write +3 subscribe +4 unsubscribe +5 disconnect + +11 read once, then disconnect +12 write once, then disconnect +13 subscribe once, then disconnect +14 unsubscribe once, then disconnect + +BLE.conn_cb(cb,buffer) +BLE.adv_cb(cb,buffer) + +MI32.devices() +MI32.get_name(slot) +MI32.get_MAC(slot) +MI32.set_bat(slot,int) +MI32.set_hum(slot,float) +MI32.set_temp(slot,float) + +*/ diff --git a/tasmota/xdrv_52_3_berry_gpio.ino b/tasmota/xdrv_52_3_berry_gpio.ino index f694b6444..20a937dd2 100644 --- a/tasmota/xdrv_52_3_berry_gpio.ino +++ b/tasmota/xdrv_52_3_berry_gpio.ino @@ -21,6 +21,7 @@ #ifdef USE_BERRY #include +#include "esp8266toEsp32.h" #if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2) #include @@ -39,7 +40,7 @@ extern "C" { // virtual member int gp_member(bvm *vm); int gp_member(bvm *vm) { - if (be_module_member(vm, lv_gpio_constants, lv_gpio_constants_size)) { + if (be_const_module_member(vm, lv_gpio_constants, lv_gpio_constants_size)) { be_return(vm); } else { be_return_nil(vm); @@ -62,8 +63,8 @@ extern "C" { // DAC #if defined(CONFIG_IDF_TARGET_ESP32) if (25 == pin || 26 == pin) { - uint32_t channel = pin - 25 + 1; // 1 or 2 - esp_err_t err = dac_output_enable((dac_channel_t) channel); + dac_channel_t channel = (25 == pin) ? DAC_CHANNEL_1 : DAC_CHANNEL_2; + esp_err_t err = dac_output_enable(channel); if (err) { be_raisef(vm, "value_error", "Error: dac_output_enable(%i) -> %i", channel, err); } @@ -72,8 +73,8 @@ extern "C" { } #elif defined(CONFIG_IDF_TARGET_ESP32S2) if (17 == pin || 18 == pin) { - uint32_t channel = pin - 17 + 1; // 1 or 2 - esp_err_t err = dac_output_enable((dac_channel_t) channel); + dac_channel_t channel = (17 == pin) ? DAC_CHANNEL_1 : DAC_CHANNEL_2; + esp_err_t err = dac_output_enable(channel); if (err) { be_raisef(vm, "value_error", "Error: dac_output_enable(%i) -> %i", channel, err); } @@ -133,8 +134,8 @@ extern "C" { uint32_t dac_value = changeUIntScale(mV, 0, 3300, 0, 255); // convert from 0..3300 ms to 0..255 #if defined(CONFIG_IDF_TARGET_ESP32) if (25 == pin || 26 == pin) { - uint32_t channel = pin - 25 + 1; // 1 or 2 - esp_err_t err = dac_output_voltage((dac_channel_t) channel, dac_value); + dac_channel_t channel = (25 == pin) ? DAC_CHANNEL_1 : DAC_CHANNEL_2; + esp_err_t err = dac_output_voltage(channel, dac_value); if (err) { be_raisef(vm, "internal_error", "Error: esp_err_tdac_output_voltage(%i, %i) -> %i", channel, dac_value, err); } @@ -143,8 +144,8 @@ extern "C" { } #elif defined(CONFIG_IDF_TARGET_ESP32S2) if (17 == pin || 18 == pin) { - uint32_t channel = pin - 17 + 1; // 1 or 2 - esp_err_t err = dac_output_voltage((dac_channel_t) channel, dac_value); + dac_channel_t channel = (17 == pin) ? DAC_CHANNEL_1 : DAC_CHANNEL_2; + esp_err_t err = dac_output_voltage(channel, dac_value); if (err) { be_raisef(vm, "internal_error", "Error: esp_err_tdac_output_voltage(%i, %i) -> %i", channel, dac_value, err); } @@ -201,8 +202,10 @@ extern "C" { be_raise(vm, kTypeError, nullptr); } + void gp_set_duty(int32_t pin, int32_t duty, int32_t hpoint) { + analogWritePhase(pin, duty, hpoint); + } + } - - #endif // USE_BERRY diff --git a/tasmota/xdrv_52_3_berry_light.ino b/tasmota/xdrv_52_3_berry_light.ino index 19aa3cfb6..89ba735e3 100644 --- a/tasmota/xdrv_52_3_berry_light.ino +++ b/tasmota/xdrv_52_3_berry_light.ino @@ -50,11 +50,11 @@ extern "C" { light_controller.calcLevels(channels); uint8_t bri = light_state.getBri(); - // map_insert_int(vm, "_devices_present", TasmotaGlobal.devices_present); - // map_insert_int(vm, "_light_device", Light.device); - // map_insert_int(vm, "_light_subtype", Light.subtype); - // map_insert_int(vm, "_light_multi", Light.pwm_multi_channels); - // map_insert_int(vm, "_light_linked", light_controller.isCTRGBLinked()); + // be_map_insert_int(vm, "_devices_present", TasmotaGlobal.devices_present); + // be_map_insert_int(vm, "_light_device", Light.device); + // be_map_insert_int(vm, "_light_subtype", Light.subtype); + // be_map_insert_int(vm, "_light_multi", Light.pwm_multi_channels); + // be_map_insert_int(vm, "_light_linked", light_controller.isCTRGBLinked()); if (!Light.pwm_multi_channels) { uint32_t subtype = Light.subtype; // virtual sub-type, for SO37 128 @@ -64,7 +64,7 @@ extern "C" { if (light_controller.isCTRGBLinked() && (light_num == 0)) { data_present = true; // valid combination if (subtype >= LST_RGBW) { - map_insert_str(vm, "colormode", (light_state.getColorMode() & LCM_RGB ? "rgb" : "ct")); + be_map_insert_str(vm, "colormode", (light_state.getColorMode() & LCM_RGB ? "rgb" : "ct")); } } if (!light_controller.isCTRGBLinked()) { @@ -83,33 +83,33 @@ extern "C" { if (data_present) { // see ResponseLightState() - map_insert_bool(vm, "power", bitRead(TasmotaGlobal.power, light_num + Light.device - 1)); - map_insert_int(vm, "bri", bri); + be_map_insert_bool(vm, "power", bitRead(TasmotaGlobal.power, light_num + Light.device - 1)); + be_map_insert_int(vm, "bri", bri); if (subtype >= LST_RGB) { uint16_t hue; uint8_t sat, bri; light_state.getHSB(&hue, &sat, &bri); - map_insert_int(vm, "hue", hue); - map_insert_int(vm, "sat", sat); + be_map_insert_int(vm, "hue", hue); + be_map_insert_int(vm, "sat", sat); } if ((LST_COLDWARM == subtype) || (LST_RGBW <= subtype)) { - map_insert_int(vm, "ct", light_state.getCT()); + be_map_insert_int(vm, "ct", light_state.getCT()); } if (subtype >= LST_RGB) { snprintf(s_rgb, sizeof(s_rgb), PSTR("%02X%02X%02X"), channels[0], channels[1], channels[2]); - map_insert_str(vm, "rgb", s_rgb); + be_map_insert_str(vm, "rgb", s_rgb); } if (subtype > LST_NONE) { - map_insert_list_uint8(vm, "channels", &channels[chanidx], subtype); + be_map_insert_list_uint8(vm, "channels", &channels[chanidx], subtype); } } } else { // Light.pwm_multi_channels if ((light_num >= 0) && (light_num < LST_MAX)) { data_present = true; - map_insert_bool(vm, "power", Light.power & (1 << light_num)); - map_insert_int(vm, "bri", Light.current_color[light_num]); - map_insert_list_uint8(vm, "channels", &channels[light_num], 1); + be_map_insert_bool(vm, "power", Light.power & (1 << light_num)); + be_map_insert_int(vm, "bri", Light.current_color[light_num]); + be_map_insert_list_uint8(vm, "channels", &channels[light_num], 1); } } diff --git a/tasmota/xdrv_52_3_berry_lvgl.ino b/tasmota/xdrv_52_3_berry_lvgl.ino index 39e7737ed..0f4ac4262 100644 --- a/tasmota/xdrv_52_3_berry_lvgl.ino +++ b/tasmota/xdrv_52_3_berry_lvgl.ino @@ -23,18 +23,16 @@ #include #include "lvgl.h" -#include "be_lvgl.h" +#include "be_mapping.h" #include "be_ctypes.h" +#include "lv_berry.h" #include "Adafruit_LvGL_Glue.h" -#ifdef USE_LVGL_FREETYPE -#include "esp_task_wdt.h" -#include "lv_freetype.h" -#endif - // Berry easy logging extern "C" { extern void berry_log_C(const char * berry_buf, ...); + extern const be_ntv_class_def_t lv_classes[]; + extern const size_t lv_classes_size; } extern Adafruit_LvGL_Glue * glue; @@ -99,209 +97,9 @@ LVBE_globals lvbe; extern void start_lvgl(const char * uconfig); extern void lv_ex_get_started_1(void); -/*********************************************************************************************\ - * Calling any LVGL function with auto-mapping - * -\*********************************************************************************************/ - -// check input parameters, and create callbacks if needed -// change values in place -// -// Format: -// - either a lowercase character encoding for a simple type -// - 'b': bool -// - 'i': int (int32_t) -// - 's': string (const char *) -// -// - a class name surroungded by parenthesis -// - '(lv_button)' -> lv_button class or derived -// - '[lv_event_cb]' -> callback type, still prefixed with '^' to mark that it is cb -// -void be_check_arg_type(bvm *vm, int32_t arg_start, int32_t argc, const char * arg_type, int32_t p[8]); -void be_check_arg_type(bvm *vm, int32_t arg_start, int32_t argc, const char * arg_type, int32_t p[8]) { - bool arg_type_check = (arg_type != nullptr); // is type checking activated - int32_t arg_idx = 0; // position in arg_type string - char type_short_name[32]; - - for (uint32_t i = 0; i < argc; i++) { - type_short_name[0] = 0; // clear string - // extract individual type - if (nullptr != arg_type) { - switch (arg_type[arg_idx]) { - case '.': - case 'a'...'z': - type_short_name[0] = arg_type[arg_idx]; - type_short_name[1] = 0; - arg_idx++; - break; - case '(': - case '^': - { - uint32_t prefix = 0; - if (arg_type[arg_idx] == '^') { - type_short_name[0] = '^'; - type_short_name[1] = 0; - prefix = 1; - } - uint32_t offset = 0; - arg_idx++; - while (arg_type[arg_idx + offset] != ')' && arg_type[arg_idx + offset] != '^' && arg_type[arg_idx + offset] != 0 && offset+prefix+1 < sizeof(type_short_name)) { - type_short_name[offset+prefix] = arg_type[arg_idx + offset]; - type_short_name[offset+prefix+1] = 0; - offset++; - } - if (arg_type[arg_idx + offset] == 0) { - arg_type = nullptr; // no more parameters, stop iterations - } - arg_idx += offset + 1; - } - break; - case 0: - arg_type = nullptr; // stop iterations - break; - } - } - // AddLog(LOG_LEVEL_INFO, ">> be_call_c_func arg %i, type %s", i, arg_type_check ? type_short_name : ""); - p[i] = be_convert_single_elt(vm, i + arg_start, arg_type_check ? type_short_name : nullptr, p[0]); - } - - // check if we are missing arguments - if (arg_type != nullptr && arg_type[arg_idx] != 0) { - berry_log_C("Missing arguments, remaining type '%s'", &arg_type[arg_idx]); - } -} - -typedef int32_t (*fn_any_callable)(int32_t p0, int32_t p1, int32_t p2, int32_t p3, - int32_t p4, int32_t p5, int32_t p6, int32_t p7); extern "C" { - void lv_init_set_member(bvm *vm, int index, void * ptr); - int be_call_c_func(bvm *vm, void * func, const char * return_type, const char * arg_type); - - // native closure to call `be_call_c_func` - int lvx_call_c(bvm *vm) { - // berry_log_C("lvx_call_c enter"); - // keep parameters unchanged - be_getupval(vm, 0, 0); // if index is zero, it's the current native closure - void * func = be_tocomptr(vm, -1); - be_getupval(vm, 0, 1); // if index is zero, it's the current native closure - const char * return_type = be_tostring(vm, -1); - be_getupval(vm, 0, 2); // if index is zero, it's the current native closure - const char * arg_type = be_tostring(vm, -1); - be_pop(vm, 3); // remove 3 upvals - - // berry_log_C("lvx_call_c %p '%s' <- (%s)", func, return_type, arg_type); - return be_call_c_func(vm, func, return_type, arg_type); - } - - // virtual method, arg1: instance, arg2: name of method - int lvx_member(bvm *vm) { - int32_t argc = be_top(vm); // Get the number of arguments - if (argc == 2 && be_isinstance(vm, 1) && be_isstring(vm, 2)) { - const char * method_name = be_tostring(vm, 2); // the method we are looking for - while (be_isinstance(vm, 1)) { - const char * class_name = be_classname(vm, 1); - // berry_log_C("lvx_member looking for method '%s' of class '%s'", method_name, class_name); - - // look for class descriptor - int32_t class_idx = bin_search(class_name, &lv_classes[0].name, sizeof(lv_classes[0]), lv_classes_size); - if (class_idx >= 0) { - const lvbe_call_c_t * methods_calls = lv_classes[class_idx].func_table; - size_t methods_size = lv_classes[class_idx].size; - - int32_t method_idx = bin_search(method_name, methods_calls, sizeof(lvbe_call_c_t), methods_size); - if (method_idx >= 0) { - // method found - const lvbe_call_c_t * method = &methods_calls[method_idx]; - // berry_log_C("lvx_member method found func=%p return_type=%s arg_type=%s", method->func, method->return_type, method->arg_type); - // push native closure - be_pushntvclosure(vm, &lvx_call_c, 3); // 3 upvals - - be_pushcomptr(vm, method->func); - be_setupval(vm, -2, 0); - be_pop(vm, 1); - - be_pushstring(vm, method->return_type); - be_setupval(vm, -2, 1); - be_pop(vm, 1); - - be_pushstring(vm, method->arg_type); - be_setupval(vm, -2, 2); - be_pop(vm, 1); - - // all good - be_return(vm); - } - } - - // get super if any, or nil if none - be_getsuper(vm, 1); - be_moveto(vm, -1, 1); - be_pop(vm, 1); - } - // berry_log_C("lvx_member method not found"); - be_return_nil(vm); - } - be_raise(vm, kTypeError, nullptr); - } - - int be_call_c_func(bvm *vm, void * func, const char * return_type, const char * arg_type) { - // AddLog(LOG_LEVEL_INFO, ">> be_call_c_func, func=%p, return_type=%s, arg_type=%s", func, return_type ? return_type : "", arg_type ? arg_type : ""); - int32_t p[8] = {0,0,0,0,0,0,0,0}; - int32_t argc = be_top(vm); // Get the number of arguments - - // the following describe the active payload for the C function (start and count) - // this is because the `init()` constructor first arg is not passed to the C function - int32_t arg_start = 1; // start with standard values - int32_t arg_count = argc; - - // check if we call a constructor, in this case we store the return type into the new object - // check if we call a constructor with a comptr as first arg - if (return_type && return_type[0] == '+') { - if (argc > 1 && be_iscomptr(vm, 2)) { - lv_obj_t * obj = (lv_obj_t*) be_tocomptr(vm, 2); - lv_init_set_member(vm, 1, obj); - be_return_nil(vm); - } else { - // we need to discard the first arg - arg_start++; - arg_count--; - } - } - - fn_any_callable f = (fn_any_callable) func; - // AddLog(LOG_LEVEL_INFO, ">> before be_check_arg_type argc=%i - %i", arg_count, arg_start); - be_check_arg_type(vm, arg_start, arg_count, arg_type, p); - // AddLog(LOG_LEVEL_INFO, ">> be_call_c_func(%p) - %p,%p,%p,%p,%p - %s", f, p[0], p[1], p[2], p[3], p[4], return_type ? return_type : "NULL"); - int32_t ret = (*f)(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); - // AddLog(LOG_LEVEL_INFO, ">> be_call_c_func, ret = %p", ret); - if ((return_type == nullptr) || (strlen(return_type) == 0)) { be_return_nil(vm); } // does not return - else if (return_type[0] == '+') { - lv_obj_t * obj = (lv_obj_t*) ret; - lv_init_set_member(vm, 1, obj); - be_return_nil(vm); - } - else if (strlen(return_type) == 1) { - switch (return_type[0]) { - case '.': // fallback next - case 'i': be_pushint(vm, ret); break; - case 'b': be_pushbool(vm, ret); break; - case 's': be_pushstring(vm, (const char*) ret); break; - case 'c': be_pushint(vm, ret); break; // TODO missing 'c' general callback type - default: be_raise(vm, "internal_error", "Unsupported return type"); break; - } - be_return(vm); - } else { // class name - // AddLog(LOG_LEVEL_INFO, ">> be_call_c_func, create_obj ret=%i return_type=%s", ret, return_type); - be_find_class(vm, return_type); - be_pushcomptr(vm, (void*) ret); // stack = class, ptr - be_pushcomptr(vm, (void*) -1); // stack = class, ptr, -1 - be_call(vm, 2); // instanciate with 2 arguments, stack = instance, -1, ptr - be_pop(vm, 2); // stack = instance - be_return(vm); - } - } } /*********************************************************************************************\ @@ -314,116 +112,6 @@ extern "C" { \*********************************************************************************************/ extern "C" { -#include "be_exec.h" -#include "be_vm.h" -#include "be_mem.h" - - /*********************************************************************************************\ - * Support for lv_color - \*********************************************************************************************/ - inline lv_color_t lv_color_from_uint32(uint32_t ucol) { - lv_color_t * col = (lv_color_t*) &ucol; - return *col; - } - inline uint32_t lv_color_to_uint32(lv_color_t col) { - uint16_t *p = (uint16_t*) &col; - return *p; - } - - // lv_color - // First arg is a 24 bits RGB color - // If first arg is `nil` second arg is the native value of color - int lco_init(bvm *vm) { - int argc = be_top(vm); - uint32_t color32 = 0x000000; // default to black - - if (argc > 1) { - color32 = be_toint(vm, 2); - } - lv_color_t lv_color = lv_color_hex(color32); - if (argc > 2 && be_toint(vm, 3) == -1) { - lv_color.full = be_toint(vm, 2); - } - be_pushint(vm, lv_color_to_uint32(lv_color)); - be_setmember(vm, 1, "_p"); - be_return_nil(vm); - } - - int lco_tostring(bvm *vm) { - lv_color_t lv_color = {}; - be_getmember(vm, 1, "_p"); - uint32_t ntv_color = be_toint(vm, -1); - lv_color = lv_color_from_uint32(ntv_color); - uint32_t color = lv_color_to32(lv_color) & 0xFFFFFF; - be_pop(vm, 1); // remove attribute - char s[48]; - snprintf(s, sizeof(s), "lv_color(0x%06x - native:0x%04x)", color, ntv_color); - be_pushnstring(vm, s, strlen(s)); /* make escape string from buffer */ - be_return(vm); - } - - int lco_toint(bvm *vm) { - lv_color_t lv_color = {}; - be_getmember(vm, 1, "_p"); - uint32_t ntv_color = be_toint(vm, -1); - be_pushint(vm, ntv_color); - be_return(vm); - } - - - /*********************************************************************************************\ - * Support for lv - \*********************************************************************************************/ - // Get the `_p` member of instance at `index` - void * lv_get_arg(bvm *vm, int index) { - void * ret = nullptr; - if (be_isinstance(vm, index)) { - be_getmember(vm, index, "_p"); - ret = be_tocomptr(vm, -1); - be_pop(vm, 1); // remove _p attribute - } - return ret; - } - - // called during init, set the `_p` member with the pointer - void lv_init_set_member(bvm *vm, int index, void * ptr) { - be_pushcomptr(vm, ptr); - be_setmember(vm, index, "_p"); - be_pop(vm, 1); - } - - // function is (void) -> lv_obt_t* - typedef lv_obj_t* (*fn_lvobj__void)(void); // f() -> newly created lv_obj() - int lv0_lvobj__void_call(bvm *vm, fn_lvobj__void func) { - lv_obj_t * obj = (*func)(); - be_find_class(vm, "lv.lv_obj"); - be_pushcomptr(vm, (void*) -1); // stack = class, -1 - be_pushcomptr(vm, (void*) obj); // stack = class, -1, ptr - be_call(vm, 2); // instanciate, stack = instance (don't call init() ) - be_pop(vm, 2); // stack = instance - be_return(vm); - } - - /*********************************************************************************************\ - * Support for lv_fonts - \*********************************************************************************************/ - // load font by name on file-system - int lv0_load_font(bvm *vm) { - int argc = be_top(vm); - if (argc == 1 && be_isstring(vm, 1)) { - lv_font_t * font = lv_font_load(be_tostring(vm, 1)); - if (font != nullptr) { - be_find_class(vm, "lv.lv_font"); - be_pushcomptr(vm, font); - be_call(vm, 1); - be_pop(vm, 1); - be_return(vm); - } else { - be_return_nil(vm); - } - } - be_raise(vm, kTypeError, nullptr); - } /*********************************************************************************************\ * Support for Freetype fonts @@ -433,7 +121,7 @@ extern "C" { #ifdef USE_LVGL_FREETYPE int argc = be_top(vm); if (argc == 3 && be_isstring(vm, 1) && be_isint(vm, 2) && be_isint(vm, 3)) { - lv_ft_info_t info; + lv_ft_info_t info = {}; info.name = be_tostring(vm, 1); info.weight = be_toint(vm, 2); info.style = be_toint(vm, 3); @@ -441,7 +129,7 @@ extern "C" { lv_font_t * font = info.font; if (font != nullptr) { - be_find_class(vm, "lv.lv_font"); + be_find_global_or_module_member(vm, "lv.lv_font"); be_pushcomptr(vm, font); be_call(vm, 1); be_pop(vm, 1); @@ -637,7 +325,7 @@ extern "C" { be_raisef(vm, "value_error", "unknown font size '%s-%i'", name, size); } - be_find_class(vm, "lv.lv_font"); + be_find_global_or_module_member(vm, "lv.lv_font"); be_pushcomptr(vm, (void*)font_entry->font); be_call(vm, 1); be_pop(vm, 1); @@ -668,82 +356,6 @@ extern "C" { lv_img_set_src(img, &tasmota_logo_64_truecolor); } - /*********************************************************************************************\ - * LVGL top level virtual members - * - * Responds to virtual constants - \*********************************************************************************************/ - - extern const lvbe_call_c_t lv_func[]; - extern const size_t lv_func_size; - - extern const be_constint_t lv0_constants[]; - extern const size_t lv0_constants_size; - - extern const be_ctypes_class_by_name_t be_ctypes_lvgl_classes[]; - extern const size_t be_ctypes_lvgl_classes_size; - - int lv0_member(bvm *vm); - int lv0_member(bvm *vm) { - // first try the standard way - if (be_module_member(vm, lv0_constants, lv0_constants_size)) { - be_return(vm); - } - // try alternative members - int32_t argc = be_top(vm); // Get the number of arguments - if (argc == 1 && be_isstring(vm, 1)) { - const char * needle = be_tostring(vm, 1); - int32_t idx; - - // search for a class with this name - char cl_prefixed[32]; - snprintf(cl_prefixed, sizeof(cl_prefixed), "lv_%s", needle); // we try both actual name and prefixed with `lv_` so both `lv.obj` and `lv.lv_obj` work - idx = bin_search(cl_prefixed, &lv_classes[0].name, sizeof(lv_classes[0]), lv_classes_size); - if (idx < 0) { - idx = bin_search(needle, &lv_classes[0].name, sizeof(lv_classes[0]), lv_classes_size); - } - if (idx >= 0) { - // we did have a match - be_pushntvclass(vm, lv_classes[idx].cl); - be_return(vm); - } - // same search for ctypes - idx = bin_search(cl_prefixed, &be_ctypes_lvgl_classes[0].name, sizeof(be_ctypes_lvgl_classes[0]), be_ctypes_lvgl_classes_size); - if (idx < 0) { - idx = bin_search(needle, &be_ctypes_lvgl_classes[0].name, sizeof(be_ctypes_lvgl_classes[0]), be_ctypes_lvgl_classes_size); - } - if (idx >= 0) { - // we did have a match - be_pushntvclass(vm, be_ctypes_lvgl_classes[idx].cl); - be_return(vm); - } - - // search for a method with this name - idx = bin_search(needle, &lv_func[0].name, sizeof(lv_func[0]), lv_func_size); - if (idx >= 0) { - const lvbe_call_c_t * method = &lv_func[idx]; - // push native closure - be_pushntvclosure(vm, &lvx_call_c, 3); // 3 upvals - - be_pushcomptr(vm, method->func); - be_setupval(vm, -2, 0); - be_pop(vm, 1); - - be_pushstring(vm, method->return_type); - be_setupval(vm, -2, 1); - be_pop(vm, 1); - - be_pushstring(vm, method->arg_type); - be_setupval(vm, -2, 2); - be_pop(vm, 1); - - // all good - be_return(vm); - } - } - be_return_nil(vm); - } - /*********************************************************************************************\ * LVGL Start * @@ -803,7 +415,7 @@ extern "C" { lv_indev_t * indev = lv_indev_drv_register(&lvbe.indev_drv); lvbe.indev_list.addHead(indev); // keep track of indevs - be_find_class(vm, "lv.lv_indev"); + be_find_global_or_module_member(vm, "lv.lv_indev"); be_pushint(vm, (int32_t) indev); be_call(vm, 1); be_pop(vm, 1); @@ -851,62 +463,6 @@ extern "C" { } } - /*********************************************************************************************\ - * Support for lv_indev and objects that don't need creator - \*********************************************************************************************/ - int lv0_init(bvm *vm); - int lv0_init(bvm *vm) { - void * obj = nullptr; - int argc = be_top(vm); - if (argc > 1) { - obj = (void*) be_convert_single_elt(vm, 2); - } - lv_init_set_member(vm, 1, obj); - be_return_nil(vm); - } - - /*********************************************************************************************\ - * Generalized tostring method, shows class and _p value - \*********************************************************************************************/ - int lvx_tostring(bvm *vm) { - lv_obj_t * obj = (lv_obj_t*) lv_get_arg(vm, 1); - const char * classname = be_classname(vm, 1); - char s[48]; - snprintf(s, sizeof(s), "", classname, obj); - be_pushnstring(vm, s, strlen(s)); /* make escape string from buffer */ - be_return(vm); - } - - /*********************************************************************************************\ - * Support for lv_style - \*********************************************************************************************/ - int lvs_init(bvm *vm) { - int argc = be_top(vm); - lv_style_t * style = nullptr; - - if (argc > 1) { - style = (lv_style_t*) be_convert_single_elt(vm, 2); - } - if (style == nullptr) { - style = (lv_style_t*) be_malloc(vm, sizeof(lv_style_t)); - if (style == nullptr) { - be_throw(vm, BE_MALLOC_FAIL); - } - if (style != nullptr) { - lv_style_init(style); - } - } - lv_init_set_member(vm, 1, style); - be_return_nil(vm); - } - - int lvs_tostring(bvm *vm) { - lv_style_t * style1 = (lv_style_t*) lv_get_arg(vm, 1); - char s[32]; - snprintf(s, sizeof(s), "", style1); - be_pushnstring(vm, s, strlen(s)); /* make escape string from buffer */ - be_return(vm); - } /*********************************************************************************************\ * Screenshot in raw format \********************************************************************************************/ @@ -974,8 +530,6 @@ extern "C" { } } -#include "lvgl_berry/be_lv_c_mapping.h" - #else // USE_LVGL // // define weak aliases diff --git a/tasmota/xdrv_52_3_berry_md5.ino b/tasmota/xdrv_52_3_berry_md5.ino deleted file mode 100644 index a4adee029..000000000 --- a/tasmota/xdrv_52_3_berry_md5.ino +++ /dev/null @@ -1,105 +0,0 @@ -/* - xdrv_52_3_berry_md5.ino - Berry scripting language, Md5 class - - Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry - - This program 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 . -*/ - - -#ifdef USE_BERRY - -#include -#include "MD5Builder.h" -#include "be_mem.h" - -/*********************************************************************************************\ - * Md5 class - * -\*********************************************************************************************/ -extern "C" { - - int free_ctx(bvm* vm) { - int argc = be_top(vm); - if (argc > 0) { - be_getmember(vm, 1, ".p"); - struct MD5Context * ctx = (struct MD5Context *) be_tocomptr(vm, -1); - if (ctx != NULL) { - be_os_free(ctx); - } - } - be_return_nil(vm); - } - - // `Md5.init() -> ` - int32_t m_md5_init(struct bvm *vm); - int32_t m_md5_init(struct bvm *vm) { - - struct MD5Context * ctx = (struct MD5Context *) be_os_malloc(sizeof(struct MD5Context)); - if (!ctx) { - be_throw(vm, BE_MALLOC_FAIL); - } - MD5Init(ctx); - - be_newcomobj(vm, ctx, &free_ctx); - be_setmember(vm, 1, ".p"); - be_return_nil(vm); - } - - // `Md5.update(content:bytes()) -> nil` - // - // Add raw bytes to the MD5 calculation - int32_t m_md5_update(struct bvm *vm); - int32_t m_md5_update(struct bvm *vm) { - int32_t argc = be_top(vm); // Get the number of arguments - if (argc >= 2 && be_isinstance(vm, 2)) { - do { - be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */ - if (!be_isderived(vm, 2)) break; - size_t length = 0; - const void * bytes = be_tobytes(vm, 2, &length); - if (!bytes) break; - - be_getmember(vm, 1, ".p"); - struct MD5Context * ctx; - ctx = (struct MD5Context *) be_tocomptr(vm, -1); - if (!ctx) break; - - if (length > 0) { - MD5Update(ctx, (const uint8_t*) bytes, length); - } - be_return_nil(vm); - // success - } while (0); - } - be_raise(vm, kTypeError, nullptr); - } - - // `Md5.update(content:bytes()) -> nil` - // - // Add raw bytes to the MD5 calculation - int32_t m_md5_finish(struct bvm *vm); - int32_t m_md5_finish(struct bvm *vm) { - be_getmember(vm, 1, ".p"); - struct MD5Context * ctx; - ctx = (struct MD5Context *) be_tocomptr(vm, -1); - - uint8_t output[16]; - MD5Final(output, ctx); - be_pushbytes(vm, output, sizeof(output)); - be_return(vm); - } -} - -#endif // USE_BERRY diff --git a/tasmota/xdrv_52_3_berry_tasmota.ino b/tasmota/xdrv_52_3_berry_tasmota.ino index cfc847e7a..c7c13c007 100644 --- a/tasmota/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/xdrv_52_3_berry_tasmota.ino @@ -26,25 +26,25 @@ const uint32_t BERRY_MAX_LOGS = 16; // max number of print output recorded when outside of REPL, used to avoid infinite grow of logs const uint32_t BERRY_MAX_REPL_LOGS = 1024; // max number of print output recorded when inside REPL -/*********************************************************************************************\ - * Return C callback from index - * -\*********************************************************************************************/ -extern "C" { - int32_t l_get_cb(struct bvm *vm); - int32_t l_get_cb(struct bvm *vm) { - int32_t argc = be_top(vm); // Get the number of arguments - if (argc >= 2 && be_isint(vm, 2)) { - int32_t idx = be_toint(vm, 2); - if (idx >= 0 && idx < ARRAY_SIZE(berry_callback_array)) { - const berry_callback_t c_ptr = berry_callback_array[idx]; - be_pushcomptr(vm, (void*) c_ptr); - be_return(vm); - } - } - be_raise(vm, kTypeError, nullptr); - } -} +// /*********************************************************************************************\ +// * Return C callback from index +// * +// \*********************************************************************************************/ +// extern "C" { +// extern int32_t be_cb__get_cb(struct bvm *vm); +// int32_t be_cb__get_cb(struct bvm *vm) { +// int32_t argc = be_top(vm); // Get the number of arguments +// if (argc >= 2 && be_isint(vm, 2)) { +// int32_t idx = be_toint(vm, 2); +// if (idx >= 0 && idx < ARRAY_SIZE(berry_callback_array)) { +// const berry_callback_t c_ptr = berry_callback_array[idx]; +// be_pushcomptr(vm, (void*) c_ptr); +// be_return(vm); +// } +// } +// be_raise(vm, kTypeError, nullptr); +// } +// } /*********************************************************************************************\ * Native functions mapped to Berry functions @@ -68,34 +68,45 @@ extern "C" { * \*********************************************************************************************/ extern "C" { - // Berry: `tasmota.publish(topic, payload [,retain]) -> nil`` + // Berry: `tasmota.publish(topic, payload [, retain:bool, start:int, len:int]) -> nil`` // int32_t l_publish(struct bvm *vm); int32_t l_publish(struct bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments - if (top >= 3 && be_isstring(vm, 2) && (be_isstring(vm, 3) || be_isinstance(vm, 3))) { // 2 mandatory string arguments - if (top == 3 || (top == 4 && be_isbool(vm, 4))) { // 3rd optional argument must be bool - const char * topic = be_tostring(vm, 2); - const char * payload = nullptr; - size_t payload_len = 0; - if (be_isstring(vm, 3)) { - payload = be_tostring(vm, 3); - payload_len = strlen(payload); - } else { - be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */ - if (be_isderived(vm, 3)) { - payload = (const char *) be_tobytes(vm, 3, &payload_len); - } - } - bool retain = false; - if (top == 4) { - retain = be_tobool(vm, 4); - } - if (!payload) { be_raise(vm, "value_error", "Empty payload"); } - be_pop(vm, be_top(vm)); - MqttPublishPayload(topic, payload, payload_len, retain); - be_return_nil(vm); // Return + if (top >= 3 && be_isstring(vm, 2) && (be_isstring(vm, 3) || be_isbytes(vm, 3))) { // 2 mandatory string arguments + bool retain = false; + int32_t payload_start = 0; + int32_t len = -1; // send all of it + if (top >= 4) { retain = be_tobool(vm, 4); } + if (top >= 5) { + payload_start = be_toint(vm, 5); + if (payload_start < 0) payload_start = 0; } + if (top >= 6) { len = be_toint(vm, 6); } + const char * topic = be_tostring(vm, 2); + const char * payload = nullptr; + size_t payload_len = 0; + + if (be_isstring(vm, 3)) { + payload = be_tostring(vm, 3); + payload_len = strlen(payload); + } else { + payload = (const char *) be_tobytes(vm, 3, &payload_len); + } + if (!payload) { be_raise(vm, "value_error", "Empty payload"); } + + // adjust start and len + if (payload_start >= payload_len) { len = 0; } // send empty packet + else if (len < 0) { len = payload_len - payload_start; } // send all packet, adjust len + else if (payload_start + len > payload_len) { len = payload_len - payload_start; } // len is too long, adjust + // adjust start + payload = payload + payload_start; + + be_pop(vm, be_top(vm)); // clear stack to avoid any indirect warning message in subsequent calls to Berry + + MqttPublishPayload(topic, payload, len, retain); + + be_return_nil(vm); // Return } be_raise(vm, kTypeError, nullptr); } @@ -181,10 +192,10 @@ extern "C" { int32_t top = be_top(vm); // Get the number of arguments if (top == 1) { // no argument (instance only) be_newobject(vm, "map"); - map_insert_int(vm, "utc", Rtc.utc_time); - map_insert_int(vm, "local", Rtc.local_time); - map_insert_int(vm, "restart", Rtc.restart_time); - map_insert_int(vm, "timezone", Rtc.time_timezone); + be_map_insert_int(vm, "utc", Rtc.utc_time); + be_map_insert_int(vm, "local", Rtc.local_time); + be_map_insert_int(vm, "restart", Rtc.restart_time); + be_map_insert_int(vm, "timezone", Rtc.time_timezone); be_pop(vm, 1); be_return(vm); } @@ -198,14 +209,21 @@ extern "C" { int32_t top = be_top(vm); // Get the number of arguments if (top == 1) { // no argument (instance only) be_newobject(vm, "map"); - map_insert_int(vm, "flash", ESP.getFlashChipSize() / 1024); - map_insert_int(vm, "program", ESP_getSketchSize() / 1024); - map_insert_int(vm, "program_free", ESP.getFreeSketchSpace() / 1024); - map_insert_int(vm, "heap_free", ESP_getFreeHeap() / 1024); - map_insert_int(vm, "frag", ESP_getHeapFragmentation()); + be_map_insert_int(vm, "flash", ESP.getFlashChipSize() / 1024); + be_map_insert_int(vm, "program", ESP_getSketchSize() / 1024); + be_map_insert_int(vm, "program_free", ESP.getFreeSketchSpace() / 1024); + be_map_insert_int(vm, "heap_free", ESP_getFreeHeap() / 1024); + be_map_insert_int(vm, "frag", ESP_getHeapFragmentation()); + // give info about stack size + be_map_insert_int(vm, "stack_size", SET_ESP32_STACK_SIZE / 1024); + be_map_insert_int(vm, "stack_low", uxTaskGetStackHighWaterMark(nullptr) / 1024); if (UsePSRAM()) { - map_insert_int(vm, "psram", ESP.getPsramSize() / 1024); - map_insert_int(vm, "psram_free", ESP.getFreePsram() / 1024); + be_map_insert_int(vm, "psram", ESP.getPsramSize() / 1024); + be_map_insert_int(vm, "psram_free", ESP.getFreePsram() / 1024); + } else { + // IRAM information + int32_t iram_free = (int32_t)heap_caps_get_free_size(MALLOC_CAP_32BIT) - (int32_t)heap_caps_get_free_size(MALLOC_CAP_8BIT); + be_map_insert_int(vm, "iram_free", iram_free / 1024); } be_pop(vm, 1); be_return(vm); @@ -222,17 +240,17 @@ extern "C" { be_newobject(vm, "map"); if (Settings->flag4.network_wifi) { int32_t rssi = WiFi.RSSI(); - map_insert_int(vm, "rssi", rssi); - map_insert_int(vm, "quality", WifiGetRssiAsQuality(rssi)); + be_map_insert_int(vm, "rssi", rssi); + be_map_insert_int(vm, "quality", WifiGetRssiAsQuality(rssi)); #if LWIP_IPV6 String ipv6_addr = WifiGetIPv6(); if (ipv6_addr != "") { - map_insert_str(vm, "ip6", ipv6_addr.c_str()); + be_map_insert_str(vm, "ip6", ipv6_addr.c_str()); } #endif if (static_cast(WiFi.localIP()) != 0) { - map_insert_str(vm, "mac", WiFi.macAddress().c_str()); - map_insert_str(vm, "ip", WiFi.localIP().toString().c_str()); + be_map_insert_str(vm, "mac", WiFi.macAddress().c_str()); + be_map_insert_str(vm, "ip", WiFi.localIP().toString().c_str()); } } be_pop(vm, 1); @@ -250,8 +268,8 @@ extern "C" { be_newobject(vm, "map"); #ifdef USE_ETHERNET if (static_cast(EthernetLocalIP()) != 0) { - map_insert_str(vm, "mac", EthernetMacAddress().c_str()); - map_insert_str(vm, "ip", EthernetLocalIP().toString().c_str()); + be_map_insert_str(vm, "mac", EthernetMacAddress().c_str()); + be_map_insert_str(vm, "ip", EthernetLocalIP().toString().c_str()); } #endif be_pop(vm, 1); @@ -262,14 +280,14 @@ extern "C" { static void l_push_time(bvm *vm, struct tm *t, const char *unparsed) { be_newobject(vm, "map"); - map_insert_int(vm, "year", t->tm_year + 1900); - map_insert_int(vm, "month", t->tm_mon + 1); - map_insert_int(vm, "day", t->tm_mday); - map_insert_int(vm, "hour", t->tm_hour); - map_insert_int(vm, "min", t->tm_min); - map_insert_int(vm, "sec", t->tm_sec); - map_insert_int(vm, "weekday", t->tm_wday); - if (unparsed) map_insert_str(vm, "unparsed", unparsed); + be_map_insert_int(vm, "year", t->tm_year + 1900); + be_map_insert_int(vm, "month", t->tm_mon + 1); + be_map_insert_int(vm, "day", t->tm_mday); + be_map_insert_int(vm, "hour", t->tm_hour); + be_map_insert_int(vm, "min", t->tm_min); + be_map_insert_int(vm, "sec", t->tm_sec); + be_map_insert_int(vm, "weekday", t->tm_wday); + if (unparsed) be_map_insert_str(vm, "unparsed", unparsed); be_pop(vm, 1); } @@ -332,27 +350,14 @@ extern "C" { // ESP object int32_t l_yield(bvm *vm); int32_t l_yield(bvm *vm) { - BrTimeoutYield(); // reset timeout - be_return_nil(vm); + return be_call_c_func(vm, (void*) &BrTimeoutYield, NULL, "-"); } // Berry: tasmota.scale_uint(int * 5) -> int // int32_t l_scaleuint(struct bvm *vm); int32_t l_scaleuint(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 6 && be_isint(vm, 2) && be_isint(vm, 3) && be_isint(vm, 4) && be_isint(vm, 5) && be_isint(vm, 6)) { // only 1 argument of type string accepted - int32_t v = be_toint(vm, 2); - int32_t from1 = be_toint(vm, 3); - int32_t from2 = be_toint(vm, 4); - int32_t to1 = be_toint(vm, 5); - int32_t to2 = be_toint(vm, 6); - - int32_t ret = changeUIntScale(v, from1, from2, to1, to2); - be_pushint(vm, ret); - be_return(vm); - } - be_raise(vm, kTypeError, nullptr); + return be_call_c_func(vm, (void*) &changeUIntScale, "i", "-iiiii"); } int32_t l_respCmnd(bvm *vm); @@ -379,20 +384,17 @@ extern "C" { int32_t l_respCmndDone(bvm *vm); int32_t l_respCmndDone(bvm *vm) { - ResponseCmndDone(); - be_return_nil(vm); + return be_call_c_func(vm, (void*) &ResponseCmndDone, NULL, "-"); } int32_t l_respCmndError(bvm *vm); int32_t l_respCmndError(bvm *vm) { - ResponseCmndError(); - be_return_nil(vm); + return be_call_c_func(vm, (void*) &ResponseCmndError, NULL, "-"); } int32_t l_respCmndFailed(bvm *vm); int32_t l_respCmndFailed(bvm *vm) { - ResponseCmndFailed(); - be_return_nil(vm); + return be_call_c_func(vm, (void*) &ResponseCmndFailed, NULL, "-"); } // update XdrvMailbox.command with actual command @@ -634,6 +636,16 @@ extern "C" { if (len+3 > LOGSZ) { strcat(log_data, "..."); } // Actual data is more berry_log(log_data); } + + void tasmota_log_C(int32_t loglevel, const char * berry_buf, ...) { + va_list arg; + va_start(arg, berry_buf); + char* log_data = ext_vsnprintf_malloc_P(berry_buf, arg); + va_end(arg); + if (log_data == nullptr) { return; } + AddLogData(loglevel, log_data); + free(log_data); + } } #endif // USE_BERRY diff --git a/tasmota/xdrv_52_3_berry_tasmota_global.ino b/tasmota/xdrv_52_3_berry_tasmota_global.ino index e5f3bad46..a3ebc17f1 100644 --- a/tasmota/xdrv_52_3_berry_tasmota_global.ino +++ b/tasmota/xdrv_52_3_berry_tasmota_global.ino @@ -33,10 +33,11 @@ extern "C" { extern const be_ctypes_structure_t be_tasmota_global_struct = { sizeof(TasmotaGlobal), /* size in bytes */ - 2, /* number of elements */ + 3, /* number of elements */ nullptr, - (const be_ctypes_structure_item_t[2]) { + (const be_ctypes_structure_item_t[3]) { { "devices_present", offsetof(TasmotaGlobal_t, devices_present), 0, 0, ctypes_u8, 0 }, + { "fast_loop_enabled", offsetof(TasmotaGlobal_t, berry_fast_loop_enabled), 0, 0, ctypes_u8, 0 }, { "sleep", offsetof(TasmotaGlobal_t, sleep), 0, 0, ctypes_u8, 0 }, }}; diff --git a/tasmota/xdrv_52_3_berry_unishox.ino b/tasmota/xdrv_52_3_berry_unishox.ino deleted file mode 100644 index c2ca1b5e7..000000000 --- a/tasmota/xdrv_52_3_berry_unishox.ino +++ /dev/null @@ -1,94 +0,0 @@ -/* - xdrv_52_3_berry_unishox.ino - Berry scripting language, native fucnctions - - Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry - - This program 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 . -*/ - - -#ifdef USE_BERRY - -#include - -#ifdef USE_UNISHOX_COMPRESSION - -extern Unishox compressor; - -/*********************************************************************************************\ - * Native functions mapped to Berry functions - * - * import unishox - * - * -\*********************************************************************************************/ -extern "C" { - - int be_ntv_unishox_compress(bvm *vm); - int be_ntv_unishox_compress(bvm *vm) { - int32_t argc = be_top(vm); // Get the number of arguments - if (argc == 1 && be_isstring(vm, 1)) { - const char * s = be_tostring(vm, 1); - // do a dry-run to know the compressed size - int32_t compressed_size = compressor.unishox_compress(s, strlen(s), (char*) nullptr, 0); - if (compressed_size < 0) { - be_raise(vm, "internal_error", nullptr); - } - void * buf = be_pushbytes(vm, NULL, compressed_size); - if (compressed_size > 0) { - int32_t ret = compressor.unishox_compress(s, strlen(s), (char*) buf, compressed_size+5); // We expand by 4 the buffer size to avoid an error, but we are sure it will not overflow (see unishox implementation) - if (ret < 0 || ret != compressed_size) { - be_raisef(vm, "internal_error", "unishox size=%i ret=%i", compressed_size, ret); - } - } - be_return(vm); - } - be_raise(vm, kTypeError, nullptr); - } - - int be_ntv_unishox_decompress(bvm *vm); - int be_ntv_unishox_decompress(bvm *vm) { - int32_t argc = be_top(vm); // Get the number of arguments - if (argc == 1 && be_isbytes(vm, 1)) { - size_t len; - const void * buf = be_tobytes(vm, 1, &len); - if (len == 0) { - be_pushstring(vm, ""); - } else { - int32_t decomp_size = compressor.unishox_decompress((const char*)buf, len, (char*) nullptr, 0); - if (decomp_size < 0) { - be_raise(vm, "internal_error", nullptr); - } - if (decomp_size == 0) { - be_pushstring(vm, ""); - } else { - void * buf_out = be_pushbuffer(vm, decomp_size); - int32_t ret = compressor.unishox_decompress((const char*)buf, len, (char*) buf_out, decomp_size); - if (ret < 0 || ret != decomp_size) { - be_raisef(vm, "internal_error", "unishox size=%i ret=%i", decomp_size, ret); - } - be_pushnstring(vm, (const char*) buf_out, decomp_size); - } - } - be_return(vm); - } - be_raise(vm, kTypeError, nullptr); - } - -} - - -#endif // USE_UNISHOX_COMPRESSION - -#endif // USE_BERRY diff --git a/tasmota/xdrv_52_3_berry_webclient.ino b/tasmota/xdrv_52_3_berry_webclient.ino index 5c1700ebf..71b0aaab4 100644 --- a/tasmota/xdrv_52_3_berry_webclient.ino +++ b/tasmota/xdrv_52_3_berry_webclient.ino @@ -57,7 +57,7 @@ String wc_UrlEncode(const String& text) { /*********************************************************************************************\ * Int constants *********************************************************************************************/ -// const be_constint_t webserver_constants[] = { +// const be_const_member_t webserver_constants[] = { // { "BUTTON_CONFIGURATION", BUTTON_CONFIGURATION }, // { "BUTTON_INFORMATION", BUTTON_INFORMATION }, // { "BUTTON_MAIN", BUTTON_MAIN }, @@ -325,10 +325,17 @@ extern "C" { int32_t wc_tcp_read(struct bvm *vm); int32_t wc_tcp_read(struct bvm *vm) { WiFiClient * tcp = wc_getwificlient(vm); + int32_t max_read = -1; // by default read as much as we can + if (be_top(vm) >= 2 && be_isint(vm, 2)) { + max_read = be_toint(vm, 2); + } int32_t btr = tcp->available(); if (btr <= 0) { be_pushstring(vm, ""); } else { + if ((max_read >= 0) && (btr > max_read)) { + btr = max_read; + } char * buf = (char*) be_pushbuffer(vm, btr); int32_t btr2 = tcp->read((uint8_t*) buf, btr); be_pushnstring(vm, buf, btr2); @@ -340,10 +347,17 @@ extern "C" { int32_t wc_tcp_readbytes(struct bvm *vm); int32_t wc_tcp_readbytes(struct bvm *vm) { WiFiClient * tcp = wc_getwificlient(vm); + int32_t max_read = -1; // by default read as much as we can + if (be_top(vm) >= 2 && be_isint(vm, 2)) { + max_read = be_toint(vm, 2); + } int32_t btr = tcp->available(); if (btr <= 0) { be_pushbytes(vm, nullptr, 0); } else { + if ((max_read >= 0) && (btr > max_read)) { + btr = max_read; + } uint8_t * buf = (uint8_t*) be_pushbuffer(vm, btr); int32_t btr2 = tcp->read(buf, btr); be_pushbytes(vm, buf, btr2); diff --git a/tasmota/xdrv_52_3_berry_webserver.ino b/tasmota/xdrv_52_3_berry_webserver.ino index 2faa223ba..00f260d5a 100644 --- a/tasmota/xdrv_52_3_berry_webserver.ino +++ b/tasmota/xdrv_52_3_berry_webserver.ino @@ -27,7 +27,7 @@ /*********************************************************************************************\ * Int constants *********************************************************************************************/ -const be_constint_t webserver_constants[] = { +const be_const_member_t webserver_constants[] = { { "BUTTON_CONFIGURATION", BUTTON_CONFIGURATION }, { "BUTTON_INFORMATION", BUTTON_INFORMATION }, { "BUTTON_MAIN", BUTTON_MAIN }, @@ -51,7 +51,7 @@ extern "C" { if (argc == 1 && be_isstring(vm, 1)) { const char * needle = be_tostring(vm, 1); - int32_t constant_idx = bin_search(needle, &webserver_constants[0].name, sizeof(webserver_constants[0]), ARRAY_SIZE(webserver_constants)); + int32_t constant_idx = be_map_bin_search(needle, &webserver_constants[0].name, sizeof(webserver_constants[0]), ARRAY_SIZE(webserver_constants)); if (constant_idx >= 0) { // we did have a match, low == high diff --git a/tasmota/xdrv_52_7_berry_embedded.ino b/tasmota/xdrv_52_7_berry_embedded.ino index cbf933d07..95eddb375 100644 --- a/tasmota/xdrv_52_7_berry_embedded.ino +++ b/tasmota/xdrv_52_7_berry_embedded.ino @@ -50,6 +50,7 @@ const char berry_prog[] = #ifdef USE_LVGL "import lv " + "import lv_tasmota " // create the '_lvgl' global singleton "_lvgl = LVGL_glob() " diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino index 84a4f698c..3435053d5 100644 --- a/tasmota/xdrv_52_9_berry.ino +++ b/tasmota/xdrv_52_9_berry.ino @@ -23,6 +23,7 @@ #define XDRV_52 52 #include +#include "berry_tasmota.h" #include "be_vm.h" #include "ZipReadFS.h" @@ -50,7 +51,7 @@ void checkBeTop(void) { int32_t top = be_top(berry.vm); if (top != 0) { be_pop(berry.vm, top); // TODO should not be there - AddLog(LOG_LEVEL_ERROR, D_LOG_BERRY "Error be_top is non zero=%d", top); + AddLog(LOG_LEVEL_DEBUG, D_LOG_BERRY "Error be_top is non zero=%d", top); } } @@ -83,6 +84,29 @@ extern "C" { } #endif // USE_BERRY_PSRAM + + void *berry_malloc32(uint32_t size) { + #ifdef USE_BERRY_IRAM + return special_malloc32(size); + #else + return special_malloc(size); + #endif + } + void *berry_realloc32(void *ptr, size_t size) { + #ifdef USE_BERRY_IRAM + return special_realloc32(ptr, size); + #else + return special_realloc(ptr, size); + #endif + } + void *berry_calloc32(size_t num, size_t size) { + #ifdef USE_BERRY_IRAM + return special_calloc32(num, size); + #else + return special_calloc(num, size); + #endif + } + void berry_free(void *ptr) { free(ptr); } @@ -110,93 +134,6 @@ size_t callBerryGC(void) { return callBerryEventDispatcher(PSTR("gc"), nullptr, 0, nullptr); } -void BerryDumpErrorAndClear(bvm *vm, bool berry_console); -void BerryDumpErrorAndClear(bvm *vm, bool berry_console) { - int32_t top = be_top(vm); - // check if we have two strings for an Exception - if (top >= 2 && be_isstring(vm, -1) && be_isstring(vm, -2)) { - if (berry_console) { - berry_log_C(PSTR(D_LOG_BERRY "Exception> '%s' - %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1)); - be_tracestack(vm); - top = be_top(vm); // update top after dump - } else { - AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_BERRY "Exception> '%s' - %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1)); - be_tracestack(vm); - } - } else { - be_dumpstack(vm); - } -} - -// void callBerryMqttData(void) { -// AddLog(LOG_LEVEL_INFO, D_LOG_BERRY "callBerryMqttData"); -// if (nullptr == berry.vm) { return; } -// if (XdrvMailbox.data_len < 1) { -// return; -// } -// const char * topic = XdrvMailbox.topic; -// const char * payload = XdrvMailbox.data; - -// checkBeTop(); -// be_getglobal(berry.vm, "mqtt_data_dispatch"); -// if (!be_isnil(berry.vm, -1)) { -// be_pushstring(berry.vm, topic); -// be_pushstring(berry.vm, payload); -// be_pcall(berry.vm, 0); -// be_pop(berry.vm, 3); // remove function object -// } else { -// be_pop(berry.vm, 1); // remove nil object -// } -// checkBeTop(); -// } - -/* -// Call a method of a global object, with n args -// Before: stack must containt n args -// After: stack contains return value or nil if something wrong (args removes) -// returns true is successful, false if object or method not found -bool callMethodObjectWithArgs(const char * objname, const char * method, size_t argc) { - if (nullptr == berry.vm) { return false; } - int32_t top = be_top(berry.vm); - // stacks contains n x arg - be_getglobal(berry.vm, objname); - // stacks contains n x arg + object - if (!be_isnil(berry.vm, -1)) { - be_getmethod(berry.vm, -1, method); - // stacks contains n x arg + object + method - if (!be_isnil(berry.vm, -1)) { - // reshuffle the entire stack since we want: method + object + n x arg - be_pushvalue(berry.vm, -1); // add instance as first arg - // stacks contains n x arg + object + method + method - be_pushvalue(berry.vm, -3); // add instance as first arg - // stacks contains n x arg + object + method + method + object - // now move args 2 slots up to make room for method and object - for (uint32_t i = 1; i <= argc; i++) { - be_moveto(berry.vm, -4 - i, -2 - i); - } - // stacks contains free + free + n x arg + method + object - be_moveto(berry.vm, -2, -4 - argc); - be_moveto(berry.vm, -1, -3 - argc); - // stacks contains method + object + n x arg + method + object - be_pop(berry.vm, 2); - // stacks contains method + object + n x arg - be_pcall(berry.vm, argc + 1); - // stacks contains return_val + object + n x arg - be_pop(berry.vm, argc + 1); - // stacks contains return_val - return true; - } - be_pop(berry.vm, 1); // remove method - // stacks contains n x arg + object - } - // stacks contains n x arg + object - be_pop(berry.vm, argc + 1); // clear stack - be_pushnil(berry.vm); // put nil object - return false; -} -*/ - - // call the event dispatcher from Tasmota object // if data_len is non-zero, the event is also sent as raw `bytes()` object because the string may lose data int32_t callBerryEventDispatcher(const char *type, const char *cmd, int32_t idx, const char *payload, uint32_t data_len) { @@ -224,8 +161,7 @@ int32_t callBerryEventDispatcher(const char *type, const char *cmd, int32_t idx, } BrTimeoutReset(); if (ret != 0) { - BerryDumpErrorAndClear(vm, false); // log in Tasmota console only - be_pop_all(berry.vm); // clear Berry stack + be_error_pop_all(berry.vm); // clear Berry stack return ret; } be_pop(vm, 5); @@ -241,6 +177,29 @@ int32_t callBerryEventDispatcher(const char *type, const char *cmd, int32_t idx, return ret; } +// Simplified version of event loop. Just call `tasmota.fast_loop()` +void callBerryFastLoop(void) { + bvm *vm = berry.vm; + + if (nullptr == vm) { return; } + + if (be_getglobal(vm, "tasmota")) { + if (be_getmethod(vm, -1, "fast_loop")) { + be_pushvalue(vm, -2); // add instance as first arg + BrTimeoutStart(); + int32_t ret = be_pcall(vm, 1); + if (ret != 0) { + be_error_pop_all(berry.vm); // clear Berry stack + } + BrTimeoutReset(); + be_pop(vm, 1); + } + be_pop(vm, 1); // remove method + } + be_pop(vm, 1); // remove instance object + be_pop(vm, be_top(vm)); // clean +} + /*********************************************************************************************\ * VM Observability \*********************************************************************************************/ @@ -252,6 +211,17 @@ void BerryObservability(bvm *vm, int event...) { static uint32_t gc_time = 0; switch (event) { + case BE_OBS_PCALL_ERROR: // error after be_pcall + { + int32_t top = be_top(vm); + // check if we have two strings for an Exception + if (top >= 2 && be_isstring(vm, -1) && be_isstring(vm, -2)) { + berry_log_C(PSTR(D_LOG_BERRY "Exception> '%s' - %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1)); + be_tracestack(vm); + } else { + be_dumpstack(vm); + } + } case BE_OBS_GC_START: { gc_time = millis(); @@ -264,7 +234,7 @@ void BerryObservability(bvm *vm, int event...) { uint32_t gc_elapsed = millis() - gc_time; uint32_t vm_scanned = va_arg(param, uint32_t); uint32_t vm_freed = va_arg(param, uint32_t); - AddLog(LOG_LEVEL_DEBUG, D_LOG_BERRY "GC from %i to %i bytes, objects freed %i/%i (in %d ms)", + AddLog(LOG_LEVEL_DEBUG_MORE, D_LOG_BERRY "GC from %i to %i bytes, objects freed %i/%i (in %d ms)", vm_usage, vm_usage2, vm_freed, vm_scanned, gc_elapsed); // make new threshold tighter when we reach high memory usage if (!UsePSRAM() && vm->gc.threshold > 20*1024) { @@ -276,7 +246,7 @@ void BerryObservability(bvm *vm, int event...) { { int32_t stack_before = va_arg(param, int32_t); int32_t stack_after = va_arg(param, int32_t); - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Stack resized from %i to %i bytes"), stack_before, stack_after); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_BERRY "Stack resized from %i to %i bytes"), stack_before, stack_after); } break; case BE_OBS_VM_HEARTBEAT: @@ -323,6 +293,7 @@ void BerryInit(void) { be_set_obs_hook(berry.vm, &BerryObservability); /* attach observability hook */ comp_set_named_gbl(berry.vm); /* Enable named globals in Berry compiler */ comp_set_strict(berry.vm); /* Enable strict mode in Berry compiler, equivalent of `import strict` */ + be_set_ctype_func_hanlder(berry.vm, be_call_ctype_func); be_load_custom_libs(berry.vm); // load classes and modules @@ -331,31 +302,28 @@ void BerryInit(void) { ret_code1 = be_loadstring(berry.vm, berry_prog); if (ret_code1 != 0) { - BerryDumpErrorAndClear(berry.vm, false); - be_pop_all(berry.vm); // clear Berry stack + be_error_pop_all(berry.vm); // clear Berry stack break; } // AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code loaded, RAM used=%u"), be_gc_memcount(berry.vm)); ret_code2 = be_pcall(berry.vm, 0); if (ret_code1 != 0) { - BerryDumpErrorAndClear(berry.vm, false); - be_pop_all(berry.vm); // clear Berry stack + be_error_pop_all(berry.vm); // clear Berry stack break; } // AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code ran, RAM used=%u"), be_gc_memcount(berry.vm)); if (be_top(berry.vm) > 1) { - BerryDumpErrorAndClear(berry.vm, false); - be_pop_all(berry.vm); // clear Berry stack + be_error_pop_all(berry.vm); // clear Berry stack } else { be_pop(berry.vm, 1); } - AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_BERRY "Berry initialized, RAM used=%u"), callBerryGC()); + AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_BERRY "Berry initialized, RAM used=%u bytes"), callBerryGC()); berry_init_ok = true; - // we generate a synthetic event `autoexec` + // we generate a synthetic event `autoexec` callBerryEventDispatcher(PSTR("preinit"), nullptr, 0, nullptr); - + // Run pre-init BrLoad("preinit.be"); // run 'preinit.be' if present } while (0); @@ -389,17 +357,16 @@ void BrLoad(const char * script_name) { BrTimeoutStart(); if (be_pcall(berry.vm, 1) != 0) { - BerryDumpErrorAndClear(berry.vm, false); - be_pop_all(berry.vm); // clear Berry stack + be_error_pop_all(berry.vm); // clear Berry stack return; } BrTimeoutReset(); bool loaded = be_tobool(berry.vm, -2); // did it succeed? be_pop(berry.vm, 2); if (loaded) { - AddLog(LOG_LEVEL_INFO, D_LOG_BERRY "successfully loaded '%s'", script_name); + AddLog(LOG_LEVEL_INFO, D_LOG_BERRY "Successfully loaded '%s'", script_name); } else { - AddLog(LOG_LEVEL_INFO, D_LOG_BERRY "no '%s'", script_name); + AddLog(LOG_LEVEL_DEBUG, D_LOG_BERRY "No '%s'", script_name); } } } @@ -437,10 +404,6 @@ void CmndBrRun(void) { } while (0); if (0 == ret_code) { - // AddLog(LOG_LEVEL_INFO, "run: top=%d", be_top(berry.vm)); - // AddLog(LOG_LEVEL_INFO, "run: type(1)=%s", be_typename(berry.vm, 1)); - // AddLog(LOG_LEVEL_INFO, "run: type(2)=%s", be_typename(berry.vm, 2)); - // code taken from REPL, look first at top, and if nil, look at return value // if (!be_isnil(berry.vm, 1)) { ret_val = be_tostring(berry.vm, 1); @@ -495,14 +458,7 @@ void BrREPLRun(char * cmd) { } } if (BE_EXCEPTION == ret_code) { - BerryDumpErrorAndClear(berry.vm, true); - be_pop_all(berry.vm); // clear Berry stack - // be_dumpstack(berry.vm); - // char exception_s[120]; - // ext_snprintf_P(exception_s, sizeof(exception_s), PSTR("%s: %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1)); - // berry.log.addString(exception_s, nullptr, "\n"); - // // AddLog(LOG_LEVEL_INFO, PSTR(">>> %s"), exception_s); - // be_pop(berry.vm, 2); + be_error_pop_all(berry.vm); // clear Berry stack } } while(0); @@ -711,9 +667,6 @@ void HandleBerryConsoleRefresh(void) void HandleBerryConsole(void) { if (!HttpCheckPriviledgedAccess()) { return; } - // int i=16; - // // AddLog(LOG_LEVEL_INFO, PSTR("Size = %d %d"), sizeof(LList_elt), sizeof(LList_elt)+12); - // LList_elt * elt = (LList_elt*) ::operator new(sizeof(LList_elt) + 12); if (Webserver->hasArg(F("c2"))) { // Console refresh requested HandleBerryConsoleRefresh(); @@ -733,38 +686,6 @@ void HandleBerryConsole(void) WSContentStop(); } -// void HandleBerryConsoleRefresh(void) -// { -// String svalue = Webserver->arg(F("c1")); -// if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) { -// // TODO run command and store result -// // AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), svalue.c_str()); -// // ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCONSOLE); -// } - -// char stmp[8]; -// WebGetArg(PSTR("c2"), stmp, sizeof(stmp)); -// uint32_t index = 0; // Initial start, dump all -// if (strlen(stmp)) { index = atoi(stmp); } - -// WSContentBegin(200, CT_PLAIN); -// WSContentSend_P(PSTR("%d}1%d}1"), TasmotaGlobal.log_buffer_pointer, Web.reset_web_log_flag); -// if (!Web.reset_web_log_flag) { -// index = 0; -// Web.reset_web_log_flag = true; -// } -// bool cflg = (index); -// char* line; -// size_t len; -// while (GetLog(Settings->weblog_level, &index, &line, &len)) { -// if (cflg) { WSContentSend_P(PSTR("\n")); } -// WSContentFlush(); -// Webserver->sendContent(line, len -1); -// cflg = true; -// } -// WSContentSend_P(PSTR("}1")); -// WSContentEnd(); -// } #endif // USE_WEBSERVER /*********************************************************************************************\ @@ -775,18 +696,17 @@ bool Xdrv52(uint8_t function) bool result = false; switch (function) { - // case FUNC_PRE_INIT: // we start Berry in pre_init so that other modules can call Berry in their init methods - // // case FUNC_INIT: - // BerryInit(); - // break; case FUNC_LOOP: if (!berry.autoexec_done) { - // we generate a synthetic event `autoexec` + // we generate a synthetic event `autoexec` callBerryEventDispatcher(PSTR("autoexec"), nullptr, 0, nullptr); BrLoad("autoexec.be"); // run autoexec.be at first tick, so we know all modules are initialized berry.autoexec_done = true; } + if (TasmotaGlobal.berry_fast_loop_enabled) { // call only if enabled at global level + callBerryFastLoop(); // call `tasmota.fast_loop()` optimized for minimal performance impact + } break; // Berry wide commands and events @@ -798,7 +718,7 @@ bool Xdrv52(uint8_t function) break; case FUNC_MQTT_DATA: result = callBerryEventDispatcher(PSTR("mqtt_data"), XdrvMailbox.topic, 0, XdrvMailbox.data, XdrvMailbox.data_len); - break; + break; case FUNC_COMMAND: result = DecodeCommand(kBrCommands, BerryCommand); if (!result) { @@ -813,6 +733,12 @@ bool Xdrv52(uint8_t function) case FUNC_EVERY_100_MSECOND: callBerryEventDispatcher(PSTR("every_100ms"), nullptr, 0, nullptr); break; + case FUNC_EVERY_200_MSECOND: + callBerryEventDispatcher(PSTR("every_200ms"), nullptr, 0, nullptr); + break; + case FUNC_EVERY_250_MSECOND: + callBerryEventDispatcher(PSTR("every_250ms"), nullptr, 0, nullptr); + break; case FUNC_EVERY_SECOND: callBerryEventDispatcher(PSTR("every_second"), nullptr, 0, nullptr); break; diff --git a/tasmota/xdrv_53_projector_ctrl.ino b/tasmota/xdrv_53_projector_ctrl.ino index 6e559b71e..1fd8f8446 100644 --- a/tasmota/xdrv_53_projector_ctrl.ino +++ b/tasmota/xdrv_53_projector_ctrl.ino @@ -112,7 +112,7 @@ projector_ctrl_pre_init(void) sc->sc_serial = new TasmotaSerial(Pin(GPIO_PROJECTOR_CTRL_RX), Pin(GPIO_PROJECTOR_CTRL_TX), 2); - if (!sc->sc_serial->begin(baudrate, 2)) { + if (!sc->sc_serial->begin(baudrate)) { AddLog(LOG_LEVEL_ERROR, PSTR(PROJECTOR_CTRL_LOGNAME ": unable to begin serial " "(baudrate %d)"), baudrate); goto del; diff --git a/tasmota/xdrv_54_lvgl.ino b/tasmota/xdrv_54_lvgl.ino index d36a8f098..6878ea1a8 100644 --- a/tasmota/xdrv_54_lvgl.ino +++ b/tasmota/xdrv_54_lvgl.ino @@ -32,14 +32,6 @@ #include "Adafruit_LvGL_Glue.h" -#ifdef USE_LVGL_PNG_DECODER - #include "lv_png.h" -#endif // USE_LVGL_PNG_DECODER - -#ifdef USE_LVGL_FREETYPE - #include "lv_freetype.h" -#endif // USE_LVGL_FREETYPE - Adafruit_LvGL_Glue * glue; // ************************************************** @@ -79,11 +71,13 @@ void lv_flush_callback(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *c uint16_t * pix = (uint16_t*) color_p; for (uint32_t i = 0; i < btw / 2; i++) (pix[i] = pix[i] << 8 | pix[i] >> 8); #endif - int32_t ret = glue->getScreenshotFile()->write((const uint8_t*) color_p, btw); - if (ret >= 0) { - btw -= ret; - } else { - btw = 0; // abort + if (btw > 0) { // if we had a previous error (ex disk full) don't try to write anymore + int32_t ret = glue->getScreenshotFile()->write((const uint8_t*) color_p, btw); + if (ret >= 0) { + btw -= ret; + } else { + btw = 0; // abort + } } } lv_disp_flush_ready(disp); @@ -354,7 +348,7 @@ void start_lvgl(const char * uconfig); void start_lvgl(const char * uconfig) { if (glue != nullptr) { - AddLog(LOG_LEVEL_INFO, D_LOG_LVGL " LVGL was already initialized"); + AddLog(LOG_LEVEL_INFO, D_LOG_LVGL "LVGL was already initialized"); return; } diff --git a/tasmota/xdrv_55_touch.ino b/tasmota/xdrv_55_touch.ino index 269f775af..d553f419c 100644 --- a/tasmota/xdrv_55_touch.ino +++ b/tasmota/xdrv_55_touch.ino @@ -31,6 +31,8 @@ bool FT5206_found = false; bool XPT2046_found = false; +int16_t raw_touch_xp; +int16_t raw_touch_yp; int16_t touch_xp; int16_t touch_yp; bool touched; @@ -43,7 +45,7 @@ bool touched; VButton *buttons[MAX_TOUCH_BUTTONS]; #endif -uint32_t Touch_Status(uint32_t sel) { +uint32_t Touch_Status(int32_t sel) { if (FT5206_found || XPT2046_found) { switch (sel) { case 0: @@ -52,6 +54,10 @@ uint32_t Touch_Status(uint32_t sel) { return touch_xp; case 2: return touch_yp; + case -1: // before calibration + return raw_touch_xp; + case -2: + return raw_touch_yp; } return 0; } else { @@ -127,22 +133,27 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) { #ifdef USE_FT5206 if (FT5206_found) { - touch_xp = FT5206_x(); - touch_yp = FT5206_y(); touched = FT5206_touched(); + if (touched) { + touch_xp = FT5206_x(); + touch_yp = FT5206_y(); + } } #endif // USE_FT5206 #ifdef USE_XPT2046 if (XPT2046_found) { - touch_xp = XPT2046_x(); - touch_yp = XPT2046_y(); touched = XPT2046_touched(); + if (touched) { + touch_xp = XPT2046_x(); + touch_yp = XPT2046_y(); + } } #endif // USE_XPT2046 + raw_touch_xp = touch_xp; + raw_touch_yp = touch_yp; if (touched) { - #ifdef USE_TOUCH_BUTTONS #ifdef USE_M5STACK_CORE2 // handle 3 built in touch buttons @@ -165,6 +176,7 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) { #endif // USE_TOUCH_BUTTONS rotconvert(&touch_xp, &touch_yp); + AddLog(LOG_LEVEL_DEBUG_MORE, "TS : touched x=%i y=%i (raw x=%i y=%i)", touch_xp, touch_yp, raw_touch_xp, raw_touch_yp); #ifdef USE_TOUCH_BUTTONS CheckTouchButtons(touched, touch_xp, touch_yp); @@ -182,6 +194,7 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) { } #endif // USE_M5STACK_CORE2 + rotconvert(&touch_xp, &touch_yp); // still do rot convert if not touched #ifdef USE_TOUCH_BUTTONS CheckTouchButtons(touched, touch_xp, touch_yp); #endif // USE_TOUCH_BUTTONS @@ -290,8 +303,8 @@ void CheckTouchButtons(bool touched, int16_t touch_x, int16_t touch_y) { } } } - touch_xp = 0; - touch_yp = 0; + raw_touch_xp = touch_xp = 0; + raw_touch_yp = touch_yp = 0; } } #endif // USE_TOUCH_BUTTONS @@ -317,9 +330,12 @@ bool Xdrv55(uint8_t function) { } return result; } -#else + +#else // #if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_TOUCH_BUTTONS) + // dummy for LVGL without a touch controller -uint32_t Touch_Status(uint32_t sel) { -return 0; +uint32_t Touch_Status(int32_t sel) { + return 0; } + #endif // #if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_TOUCH_BUTTONS) diff --git a/tasmota/xdrv_81_esp32_webcam.ino b/tasmota/xdrv_81_esp32_webcam.ino index dca8ec936..b89bc7930 100644 --- a/tasmota/xdrv_81_esp32_webcam.ino +++ b/tasmota/xdrv_81_esp32_webcam.ino @@ -26,7 +26,7 @@ * {"NAME":"AITHINKER CAM","GPIO":[4992,1,672,1,416,5088,1,1,1,6720,736,704,1,1,5089,5090,0,5091,5184,5152,0,5120,5024,5056,0,0,0,0,4928,1,5094,5095,5092,0,0,5093],"FLAG":0,"BASE":2} * * Supported commands: - * WcStream = Control streaming, 0 = stop, 1 = start + * WcInterrupt = Control streaming, 0 = stop, 1 = start * WcResolution = Set resolution 0 = FRAMESIZE_96X96, // 96x96 1 = FRAMESIZE_QQVGA, // 160x120 @@ -78,6 +78,7 @@ #define XDRV_81 81 +#include "cam_hal.h" #include "esp_camera.h" #include "sensor.h" #include "fb_gfx.h" @@ -162,10 +163,21 @@ struct { #endif // ENABLE_RTSPSERVER } Wc; - - /*********************************************************************************************/ +void WcInterrupt(uint32_t state) { + // Stop camera ISR if active to fix TG1WDT_SYS_RESET + if (!Wc.up) { return; } + + if (state) { + // Re-enable interrupts + cam_start(); + } else { + // Stop interrupts + cam_stop(); + } +} + bool WcPinUsed(void) { bool pin_used = true; for (uint32_t i = 0; i < MAX_WEBCAM_DATA; i++) { @@ -711,7 +723,7 @@ void HandleImageBasic(void) { if (Settings->webcam_config.stream) { if (!Wc.CamServer) { - WcStreamControl(); + WcInterruptControl(); } } @@ -871,7 +883,7 @@ uint32_t WcSetStreamserver(uint32_t flag) { return 0; } -void WcStreamControl() { +void WcInterruptControl() { WcSetStreamserver(Settings->webcam_config.stream); WcSetup(Settings->webcam_config.resolution); } @@ -880,6 +892,8 @@ void WcStreamControl() { void WcLoop(void) { + if (4 == Wc.stream_active) { return; } + if (Wc.CamServer) { Wc.CamServer->handleClient(); if (Wc.stream_active) { HandleWebcamMjpegTask(); } @@ -941,7 +955,7 @@ void WcShowStream(void) { if (Settings->webcam_config.stream) { // if (!Wc.CamServer || !Wc.up) { if (!Wc.CamServer) { - WcStreamControl(); + WcInterruptControl(); delay(50); // Give the webcam webserver some time to prepare the stream } if (Wc.CamServer && Wc.up) { @@ -1014,7 +1028,7 @@ void CmndWebcam(void) { void CmndWebcamStream(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { Settings->webcam_config.stream = XdrvMailbox.payload; - if (!Settings->webcam_config.stream) { WcStreamControl(); } // Stop stream + if (!Settings->webcam_config.stream) { WcInterruptControl(); } // Stop stream } ResponseCmndStateText(Settings->webcam_config.stream); } @@ -1068,7 +1082,7 @@ void CmndWebcamContrast(void) { } void CmndWebcamInit(void) { - WcStreamControl(); + WcInterruptControl(); ResponseCmndDone(); } diff --git a/tasmota/xdrv_82_esp32_ethernet.ino b/tasmota/xdrv_82_esp32_ethernet.ino index 1deb646b5..57d740b9a 100644 --- a/tasmota/xdrv_82_esp32_ethernet.ino +++ b/tasmota/xdrv_82_esp32_ethernet.ino @@ -83,6 +83,7 @@ #include char eth_hostname[sizeof(TasmotaGlobal.hostname)]; +uint8_t eth_config_change; void EthernetEvent(WiFiEvent_t event) { switch (event) { @@ -97,14 +98,16 @@ void EthernetEvent(WiFiEvent_t event) { case ARDUINO_EVENT_ETH_GOT_IP: AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: Mac %s, IPAddress %_I, Hostname %s"), ETH.macAddress().c_str(), (uint32_t)ETH.localIP(), eth_hostname); - Settings->ipv4_address[1] = (uint32_t)ETH.gatewayIP(); - Settings->ipv4_address[2] = (uint32_t)ETH.subnetMask(); - Settings->ipv4_address[3] = (uint32_t)ETH.dnsIP(); - Settings->ipv4_address[4] = (uint32_t)ETH.dnsIP(1); + Settings->eth_ipv4_address[1] = (uint32_t)ETH.gatewayIP(); + Settings->eth_ipv4_address[2] = (uint32_t)ETH.subnetMask(); + Settings->eth_ipv4_address[3] = (uint32_t)ETH.dnsIP(); + Settings->eth_ipv4_address[4] = (uint32_t)ETH.dnsIP(1); + TasmotaGlobal.rules_flag.eth_connected = 1; TasmotaGlobal.global_state.eth_down = 0; break; case ARDUINO_EVENT_ETH_DISCONNECTED: AddLog(LOG_LEVEL_INFO, PSTR("ETH: Disconnected")); + TasmotaGlobal.rules_flag.eth_disconnected = 1; TasmotaGlobal.global_state.eth_down = 1; break; case ARDUINO_EVENT_ETH_STOP: @@ -116,6 +119,11 @@ void EthernetEvent(WiFiEvent_t event) { } } +void EthernetSetIp(void) { + // IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2 + ETH.config(Settings->eth_ipv4_address[0], Settings->eth_ipv4_address[1], Settings->eth_ipv4_address[2], Settings->eth_ipv4_address[3], Settings->eth_ipv4_address[4]); // Set static IP +} + void EthernetInit(void) { if (!Settings->flag4.network_ethernet) { return; } if (!PinUsed(GPIO_ETH_PHY_MDC) && !PinUsed(GPIO_ETH_PHY_MDIO)) { @@ -123,6 +131,8 @@ void EthernetInit(void) { return; } + eth_config_change = 0; + if (WT32_ETH01 == TasmotaGlobal.module_type) { Settings->eth_address = 1; // EthAddress Settings->eth_type = ETH_PHY_LAN8720; // EthType @@ -140,7 +150,12 @@ void EthernetInit(void) { int eth_mdio = Pin(GPIO_ETH_PHY_MDIO); if (!ETH.begin(Settings->eth_address, eth_power, eth_mdc, eth_mdio, (eth_phy_type_t)Settings->eth_type, (eth_clock_mode_t)Settings->eth_clk_mode)) { AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: Bad PHY type or init error")); + return; }; + + if (Settings->eth_ipv4_address[0]) { + EthernetSetIp(); // Set static IP + } } IPAddress EthernetLocalIP(void) { @@ -155,22 +170,38 @@ String EthernetMacAddress(void) { return ETH.macAddress(); } +void EthernetConfigChange(void) { + if (eth_config_change) { + eth_config_change--; + if (!eth_config_change) { + EthernetSetIp(); + } + } +} + /*********************************************************************************************\ * Commands \*********************************************************************************************/ -#define D_CMND_ETHADDRESS "EthAddress" -#define D_CMND_ETHTYPE "EthType" -#define D_CMND_ETHCLOCKMODE "EthClockMode" +#define D_CMND_ETHADDRESS "Address" +#define D_CMND_ETHTYPE "Type" +#define D_CMND_ETHCLOCKMODE "ClockMode" +#define D_CMND_ETHIPADDRESS D_CMND_IPADDRESS +#define D_CMND_ETHGATEWAY D_JSON_GATEWAY +#define D_CMND_ETHNETMASK D_JSON_SUBNETMASK +#define D_CMND_ETHDNS D_JSON_DNSSERVER -const char kEthernetCommands[] PROGMEM = "|" // No prefix - D_CMND_ETHERNET "|" D_CMND_ETHADDRESS "|" D_CMND_ETHTYPE "|" D_CMND_ETHCLOCKMODE; +const char kEthernetCommands[] PROGMEM = "Eth|" // Prefix + "ernet|" D_CMND_ETHADDRESS "|" D_CMND_ETHTYPE "|" D_CMND_ETHCLOCKMODE "|" + D_CMND_ETHIPADDRESS "|" D_CMND_ETHGATEWAY "|" D_CMND_ETHNETMASK "|" D_CMND_ETHDNS ; void (* const EthernetCommand[])(void) PROGMEM = { - &CmndEthernet, &CmndEthAddress, &CmndEthType, &CmndEthClockMode }; + &CmndEthernet, &CmndEthAddress, &CmndEthType, &CmndEthClockMode, + &CmndEthSetIpConfig, &CmndEthSetIpConfig, &CmndEthSetIpConfig, &CmndEthSetIpConfig }; -void CmndEthernet(void) -{ +#define ETH_PARAM_OFFSET 4 // Offset of command index in above table of first CmndEthIpConfig + +void CmndEthernet(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { Settings->flag4.network_ethernet = XdrvMailbox.payload; TasmotaGlobal.restart_flag = 2; @@ -178,8 +209,7 @@ void CmndEthernet(void) ResponseCmndStateText(Settings->flag4.network_ethernet); } -void CmndEthAddress(void) -{ +void CmndEthAddress(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 31)) { Settings->eth_address = XdrvMailbox.payload; TasmotaGlobal.restart_flag = 2; @@ -187,8 +217,7 @@ void CmndEthAddress(void) ResponseCmndNumber(Settings->eth_address); } -void CmndEthType(void) -{ +void CmndEthType(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { Settings->eth_type = XdrvMailbox.payload; TasmotaGlobal.restart_flag = 2; @@ -196,8 +225,7 @@ void CmndEthType(void) ResponseCmndNumber(Settings->eth_type); } -void CmndEthClockMode(void) -{ +void CmndEthClockMode(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { Settings->eth_clk_mode = XdrvMailbox.payload; TasmotaGlobal.restart_flag = 2; @@ -205,6 +233,35 @@ void CmndEthClockMode(void) ResponseCmndNumber(Settings->eth_clk_mode); } +void CmndEthSetIpConfig(void) { + uint32_t param_id = XdrvMailbox.command_code -ETH_PARAM_OFFSET; + + char cmnd_idx[2] = { 0 }; + if (3 == param_id) { // EthDnsServer + if ((XdrvMailbox.index < 1) || (XdrvMailbox.index > 2)) { + XdrvMailbox.index = 1; + } + cmnd_idx[0] = '0' + XdrvMailbox.index; + param_id += XdrvMailbox.index -1; // EthDnsServer2 + } + + if (XdrvMailbox.data_len) { + uint32_t ipv4_address; + if (ParseIPv4(&ipv4_address, XdrvMailbox.data)) { + Settings->eth_ipv4_address[param_id] = ipv4_address; + eth_config_change = 2; + } + } + + char network_address[22] = { 0 }; + if (0 == param_id) { + if (!Settings->eth_ipv4_address[0]) { + ext_snprintf_P(network_address, sizeof(network_address), PSTR(" (%_I)"), (uint32_t)ETH.localIP()); + } + } + Response_P(PSTR("{\"%s%s\":\"%_I%s\"}"), XdrvMailbox.command, cmnd_idx, Settings->eth_ipv4_address[param_id], network_address); +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -213,6 +270,9 @@ bool Xdrv82(uint8_t function) { bool result = false; switch (function) { + case FUNC_EVERY_SECOND: + EthernetConfigChange(); + break; case FUNC_COMMAND: result = DecodeCommand(kEthernetCommands, EthernetCommand); break; diff --git a/tasmota/xdrv_85_BLE_EQ3_TRV.ino b/tasmota/xdrv_85_BLE_EQ3_TRV.ino index d69368268..d77d63e94 100644 --- a/tasmota/xdrv_85_BLE_EQ3_TRV.ino +++ b/tasmota/xdrv_85_BLE_EQ3_TRV.ino @@ -79,7 +79,12 @@ stat/EQ3/001A22092C9A = { "dst":"set", "window":"closed", "state":"unlocked", - "battery":"GOOD" + "battery":"GOOD", + "windowtemp": 12.0, + "windowdur": 15, + "day": 21.0, + "night": 17.0, + "offset": 0.0 } holiday: @@ -188,7 +193,8 @@ const char *cmdnames[] = { "day", "night", "reqprofile", - "setprofile" + "setprofile", + "lock", }; const uint8_t *macprefixes[1] = { @@ -206,7 +212,7 @@ struct eq3_device_tag{ int8_t RSSI; uint64_t timeoutTime; uint8_t pairing; - uint8_t lastStatus[10]; // last received 02 stat + uint8_t lastStatus[16]; // last received 02 stat uint8_t lastStatusLen; uint32_t lastStatusTime; // in utc uint8_t nextDiscoveryData; @@ -433,8 +439,8 @@ int EQ3ParseOp(BLE_ESP32::generic_sensor_t *op, bool success, int retries){ if (success){ if ((op->notifylen >= 6) && (op->dataNotify[0] == 2) && (op->dataNotify[1] == 1)){ if (eq3){ - memcpy(eq3->lastStatus, op->dataNotify, (op->notifylen <= 10)?op->notifylen:10); - eq3->lastStatusLen = (op->notifylen <= 10)?op->notifylen:10; + memcpy(eq3->lastStatus, op->dataNotify, (op->notifylen <= 10)?op->notifylen:16); + eq3->lastStatusLen = (op->notifylen <= 10)?op->notifylen:16; eq3->lastStatusTime = UtcTime(); } } @@ -504,6 +510,15 @@ int EQ3ParseOp(BLE_ESP32::generic_sensor_t *op, bool success, int retries){ status[6], hh, mm ); + + if (statlen >= 15) { + ResponseAppend_P(PSTR(",\"windowtemp\":%2.1f"), ((float)status[10])/2); + ResponseAppend_P(PSTR(",\"windowdur\":%d"), ((int)status[11])*5); + ResponseAppend_P(PSTR(",\"day\":%2.1f"), ((float)status[12])/2); + ResponseAppend_P(PSTR(",\"night\":%2.1f"), ((float)status[13])/2); + ResponseAppend_P(PSTR(",\"offset\":%2.1f"), ((float)status[14]-7) /2); + } + } if (success) { @@ -1216,7 +1231,7 @@ int EQ3Send(const uint8_t* addr, const char *cmd, char* param, char* param2, int if (!strcmp(cmd, "unboost")) { cmdtype = 10; d[0] = 0x45; d[1] = 0x00; dlen = 2; break; } - if (!strcmp(cmd, "lock")) { d[0] = 0x80; d[1] = 0x01; + if (!strcmp(cmd, "lock")) { cmdtype = 23; d[0] = 0x80; d[1] = 0x01; if (param && (!strcmp(param, "off") || param[0] == '0')){ d[1] = 0x00; } diff --git a/tasmota/xdrv_86_esp32_sonoff_spm.ino b/tasmota/xdrv_86_esp32_sonoff_spm.ino index dc770c7e4..225db6ccc 100644 --- a/tasmota/xdrv_86_esp32_sonoff_spm.ino +++ b/tasmota/xdrv_86_esp32_sonoff_spm.ino @@ -22,13 +22,13 @@ #ifdef ESP32 #ifdef USE_SONOFF_SPM /*********************************************************************************************\ - * Sonoff Stackable Power Manager (Current state: PROOF OF CONCEPT) + * Sonoff Stackable Power Manager + * + * {"NAME":"Sonoff SPM","GPIO":[0,0,0,0,3200,5536,0,0,0,0,0,0,3232,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,544,0,0,32,0,0,0,0],"FLAG":0,"BASE":1} * * Initial POC template: * {"NAME":"Sonoff SPM (POC1)","GPIO":[1,1,1,1,3200,1,1,1,1,1,1,1,3232,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,544,1,1,32,1,0,0,1],"FLAG":0,"BASE":1} * Add ethernet support: - * {"NAME":"Sonoff SPM (POC2)","GPIO":[1,0,1,0,3200,5536,0,0,1,1,1,0,3232,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,544,1,1,32,1,0,0,1],"FLAG":0,"BASE":1} - * Remove all user selectable GPIOs: * {"NAME":"Sonoff SPM (POC2)","GPIO":[0,0,0,0,3200,5536,0,0,0,0,0,0,3232,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,544,0,0,32,0,0,0,0],"FLAG":0,"BASE":1} * * Things to know: @@ -37,6 +37,8 @@ * Green led is controlled by ARM processor indicating SD-Card access. * ESP32 is used as interface between eWelink and ARM processor in SPM-Main unit communicating over proprietary serial protocol. * Power on sequence for two SPM-4Relay modules is 00-00-15-10-(0F)-(13)-(13)-(19)-0C-09-04-09-04-0B-0B + * Up to six months of daily energy are stored onthe SD-Card. Previous data is lost. + * Tasmota support is based on Sonoff SPM v1.0.0 ARM firmware. * * Tasmota POC1: * Up to 7 SPM-4Relay units supporting up to 28 relays. @@ -49,9 +51,13 @@ * Gui optimized for energy display. * Yellow led lights if no ARM connection can be made. * Yellow led blinks 2 seconds if an ARM-ESP comms CRC error is detected. + * Persistence for module mapping * Supported commands: * SspmDisplay 0|1 - Select alternative GUI rotating display either all or powered on only + * SspmHistory - Retrieve daily energy of last six month (as defined by ARM firmware) * SspmIAmHere - Blink ERROR in SPM-4Relay where relay resides + * SspmLog [x] - Retrieve relay power state change and cause logging + * SspmMap 2,3,1,.. - Map scanned module number to physical module number using positional numbering * SspmScan - Rescan ARM modbus taking around 20 seconds * SspmReset 1 - Reset ARM and restart ESP * @@ -69,9 +75,9 @@ * GPIO03 - Serial console RX * GPIO04 - ARM processor TX (115200bps8N1) * GPIO05 - ETH POWER - * GPIO12 - SPI MOSI ARM output (pin36 - PB15) - ESP input - * GPIO13 - SPI MISO ESP output - ARM input (pin35 - PB14) - * GPIO14 - SPI CLK ESP input (ARM pin34 - PB13) + * GPIO12 - SPI MISO to MOSI ARM output (pin36 - PB15) + * GPIO13 - SPI MOSI to MISO ARM input (pin35 - PB14) + * GPIO14 - SPI SCLK to ARM input (ARM pin34 - PB13) * GPIO15 - ARM reset (output) - 18ms low active 125ms after restart esp32 * GPIO16 - ARM processor RX * GPIO17 - EMAC_CLK_OUT_180 @@ -96,8 +102,12 @@ * relay = 0 to 127 Relays \*********************************************************************************************/ +#ifndef SSPM_JSON_ENERGY_TODAY #define SSPM_JSON_ENERGY_TODAY // Show JSON energy today +#endif +#ifndef SSPM_JSON_ENERGY_YESTERDAY #define SSPM_JSON_ENERGY_YESTERDAY // Show JSON energy yesterday +#endif /*********************************************************************************************\ * Fixed defines - Do not change @@ -140,6 +150,10 @@ /*********************************************************************************************/ +#define SSPM_TOTAL_MODULES 32 // Max number of SPM-4RELAY units for a total of 128 relays + +const uint32_t SSPM_VERSION = 0x01010103; // Latest driver version (See settings deltas below) + enum SspmMachineStates { SPM_NONE, // Do nothing SPM_WAIT, // Wait 100ms SPM_RESET, // Toggle ARM reset pin @@ -153,10 +167,21 @@ enum SspmMachineStates { SPM_NONE, // Do nothing SPM_UPDATE_CHANNELS // Update Energy for powered on channels }; +const char kSSPMTriggers[] PROGMEM = "Tasmota|Device|Overload|Overtemp"; + #include TasmotaSerial *SspmSerial; +// Global structure containing driver saved variables typedef struct { + uint32_t crc32; // To detect file changes + uint32_t version; // To detect driver function changes + uint16_t module_map[SSPM_TOTAL_MODULES]; // Max possible SPM relay modules + float energy_total[SSPM_TOTAL_MODULES][4]; // Total energy in kWh - float allows up to 262143.99 kWh +} tSspmSettings; + +typedef struct { + tSspmSettings Settings; float voltage[SSPM_MAX_MODULES][4]; // 123.12 V float current[SSPM_MAX_MODULES][4]; // 123.12 A float active_power[SSPM_MAX_MODULES][4]; // 123.12 W @@ -186,14 +211,146 @@ typedef struct { uint8_t mstate; uint8_t last_button; uint8_t error_led_blinks; + uint8_t yesterday; + uint8_t history_relay; + uint8_t log_relay; + bool map_change; bool discovery_triggered; } TSspm; uint8_t *SspmBuffer = nullptr; TSspm *Sspm = nullptr; +/*********************************************************************************************\ + * Driver Settings load and save using filesystem +\*********************************************************************************************/ + +uint32_t SSPMSettingsCrc32(void) { + // Use Tasmota CRC calculation function + return GetCfgCrc32((uint8_t*)&Sspm->Settings +4, sizeof(tSspmSettings) -4); // Skip crc32 +} + +void SSPMSettingsDefault(void) { + // Init default values in case file is not found + AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: SPM " D_USE_DEFAULTS)); + + memset(&Sspm->Settings, 0x00, sizeof(tSspmSettings)); + Sspm->Settings.version = SSPM_VERSION; + // Init any other parameter in struct SSPMSettings +} + +void SSPMSettingsDelta(void) { + // Fix possible setting deltas + if (Sspm->Settings.version != SSPM_VERSION) { // Fix version dependent changes + +// if (Settings->version < 0x01010101) { + +// } + + // Set current version and save settings + Sspm->Settings.version = SSPM_VERSION; + SSPMSettingsSave(); + } +} + +void SSPMSettingsLoad(void) { + // Init default values in case file is not found + SSPMSettingsDefault(); + + // Try to load file /.drvset086 + char filename[20]; + // Use for drivers: + snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_DRIVER), XDRV_86); + +#ifdef USE_UFILESYS + if (TfsLoadFile(filename, (uint8_t*)&Sspm->Settings, sizeof(tSspmSettings))) { + // Fix possible setting deltas + SSPMSettingsDelta(); + + AddLog(LOG_LEVEL_INFO, PSTR("CFG: SPM loaded from file")); + } else { + // File system not ready: No flash space reserved for file system + AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: SPM ERROR File system not ready or file not found")); + } +#else + AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: SPM ERROR File system not enabled")); +#endif // USE_UFILESYS + + Sspm->Settings.crc32 = SSPMSettingsCrc32(); +} + +void SSPMSettingsSave(void) { + // Called from FUNC_SAVE_SETTINGS every SaveData second and at restart + if (SSPMSettingsCrc32() != Sspm->Settings.crc32) { + // Try to save file /.drvset086 + Sspm->Settings.crc32 = SSPMSettingsCrc32(); + + char filename[20]; + // Use for drivers: + snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_DRIVER), XDRV_86); + +#ifdef USE_UFILESYS + if (TfsSaveFile(filename, (const uint8_t*)&Sspm->Settings, sizeof(tSspmSettings))) { + AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: SPM saved to file")); + } else { + // File system not ready: No flash space reserved for file system + AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: SPM ERROR File system not ready or unable to save file")); + } +#else + AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: SPM ERROR File system not enabled")); +#endif // USE_UFILESYS + } +} + /*********************************************************************************************/ +uint32_t SSMPGetModuleId(uint32_t module) { + // Return short module id + uint32_t module_id = 0; + if (module < Sspm->module_max) { + module_id = Sspm->module[module][0] << 8 | Sspm->module[module][1]; + } + return module_id; // 0 if not found, else first two bytes of module_id +} + +int SSPMGetMappedModuleIdIfFound(uint32_t module) { + // Return mapped module number + for (uint32_t module_nr = 0; module_nr < Sspm->module_max; module_nr++) { + if (Sspm->Settings.module_map[module] == SSMPGetModuleId(module_nr)) { + return module_nr; // 0, 1, .. + } + } + return -1; // -1 if not found +} + +uint32_t SSPMGetMappedModuleId(uint32_t module) { + // Return mapped module number + int module_nr = SSPMGetMappedModuleIdIfFound(module); + if (-1 == module_nr) { + module_nr = module; // input module number if not found used as fallback + } + return (uint32_t)module_nr; // 0, 1, ... +} + +int SSPMGetModuleNumberFromMapIfFound(uint32_t id) { + // Return module number based on first two bytes of module id + for (uint32_t module_nr = 0; module_nr < SSPM_MAX_MODULES; module_nr++) { + if (id == Sspm->Settings.module_map[module_nr]) { + return module_nr; // 0, 1, ... + } + } + return -1; // -1 if not found +} + +uint32_t SSPMGetModuleNumberFromMap(uint32_t id) { + // Return module number based on first two bytes of module id + int module_nr = SSPMGetModuleNumberFromMapIfFound(id); + if (-1 == module_nr) { + module_nr = 0; // 0 if not found used as fallback + } + return (uint32_t)module_nr; // 0, 1, ... +} + void SSPMSetLock(uint32_t seconds) { Sspm->timeout = seconds * 10; // Decremented every 100mSec Sspm->allow_updates = 0; // Disable requests from 100mSec loop @@ -211,6 +368,8 @@ uint16_t SSPMCalculateCRC(uint8_t *frame, uint32_t num) { return crc ^ 0; } +/*********************************************************************************************/ + void SSPMSend(uint32_t size) { uint16_t crc = SSPMCalculateCRC(SspmBuffer, size -2); SspmBuffer[size -2] = (uint8_t)(crc >> 8); @@ -303,7 +462,7 @@ void SSPMSendGetOps(uint32_t module) { Marker |Module id |Ac|Cm|Size |Ix|Chksm| */ SSPMInitSend(); - memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + memcpy(SspmBuffer +3, Sspm->module[SSPMGetMappedModuleId(module)], SSPM_MODULE_NAME_SIZE); SspmBuffer[16] = SSPM_FUNC_GET_OPS; // 0x04 Sspm->command_sequence++; SspmBuffer[19] = Sspm->command_sequence; @@ -323,7 +482,7 @@ void SSPMSendSetRelay(uint32_t relay, uint32_t state) { } uint8_t module = relay >> 2; SSPMInitSend(); - memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + memcpy(SspmBuffer +3, Sspm->module[SSPMGetMappedModuleId(module)], SSPM_MODULE_NAME_SIZE); SspmBuffer[16] = SSPM_FUNC_SET_RELAY; // 0x08 SspmBuffer[18] = 0x01; SspmBuffer[19] = channel; @@ -340,7 +499,7 @@ void SSPMSendGetModuleState(uint32_t module) { Marker |Module id |Ac|Cm|Size |Pl|Ix|Chksm| */ SSPMInitSend(); - memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + memcpy(SspmBuffer +3, Sspm->module[SSPMGetMappedModuleId(module)], SSPM_MODULE_NAME_SIZE); SspmBuffer[16] = SSPM_FUNC_GET_MODULE_STATE; // 0x09 SspmBuffer[18] = 0x01; SspmBuffer[19] = 0x0F; // State of all four relays @@ -407,7 +566,7 @@ void SSPMSendGetScheme(uint32_t module) { Marker |Module id |Ac|Cm|Size |Ix|Chksm| */ SSPMInitSend(); - memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + memcpy(SspmBuffer +3, Sspm->module[SSPMGetMappedModuleId(module)], SSPM_MODULE_NAME_SIZE); SspmBuffer[16] = SSPM_FUNC_GET_SCHEME; // 0x0B Sspm->command_sequence++; SspmBuffer[19] = Sspm->command_sequence; @@ -459,7 +618,7 @@ void SSPMSendIAmHere(uint32_t relay) { */ uint8_t module = relay >> 2; SSPMInitSend(); - memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + memcpy(SspmBuffer +3, Sspm->module[SSPMGetMappedModuleId(module)], SSPM_MODULE_NAME_SIZE); SspmBuffer[16] = SSPM_FUNC_IAMHERE; // 0x0D Sspm->command_sequence++; SspmBuffer[19] = Sspm->command_sequence; @@ -507,7 +666,7 @@ void SSPMSendGetEnergyTotal(uint32_t relay) { SSPMInitSend(); SspmBuffer[16] = SSPM_FUNC_GET_ENERGY_TOTAL; // 0x16 SspmBuffer[18] = 0x0D; - memcpy(SspmBuffer +19, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + memcpy(SspmBuffer +19, Sspm->module[SSPMGetMappedModuleId(module)], SSPM_MODULE_NAME_SIZE); SspmBuffer[31] = channel; Sspm->command_sequence++; SspmBuffer[32] = Sspm->command_sequence; @@ -527,7 +686,7 @@ void SSPMSendGetEnergy(uint32_t relay) { SSPMInitSend(); SspmBuffer[16] = SSPM_FUNC_GET_ENERGY; // 0x18 SspmBuffer[18] = 0x10; - memcpy(SspmBuffer +19, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + memcpy(SspmBuffer +19, Sspm->module[SSPMGetMappedModuleId(module)], SSPM_MODULE_NAME_SIZE); SspmBuffer[31] = 0x01; SspmBuffer[32] = channel; SspmBuffer[33] = 0; @@ -551,7 +710,7 @@ void SSPMSendGetLog(uint32_t relay, uint32_t entries) { SSPMInitSend(); SspmBuffer[16] = SSPM_FUNC_GET_LOG; // 0x1A SspmBuffer[18] = 0x10; - memcpy(SspmBuffer +19, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + memcpy(SspmBuffer +19, Sspm->module[SSPMGetMappedModuleId(module)], SSPM_MODULE_NAME_SIZE); SspmBuffer[31] = startlog >> 8; // MSB start log SspmBuffer[32] = startlog; // LSB start log SspmBuffer[33] = entries >> 8; // MSB end log @@ -565,12 +724,18 @@ void SSPMSendGetLog(uint32_t relay, uint32_t entries) { /*********************************************************************************************/ void SSPMHandleReceivedData(void) { - uint8_t command = SspmBuffer[16]; - bool ack = (0x80 == SspmBuffer[15]); - uint8_t command_sequence = SspmBuffer[19 + Sspm->expected_bytes]; + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 80 04 00 02 00 00 06 98 06 + Marker |Module id |Ac|Cm|Size | |Ix|Chksm| + */ + bool ack = (0x80 == SspmBuffer[15]); // Ac + uint32_t command = SspmBuffer[16]; // Cm + uint32_t expected_bytes = (SspmBuffer[17] << 8) + SspmBuffer[18]; // Size + uint32_t command_sequence = SspmBuffer[19 + expected_bytes]; // Ix // AddLog(LOG_LEVEL_DEBUG, PSTR("SPM: Rcvd ack %d, cmnd %d, seq %d, size %d"), -// ack, command, command_sequence, Sspm->expected_bytes); +// ack, command, command_sequence, expected_bytes); if (ack) { // Responses from ARM (Acked) @@ -581,7 +746,7 @@ void SSPMHandleReceivedData(void) { AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 01 00 00 fc 73 |Er| |St| */ - if ((1 == Sspm->expected_bytes) && (0 == SspmBuffer[19])) { + if ((1 == expected_bytes) && (0 == SspmBuffer[19])) { Sspm->mstate++; // Cycle to } break; @@ -597,7 +762,7 @@ void SSPMHandleReceivedData(void) { Marker |Module id |Ac|Cm|Size | |Ch|Ra|Max P |Min P |Max U |Min U |Max I |De|Ix|Chksm| | | | 4400W| 0.1W| 240V| 0.1V| 20A| | */ - if (0x02 == Sspm->expected_bytes) { + if (0x02 == expected_bytes) { } @@ -614,12 +779,13 @@ void SSPMHandleReceivedData(void) { AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 80 09 00 06 00 0f 01 01 01 01 05 fe 35 |OS|4RelayMasks| */ - if (0x06 == Sspm->expected_bytes) { + if (0x06 == expected_bytes) { // SspmBuffer[20] & 0x0F // Relays operational power_t current_state = SspmBuffer[20] >> 4; // Relays state power_t mask = 0x0000000F; for (uint32_t i = 0; i < Sspm->module_max; i++) { - if ((SspmBuffer[3] == Sspm->module[i][0]) && (SspmBuffer[4] == Sspm->module[i][1])) { + uint32_t module = SSPMGetMappedModuleId(i); + if ((SspmBuffer[3] == Sspm->module[module][0]) && (SspmBuffer[4] == Sspm->module[module][1])) { current_state <<= (i * 4); mask <<= (i * 4); TasmotaGlobal.power &= (POWER_MASK ^ mask); @@ -638,7 +804,7 @@ void SSPMHandleReceivedData(void) { AA 55 01 6b 7e 32 37 39 37 34 13 4b 35 36 37 80 0b 00 02 00 00 09 bb c7 |?? ??| */ - if (0x02 == Sspm->expected_bytes) { + if (0x02 == expected_bytes) { } Sspm->module_selected++; @@ -667,8 +833,12 @@ void SSPMHandleReceivedData(void) { /* 0x15 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 15 00 04 00 01 00 00 01 81 b1 - |?? ?? ?? ??| + |Ty|FwVersio| + | 0| 1.0.0| */ + AddLog(LOG_LEVEL_INFO, PSTR("SPM: Main type %d version %d.%d.%d found"), + SspmBuffer[19], SspmBuffer[20], SspmBuffer[21], SspmBuffer[22]); + Sspm->mstate = SPM_START_SCAN; break; case SSPM_FUNC_GET_ENERGY_TOTAL: @@ -689,28 +859,76 @@ void SSPMHandleReceivedData(void) { 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 67 46 */ - { - float energy_today = 0; - float energy_yesterday = 0; - float energy_total = 0; - uint32_t entries = (Sspm->expected_bytes - 22) / 2; - - for (uint32_t i = 0; i < entries; i++) { - float today_energy = SspmBuffer[41 + (i*2)] + (float)SspmBuffer[42 + (i*2)] / 100; // x.xxkWh - if (112.30 == today_energy) { today_energy = 0; } // Unknown why sometimes 0x701E (=112.30kWh) pops up - if (0 == i) { energy_today = today_energy; } - if (1 == i) { energy_yesterday = today_energy; } - energy_total += today_energy; + if (expected_bytes < 24) { + AddLog(LOG_LEVEL_DEBUG, PSTR("SPM: History error%d"), SspmBuffer[19]); + } else { + uint32_t entries = (expected_bytes - 22) / 2; + // Find last valid (= non-zero) entry in 6 month fifo buffer + uint16_t energy = 0; + while (!energy && --entries) { + energy = SspmBuffer[41 + (entries *2)] + SspmBuffer[42 + (entries *2)]; + if (0x701E == energy) { energy = 0; } // Unknown why sometimes 0x701E (=112.30kWh) pops up } + uint32_t channel = SspmBuffer[32]; - for (uint32_t module = 0; module < Sspm->module_max; module++) { - if ((SspmBuffer[20] == Sspm->module[module][0]) && (SspmBuffer[21] == Sspm->module[module][1])) { - Sspm->energy_today[module][channel] = energy_today; - Sspm->energy_yesterday[module][channel] = energy_yesterday; - Sspm->energy_total[module][channel] = energy_total; // x.xxkWh - break; + uint32_t module = SSPMGetModuleNumberFromMap(SspmBuffer[20] << 8 | SspmBuffer[21]); +/* + if (!module && !channel) { + AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: SSPMHistory1 '%50_H'"), SspmBuffer); + } +*/ + if (Sspm->history_relay < 255) { + uint32_t history_module = Sspm->history_relay >> 2; + uint32_t history_channel = Sspm->history_relay & 0x03; // Channel relays are NOT bit masked this time + if ((history_channel == channel) && (history_module == module)) { + Response_P(PSTR("{\"SSPMHistory%d\":["), Sspm->history_relay +1); + } else { + Sspm->history_relay = 255; } } + + float last_energy_today = Sspm->energy_yesterday[module][channel]; + float energy_total = 0; + for (uint32_t i = 0; i <= entries; i++) { + float energy = SspmBuffer[41 + (i*2)] + (float)SspmBuffer[42 + (i*2)] / 100; // x.xxkWh + if (112.30 == energy) { energy = 0; } // Unknown why sometimes 0x701E (=112.30kWh) pops up + + if (Sspm->history_relay < 255) { + ResponseAppend_P(PSTR("%s%*_f"), (i)?",":"", Settings->flag2.energy_resolution, &energy); + } + + if (0 == i) { + Sspm->energy_today[module][channel] = energy; + } else { + if (1 == i) { Sspm->energy_yesterday[module][channel] = energy; } + energy_total += energy; + } + } + if (0 == Sspm->Settings.energy_total[module][channel]) { + Sspm->Settings.energy_total[module][channel] = energy_total; // Initial setting + } + + // If received daily energy is below previous daily energy then update total energy + // This happens around midnight in normal situations + if (Sspm->energy_today[module][channel] < last_energy_today) { + Sspm->Settings.energy_total[module][channel] += last_energy_today; // Daily incremental save + } +/* + if (255 == Sspm->yesterday) { Sspm->yesterday = SspmBuffer[36]; } // Initial setting + // If the day has changed then update total energy + if (Sspm->yesterday != SspmBuffer[36]) { // Next day + Sspm->Settings.energy_total[module][channel] += last_energy_today; // Daily incremental save + } + Sspm->yesterday = SspmBuffer[36]; +*/ + Sspm->energy_total[module][channel] = Sspm->Settings.energy_total[module][channel] + Sspm->energy_today[module][channel]; + + if (Sspm->history_relay < 255) { + ResponseAppend_P(PSTR("]}")); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR("SSPMHistory")); + Sspm->history_relay = 255; // Disable display energy history + } + Sspm->allow_updates = 1; } break; @@ -730,14 +948,9 @@ void SSPMHandleReceivedData(void) { |----------------------- Month = 11 = November ----------------------------- Year 07 e5 = 2021 07 e5 0b 06 0f 1f 08 00 00 01 - 07 e5 0b 06 0f 1f 04 02 00 01 - 07 e5 0b 06 0f 1e 32 01 00 01 07 e5 0b 06 0f 1e 1e 01 01 01 - 07 e5 0b 06 0f 18 38 02 01 01 - 07 e5 0b 06 0f 12 38 00 01 01 07 e5 0b 06 0e 37 36 03 00 00 07 e5 0b 06 0e 37 36 01 00 00 - 07 e5 0b 06 0e 37 1e 03 01 00 07 e5 0b 06 0e 36 37 01 01 00 ... 07 e5 0b 06 0d 30 2d 03 00 01 09 89 fe @@ -746,7 +959,40 @@ void SSPMHandleReceivedData(void) { AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 1A 00 01 03 E5 45 EB | | */ - + if (Sspm->log_relay < 255) { + uint32_t module = Sspm->log_relay >> 2; + uint32_t channel = Sspm->log_relay & 0x03; // Channel relays are NOT bit masked this time + Response_P(PSTR("{\"SSPMLog%d\":"), Sspm->log_relay +1); + if (expected_bytes < 15) { + ResponseAppend_P(PSTR("\"Error%d\"}"), SspmBuffer[19]); + } else if (module != SSPMGetModuleNumberFromMap(SspmBuffer[20] << 8 | SspmBuffer[21])) { + ResponseAppend_P(PSTR("\"Wrong module\"}")); + } else { + uint32_t entries = SspmBuffer[32]; + uint32_t offset = 33; + bool more = false; + for (uint32_t i = 0; i < entries; i++) { + if (SspmBuffer[offset +7] == channel) { + uint32_t year = SspmBuffer[offset] << 8 | SspmBuffer[offset +1]; + char stemp[10]; // One of "App|Device|Overload|Overtemp" + ResponseAppend_P(PSTR("%s{\"Time\":\"%d-%02d-%02dT%02d:%02d:%02d\",\"Trigger\":\"%s\",\"State\":\"%s\"}"), + (more)?",":"[", year, SspmBuffer[offset +2], SspmBuffer[offset +3], + SspmBuffer[offset +4], SspmBuffer[offset +5], SspmBuffer[offset +6], + GetTextIndexed(stemp, sizeof(stemp), SspmBuffer[offset +9] & 0x03, kSSPMTriggers), + GetStateText(SspmBuffer[offset +8])); + more = true; + } + offset += 10; + } + if (more) { + ResponseAppend_P(PSTR("]}")); + }else { + ResponseAppend_P(PSTR("\"None\"}")); + } + } + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR("SSPMLog")); + Sspm->log_relay = 255; // Disable display energy history + } break; case SSPM_FUNC_ENERGY_PERIOD: /* 0x1B @@ -787,19 +1033,15 @@ void SSPMHandleReceivedData(void) { if (SspmBuffer[31] & 1) { break; } SspmBuffer[31] >>= 1; } - for (uint32_t module = 0; module < Sspm->module_max; module++) { - if ((SspmBuffer[19] == Sspm->module[module][0]) && (SspmBuffer[20] == Sspm->module[module][1])) { - Sspm->current[module][channel] = SspmBuffer[32] + (float)SspmBuffer[33] / 100; // x.xxA - Sspm->voltage[module][channel] = (SspmBuffer[34] << 8) + SspmBuffer[35] + (float)SspmBuffer[36] / 100; // x.xxV - Sspm->active_power[module][channel] = (SspmBuffer[37] << 8) + SspmBuffer[38] + (float)SspmBuffer[39] / 100; // x.xxW - Sspm->reactive_power[module][channel] = (SspmBuffer[40] << 8) + SspmBuffer[41] + (float)SspmBuffer[42] / 100; // x.xxVAr - Sspm->apparent_power[module][channel] = (SspmBuffer[43] << 8) + SspmBuffer[44] + (float)SspmBuffer[45] / 100; // x.xxVA - float power_factor = (Sspm->active_power[module][channel] && Sspm->apparent_power[module][channel]) ? Sspm->active_power[module][channel] / Sspm->apparent_power[module][channel] : 0; - if (power_factor > 1) { power_factor = 1; } - Sspm->power_factor[module][channel] = power_factor; - break; - } - } + uint32_t module = SSPMGetModuleNumberFromMap(SspmBuffer[19] << 8 | SspmBuffer[20]); + Sspm->current[module][channel] = SspmBuffer[32] + (float)SspmBuffer[33] / 100; // x.xxA + Sspm->voltage[module][channel] = (SspmBuffer[34] << 8) + SspmBuffer[35] + (float)SspmBuffer[36] / 100; // x.xxV + Sspm->active_power[module][channel] = (SspmBuffer[37] << 8) + SspmBuffer[38] + (float)SspmBuffer[39] / 100; // x.xxW + Sspm->reactive_power[module][channel] = (SspmBuffer[40] << 8) + SspmBuffer[41] + (float)SspmBuffer[42] / 100; // x.xxVAr + Sspm->apparent_power[module][channel] = (SspmBuffer[43] << 8) + SspmBuffer[44] + (float)SspmBuffer[45] / 100; // x.xxVA + float power_factor = (Sspm->active_power[module][channel] && Sspm->apparent_power[module][channel]) ? Sspm->active_power[module][channel] / Sspm->apparent_power[module][channel] : 0; + if (power_factor > 1) { power_factor = 1; } + Sspm->power_factor[module][channel] = power_factor; SSPMSendAck(command_sequence); Sspm->allow_updates = 1; } @@ -814,7 +1056,8 @@ void SSPMHandleReceivedData(void) { power_t relay = SspmBuffer[31] & 0x0F; // Relays active power_t relay_state = SspmBuffer[31] >> 4; // Relays state for (uint32_t i = 0; i < Sspm->module_max; i++) { - if ((SspmBuffer[19] == Sspm->module[i][0]) && (SspmBuffer[20] == Sspm->module[i][1])) { + uint32_t module = SSPMGetMappedModuleId(i); + if ((SspmBuffer[19] == Sspm->module[module][0]) && (SspmBuffer[20] == Sspm->module[module][1])) { relay <<= (i * 4); relay_state <<= (i * 4); break; @@ -846,10 +1089,38 @@ void SSPMHandleReceivedData(void) { |130| 1.0.0| 20A| 0.1A| 240V| 0.1V| 4400W| 0.1W| Ty = Type of sub-device. 130: Four-channel sub-device */ - if ((0x24 == Sspm->expected_bytes) && (Sspm->module_max < SSPM_MAX_MODULES)) { - memcpy(Sspm->module[1], Sspm->module[0], (SSPM_MAX_MODULES -1) * SSPM_MODULE_NAME_SIZE); - memcpy(Sspm->module[0], SspmBuffer + 19, SSPM_MODULE_NAME_SIZE); + if ((0x24 == expected_bytes) && (Sspm->module_max < SSPM_MAX_MODULES)) { + memcpy(Sspm->module[Sspm->module_max], SspmBuffer + 19, SSPM_MODULE_NAME_SIZE); + uint32_t module_id = SspmBuffer[19] << 8 | SspmBuffer[20]; + if (0 == Sspm->Settings.module_map[Sspm->module_max]) { + Sspm->Settings.module_map[Sspm->module_max] = module_id; + } + int mapped = SSPMGetModuleNumberFromMapIfFound(module_id); + if (-1 == mapped) { Sspm->map_change = true; } + mapped++; + AddLog(LOG_LEVEL_INFO, PSTR("SPM: 4Relay %d (mapped to %d) type %d version %d.%d.%d found with id %12_H"), + Sspm->module_max +1, mapped, SspmBuffer[35], SspmBuffer[36], SspmBuffer[37], SspmBuffer[38], Sspm->module[Sspm->module_max]); + Sspm->module_max++; +/* + // Debugging module removal/addition/change (exception 3) + if ((1 == Sspm->module_max) && (Settings->flag3.user_esp8285_enable)) { // SO51 + SspmBuffer[19] = 0x4B; + SspmBuffer[20] = 0x62; + memcpy(Sspm->module[Sspm->module_max], SspmBuffer + 19, SSPM_MODULE_NAME_SIZE); + module_id = SspmBuffer[19] << 8 | SspmBuffer[20]; + if (0 == Sspm->Settings.module_map[Sspm->module_max]) { + Sspm->Settings.module_map[Sspm->module_max] = module_id; + } + mapped = SSPMGetModuleNumberFromMapIfFound(module_id); + if (-1 == mapped) { Sspm->map_change = true; } + mapped++; + AddLog(LOG_LEVEL_INFO, PSTR("SPM: 4Relay %d (mapped to %d) type %d version %d.%d.%d found with id %12_H"), + Sspm->module_max +1, mapped, SspmBuffer[35], SspmBuffer[36], SspmBuffer[37], SspmBuffer[38], Sspm->module[Sspm->module_max]); + + Sspm->module_max++; + } +*/ } SSPMSendAck(command_sequence); break; @@ -858,6 +1129,40 @@ void SSPMHandleReceivedData(void) { AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 19 00 00 03 a1 16 */ SSPMSendAck(command_sequence); + + // Warn for mapping change when removal or addition of 4Relay modules + for (uint32_t module = Sspm->module_max; module < SSPM_MAX_MODULES; module++) { + // Clear obsolete mapping slots + Sspm->Settings.module_map[module] = 0; + } + for (uint32_t module = 0; module < Sspm->module_max; module++) { + // Remove not scanned module (probably physical removed) from mapping + if (-1 == SSPMGetMappedModuleIdIfFound(module)) { + // Clear mapping slot + Sspm->Settings.module_map[module] = 0; + Sspm->map_change = true; + } + } + for (uint32_t module = 0; module < Sspm->module_max; module++) { + // Add scanned module to mapping + uint32_t module_id = SSMPGetModuleId(module); + if (-1 == SSPMGetModuleNumberFromMapIfFound(module_id)) { + // Scanned module not in mapping list (probably due to physical install) + for (uint32_t i = 0; i < Sspm->module_max; i++) { + // Find empty slot in mapping and insert + if (0 == Sspm->Settings.module_map[i]) { + Sspm->Settings.module_map[i] = module_id; + Sspm->map_change = true; + break; + } + } + } + } + if (Sspm->map_change) { + Sspm->map_change = false; + AddLog(LOG_LEVEL_INFO, PSTR("SPM: WARNING 4Relay mapping possibly changed")); + } + Sspm->module_selected = Sspm->module_max; SSPMSendSetTime(); break; @@ -888,10 +1193,10 @@ void SSPMSerialInput(void) { } if (Sspm->serial_in_byte_counter < SSPM_SERIAL_BUFFER_SIZE -1) { SspmBuffer[Sspm->serial_in_byte_counter++] = serial_in_byte; - if (19 == Sspm->serial_in_byte_counter) { - Sspm->expected_bytes = (SspmBuffer[Sspm->serial_in_byte_counter -2] << 8) + SspmBuffer[Sspm->serial_in_byte_counter -1]; + if ((0xAA == SspmBuffer[0]) && (0x55 == SspmBuffer[1]) && (19 == Sspm->serial_in_byte_counter)) { + Sspm->expected_bytes = 22 + (SspmBuffer[17] << 8) + SspmBuffer[18]; } - if (Sspm->serial_in_byte_counter == (22 + Sspm->expected_bytes)) { + if (Sspm->serial_in_byte_counter == Sspm->expected_bytes) { AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SPM: ARM %*_H"), Sspm->serial_in_byte_counter, SspmBuffer); @@ -917,11 +1222,9 @@ void SSPMSerialInput(void) { /*********************************************************************************************/ void SSPMInit(void) { - if (!ValidTemplate(PSTR("Sonoff SPM (POC1)")) && - !ValidTemplate(PSTR("Sonoff SPM (POC2)"))) { return; } - if (!PinUsed(GPIO_RXD) || !PinUsed(GPIO_TXD)) { return; } + if (!ValidTemplate(PSTR("Sonoff SPM")) || !PinUsed(GPIO_RXD) || !PinUsed(GPIO_TXD)) { return; } - Sspm = (TSspm*)calloc(sizeof(TSspm), 1); + Sspm = (TSspm*)calloc(sizeof(TSspm), 1); // Need calloc to reset registers to 0/false if (!Sspm) { return; } SspmBuffer = (uint8_t*)malloc(SSPM_SERIAL_BUFFER_SIZE); if (!SspmBuffer) { @@ -935,6 +1238,8 @@ void SSPMInit(void) { return; } + SSPMSettingsLoad(); + pinMode(SSPM_GPIO_ARM_RESET, OUTPUT); digitalWrite(SSPM_GPIO_ARM_RESET, 1); @@ -956,6 +1261,9 @@ void SSPMInit(void) { #endif #endif + Sspm->yesterday = 255; // Not initialized + Sspm->history_relay = 255; // Disable display energy history + Sspm->log_relay = 255; // Disable display logging Sspm->old_power = TasmotaGlobal.power; Sspm->mstate = SPM_WAIT; // Start init sequence } @@ -1022,9 +1330,15 @@ void SSPMEvery100ms(void) { Sspm->module_max = 0; SSPMSendInitScan(); Sspm->mstate = SPM_WAIT_FOR_SCAN; + Sspm->last_totals = 0; break; case SPM_WAIT_FOR_SCAN: - // Wait for scan sequence to complete + // Wait for scan sequence to complete within 60 seconds + if (Sspm->last_totals > 600) { + AddLog(LOG_LEVEL_DEBUG, PSTR("SPM: Relay scan timeout")); + Sspm->mstate = SPM_NONE; + Sspm->error_led_blinks = 255; + } break; case SPM_SCAN_COMPLETE: // Scan sequence finished @@ -1090,7 +1404,7 @@ bool SSPMSetDevicePower(void) { power_t new_power = XdrvMailbox.index; if (new_power != Sspm->old_power) { for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { - uint8_t new_state = (new_power >> i) &1; + uint32_t new_state = (new_power >> i) &1; if (new_state != ((Sspm->old_power >> i) &1)) { SSPMSendSetRelay(i, new_state); Sspm->no_send_key = 10; // Disable buttons for 10 * 0.1 second @@ -1203,14 +1517,15 @@ void SSPMEnergyShow(bool json) { } if (index) { - uint32_t offset = 0; if (index > 4) { Sspm->rotate++; - if (Sspm->rotate >= ((index -1) >> 2) << 3) { - Sspm->rotate = 0; - } - offset = (Sspm->rotate >> 2) * 4; + } else { + Sspm->rotate = 0; } + if (Sspm->rotate > ((index -1) | 0x3)) { // Always test in case index has changed due to use of SspmDisplay command + Sspm->rotate = 0; + } + uint32_t offset = (Sspm->rotate >> 2) * 4; uint32_t count = index - offset; if (count > 4) { count = 4; } WSContentSend_P(PSTR("{t}{s}")); // First column is empty ({t} = , {s} = ")); + char number[4]; + uint32_t idx = 0; + for (uint32_t i = 0; i < rows; i++) { + if (idx > 0) { WSContentSend_P(PSTR("")); } + for (uint32_t j = 0; j < cols; j++) { + idx++; + WSContentSend_P(PSTR(""), // &lsc is related to WebGetArg("lsc", tmp, sizeof(tmp)); + 100 / cols, + idx -1, + (strlen(SettingsText(SET_BUTTON1 + idx))) ? SettingsText(SET_BUTTON1 + idx) : itoa(idx, number, 10)); + } + } + WSContentSend_P(PSTR("
) @@ -1240,17 +1555,35 @@ void SSPMEnergyShow(bool json) { \*********************************************************************************************/ const char kSSPMCommands[] PROGMEM = "SSPM|" // Prefix - "Log|Energy|History|Scan|IamHere|Display|Reset" ; + "Log|Energy|History|Scan|IamHere|Display|Reset|Map|" D_CMND_ENERGYTOTAL; void (* const SSPMCommand[])(void) PROGMEM = { - &CmndSSPMLog, &CmndSSPMEnergy, &CmndSSPMEnergyHistory, &CmndSSPMScan, &CmndSSPMIamHere, &CmndSSPMDisplay, &CmndSSPMReset }; + &CmndSSPMLog, &CmndSSPMEnergy, &CmndSSPMHistory, &CmndSSPMScan, &CmndSSPMIamHere, + &CmndSSPMDisplay, &CmndSSPMReset, &CmndSSPMMap, &CmndSpmEnergyTotal }; + +void CmndSpmEnergyTotal(void) { + // Reset Energy Total + // SspmEnergyTotal 0 - Set total energy from midnight with sum of last month history + // SspmEnergyTotal 4.23 - Set total energy from midnight (without today's energy) + uint32_t relay = XdrvMailbox.index -1; + uint32_t module = relay >> 2; + uint32_t channel = relay & 0x03; + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.devices_present) && XdrvMailbox.data_len) { + Sspm->Settings.energy_total[module][channel] = CharToFloat(XdrvMailbox.data); + Sspm->energy_total[module][channel] = Sspm->Settings.energy_total[module][channel] + Sspm->energy_today[module][channel]; + } + ResponseCmndFloat(Sspm->energy_total[module][channel], Settings->flag2.energy_resolution); +} void CmndSSPMLog(void) { - // Report 29 log entries + // SspmLog - Report from up to 29 latest log entries + // SspmLog 10 - Report from up to 10 latest log entries + // SspmLog 100 - Report from up to 29 log entries if ((XdrvMailbox.index < 1) || (XdrvMailbox.index > TasmotaGlobal.devices_present)) { XdrvMailbox.index = 1; } - XdrvMailbox.payload &= 0xFFFF; // Max 65000 entries - SSPMSendGetLog(XdrvMailbox.index -1, XdrvMailbox.payload +1); - ResponseCmndDone(); + if ((XdrvMailbox.payload < 1) || (XdrvMailbox.payload > 65000)) { XdrvMailbox.payload = 28; } + Sspm->log_relay = XdrvMailbox.index -1; + SSPMSendGetLog(Sspm->log_relay, XdrvMailbox.payload +1); + ResponseClear(); } void CmndSSPMEnergy(void) { @@ -1259,20 +1592,25 @@ void CmndSSPMEnergy(void) { ResponseCmndDone(); } -void CmndSSPMEnergyHistory(void) { +void CmndSSPMHistory(void) { + // Retreive daily history of one relay up to six month + // SspmHistory if ((XdrvMailbox.index < 1) || (XdrvMailbox.index > TasmotaGlobal.devices_present)) { XdrvMailbox.index = 1; } - SSPMSendGetEnergyTotal(XdrvMailbox.index -1); - ResponseCmndDone(); + Sspm->history_relay = XdrvMailbox.index -1; + SSPMSendGetEnergyTotal(Sspm->history_relay); + ResponseClear(); } void CmndSSPMScan(void) { // Start relay module scan taking up to 20 seconds + // SspmScan Sspm->mstate = SPM_START_SCAN; ResponseCmndChar(PSTR(D_JSON_STARTED)); } void CmndSSPMIamHere(void) { // Blink module ERROR led containing relay + // SspmIamHere 6 if ((XdrvMailbox.payload < 1) || (XdrvMailbox.payload > TasmotaGlobal.devices_present)) { XdrvMailbox.payload = 1; } SSPMSendIAmHere(XdrvMailbox.payload -1); ResponseCmndDone(); @@ -1280,6 +1618,7 @@ void CmndSSPMIamHere(void) { void CmndSSPMDisplay(void) { // Select either all relays or only powered on relays + // SspmDisplay 0 or SspmDisplay 1 if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { Settings->sbflag1.sspm_display = XdrvMailbox.payload; } @@ -1288,6 +1627,7 @@ void CmndSSPMDisplay(void) { void CmndSSPMReset(void) { // Reset ARM and restart + // Reset 1 if (1 == XdrvMailbox.payload) { Sspm->mstate = SPM_NONE; SSPMSendCmnd(SSPM_FUNC_RESET); @@ -1298,6 +1638,28 @@ void CmndSSPMReset(void) { } } +void CmndSSPMMap(void) { + // Map scanned module number to physical module number using positional numbering + // SspmMap 1,3,4,2 + // TODO: Might need input checks on count and valid different numbers + if (Sspm->module_max) { // Valid after initial scan + char *p; + uint32_t i = 0; + for (char* str = strtok_r(XdrvMailbox.data, ",", &p); str && i < Sspm->module_max; str = strtok_r(nullptr, ",", &p)) { + uint32_t module = atoi(str); + if ((module > 0) && (module <= Sspm->module_max)) { // Only valid modules 1 to x + Sspm->Settings.module_map[i] = SSMPGetModuleId(module -1); + } + i++; + } + Response_P(PSTR("{\"%s\":["), XdrvMailbox.command); + for (uint32_t i = 0; i < Sspm->module_max; i++) { + ResponseAppend_P(PSTR("%s%d"), (i)?",":"", SSPMGetModuleNumberFromMap(SSMPGetModuleId(i)) +1); + } + ResponseAppend_P(PSTR("]}")); + } +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -1316,6 +1678,9 @@ bool Xdrv86(uint8_t function) { case FUNC_EVERY_100_MSECOND: SSPMEvery100ms(); break; + case FUNC_SAVE_SETTINGS: + SSPMSettingsSave(); + break; case FUNC_SET_DEVICE_POWER: result = SSPMSetDevicePower(); break; diff --git a/tasmota/xdrv_99_debug.ino b/tasmota/xdrv_99_debug.ino index 6e33431a0..61896a610 100644 --- a/tasmota/xdrv_99_debug.ino +++ b/tasmota/xdrv_99_debug.ino @@ -42,6 +42,7 @@ * Debug commands \*********************************************************************************************/ +#define D_CMND_MEMDUMP "MemDump" #define D_CMND_CFGDUMP "CfgDump" #define D_CMND_CFGPEEK "CfgPeek" #define D_CMND_CFGPOKE "CfgPoke" @@ -60,7 +61,7 @@ #define D_CMND_SERBUFF "SerBufSize" const char kDebugCommands[] PROGMEM = "|" // No prefix - D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" + D_CMND_MEMDUMP "|" D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" #ifdef USE_WEBSERVER D_CMND_CFGXOR "|" #endif @@ -75,7 +76,7 @@ const char kDebugCommands[] PROGMEM = "|" // No prefix ; void (* const DebugCommand[])(void) PROGMEM = { - &CmndCfgDump, &CmndCfgPeek, &CmndCfgPoke, + &CmndMemDump, &CmndCfgDump, &CmndCfgPeek, &CmndCfgPoke, #ifdef USE_WEBSERVER &CmndCfgXor, #endif @@ -313,8 +314,8 @@ void DebugDump(uint32_t start, uint32_t size) { uint32_t col; char *p; - uint8_t *buffer = (uint8_t *)&start; - maxrow = ((start + size + CFG_COLS) / CFG_COLS); + uint8_t *buffer = (uint8_t *)(start); + maxrow = ((size + CFG_COLS) / CFG_COLS); uint32_t srow = 0; uint32_t mrow = maxrow; @@ -334,7 +335,7 @@ void DebugDump(uint32_t start, uint32_t size) { char log_data[150]; // 020: C7 2B 2E AB 70 E8 09 AE C8 88 3D EA 7C FF 48 2F 0E A7 D7 BF 02 0E D7 7D C9 6F B9 3A 1D 01 3F 28 | +. p = | H/ } o : ?(| for (row = srow; row < maxrow; row++) { idx = row * CFG_COLS; - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); + snprintf_P(log_data, sizeof(log_data), PSTR("%08X:"), start + idx); for (col = 0; col < CFG_COLS; col++) { if (!(col%4)) { snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); @@ -354,6 +355,7 @@ void DebugDump(uint32_t start, uint32_t size) { } } + void DebugCfgDump(char* parms) { uint32_t CFG_COLS = 16; @@ -489,6 +491,19 @@ void CmndRtcDump(void) ResponseCmndDone(); } +void CmndMemDump(void) { + // MemDump 0x3fff1aa8 200 + if (XdrvMailbox.payload >= 0) { + char *p; + + uint32_t start = strtol(XdrvMailbox.data, &p, 16); + uint32_t size = strtol(p, &p, 10); + if (0 == size) { size = 32; } + DebugDump(start, size); + } + ResponseCmndDone(); +} + void CmndCfgDump(void) { DebugCfgDump(XdrvMailbox.data); diff --git a/tasmota/xdsp_17_universal.ino b/tasmota/xdsp_17_universal.ino index a37d5af5e..bd77e2a2b 100644 --- a/tasmota/xdsp_17_universal.ino +++ b/tasmota/xdsp_17_universal.ino @@ -79,7 +79,7 @@ int8_t cs; if (desc) { memcpy_P(fbuff, desc, DISPDESC_SIZE - 1); ddesc = fbuff; - AddLog(LOG_LEVEL_INFO, PSTR("DSP: const char descriptor used")); + AddLog(LOG_LEVEL_DEBUG, PSTR("DSP: const char descriptor used")); } @@ -92,7 +92,7 @@ int8_t cs; fp.read((uint8_t*)fbuff, size); fp.close(); ddesc = fbuff; - AddLog(LOG_LEVEL_INFO, PSTR("DSP: File descriptor used")); + AddLog(LOG_LEVEL_DEBUG, PSTR("DSP: File descriptor used")); } } #endif // USE_UFILESYS @@ -106,7 +106,7 @@ int8_t cs; while (*lp != '\n') lp++; memcpy(fbuff, lp + 1, DISPDESC_SIZE - 1); ddesc = fbuff; - AddLog(LOG_LEVEL_INFO, PSTR("DSP: Script descriptor used")); + AddLog(LOG_LEVEL_DEBUG, PSTR("DSP: Script descriptor used")); } } #endif // USE_SCRIPT @@ -123,7 +123,7 @@ int8_t cs; if (fbuff[cnt] == ' ') fbuff[cnt] = '\n'; } ddesc = fbuff; - AddLog(LOG_LEVEL_INFO, PSTR("DSP: Rule 3 descriptor used")); + AddLog(LOG_LEVEL_DEBUG, PSTR("DSP: Rule 3 descriptor used")); } } @@ -134,12 +134,12 @@ int8_t cs; if (!ddesc) { memcpy_P(fbuff, DSP_SAMPLE_DESC, sizeof(DSP_SAMPLE_DESC)); ddesc = fbuff; - AddLog(LOG_LEVEL_INFO, PSTR("DSP: Flash descriptor used")); + AddLog(LOG_LEVEL_DEBUG, PSTR("DSP: Flash descriptor used")); } #endif // DSP_ROM_DESC if (!ddesc) { - AddLog(LOG_LEVEL_INFO, PSTR("DSP: No valid descriptor found")); + AddLog(LOG_LEVEL_DEBUG, PSTR("DSP: No valid descriptor found")); if (fbuff) free(fbuff); return 0; } @@ -238,7 +238,7 @@ int8_t cs; // init renderer if (renderer) { delete renderer; - AddLog(LOG_LEVEL_INFO, PSTR("DSP: reinit")); + AddLog(LOG_LEVEL_DEBUG, PSTR("DSP: reinit")); } udisp = new uDisplay(ddesc); @@ -328,7 +328,7 @@ int8_t cs; #endif // SHOW_SPLASH udisp_init_done = true; - AddLog(LOG_LEVEL_INFO, PSTR("DSP: %s!"), renderer->devname()); + AddLog(LOG_LEVEL_INFO, PSTR("DSP: Configured display '%s'"), renderer->devname()); return renderer; } diff --git a/tasmota/xdsp_19_max7219_matrix.ino b/tasmota/xdsp_19_max7219_matrix.ino new file mode 100644 index 000000000..3e1a5c258 --- /dev/null +++ b/tasmota/xdsp_19_max7219_matrix.ino @@ -0,0 +1,376 @@ +/* + xdsp_19_max7219_matrix.ino.ino - Support for MAX7219 based 8x8 dot matrix displays for Tasmota + + Copyright (C) 2021 Michael Beuss + + This program 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 . +*/ + +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_MAX7219_MATRIX +/*********************************************************************************************\ + This driver enables the display of ascii text on MAX7219 based 8x8 LED dot matrix modules (1088AS). + + Connect the MAX7219 display module's pins to any free GPIOs of the ESP8266 or ESP32 module. + VCC should be 5V. Depending on the number of used modules and the brightness, the used current can be more than 500 mA. + + Connect the 5 outgoing pins (VCC, GND, DI, CS, CLK) of the first module to the next one. + With this you can connect up to 32 modules. + To extend the display hieght, multiple rows are supported. Each module row starts from left to right. + + Assign the pins as follows from Tasmota's GUI: + + DIN hardware pin --> "MAX7219 DIN" + CS hardware pin --> "MAX7219 CS" + CLK hardware pin --> "MAX7219 CLK" + + + Once the GPIO configuration is saved and the ESP8266/ESP32 module restarts, + set the Display Model to 19 and Display Mode to 0 + + Depending on order of the wired 8x8 matrix modules you have got a display of size pixel_width x pixel_height. + The size has to be set with the commands "DisplayWidth " and "DisplayHeight " + + After the ESP8266/ESP32 module restarts again, turn ON the display with the command "Power 1" + + + Now, the following "Display" commands can be used: + + DisplayText text + Sends the text to the display. + If the text fits into the display, it is shown in the center. + Otherwise it scrolls to the left and repeats as long it is cleared or new "DisplayText" overwrites it. + + DisplayDimmer [0..100] + Sets the intensity of the display. + + DisplayBlinkrate [0..3] + 0: not blinking + 1: slow, 2: medium 3: fast blinking + + Power [ON|OFF] + Sitches the display on or off. When "off", the display buffer is not cleared and will be shown again when after "Power ON". + Other display commands are still active when off. + + DisplayClear + Clears the display + + DisplayScrollDelay [0..15] // default = 0 + Sets the speed of text scroll. Smaller delay = faster scrolling. + The maximum scroll speed is 50ms per pixel on DisplayScrollDelay 0. + + DisplayWidth [8..256] + Sets the pixel width of the display (8x number of modules in a row) + + DisplayHeight [8..256] + Sets the pixel height of the display (8x number of module rows) + + DisplayRotate [0|2] + 0: normal orientation; devide 0 starts at top left + 2: upside down; device 0 starts at bottom right + + DisplayClock [0|1|2] + Displays a clock. + Commands "DisplayClock 1" // 12 hr format + "DisplayClock 2" // 24 hr format + "DisplayClock 0" // turn off clock; please use additional cammand: DisplayMode 0 + + If you would like to use the UTF8 latin1 character set, it cam be added by copile option: + #define USE_UTF8_LATIN1 + +\*********************************************************************************************/ + +#define XDSP_19 19 + +#include + +LedMatrix *max7219_Matrix = nullptr; +bool max2791Matrix_initDriver_done = false; +struct +{ + byte modulesPerRow = 4; + byte modulesPerCol = 1; + byte scroll_delay = 0; + byte scroll_iteration = 0; + bool show_clock = false; + bool timeFormat24 = true; + byte blink_delay = 0; // 0: not blinking + byte blink_iteration = 0; + +} LedMatrix_settings; + +// FUNC_DISPLAY_INIT_DRIVER +bool MAX7291Matrix_initDriver(void) +{ + if (!PinUsed(GPIO_MAX7219DIN) || !PinUsed(GPIO_MAX7219CLK) || !PinUsed(GPIO_MAX7219CS)) + { + AddLog(LOG_LEVEL_INFO, PSTR("DSP: MAX7291Matrix_init GPIO pins missing DIN:%d, CLK:%d, CS:%d"), Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS) ); + return false; // ensure necessariy pins are configurated + } + + Settings->display_model = XDSP_19; + renderer = nullptr; // renderer not yet used + if (Settings->display_width) // [pixel] + { + LedMatrix_settings.modulesPerRow = (Settings->display_width - 1) / 8 + 1; + } + Settings->display_width = 8 * LedMatrix_settings.modulesPerRow; + Settings->display_cols[0] = LedMatrix_settings.modulesPerRow; + if (Settings->display_height) // [pixel] + { + LedMatrix_settings.modulesPerCol = (Settings->display_height - 1) / 8 + 1; + } + Settings->display_height = 8 * LedMatrix_settings.modulesPerCol; + Settings->display_rows = LedMatrix_settings.modulesPerCol; + Settings->display_cols[1] = LedMatrix_settings.modulesPerCol; + max7219_Matrix = new LedMatrix(Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), LedMatrix_settings.modulesPerRow, LedMatrix_settings.modulesPerCol); + max2791Matrix_initDriver_done = true; + + AddLog(LOG_LEVEL_INFO, PSTR("MTX: MAX7291Matrix_initDriver DIN:%d CLK:%d CS:%d size(%dx%d)"), Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), LedMatrix_settings.modulesPerRow, LedMatrix_settings.modulesPerCol); + return MAX7291Matrix_init(); +} + +// FUNC_DISPLAY_INIT +bool MAX7291Matrix_init(void) +{ + Settings->display_mode = 0; // text mode + LedMatrix_settings.show_clock = 0; // no + LedMatrix_settings.blink_delay = 0; // no blinking + + int intensity = GetDisplayDimmer16(); // 0..15 + max7219_Matrix->setIntensity(intensity); + + max7219_Matrix->power(true); // power on + if(Settings->display_rotate <= 3) + { + max7219_Matrix->setOrientation((LedMatrix::ModuleOrientation)Settings->display_rotate ); + } + else + { + // default for most 32x8 modules + Settings->display_rotate = LedMatrix::ORIENTATION_UPSIDE_DOWN; + max7219_Matrix->setOrientation( LedMatrix::ORIENTATION_UPSIDE_DOWN ); + } + AddLog(LOG_LEVEL_INFO, PSTR("MTX: MAX7291Matrix_init orientation: %d, intensity: %d"), Settings->display_rotate, intensity); + return true; +} + +bool MAX7291Matrix_setText(bool clearBefore=true) +{ + if(Settings->display_mode != 0) MAX7291Matrix_init(); + LedMatrix_settings.blink_delay = 0; // no blinking + return max7219_Matrix->drawText(XdrvMailbox.data, clearBefore); +} + +// FUNC_DISPLAY_SCROLLDELAY +bool MAX7291Matrix_scrollDelay(void) +{ + if (ArgC() == 0) + { + XdrvMailbox.payload = LedMatrix_settings.scroll_delay; + return true; + } + if (LedMatrix_settings.scroll_delay < 0) + LedMatrix_settings.scroll_delay = 0; + LedMatrix_settings.scroll_delay = XdrvMailbox.payload; + return true; +} + +// FUNC_DISPLAY_EVERY_50_MSECOND +bool MAX7291Matrix_scrollText(void) +{ + // This function is called every 50 ms. + // scroll_delay defines the number of cycles to be ignored until the display scrolls by one pixel to the left. + // e.g. scrall_delay = 4 causes a scroll each 200 ms. + + if(!max7219_Matrix->isPowerOn()) return false; // do not scroll on power off + LedMatrix_settings.scroll_iteration++; + if (LedMatrix_settings.scroll_delay) + LedMatrix_settings.scroll_iteration = LedMatrix_settings.scroll_iteration % LedMatrix_settings.scroll_delay; + else + LedMatrix_settings.scroll_iteration = 0; + if (LedMatrix_settings.scroll_iteration) + return false; + + return max7219_Matrix->scrollText(); +} + +bool MAX7291Matrix_blink(void) +{ + // This function is called every 50 ms. + // blink_delay defines the number of cycles to be ignored until the blinkstate changes. + if(LedMatrix_settings.blink_delay == 0) return false; + + LedMatrix_settings.blink_iteration++; + if(LedMatrix_settings.blink_iteration == LedMatrix_settings.blink_delay) + { + max7219_Matrix->power(false); + } + else if(LedMatrix_settings.blink_iteration == 2* LedMatrix_settings.blink_delay ) + { + LedMatrix_settings.blink_iteration = 0; + max7219_Matrix->power(true); + } + return true; +} + + +bool MAX7291Matrix_setBlinkRate() +{ + LedMatrix_settings.blink_iteration = 0; + max7219_Matrix->power(true); + if (ArgC() == 0) + { + XdrvMailbox.payload = 0; + } + if (XdrvMailbox.payload) + LedMatrix_settings.blink_delay = 20 / XdrvMailbox.payload; // 1: once per second; 2: twice per second; 3: three times per second + else + LedMatrix_settings.blink_delay = 0; // do not blink + return true; +} + +#ifdef USE_DISPLAY_MODES1TO5 +// FUNC_DISPLAY_CLOCK +bool MAX7291Matrix_clock(void) +{ + LedMatrix_settings.show_clock = XdrvMailbox.payload; + if (ArgC() == 0) + XdrvMailbox.payload = 2; + switch(XdrvMailbox.payload) + { + case 0: + // no clock, switch to text mode + Settings->display_mode = 0; + return true; + case 1: + // 12 h clock + LedMatrix_settings.timeFormat24 = false; + Settings->display_mode = 1; + break; + case 2: + // 24 h clock + LedMatrix_settings.timeFormat24 = true; + Settings->display_mode = 1; + break; + default: + return false; + } + + AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: LedMatrix_settings.show_clock %d, 24h: %b"), LedMatrix_settings.show_clock, LedMatrix_settings.timeFormat24); + + max7219_Matrix->clearDisplay(); + MAX7291Matrix_showTime(); + return true; +} + +// FUNC_DISPLAY_EVERY_SECOND +bool MAX7291Matrix_showTime() +{ + if(!LedMatrix_settings.show_clock) return false; + + uint8_t hr = RtcTime.hour; + uint8_t mn = RtcTime.minute; + uint8_t sc = RtcTime.second; + char timeStr[10]; + if(!LedMatrix_settings.timeFormat24) + { + if(hr == 0) hr = 12; + if(hr > 12 ) hr -= 12; + } + + if(LedMatrix_settings.modulesPerRow >= 6) + { + snprintf(timeStr, 10, "%02d:%02d:%02d", hr , mn, sc); + } + else + { + snprintf(timeStr, 10, "%02d:%02d", hr , mn); + } + max7219_Matrix->drawText(timeStr, false); // false: do not clear desplay on update to prevent flicker + return true; +} + +#endif // USE_DISPLAY_MODES1TO5 + + +bool Xdsp19(uint8_t function) +{ + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function && !max2791Matrix_initDriver_done ) + { + result = MAX7291Matrix_initDriver(); + } + else if (max2791Matrix_initDriver_done && max7219_Matrix && (XDSP_19 == Settings->display_model)) + { + switch (function) + { + case FUNC_DISPLAY_INIT: + result = MAX7291Matrix_init(); + break; + case FUNC_DISPLAY_POWER: + max7219_Matrix->power(disp_power!=0); + break; + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_CLEAR: + result = max7219_Matrix->clearDisplay(); + break; + case FUNC_DISPLAY_DIM: + result = max7219_Matrix->setIntensity(GetDisplayDimmer16()); + break; + case FUNC_DISPLAY_DRAW_STRING: + case FUNC_DISPLAY_SCROLLTEXT: + case FUNC_DISPLAY_SEVENSEG_TEXT: + result = MAX7291Matrix_setText(true); // true: clears display before drawing text + break; + case FUNC_DISPLAY_SEVENSEG_TEXTNC: + result = MAX7291Matrix_setText(false); // false: does not clear display before drawing text + break; + case FUNC_DISPLAY_SCROLLDELAY: + result = MAX7291Matrix_scrollDelay(); + break; + case FUNC_DISPLAY_BLINKRATE: + { + result = MAX7291Matrix_setBlinkRate(); + break; + } + case FUNC_DISPLAY_EVERY_50_MSECOND: + MAX7291Matrix_blink(); + result = MAX7291Matrix_scrollText(); + break; + +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_CLOCK: + result = MAX7291Matrix_clock(); + break; + case FUNC_DISPLAY_EVERY_SECOND: + if (LedMatrix_settings.show_clock) + { + result = MAX7291Matrix_showTime(); + } + break; +#endif // USE_DISPLAY_MODES1TO5 + + default: + result = false; + } + } + return result; +} + +#endif // USE_DISPLAY_MAX7219_MATRIX +#endif // USE_DISPLAY diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino index 3a9e396f3..715851e4c 100644 --- a/tasmota/xlgt_01_ws2812.ino +++ b/tasmota/xlgt_01_ws2812.ino @@ -37,7 +37,11 @@ #define XLGT_01 1 +#ifdef USE_NETWORK_LIGHT_SCHEMES +const uint8_t WS2812_SCHEMES = 10; // Number of WS2812 schemes +#else const uint8_t WS2812_SCHEMES = 9; // Number of WS2812 schemes +#endif const char kWs2812Commands[] PROGMEM = "|" // No prefix D_CMND_LED "|" D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_WIDTH "|" D_CMND_STEPPIXELS ; @@ -167,7 +171,12 @@ WsColor kwanzaa[3] = { 255,0,0, 0,0,0, 0,255,0 }; WsColor kRainbow[7] = { 255,0,0, 255,128,0, 255,255,0, 0,255,0, 0,0,255, 128,0,255, 255,0,255 }; WsColor kFire[3] = { 255,0,0, 255,102,0, 255,192,0 }; WsColor kStairs[2] = { 0,0,0, 255,255,255 }; + +#ifdef USE_NETWORK_LIGHT_SCHEMES +ColorScheme kSchemes[WS2812_SCHEMES -2] = { // Skip clock scheme and DDP scheme +#else ColorScheme kSchemes[WS2812_SCHEMES -1] = { // Skip clock scheme +#endif kIncandescent, 2, kRgb, 3, kChristmas, 2, @@ -492,6 +501,51 @@ void Ws2812Steps(uint32_t schemenr) { Ws2812StripShow(); } +#ifdef USE_NETWORK_LIGHT_SCHEMES +void Ws2812DDP(void) +{ +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor c; + c.W = 0; +#else + RgbColor c; +#endif + c.R = 0; + c.G = 0; + c.B = 0; + + // Can't be trying to initialize UDP too early. + if (TasmotaGlobal.restart_flag || TasmotaGlobal.global_state.network_down) return; + + // Start DDP listener, if fail, just set last ddp_color + if (!ddp_udp_up) { + if (!ddp_udp.begin(4048)) return; + ddp_udp_up = 1; + AddLog(LOG_LEVEL_DEBUG_MORE, "DDP: UDP Listener Started: WS2812 Scheme"); + } + + // Get the DDP payload over UDP + std::vector payload; + while (uint16_t packet_size = ddp_udp.parsePacket()) { + payload.resize(packet_size); + if (!ddp_udp.read(&payload[0], payload.size())) { + continue; + } + } + + // No verification checks performed against packet besides length + if (payload.size() > (9+3*Settings->light_pixels)) { + for (uint32_t i = 0; i < Settings->light_pixels; i++) { + c.R = payload[10+3*i]; + c.G = payload[11+3*i]; + c.B = payload[12+3*i]; + strip->SetPixelColor(i, c); + } + Ws2812StripShow(); + } +} +#endif + void Ws2812Clear(void) { strip->ClearTo(0); @@ -580,7 +634,14 @@ bool Ws2812SetChannels(void) void Ws2812ShowScheme(void) { uint32_t scheme = Settings->light_scheme - Ws2812.scheme_offset; - + +#ifdef USE_NETWORK_LIGHT_SCHEMES + if ((scheme != 9) && (ddp_udp_up)) { + ddp_udp.stop(); + ddp_udp_up = 0; + AddLog(LOG_LEVEL_DEBUG_MORE, "DDP: UDP Stopped: WS2812 Scheme not DDP"); + } +#endif switch (scheme) { case 0: // Clock if ((1 == TasmotaGlobal.state_250mS) || (Ws2812.show_next)) { @@ -588,6 +649,11 @@ void Ws2812ShowScheme(void) Ws2812.show_next = 0; } break; +#ifdef USE_NETWORK_LIGHT_SCHEMES + case 9: + Ws2812DDP(); + break; +#endif default: if(Settings->light_step_pixels > 0){ Ws2812Steps(scheme -1); diff --git a/tasmota/xlgt_02_my92x1.ino b/tasmota/xlgt_02_my92x1.ino index 2c851a9b1..ef23c3c9c 100644 --- a/tasmota/xlgt_02_my92x1.ino +++ b/tasmota/xlgt_02_my92x1.ino @@ -125,7 +125,8 @@ void My92x1ModuleSelected(void) digitalWrite(My92x1.pdcki_pin, LOW); My92x1.model = 2; - TasmotaGlobal.light_type = LT_RGBW; // RGBW (2 chips) as used in Lohas + TasmotaGlobal.light_type = LT_RGBW; // RGBW (2 chips) as used in Lohas +#ifdef ESP8266 if (AILIGHT == TasmotaGlobal.module_type) { // RGBW (1 chip) as used in Ailight My92x1.model = 0; // TasmotaGlobal.light_type = LT_RGBW; @@ -134,6 +135,7 @@ void My92x1ModuleSelected(void) My92x1.model = 1; TasmotaGlobal.light_type = LT_RGBWC; } +#endif // ESP8266 LightMy92x1Init(); diff --git a/tasmota/xlgt_03_sm16716.ino b/tasmota/xlgt_03_sm16716.ino index c08df6a90..b1d4207b8 100644 --- a/tasmota/xlgt_03_sm16716.ino +++ b/tasmota/xlgt_03_sm16716.ino @@ -143,21 +143,6 @@ void Sm16716ModuleSelected(void) Sm16716.pin_dat = Pin(GPIO_SM16716_DAT); Sm16716.pin_sel = Pin(GPIO_SM16716_SEL); -/* - // init PWM - for (uint32_t i = 0; i < Light.subtype; i++) { - Settings->pwm_value[i] = 0; // Disable direct PWM control - if (PinUsed(GPIO_PWM1, i)) { -#ifdef ESP8266 - pinMode(Pin(GPIO_PWM1, i), OUTPUT); -#endif // ESP8266 -#ifdef ESP32 - analogAttach(Pin(GPIO_PWM1, i), i); -#endif // ESP32 - } - } -*/ - // init sm16716 pinMode(Sm16716.pin_clk, OUTPUT); digitalWrite(Sm16716.pin_clk, LOW); diff --git a/tasmota/xlgt_07_lsc_mcsl.ino b/tasmota/xlgt_07_lsc_mcsl.ino index 9e8ec00e6..d7c9bbfd2 100644 --- a/tasmota/xlgt_07_lsc_mcsl.ino +++ b/tasmota/xlgt_07_lsc_mcsl.ino @@ -17,6 +17,8 @@ along with this program. If not, see . */ +#define USE_LSC_MCSL_GUI + #ifdef USE_LIGHT #ifdef USE_LSC_MCSL /*********************************************************************************************\ @@ -27,6 +29,17 @@ * Template: * {"NAME":"LSC MC Lights","GPIO":[0,0,0,0,544,32,0,0,3840,0,3872,0,0,0],"FLAG":0,"BASE":18} * + * Webbutton: + * {"WebButton1":"On / Off", + * "WebButton2":"Bright", + * "WebButton3":"Slow", + * "WebButton4":"Star", + * "WebButton5":"Flower", + * "WebButton6":"Marquee", + * "WebButton7":"Fireworks", + * "WebButton8":"Meteor", + * "WebButton9":"Stream"} + * * NL: Action LSC Multi color smart lights * * Button usage: @@ -232,6 +245,51 @@ void LscMcModuleSelected(void) { // AddLog(LOG_LEVEL_DEBUG, PSTR("LGT: LSC Multi Color Found")); } +#ifdef USE_WEBSERVER +#ifdef USE_LSC_MCSL_GUI + +void LscMcAddFuctionButtons(void) { + uint32_t rows = 1; + uint32_t cols = 8; + for (uint32_t i = 0; i < 8; i++) { + if (strlen(SettingsText(SET_BUTTON1 + i +1))) { + rows <<= 1; + cols >>= 1; + break; + } + } + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("
")); +} + +void LscMcWebGetArg(void) { + char tmp[8]; // WebGetArg numbers only + WebGetArg(PSTR("lsc"), tmp, sizeof(tmp)); // 0 - 7 functions + if (strlen(tmp)) { + uint32_t function = atoi(tmp); + char command[20]; + snprintf_P(command, sizeof(command), PSTR(D_CMND_DIMMER " %d"), (function * (100 / 8)) + ((100 / 8) / 2)); + ExecuteWebCommand(command); + } +} + +#endif // USE_LSC_MCSL_GUI +#endif // USE_WEBSERVER + + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -247,6 +305,16 @@ bool Xlgt07(uint8_t function) case FUNC_BUTTON_MULTI_PRESSED: result = LscMcMultiButtonPressed(); break; +#ifdef USE_WEBSERVER +#ifdef USE_LSC_MCSL_GUI + case FUNC_WEB_ADD_MAIN_BUTTON: + LscMcAddFuctionButtons(); + break; + case FUNC_WEB_GET_ARG: + LscMcWebGetArg(); + break; +#endif // USE_LSC_MCSL_GUI +#endif // USE_WEBSERVER case FUNC_MODULE_INIT: LscMcModuleSelected(); break; diff --git a/tasmota/xnrg_02_cse7766.ino b/tasmota/xnrg_02_cse7766.ino index 445781b37..552e2b209 100644 --- a/tasmota/xnrg_02_cse7766.ino +++ b/tasmota/xnrg_02_cse7766.ino @@ -20,7 +20,7 @@ #ifdef USE_ENERGY_SENSOR #ifdef USE_CSE7766 /*********************************************************************************************\ - * CSE7759 and CSE7766 - Energy (Sonoff S31 and Sonoff Pow R2) + * CSE7759 and CSE7766 - Energy (Sonoff S31 and Sonoff Pow R2/R3) * HLW8032 - Energy (Blitzwolf SHP5) * * Needs GPIO_CSE7766_RX only @@ -203,7 +203,9 @@ void CseEverySecond(void) { uint32_t delta = (cf_pulses * Settings->energy_power_calibration) / 36; // prevent invalid load delta steps even checksum is valid (issue #5789): // prevent invalid load delta steps even checksum is valid but allow up to 4kW (issue #7155): - if (delta <= (4000 * 1000 / 36)) { // max load for S31/Pow R2: 4.00kW +// if (delta <= (4000 * 1000 / 36)) { // max load for S31/Pow R2: 4.00kW + // prevent invalid load delta steps even checksum is valid but allow up to 5.5kW (issue #14156): + if (delta <= (5500 * 1000 / 36)) { // max load for Pow R3: 5.50kW Cse.cf_pulses_last_time = Cse.cf_pulses; Energy.kWhtoday_delta[0] += delta; } diff --git a/tasmota/xnrg_06_pzem_dc.ino b/tasmota/xnrg_06_pzem_dc.ino index 074152684..4e325594f 100644 --- a/tasmota/xnrg_06_pzem_dc.ino +++ b/tasmota/xnrg_06_pzem_dc.ino @@ -112,7 +112,7 @@ void PzemDcEverySecond(void) void PzemDcSnsInit(void) { PzemDcModbus = new TasmotaModbus(Pin(GPIO_PZEM017_RX), Pin(GPIO_PZEM0XX_TX)); - uint8_t result = PzemDcModbus->Begin(9600, 2); // Uses two stop bits!! + uint8_t result = PzemDcModbus->Begin(9600, SERIAL_8N2); if (result) { if (2 == result) { ClaimSerial(); } Energy.type_dc = true; diff --git a/tasmota/xnrg_07_ade7953.ino b/tasmota/xnrg_07_ade7953.ino index a09e4f257..6205612be 100644 --- a/tasmota/xnrg_07_ade7953.ino +++ b/tasmota/xnrg_07_ade7953.ino @@ -236,7 +236,16 @@ void Ade7953DrvInit(void) if (PinUsed(GPIO_ADE7953_IRQ, GPIO_ANY)) { // Irq on GPIO16 is not supported... uint32_t pin_irq = Pin(GPIO_ADE7953_IRQ, GPIO_ANY); pinMode(pin_irq, INPUT); // Related to resetPins() - Must be set to input - Ade7953.model = GetPin(pin_irq) - AGPIO(GPIO_ADE7953_IRQ); // 0 .. 1 ; + Ade7953.model = GetPin(pin_irq) - AGPIO(GPIO_ADE7953_IRQ); // 0 (Shelly 2.5), 1 (Shelly EM) + + if (1 == Ade7953.model) { // Shelly EM + pinMode(16, OUTPUT); // Reset pin ADE7953 + digitalWrite(16, 0); + delay(1); + digitalWrite(16, 1); + pinMode(16, INPUT); + } + delay(100); // Need 100mS to init ADE7953 if (I2cSetDevice(ADE7953_ADDR)) { if (HLW_PREF_PULSE == Settings->energy_power_calibration) { diff --git a/tasmota/xnrg_12_solaxX1.ino b/tasmota/xnrg_12_solaxX1.ino index 352757b6e..fa925e519 100644 --- a/tasmota/xnrg_12_solaxX1.ino +++ b/tasmota/xnrg_12_solaxX1.ino @@ -83,7 +83,8 @@ union { }; } ErrCode; -const char kSolaxMode[] PROGMEM = D_WAITING "|" D_CHECKING "|" D_WORKING "|" D_FAILURE; +const char kSolaxMode[] PROGMEM = D_OFF "|" D_SOLAX_MODE_0 "|" D_SOLAX_MODE_1 "|" D_SOLAX_MODE_2 "|" D_SOLAX_MODE_3 "|" + D_SOLAX_MODE_4 "|" D_SOLAX_MODE_5 "|" D_SOLAX_MODE_6; const char kSolaxError[] PROGMEM = D_SOLAX_ERROR_0 "|" D_SOLAX_ERROR_1 "|" D_SOLAX_ERROR_2 "|" D_SOLAX_ERROR_3 "|" D_SOLAX_ERROR_4 "|" D_SOLAX_ERROR_5 "|" @@ -94,7 +95,7 @@ const char kSolaxError[] PROGMEM = TasmotaSerial *solaxX1Serial; struct SOLAXX1 { - float temperature = 0; + int16_t temperature = 0; float energy_today = 0; float dc1_voltage = 0; float dc2_voltage = 0; @@ -104,7 +105,7 @@ struct SOLAXX1 { float dc1_power = 0; float dc2_power = 0; - uint8_t status = 0; + int16_t runMode = 0; uint32_t errorCode = 0; } solaxX1; @@ -155,10 +156,18 @@ void solaxX1_RS485Send(uint16_t msgLen) solaxX1Serial->read(); } + if (PinUsed(GPIO_SOLAXX1_RTS)) { + digitalWrite(Pin(GPIO_SOLAXX1_RTS), HIGH); + } solaxX1Serial->flush(); solaxX1Serial->write(message, msgLen); solaxX1Serial->write(highByte(crc)); solaxX1Serial->write(lowByte(crc)); + solaxX1Serial->flush(); + if (PinUsed(GPIO_SOLAXX1_RTS)) { + digitalWrite(Pin(GPIO_SOLAXX1_RTS), LOW); + } + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, message, msgLen); } @@ -260,7 +269,7 @@ void solaxX1250MSecond(void) // Every 250 milliseconds solaxX1_send_retry = 20; Energy.data_valid[0] = 0; - solaxX1.temperature = (float)((value[9] << 8) | value[10]); // Temperature + solaxX1.temperature = (value[9] << 8) | value[10]; // Temperature solaxX1.energy_today = (float)((value[11] << 8) | value[12]) * 0.1f; // Energy Today solaxX1.dc1_voltage = (float)((value[13] << 8) | value[14]) * 0.1f; // PV1 Voltage solaxX1.dc2_voltage = (float)((value[15] << 8) | value[16]) * 0.1f; // PV2 Voltage @@ -273,7 +282,7 @@ void solaxX1250MSecond(void) // Every 250 milliseconds //temporal = (float)((value[29] << 8) | value[30]) * 0.1f; // Not Used Energy.import_active[0] = (float)((value[31] << 24) | (value[32] << 16) | (value[33] << 8) | value[34]) * 0.1f; // Energy Total solaxX1.runtime_total = ((value[35] << 24) | (value[36] << 16) | (value[37] << 8) | value[38]); // Work Time Total - solaxX1.status = (uint8_t)((value[39] << 8) | value[40]); // Work mode + solaxX1.runMode = (value[39] << 8) | value[40]; // Work mode //temporal = (float)((value[41] << 8) | value[42]); // Grid voltage fault value 0.1V //temporal = (float)((value[43] << 8) | value[44]); // Gird frequency fault value 0.01Hz //temporal = (float)((value[45] << 8) | value[46]); // Dc injection fault value 1mA @@ -281,7 +290,7 @@ void solaxX1250MSecond(void) // Every 250 milliseconds //temporal = (float)((value[49] << 8) | value[50]); // Pv1 voltage fault value 0.1V //temporal = (float)((value[51] << 8) | value[52]); // Pv2 voltage fault value 0.1V //temporal = (float)((value[53] << 8) | value[54]); // GFC fault value - solaxX1.errorCode = ((value[58] << 24) | (value[57] << 16) | (value[56] << 8) | value[55]); // Error Code + solaxX1.errorCode = (value[58] << 24) | (value[57] << 16) | (value[56] << 8) | value[55]; // Error Code solaxX1.dc1_power = solaxX1.dc1_voltage * solaxX1.dc1_current; solaxX1.dc2_power = solaxX1.dc2_voltage * solaxX1.dc2_current; @@ -363,8 +372,8 @@ void solaxX1250MSecond(void) // Every 250 milliseconds Energy.data_valid[0] = ENERGY_WATCHDOG; solaxX1.temperature = solaxX1.dc1_voltage = solaxX1.dc2_voltage = solaxX1.dc1_current = solaxX1.dc2_current = solaxX1.dc1_power = 0; - solaxX1.dc2_power = solaxX1.status = Energy.current[0] = Energy.voltage[0] = Energy.frequency[0] = Energy.active_power[0] = 0; - //solaxX1.energy_today = solaxX1.runtime_total = 0; + solaxX1.dc2_power = Energy.current[0] = Energy.voltage[0] = Energy.frequency[0] = Energy.active_power[0] = 0; + solaxX1.runMode = -1; // off(line) } else { if (protocolStatus.queryOfflineSend) { protocolStatus.status = 0b00001000; // queryOffline @@ -380,7 +389,8 @@ void solaxX1250MSecond(void) // Every 250 milliseconds void solaxX1SnsInit(void) { AddLog(LOG_LEVEL_DEBUG, PSTR("SX1: Solax X1 Inverter Init")); - DEBUG_SENSOR_LOG(PSTR("SX1: RX pin: %d, TX pin: %d"), Pin(GPIO_SOLAXX1_RX), Pin(GPIO_SOLAXX1_TX)); + AddLog(LOG_LEVEL_DEBUG, PSTR("SX1: RX-pin: %d, TX-pin: %d, RTS-pin: %d"), Pin(GPIO_SOLAXX1_RX), Pin(GPIO_SOLAXX1_TX), Pin(GPIO_SOLAXX1_RTS)); +// DEBUG_SENSOR_LOG(PSTR("SX1: RX pin: %d, TX pin: %d"), Pin(GPIO_SOLAXX1_RX), Pin(GPIO_SOLAXX1_TX)); protocolStatus.status = 0b00100000; // hasAddress solaxX1Serial = new TasmotaSerial(Pin(GPIO_SOLAXX1_RX), Pin(GPIO_SOLAXX1_TX), 1); @@ -389,6 +399,9 @@ void solaxX1SnsInit(void) } else { TasmotaGlobal.energy_driver = ENERGY_NONE; } + if (PinUsed(GPIO_SOLAXX1_RTS)) { + pinMode(Pin(GPIO_SOLAXX1_RTS), OUTPUT); + } } void solaxX1DrvInit(void) @@ -437,7 +450,7 @@ void solaxX1Show(bool json) char runtime[33]; dtostrfd(solaxX1.runtime_total, 0, runtime); char status[33]; - GetTextIndexed(status, sizeof(status), solaxX1.status, kSolaxMode); + GetTextIndexed(status, sizeof(status), solaxX1.runMode + 1, kSolaxMode); if (json) { @@ -447,12 +460,12 @@ void solaxX1Show(bool json) ResponseAppend_P(PSTR(",\"" D_JSON_PV2_VOLTAGE "\":%s,\"" D_JSON_PV2_CURRENT "\":%s,\"" D_JSON_PV2_POWER "\":%s"), pv2_voltage, pv2_current, pv2_power); #endif - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%*_f,\"" D_JSON_RUNTIME "\":%s,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d"), - Settings->flag2.temperature_resolution, &solaxX1.temperature, runtime, status, solaxX1.errorCode); + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%d,\"" D_JSON_RUNTIME "\":%s,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d"), + solaxX1.temperature, runtime, status, solaxX1.errorCode); #ifdef USE_DOMOTICZ // Avoid bad temperature report at beginning of the day (spikes of 1200 celsius degrees) - if (0 == TasmotaGlobal.tele_period && solaxX1.temperature < 100) { DomoticzFloatSensor(DZ_TEMP, solaxX1.temperature); } + if (0 == TasmotaGlobal.tele_period && solaxX1.temperature < 100) { DomoticzSensor(DZ_TEMP, solaxX1.temperature); } #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER @@ -500,4 +513,4 @@ bool Xnrg12(uint8_t function) } #endif // USE_SOLAX_X1_NRG -#endif // USE_ENERGY_SENSOR \ No newline at end of file +#endif // USE_ENERGY_SENSOR diff --git a/tasmota/xnrg_14_bl09xx.ino b/tasmota/xnrg_14_bl09xx.ino index bca55c513..040739c24 100644 --- a/tasmota/xnrg_14_bl09xx.ino +++ b/tasmota/xnrg_14_bl09xx.ino @@ -279,7 +279,7 @@ void Bl09XXEverySecond(void) { void Bl09XXInit(void) { // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions Bl09XXSerial = new TasmotaSerial(Bl09XX.rx_pin, Pin(GPIO_TXD), 1); - if (Bl09XXSerial->begin(4800, 1)) { + if (Bl09XXSerial->begin(4800)) { if (Bl09XXSerial->hardwareSerial()) { ClaimSerial(); } diff --git a/tasmota/xnrg_15_teleinfo.ino b/tasmota/xnrg_15_teleinfo.ino index 37b16084f..33a9f35d7 100755 --- a/tasmota/xnrg_15_teleinfo.ino +++ b/tasmota/xnrg_15_teleinfo.ino @@ -333,56 +333,55 @@ void DataCallback(struct _ValueList * me, uint8_t flags) // Base, un seul index if (ilabel == LABEL_BASE) { - total = atoi(me->value); - AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: Base:%u"), total); + total = atol(me->value); + AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: Base:%ld"), total); // Heures creuses/pleines calculer total } else { // Heures creuses get heures pleines if (ilabel == LABEL_HCHC) { - hc = atoi(me->value); + hc = atol(me->value); if ( getValueFromLabelIndex(LABEL_HCHP, value) ) { - hp = atoi(value); + hp = atol(value) ; } // Heures pleines, get heures creuses } else if (ilabel == LABEL_HCHP) { - hp = atoi(me->value); + hp = atol(me->value); if ( getValueFromLabelIndex(LABEL_HCHC, value) ) { - hc = atoi(value); + hc = atol(value) ; } } - total = hc + hp; - AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u HP:%u Total:%u"), hc, hp, total); + if (hc>0 && hp>0) { + total = hc + hp; + } + AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%ld HP:%ld Total:%ld"), hc, hp, total); } - Energy.import_active[0] = total/1000.0f; - EnergyUpdateTotal(); - AddLog (LOG_LEVEL_INFO, PSTR ("TIC: Total counter updated to %u Wh"), total); + AddLog (LOG_LEVEL_INFO, PSTR ("TIC: Total counter updated to %ld Wh"), total); + if (total>0) { + Energy.import_active[0] = (float)total/1000.0f; + EnergyUpdateTotal(); + AddLog (LOG_LEVEL_DEBUG_MORE, PSTR ("TIC: import_active[0]=%.3fKWh"), Energy.import_active[0] ); + } } - // Wh total index (standard) + // Wh total index (all contract) else if ( ilabel == LABEL_EAST) { - uint32_t total = atoi(me->value); - if (contrat != CONTRAT_BAS) { - Energy.import_active[0] = total/1000.0f; - EnergyUpdateTotal(); - AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: Total:%uWh"), total); - } + uint32_t total = atol(me->value); + Energy.import_active[0] = (float)total/1000.0f; + EnergyUpdateTotal(); + AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: Total:%ldWh"), total); } // Wh indexes (standard) else if ( ilabel == LABEL_EASF01) { - if (contrat == CONTRAT_BAS) { - Energy.import_active[0] = atoi(me->value)/1000.0f; - EnergyUpdateTotal(); - } - AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u"), atoi(me->value)); + AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%ld"), atol(me->value)); } else if ( ilabel == LABEL_EASF02) { - AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: HP:%u"), atoi(me->value)); + AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: HP:%ld"), atol(me->value)); } // Contract subscribed (legacy) @@ -504,7 +503,7 @@ bool ResponseAppendTInfo(char sep, bool all) if (!isNumber) { ResponseAppend_P( PSTR("\"%s\""), me->value ); } else { - ResponseAppend_P( PSTR("%d"), atoi(me->value)); + ResponseAppend_P( PSTR("%ld"), atol(me->value)); } // Now JSON separator is needed diff --git a/tasmota/xnrg_21_sdm230.ino b/tasmota/xnrg_21_sdm230.ino new file mode 100644 index 000000000..e7b28068a --- /dev/null +++ b/tasmota/xnrg_21_sdm230.ino @@ -0,0 +1,282 @@ +/* + xnrg_21_sdm230.ino - Eastron SDM230-Modbus energy meter support for Tasmota + + Copyright (C) 2022 dad401 and Theo Arends + + This program 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 . +*/ + +#ifdef USE_ENERGY_SENSOR +#ifdef USE_SDM230 +/*********************************************************************************************\ + * Eastron SDM230 Modbus energy meter + * + * Based on: existing tasmota drivers for SDM120 and SDM630, + * https://github.com/reaper7/SDM_Energy_Meter and https://github.com/nmakel/sdm_modbus + + * manuals can be found here: + * German: https://bg-etech.de/download/manual/SDM230-Modbus.pdf + * English: https://www.eastroneurope.com/images/uploads/products/manuals/SDM230_Sereis_Manual.pdf + * Protocol Spec: https://www.eastroneurope.com/images/uploads/products/protocol/Correct_SDM230_Protocol.pdf +\*********************************************************************************************/ + +#define XNRG_21 21 + +// can be user defined in my_user_config.h +#ifndef SDM230_SPEED + #define SDM230_SPEED 9600 // default SDM230 Modbus baudrate +#endif +// can be user defined in my_user_config.h +#ifndef SDM230_ADDR + #define SDM230_ADDR 1 // default SDM120 Modbus address +#endif + +#include +TasmotaModbus *Sdm230Modbus; + +// read all default registers for generic energy driver +const uint16_t sdm230_start_addresses[] { + 0x0000, // SDM230_VOLTAGE [V] + 0x0006, // SDM230_CURRENT [A] + 0x000C, // SDM230_POWER (Active) [W] + 0x0012, // SDM230_POWER (Apparent) G [VA] + 0x0018, // SDM230_POWER (Reactive) [VAr] + 0x001E, // SDM230_POWER_FACTOR + 0x0046, // SDM230_FREQUENCY [Hz] + 0X0048, // SDM230_IMPORT_ACTIVE [kWh] + 0X004A, // SDM230_EXPORT_ACTIVE [kWh] +// 0X0156, // SDM230_TOTAL_ENERGY_ACTIVE [kWh] // = SDM230_IMPORT_ACTIVE = Energy.total + +// read more registers offered by SDM230 (may cause timing issues) +#ifdef SDM230_MORE_REGS + 0x0024, // SDM230_PHASE ANGLE [Degree] + 0X0056, // SDM230_MAXIMUM_TOTAL_DEMAND_POWER_ACTIVE [W] + 0X0180, // SDM230_RESETTABLE_TOTAL_ENERGY_ACTIVE [kWh] +#endif // SDM230_MORE_REGS + +// for documentation / further use or implementation +// 0X0158, // SDM230_TOTAL_ENERGY_REACTIVE [kVArh] +// 0X0182, // SDM230_RESETTABLE_TOTAL_ENERGY_REACTIVE [kVArh] +// 0X004C, // SDM230_IMPORT_REACTIVE [kVArh] +// 0X004E, // SDM230_EXPORT_REACTIVE [kVArh] +// 0X0054, // SDM230_TOTAL_DEMAND_POWER_ACTIVE [W] +// 0X0058, // SDM230_IMPORT_DEMAND_POWER_ACTIVE [W] +// 0X005A, // SDM230_MAXIMUM_IMPORT_DEMAND_POWER_ACTIVE [W] +// 0X005C, // SDM230_EXPORT_DEMAND_POWER_ACTIVE [W] +// 0X005E, // SDM230_MAXIMUM_EXPORT_DEMAND_POWER_ACTIVE [W] +// 0X0102, // SDM230_TOTAL_DEMAND_CURRENT [A] +// 0X0108, // SDM230_MAXIMUM_TOTAL_DEMAND_CURRENT [A] +}; + +struct SDM230 { +#ifdef SDM230_MORE_REGS + float phase_angle = 0; + float maximum_total_demand_power_active = 0; + float resettable_total_energy = 0; +#endif // SDM230_MORE_REGS + uint8_t read_state = 0; + uint8_t send_retry = 0; +} Sdm230; + +/*********************************************************************************************/ + +void SDM230Every250ms(void) +{ + bool data_ready = Sdm230Modbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; // At least 5 + (2 * 2) = 9 + + uint32_t error = Sdm230Modbus->ReceiveBuffer(buffer, 2); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Sdm230Modbus->ReceiveCount()); + + if (error) { + AddLog(LOG_LEVEL_DEBUG, PSTR("SDM: SDM230 error %d"), error); + } else { + Energy.data_valid[0] = 0; + + // 0 1 2 3 4 5 6 7 8 + // SA FC BC Fh Fl Sh Sl Cl Ch + // 01 04 04 43 66 33 34 1B 38 = 230.2 Volt + float value; + ((uint8_t*)&value)[3] = buffer[3]; // Get float values + ((uint8_t*)&value)[2] = buffer[4]; + ((uint8_t*)&value)[1] = buffer[5]; + ((uint8_t*)&value)[0] = buffer[6]; + + switch(Sdm230.read_state) { + case 0: + Energy.voltage[0] = value; // 230.2 V + break; + + case 1: + Energy.current[0] = value; // 1.260 A + break; + + case 2: + Energy.active_power[0] = value; // -196.3 W + break; + + case 3: + Energy.apparent_power[0] = value; // 223.4 VA + break; + + case 4: + Energy.reactive_power[0] = value; // 92.2 + break; + + case 5: + Energy.power_factor[0] = value; // -0.91 + break; + + case 6: + Energy.frequency[0] = value; // 50.0 Hz + break; + + case 7: + Energy.import_active[0] = value; // 6.216 kWh => used in EnergyUpdateTotal() + break; + + case 8: + Energy.export_active[0] = value; // 478.492 kWh + break; + + #ifdef SDM230_MORE_REGS + case 9: + Sdm230.phase_angle = value; // 0.00 Deg + break; + + case 10: + Sdm230.maximum_total_demand_power_active = value; + break; + + case 11: + Sdm230.resettable_total_energy = value; + break; + #endif // SDM230_MORE_REGS + } + + Sdm230.read_state++; + if (sizeof(sdm230_start_addresses)/2 == Sdm230.read_state) { + Sdm230.read_state = 0; + EnergyUpdateTotal(); // update every cycle after all registers have been read + } + + } + } // end data ready + + if (0 == Sdm230.send_retry || data_ready) { + Sdm230.send_retry = 5; + Sdm230Modbus->Send(SDM230_ADDR, 0x04, sdm230_start_addresses[Sdm230.read_state], 2); + } else { + Sdm230.send_retry--; + } +} + +void Sdm230SnsInit(void) +{ + Sdm230Modbus = new TasmotaModbus(Pin(GPIO_SDM230_RX), Pin(GPIO_SDM230_TX)); + uint8_t result = Sdm230Modbus->Begin(SDM230_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + Energy.phase_count = 1; + Energy.frequency_common = true; // Use common frequency + } else { + TasmotaGlobal.energy_driver = ENERGY_NONE; + } +} + +void Sdm230DrvInit(void) +{ + if (PinUsed(GPIO_SDM230_RX) && PinUsed(GPIO_SDM230_TX)) { + TasmotaGlobal.energy_driver = XNRG_21; + } +} + +void Sdm230Reset(void) +{ + #ifdef SDM230_MORE_REGS + Sdm230.phase_angle = 0; + Sdm230.maximum_total_demand_power_active = 0; + Sdm230.resettable_total_energy = 0; + #endif // SDM230_MORE_REGS +} + +#ifdef SDM230_MORE_REGS +#ifdef USE_WEBSERVER +const char HTTP_ENERGY_SDM230[] PROGMEM = + "{s}" D_PHASE_ANGLE "{m}%s " D_UNIT_ANGLE "{e}" + "{s}" D_MAX_POWER "{m}%s " D_UNIT_WATT "{e}" + "{s}" D_RESETTABLE_TOTAL_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; +#endif // USE_WEBSERVER +#endif // SDM230_MORE_REGS + +#ifdef SDM230_MORE_REGS +void Sdm230Show(bool json) +{ + char phase_angle_chr[FLOATSZ]; + dtostrfd(Sdm230.phase_angle, 2, phase_angle_chr); + char maximum_demand_chr[FLOATSZ]; + dtostrfd(Sdm230.maximum_total_demand_power_active, Settings->flag2.wattage_resolution, maximum_demand_chr); + char resettable_energy_chr[FLOATSZ]; + dtostrfd(Sdm230.resettable_total_energy, Settings->flag2.energy_resolution, resettable_energy_chr); + + if (json) { + ResponseAppend_P(PSTR(",\"" D_JSON_PHASE_ANGLE "\":%s,\"" D_JSON_POWERMAX "\":%s,\"" D_JSON_RESETTABLE_TOTAL_ACTIVE "\":%s"), + phase_angle_chr, maximum_demand_chr, resettable_energy_chr); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_ENERGY_SDM230, phase_angle_chr, maximum_demand_chr, resettable_energy_chr); +#endif // USE_WEBSERVER + } +} +#endif // SDM230_MORE_REGS + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xnrg21(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + SDM230Every250ms(); + break; +#ifdef SDM230_MORE_REGS + case FUNC_JSON_APPEND: + Sdm230Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sdm230Show(0); + break; +#endif // USE_WEBSERVER +#endif // SDM230_MORE_REGS + case FUNC_ENERGY_RESET: + Sdm230Reset(); + break; + case FUNC_INIT: + Sdm230SnsInit(); + break; + case FUNC_PRE_INIT: + Sdm230DrvInit(); + break; + } + return result; +} + +#endif // USE_SDM230 +#endif // USE_ENERGY_SENSOR diff --git a/tasmota/xsns_02_analog.ino b/tasmota/xsns_02_analog.ino index c6fce4051..4ba748f86 100644 --- a/tasmota/xsns_02_analog.ino +++ b/tasmota/xsns_02_analog.ino @@ -111,6 +111,41 @@ // Multiplier used to store pH with 2 decimal places in a non decimal datatype #define ANALOG_PH_DECIMAL_MULTIPLIER 100.0 +// MQ-X sensor (MQ-02, MQ-03, MQ-04, MQ-05, MQ-06, MQ-07, MQ-08, MQ-09, MQ-131, MQ-135) +// +// A0 ------------------- +// | +// GND ----------- | +// | | +// VCC --- | | +// | | | +// 3V3 GND ADC <- (A0 for nodemcu, wemos; GPIO34,35,36,39 and other analog IN/OUT pin for esp32) +//means mq type (ex for mq-02 use 2, mq-131 use 131) +#define ANALOG_MQ_TYPE 2 +//exponential regression a params +#define ANALOG_MQ_A 574.25 +//exponential regression b params +#define ANALOG_MQ_B -2.222 +/* + Exponential regression: + Gas | a | b + LPG | 44771 | -3.245 + CH4 | 2*10^31| 19.01 + CO | 521853 | -3.821 + Alcohol| 0.3934 | -1.504 + Benzene| 4.8387 | -2.68 + Hexane | 7585.3 | -2.849 + NOx | -462.43 | -2.204 + CL2 | 47.209 | -1.186 + O3 | 23.943 | -1.11 +*/ +//ratio for alarm, NOT USED yet (RS / R0 = 15 ppm) +#define ANALOG_MQ_RatioMQCleanAir 15.0 +// Multiplier used to store pH with 2 decimal places in a non decimal datatype +#define ANALOG_MQ_DECIMAL_MULTIPLIER 100.0 +// lenght of filter +#define ANALOG_MQ_SAMPLES 60 + struct { uint8_t present = 0; uint8_t type = 0; @@ -128,6 +163,8 @@ struct { uint16_t last_value = 0; uint8_t type = 0; uint8_t pin = 0; + float mq_samples[ANALOG_MQ_SAMPLES]; + int indexOfPointer = -1; } Adc[MAX_ADCS]; #ifdef ESP8266 @@ -189,6 +226,12 @@ void AdcInitParams(uint8_t idx) { Adc[idx].param3 = ANALOG_PH_CALSOLUTION_HIGH_PH * ANALOG_PH_DECIMAL_MULTIPLIER; // PH of the calibration solution 2, which is the one with the higher PH Adc[idx].param4 = ANALOG_PH_CALSOLUTION_HIGH_ANALOG_VALUE; // Reading of AnalogInput while probe is in solution 2 } + else if (ADC_MQ == Adc[idx].type) { + Adc[idx].param1 = ANALOG_MQ_TYPE; // Could be MQ-002, MQ-004, MQ-131 .... + Adc[idx].param2 = (int)(ANALOG_MQ_A * ANALOG_MQ_DECIMAL_MULTIPLIER); // Exponential regression + Adc[idx].param3 = (int)(ANALOG_MQ_B * ANALOG_MQ_DECIMAL_MULTIPLIER); // Exponential regression + Adc[idx].param4 = (int)(ANALOG_MQ_RatioMQCleanAir * ANALOG_MQ_DECIMAL_MULTIPLIER); // Exponential regression + } } if ((Adcs.type != Adc[idx].type) || (0 == Adc[idx].param1) || (Adc[idx].param1 > ANALOG_RANGE)) { if ((ADC_BUTTON == Adc[idx].type) || (ADC_BUTTON_INV == Adc[idx].type)) { @@ -200,7 +243,7 @@ void AdcInitParams(uint8_t idx) { } } -void AdcAttach(uint8_t pin, uint8_t type) { +void AdcAttach(uint32_t pin, uint8_t type) { if (Adcs.present == MAX_ADCS) { return; } Adc[Adcs.present].pin = pin; if (adcAttachPin(Adc[Adcs.present].pin)) { @@ -234,6 +277,9 @@ void AdcInit(void) { if (PinUsed(GPIO_ADC_PH, i)) { AdcAttach(Pin(GPIO_ADC_PH, i), ADC_PH); } + if (PinUsed(GPIO_ADC_MQ, i)) { + AdcAttach(Pin(GPIO_ADC_MQ, i), ADC_MQ); + } } for (uint32_t i = 0; i < MAX_KEYS; i++) { if (PinUsed(GPIO_ADC_BUTTON, i)) { @@ -334,17 +380,54 @@ uint16_t AdcGetLux(uint32_t idx) { return (uint16_t)ldrLux; } +void AddSampleMq(uint32_t idx){ + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Adding sample for mq-sensor")); + int _adc = AdcRead(Adc[idx].pin, 2); + // init af array at same value + if (Adc[idx].indexOfPointer==-1) + { + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Init samples for mq-sensor")); + for (int i = 0; i < ANALOG_MQ_SAMPLES; i ++) + Adc[idx].mq_samples[i] = _adc; + } + else + Adc[idx].mq_samples[Adc[idx].indexOfPointer] = _adc; + Adc[idx].indexOfPointer++; + if (Adc[idx].indexOfPointer==ANALOG_MQ_SAMPLES) + Adc[idx].indexOfPointer=0; +} + +float AdcGetMq(uint32_t idx) { + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Getting value for mq-sensor")); + float avg = 0.0; + float _RL = 10; //Value in KiloOhms + float _R0 = 10; + for (int i = 0; i < ANALOG_MQ_SAMPLES; i ++) + avg += Adc[idx].mq_samples[i]; + float voltage = (avg / ANALOG_MQ_SAMPLES) * ANALOG_V33 / ((FastPrecisePow(2, ANALOG_RESOLUTION)) - 1); + + float _RS_Calc = ((ANALOG_V33 * _RL) / voltage) -_RL; //Get value of RS in a gas + if (_RS_Calc < 0) _RS_Calc = 0; //No negative values accepted. + float _ratio = _RS_Calc / _R0; // Get ratio RS_gas/RS_air + float ppm= Adc[idx].param2/ANALOG_MQ_DECIMAL_MULTIPLIER*FastPrecisePow(_ratio, Adc[idx].param3/ANALOG_MQ_DECIMAL_MULTIPLIER); // <- Source excel analisis https://github.com/miguel5612/MQSensorsLib_Docs/tree/master/Internal_design_documents + if(ppm < 0) ppm = 0; //No negative values accepted or upper datasheet recomendation. + char ppm_chr[6]; + dtostrfd(ppm, 2, ppm_chr); + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Ppm read. ADC-RAW: %2_f, ppm: %s,"), &voltage, ppm_chr); + return ppm; +} + float AdcGetPh(uint32_t idx) { int adc = AdcRead(Adc[idx].pin, 2); - float y1 = Adc[idx].param1 / ANALOG_PH_DECIMAL_MULTIPLIER; - uint32_t x1 = Adc[idx].param2; - float y2 = Adc[idx].param3 / ANALOG_PH_DECIMAL_MULTIPLIER; - uint32_t x2 = Adc[idx].param4; + float y1 = (float)Adc[idx].param1 / ANALOG_PH_DECIMAL_MULTIPLIER; + int32_t x1 = Adc[idx].param2; + float y2 = (float)Adc[idx].param3 / ANALOG_PH_DECIMAL_MULTIPLIER; + int32_t x2 = Adc[idx].param4; - float m = (y2 - y1) / (x2 - x1); - float ph = m * (adc - x1) + y1; + float m = (y2 - y1) / (float)(x2 - x1); + float ph = m * (float)(adc - x1) + y1; char phLow_chr[6]; @@ -417,7 +500,7 @@ void AdcEverySecond(void) { double Rt = (adc * Adc[idx].param1) / (ANALOG_RANGE * ANALOG_V33 - (double)adc); // Shelly param1 = 32000 (ANALOG_NTC_BRIDGE_RESISTANCE) #else double Rt = (adc * Adc[idx].param1) / (ANALOG_RANGE - (double)adc); -#endif +#endif double BC = (double)Adc[idx].param3 / 10000; // Shelly param3 = 3350 (ANALOG_NTC_B_COEFFICIENT) double T = BC / (BC / ANALOG_T0 + TaylorLog(Rt / (double)Adc[idx].param2)); // Shelly param2 = 10000 (ANALOG_NTC_RESISTANCE) Adc[idx].temperature = ConvertTemp(TO_CELSIUS(T)); @@ -425,6 +508,10 @@ void AdcEverySecond(void) { else if (ADC_CT_POWER == Adc[idx].type) { AdcGetCurrentPower(idx, 5); } + else if (ADC_MQ == Adc[idx].type) { + AddSampleMq(idx); + AdcGetMq(idx); + } } } @@ -575,6 +662,25 @@ void AdcShow(bool json) { #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_SNS_PH, "", ph_chr); + #endif // USE_WEBSERVER + } + break; + } + case ADC_MQ: { + float mq = AdcGetMq(idx); + char mq_chr[6]; + dtostrfd(mq, 2, mq_chr); + + float mqnumber =Adc[idx].param1; + char mqnumber_chr[6]; + dtostrfd(mqnumber, 0, mqnumber_chr); + + if (json) { + AdcShowContinuation(&jsonflg); + ResponseAppend_P(PSTR("\"MQ%d_%d\":%s"), Adc[idx].param1, idx + offset, mq_chr); + #ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_MQ, mqnumber_chr, mq_chr); #endif // USE_WEBSERVER } break; @@ -638,6 +744,43 @@ void CmndAdcParam(void) { Adc[idx].param1 ^= CT_FLAG_ENERGY_RESET; // Cancel energy reset flag } } + if (ADC_MQ == XdrvMailbox.payload) { + float a = CharToFloat(ArgV(argument, 3)); + float b = CharToFloat(ArgV(argument, 4)); + float ratioMQCleanAir = CharToFloat(ArgV(argument, 5)); + if (a==0 && b==0 && ratioMQCleanAir==0) + { + if (Adc[idx].param1==2) + { + a=574.25; + b=-2.222; + ratioMQCleanAir=9.83; + } + if (Adc[idx].param1==4) + { + a=1012.7; + b=-2.786; + ratioMQCleanAir=4.4; + } + if (Adc[idx].param1==7) + { + a=99.042; + b=-1.518; + ratioMQCleanAir=27.5; + } + if (Adc[idx].param1==131) + { + a=23.943; + b=-1.11; + ratioMQCleanAir=15; + } + } + Adc[idx].param2 = (int)(a * ANALOG_MQ_DECIMAL_MULTIPLIER); // Exponential regression + Adc[idx].param3 = (int)(b * ANALOG_MQ_DECIMAL_MULTIPLIER); // Exponential regression + Adc[idx].param4 = (int)(ratioMQCleanAir * ANALOG_MQ_DECIMAL_MULTIPLIER); // Exponential regression + AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Analog MQ reset: mq%d, a=%2_f, b=%2_f, ratioMQCleanAir=%2_f"), + Adc[idx].param1, &a, &b, &ratioMQCleanAir); + } } else { // Set default values based on current adc type // AdcParam 2 // AdcParam 3 @@ -656,7 +799,7 @@ void CmndAdcParam(void) { // AdcParam AdcGetSettings(idx); Response_P(PSTR("{\"" D_CMND_ADCPARAM "%d\":[%d,%d,%d"), idx +1, Adcs.type, Adc[idx].param1, Adc[idx].param2); - if (ADC_RANGE == Adc[idx].type) { + if ((ADC_RANGE == Adc[idx].type) || (ADC_MQ == Adc[idx].type)){ ResponseAppend_P(PSTR(",%d,%d"), Adc[idx].param3, Adc[idx].param4); } else { int value = Adc[idx].param3; diff --git a/tasmota/xsns_05_ds18x20_esp32.ino b/tasmota/xsns_05_esp32_ds18x20.ino similarity index 99% rename from tasmota/xsns_05_ds18x20_esp32.ino rename to tasmota/xsns_05_esp32_ds18x20.ino index d07267db2..796036610 100644 --- a/tasmota/xsns_05_ds18x20_esp32.ino +++ b/tasmota/xsns_05_esp32_ds18x20.ino @@ -1,5 +1,5 @@ /* - xsns_05_ds18x20_esp32.ino - DS18x20 temperature sensor support for Tasmota + xsns_05_esp32_ds18x20.ino - DS18x20 temperature sensor support for ESP32 Tasmota Copyright (C) 2021 Heiko Krupp and Theo Arends diff --git a/tasmota/xsns_06_dht.ino b/tasmota/xsns_06_dht.ino index ffd6c4b44..bd6937f19 100644 --- a/tasmota/xsns_06_dht.ino +++ b/tasmota/xsns_06_dht.ino @@ -17,6 +17,7 @@ along with this program. If not, see . */ +#ifdef ESP8266 #ifdef USE_DHT /*********************************************************************************************\ * DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321), SI7021 - Temperature and Humidity @@ -25,6 +26,8 @@ * Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) * * Changelog + * 20211229 - Change poll time from to 2 to 4 seconds for better results + * 20211226 - https://github.com/arendst/Tasmota/pull/14173 * 20210524 - https://github.com/arendst/Tasmota/issues/12180 * 20200621 - https://github.com/arendst/Tasmota/pull/7468#issuecomment-647067015 * 20200313 - https://github.com/arendst/Tasmota/issues/7717#issuecomment-585833243 @@ -115,6 +118,9 @@ bool DhtRead(uint32_t sensor) { } } interrupts(); + + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("DHT: Read %5_H"), dht_data); + if (i < 40) { return false; } uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; @@ -149,15 +155,14 @@ bool DhtRead(uint32_t sensor) { case GPIO_SI7021: // iTead SI7021 humidity = ((dht_data[0] << 8) | dht_data[1]) * 0.1; // DHT21/22 (Adafruit): - temperature = ((int16_t)(dht_data[2] & 0x7F) << 8 ) | dht_data[3]; - temperature *= 0.1f; - if (dht_data[2] & 0x80) { - temperature *= -1; - } + int16_t temp16 = dht_data[2] << 8 | dht_data[3]; // case 1 : signed 16 bits + if ((dht_data[2] & 0xF0) == 0x80) // case 2 : negative when high nibble = 0x80 + temp16 = -(0xFFF & temp16); + temperature = 0.1f * temp16; break; } if (isnan(temperature) || isnan(humidity)) { - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "Invalid NAN reading")); + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "Invalid reading")); return false; } @@ -211,7 +216,7 @@ void DhtInit(void) { } void DhtEverySecond(void) { - if (TasmotaGlobal.uptime &1) { // Every 2 seconds + if (!(TasmotaGlobal.uptime %4)) { // Every 4 seconds for (uint32_t sensor = 0; sensor < dht_sensors; sensor++) { // DHT11 and AM2301 25mS per sensor, SI7021 5mS per sensor if (!DhtRead(sensor)) { @@ -263,3 +268,4 @@ bool Xsns06(uint8_t function) { } #endif // USE_DHT +#endif // ESP8266 diff --git a/tasmota/xsns_06_esp32_dht.ino b/tasmota/xsns_06_esp32_dht.ino new file mode 100644 index 000000000..e6c6308a7 --- /dev/null +++ b/tasmota/xsns_06_esp32_dht.ino @@ -0,0 +1,159 @@ +/* + xsns_06_esp32_dht.ino - DHTxx, AM23xx and SI7021 temperature and humidity sensor support for ESP32 Tasmota + + Copyright (C) 2021 Theo Arends + + This program 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 . +*/ + +#ifdef ESP32 +#ifdef USE_DHT +/*********************************************************************************************\ + * DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321), SI7021 - Temperature and Humidity + * + * Reading temperature or humidity takes about 250 milliseconds! + * Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) + * + * Changelog + * 20211229 - Change poll time from to 2 to 4 seconds for better results +\*********************************************************************************************/ + +#define XSNS_06 6 + +#define DHT_MAX_SENSORS 4 +#define DHT_MAX_RETRY 8 + +#include + +uint8_t dht_sensors = 0; +bool dht_active = true; // DHT configured + +struct DHTSTRUCT { + DHT *dht; + int8_t pin; + uint8_t type; + uint8_t lastresult; + char stype[12]; + float t = NAN; + float h = NAN; +} Dht[DHT_MAX_SENSORS]; + +bool DhtRead(uint32_t sensor) { + float temperature = Dht[sensor].dht->readTemperature(false, false); + float humidity = Dht[sensor].dht->readHumidity(false); + + if (isnan(temperature) || isnan(humidity)) { + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "Invalid reading")); + return false; + } + + if (humidity > 100) { humidity = 100.0; } + if (humidity < 0) { humidity = 0.1; } + Dht[sensor].h = ConvertHumidity(humidity); + Dht[sensor].t = ConvertTemp(temperature); + Dht[sensor].lastresult = 0; + + return true; +} + +/********************************************************************************************/ + +bool DhtPinState() { + if ((XdrvMailbox.index >= AGPIO(GPIO_DHT11)) && (XdrvMailbox.index <= AGPIO(GPIO_SI7021))) { + if (dht_sensors < DHT_MAX_SENSORS) { + Dht[dht_sensors].pin = XdrvMailbox.payload; + Dht[dht_sensors].type = BGPIO(XdrvMailbox.index); + dht_sensors++; + XdrvMailbox.index = AGPIO(GPIO_DHT11); + } else { + XdrvMailbox.index = 0; + } + return true; + } + return false; +} + +void DhtInit(void) { + if (dht_sensors) { + for (uint32_t i = 0; i < dht_sensors; i++) { + uint32_t type = (Dht[i].type == GPIO_DHT11) ? DHT11 : DHT22; + Dht[i].dht = new DHT(Dht[i].pin, type, 1); + uint32_t pull_time = (Dht[i].type == GPIO_SI7021) ? 30 : 50; + Dht[i].dht->begin(pull_time); + Dht[i].lastresult = DHT_MAX_RETRY; // Start with NAN + GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); + if (dht_sensors > 1) { + snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); + } + } + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v6) " D_SENSORS_FOUND " %d"), dht_sensors); + } else { + dht_active = false; + } +} + +void DhtEverySecond(void) { + if (!(TasmotaGlobal.uptime %4)) { // Every 4 seconds + for (uint32_t sensor = 0; sensor < dht_sensors; sensor++) { + // DHT11 and AM2301 25mS per sensor, SI7021 5mS per sensor + if (!DhtRead(sensor)) { + Dht[sensor].lastresult++; + if (Dht[sensor].lastresult > DHT_MAX_RETRY) { // Reset after 8 misses + Dht[sensor].t = NAN; + Dht[sensor].h = NAN; + } + } + } + } +} + +void DhtShow(bool json) { + for (uint32_t i = 0; i < dht_sensors; i++) { + TempHumDewShow(json, ((0 == TasmotaGlobal.tele_period) && (0 == i)), Dht[i].stype, Dht[i].t, Dht[i].h); + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xsns06(uint8_t function) { + bool result = false; + + if (dht_active) { + switch (function) { + case FUNC_EVERY_SECOND: + DhtEverySecond(); + break; + case FUNC_JSON_APPEND: + DhtShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DhtShow(0); + break; +#endif // USE_WEBSERVER + case FUNC_INIT: + DhtInit(); + break; + case FUNC_PIN_STATE: + result = DhtPinState(); + break; + } + } + return result; +} + +#endif // USE_DHT +#endif // ESP32 diff --git a/tasmota/xsns_09_bmp.ino b/tasmota/xsns_09_bmp.ino index a4cc85149..149c0ded2 100644 --- a/tasmota/xsns_09_bmp.ino +++ b/tasmota/xsns_09_bmp.ino @@ -30,6 +30,10 @@ #define XSNS_09 9 #define XI2C_10 10 // See I2CDEVICES.md +#ifdef USE_BME680 +#define USE_BME68X +#endif + #define BMP_ADDR1 0x76 #define BMP_ADDR2 0x77 @@ -53,10 +57,10 @@ typedef struct { char bmp_name[7]; // Sensor name - "BMPXXX" uint8_t bmp_type; uint8_t bmp_model; -#ifdef USE_BME680 +#ifdef USE_BME68X uint8_t bme680_state; float bmp_gas_resistance; -#endif // USE_BME680 +#endif // USE_BME68X float bmp_temperature; float bmp_pressure; float bmp_humidity; @@ -342,63 +346,72 @@ void Bme280Read(uint8_t bmp_idx) bmp_sensors[bmp_idx].bmp_humidity = h / 1024.0; } -#ifdef USE_BME680 +#ifdef USE_BME68X /*********************************************************************************************\ - * BME680 support by Bosch https://github.com/BoschSensortec/BME680_driver + * BME68x support by Bosch https://github.com/BoschSensortec/BME68x-Sensor-API \*********************************************************************************************/ -#include +//#define BME68X_DO_NOT_USE_FPU -struct bme680_dev *gas_sensor = nullptr; +#include -static void BmeDelayMs(uint32_t ms) -{ - delay(ms); +struct bme68x_dev *bme_dev = nullptr; +struct bme68x_conf *bme_conf = nullptr; +struct bme68x_heatr_conf *bme_heatr_conf = nullptr; + +static void Bme68x_Delayus(uint32_t period, void *intf_ptr) { + delayMicroseconds(period); } -bool Bme680Init(uint8_t bmp_idx) -{ - if (!gas_sensor) { - gas_sensor = (bme680_dev*)malloc(BMP_MAX_SENSORS * sizeof(bme680_dev)); +int8_t Bme68x_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) { + uint8_t dev_addr = *(uint8_t*)intf_ptr; + return I2cReadBuffer(dev_addr, reg_addr, reg_data, (uint16_t)len); +} + +int8_t Bme68x_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr) { + uint8_t dev_addr = *(uint8_t*)intf_ptr; + return I2cWriteBuffer(dev_addr, reg_addr, (uint8_t *)reg_data, (uint16_t)len); +} + +bool Bme680Init(uint8_t bmp_idx) { + if (!bme_dev) { + bme_heatr_conf = (bme68x_heatr_conf*)malloc(BMP_MAX_SENSORS * sizeof(bme68x_heatr_conf)); + bme_conf = (bme68x_conf*)malloc(BMP_MAX_SENSORS * sizeof(bme68x_conf)); + bme_dev = (bme68x_dev*)malloc(BMP_MAX_SENSORS * sizeof(bme68x_dev)); } - if (!gas_sensor) { return false; } + if (!bme_dev) { return false; } - gas_sensor[bmp_idx].dev_id = bmp_sensors[bmp_idx].bmp_address; - gas_sensor[bmp_idx].intf = BME680_I2C_INTF; - gas_sensor[bmp_idx].read = &I2cReadBuffer; - gas_sensor[bmp_idx].write = &I2cWriteBuffer; - gas_sensor[bmp_idx].delay_ms = BmeDelayMs; - /* amb_temp can be set to 25 prior to configuring the gas sensor - * or by performing a few temperature readings without operating the gas sensor. - */ - gas_sensor[bmp_idx].amb_temp = 25; + bme_dev[bmp_idx].intf_ptr = &bmp_sensors[bmp_idx].bmp_address; + bme_dev[bmp_idx].intf = BME68X_I2C_INTF; + bme_dev[bmp_idx].read = Bme68x_i2c_read; + bme_dev[bmp_idx].write = Bme68x_i2c_write; + bme_dev[bmp_idx].delay_us = Bme68x_Delayus; + // amb_temp can be set to 25 prior to configuring the gas sensor + // or by performing a few temperature readings without operating the gas sensor. + bme_dev[bmp_idx].amb_temp = 25; + int8_t rslt = bme68x_init(&bme_dev[bmp_idx]); + if (rslt != BME68X_OK) { return false; } - int8_t rslt = BME680_OK; - rslt = bme680_init(&gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return false; } +// AddLog(LOG_LEVEL_DEBUG, PSTR("BME: Gas variant %d"), bme_dev[bmp_idx].variant_id); - /* Set the temperature, pressure and humidity settings */ - gas_sensor[bmp_idx].tph_sett.os_hum = BME680_OS_2X; - gas_sensor[bmp_idx].tph_sett.os_pres = BME680_OS_4X; - gas_sensor[bmp_idx].tph_sett.os_temp = BME680_OS_8X; - gas_sensor[bmp_idx].tph_sett.filter = BME680_FILTER_SIZE_3; +// rslt = bme68x_get_conf(&bme_conf[bmp_idx], &bme_dev[bmp_idx]); +// if (rslt != BME68X_OK) { return false; } + // Set the temperature, pressure and humidity settings + bme_conf[bmp_idx].os_hum = BME68X_OS_2X; + bme_conf[bmp_idx].os_pres = BME68X_OS_4X; + bme_conf[bmp_idx].os_temp = BME68X_OS_8X; + bme_conf[bmp_idx].filter = BME68X_FILTER_SIZE_3; + bme_conf[bmp_idx].odr = BME68X_ODR_NONE; // This parameter defines the sleep duration after each profile + rslt = bme68x_set_conf(&bme_conf[bmp_idx], &bme_dev[bmp_idx]); + if (rslt != BME68X_OK) { return false; } - /* Set the remaining gas sensor settings and link the heating profile */ - gas_sensor[bmp_idx].gas_sett.run_gas = BME680_ENABLE_GAS_MEAS; - /* Create a ramp heat waveform in 3 steps */ - gas_sensor[bmp_idx].gas_sett.heatr_temp = 320; /* degree Celsius */ - gas_sensor[bmp_idx].gas_sett.heatr_dur = 150; /* milliseconds */ - - /* Select the power mode */ - /* Must be set before writing the sensor configuration */ - gas_sensor[bmp_idx].power_mode = BME680_FORCED_MODE; - - /* Set the required sensor settings needed */ - uint8_t set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL; - - /* Set the desired sensor configuration */ - rslt = bme680_set_sensor_settings(set_required_settings,&gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return false; } + // Set the gas sensor settings + bme_heatr_conf[bmp_idx].enable = BME68X_ENABLE; + // Create a ramp heat waveform in 3 steps + bme_heatr_conf[bmp_idx].heatr_temp = 320; // degree Celsius + bme_heatr_conf[bmp_idx].heatr_dur = 150; // milliseconds + rslt = bme68x_set_heatr_conf(BME68X_FORCED_MODE, &bme_heatr_conf[bmp_idx], &bme_dev[bmp_idx]); + if (rslt != BME68X_OK) { return false; } bmp_sensors[bmp_idx].bme680_state = 0; @@ -407,36 +420,40 @@ bool Bme680Init(uint8_t bmp_idx) void Bme680Read(uint8_t bmp_idx) { - if (!gas_sensor) { return; } + if (!bme_dev) { return; } - int8_t rslt = BME680_OK; + int8_t rslt = BME68X_OK; if (BME680_CHIPID == bmp_sensors[bmp_idx].bmp_type) { if (0 == bmp_sensors[bmp_idx].bme680_state) { - /* Trigger the next measurement if you would like to read data out continuously */ - rslt = bme680_set_sensor_mode(&gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return; } + // Trigger the next measurement if you would like to read data out continuously + rslt = bme68x_set_op_mode(BME68X_FORCED_MODE, &bme_dev[bmp_idx]); + if (rslt != BME68X_OK) { return; } - /* Get the total measurement duration so as to sleep or wait till the - * measurement is complete */ -// uint16_t meas_period; -// bme680_get_profile_dur(&meas_period, &gas_sensor[bmp_idx]); -// delay(meas_period); /* Delay till the measurement is ready */ // 183 mSec - we'll wait a second + // Calculate delay period in microseconds +// del_period = bme68x_get_meas_dur(BME68X_FORCED_MODE, &conf, &bme) + (heatr_conf.heatr_dur * 1000); +// bme.delay_us(del_period, bme.intf_ptr); bmp_sensors[bmp_idx].bme680_state = 1; } else { bmp_sensors[bmp_idx].bme680_state = 0; - struct bme680_field_data data; - rslt = bme680_get_sensor_data(&data, &gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return; } + struct bme68x_data data; + uint8_t n_fields; + rslt = bme68x_get_data(BME68X_FORCED_MODE, &data, &n_fields, &bme_dev[bmp_idx]); + if (rslt != BME68X_OK) { return; } - bmp_sensors[bmp_idx].bmp_temperature = data.temperature / 100.0; - bmp_sensors[bmp_idx].bmp_humidity = data.humidity / 1000.0; - bmp_sensors[bmp_idx].bmp_pressure = data.pressure / 100.0; - /* Avoid using measurements from an unstable heating setup */ - if (data.status & BME680_GASM_VALID_MSK) { - bmp_sensors[bmp_idx].bmp_gas_resistance = data.gas_resistance / 1000.0; +#ifdef BME68X_DO_NOT_USE_FPU + bmp_sensors[bmp_idx].bmp_temperature = data.temperature / 100.0; // Temperature in degree celsius x100 + bmp_sensors[bmp_idx].bmp_humidity = data.humidity / 1000.0; // Humidity in % relative humidity x1000 +#else + bmp_sensors[bmp_idx].bmp_temperature = data.temperature; // Temperature in degree celsius + bmp_sensors[bmp_idx].bmp_humidity = data.humidity; // Humidity in % relative humidity +#endif + bmp_sensors[bmp_idx].bmp_pressure = data.pressure / 100.0; // Pressure in Pascal (converted to hPa) + // Avoid using measurements from an unstable heating setup + if (data.status & BME68X_GASM_VALID_MSK) { + bmp_sensors[bmp_idx].bmp_gas_resistance = data.gas_resistance / 1000.0; // Gas resistance in Ohms (converted to kOhm) } else { bmp_sensors[bmp_idx].bmp_gas_resistance = 0; } @@ -445,7 +462,7 @@ void Bme680Read(uint8_t bmp_idx) return; } -#endif // USE_BME680 +#endif // USE_BME68X /********************************************************************************************/ @@ -477,12 +494,12 @@ void BmpDetect(void) bmp_sensors[bmp_count].bmp_model++; // 1 success = Bmx280Calibrate(bmp_count); break; -#ifdef USE_BME680 +#ifdef USE_BME68X case BME680_CHIPID: bmp_sensors[bmp_count].bmp_model = 3; // 3 success = Bme680Init(bmp_count); break; -#endif // USE_BME680 +#endif // USE_BME68X } if (success) { GetTextIndexed(bmp_sensors[bmp_count].bmp_name, sizeof(bmp_sensors[bmp_count].bmp_name), bmp_sensors[bmp_count].bmp_model, kBmpTypes); @@ -504,11 +521,11 @@ void BmpRead(void) case BME280_CHIPID: Bme280Read(bmp_idx); break; -#ifdef USE_BME680 +#ifdef USE_BME68X case BME680_CHIPID: Bme680Read(bmp_idx); break; -#endif // USE_BME680 +#endif // USE_BME68X } } } @@ -538,17 +555,17 @@ void BmpShow(bool json) float f_dewpoint = CalcTempHumToDew(bmp_temperature, bmp_humidity); char dewpoint[33]; dtostrfd(f_dewpoint, Settings->flag2.temperature_resolution, dewpoint); -#ifdef USE_BME680 +#ifdef USE_BME68X char gas_resistance[33]; dtostrfd(bmp_sensors[bmp_idx].bmp_gas_resistance, 2, gas_resistance); -#endif // USE_BME680 +#endif // USE_BME68X if (json) { char json_humidity[80]; snprintf_P(json_humidity, sizeof(json_humidity), PSTR(",\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_DEWPOINT "\":%s"), humidity, dewpoint); char json_sealevel[40]; snprintf_P(json_sealevel, sizeof(json_sealevel), PSTR(",\"" D_JSON_PRESSUREATSEALEVEL "\":%s"), sea_pressure); -#ifdef USE_BME680 +#ifdef USE_BME68X char json_gas[40]; snprintf_P(json_gas, sizeof(json_gas), PSTR(",\"" D_JSON_GAS "\":%s"), gas_resistance); @@ -562,14 +579,14 @@ void BmpShow(bool json) #else ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%*_f%s,\"" D_JSON_PRESSURE "\":%s%s}"), name, Settings->flag2.temperature_resolution, &bmp_temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", pressure, (Settings->altitude != 0) ? json_sealevel : ""); -#endif // USE_BME680 +#endif // USE_BME68X #ifdef USE_DOMOTICZ if ((0 == TasmotaGlobal.tele_period) && (0 == bmp_idx)) { // We want the same first sensor to report to Domoticz in case a read is missed DomoticzTempHumPressureSensor(bmp_temperature, bmp_humidity, bmp_pressure); -#ifdef USE_BME680 +#ifdef USE_BME68X if (bmp_sensors[bmp_idx].bmp_model >= 3) { DomoticzSensor(DZ_AIRQUALITY, (uint32_t)bmp_sensors[bmp_idx].bmp_gas_resistance); } -#endif // USE_BME680 +#endif // USE_BME68X } #endif // USE_DOMOTICZ @@ -591,11 +608,11 @@ void BmpShow(bool json) if (Settings->altitude != 0) { WSContentSend_PD(HTTP_SNS_SEAPRESSURE, name, sea_pressure, PressureUnit().c_str()); } -#ifdef USE_BME680 +#ifdef USE_BME68X if (bmp_sensors[bmp_idx].bmp_model >= 3) { WSContentSend_PD(PSTR("{s}%s " D_GAS "{m}%s " D_UNIT_KILOOHM "{e}"), name, gas_resistance); } -#endif // USE_BME680 +#endif // USE_BME68X #endif // USE_WEBSERVER } diff --git a/tasmota/xsns_13_ina219.ino b/tasmota/xsns_13_ina219.ino index 738c9aabe..0684e3cee 100644 --- a/tasmota/xsns_13_ina219.ino +++ b/tasmota/xsns_13_ina219.ino @@ -1,5 +1,5 @@ /* - xsns_13_ina219.ino - INA219 Current Sensor support for Tasmota + xsns_13_ina219.ino - INA219 & ISL28022 Current Sensor support for Tasmota Copyright (C) 2021 Stefan Bode and Theo Arends @@ -21,6 +21,7 @@ #ifdef USE_INA219 /*********************************************************************************************\ * INA219 - Low voltage (max 32V!) Current sensor + * Supports also ISL28022 * * Source: Adafruit Industries * @@ -30,6 +31,8 @@ #define XSNS_13 13 #define XI2C_14 14 // See I2CDEVICES.md +#define INA219_MAX_COUNT 4 + #define INA219_ADDRESS1 (0x40) // 1000000 (A0+A1=GND) #define INA219_ADDRESS2 (0x41) // 1000000 (A0=Vcc, A1=GND) #define INA219_ADDRESS3 (0x44) // 1000000 (A0=GND, A1=Vcc) @@ -43,6 +46,7 @@ #define INA219_CONFIG_BVOLTAGERANGE_MASK (0x2000) // Bus Voltage Range Mask #define INA219_CONFIG_BVOLTAGERANGE_16V (0x0000) // 0-16V Range #define INA219_CONFIG_BVOLTAGERANGE_32V (0x2000) // 0-32V Range +#define ISL28022_CONFIG_BVOLTAGERANGE_60V (0x6000) // 0-60V Range for ISL28022 #define INA219_CONFIG_GAIN_MASK (0x1800) // Gain Mask #define INA219_CONFIG_GAIN_1_40MV (0x0000) // Gain 1, 40mV Range @@ -63,6 +67,7 @@ #define INA219_CONFIG_BADCRES_12BIT_64S_34MS (0xE<<7) // 64 x 12-bit bus samples averaged together #define INA219_CONFIG_BADCRES_12BIT_128S_69MS (0xF<<7) // 128 x 12-bit bus samples averaged together +// Note: for IS28022, the ADC has 3 more bits and approximatively similar conversion times #define INA219_CONFIG_SADCRES_MASK (0x0078) // Shunt ADC Resolution and Averaging Mask #define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0<<3) // 1 x 9-bit shunt sample #define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x1<<3) // 1 x 10-bit shunt sample @@ -91,28 +96,43 @@ #define INA219_REG_POWER (0x03) #define INA219_REG_CURRENT (0x04) #define INA219_REG_CALIBRATION (0x05) +#define ISL28022_REG_SHUNTTHRESHOLD (0x06) +#define ISL28022_REG_BUSTHRESHOLD (0x07) +#define ISL28022_REG_INTRSTATUS (0x08) +#define ISL28022_REG_AUXCTRL (0x09) #define INA219_DEFAULT_SHUNT_RESISTOR_MILLIOHMS (100.0) // 0.1 Ohm -uint8_t ina219_type[4] = {0,0,0,0}; -uint8_t ina219_addresses[] = { INA219_ADDRESS1, INA219_ADDRESS2, INA219_ADDRESS3, INA219_ADDRESS4 }; - #ifdef DEBUG_TASMOTA_SENSOR // temporary strings for floating point in debug messages char __ina219_dbg1[10]; char __ina219_dbg2[10]; #endif -// The following multiplier is used to convert shunt voltage (in mV) to current (in A) -// Current_A = ShuntVoltage_mV / ShuntResistor_milliOhms = ShuntVoltage_mV * ina219_current_multiplier -// ina219_current_multiplier = 1 / ShuntResistor_milliOhms -float ina219_current_multiplier; +#define INA219_ACTIVE 1 +#define ISL28022_ACTIVE 2 + +struct INA219_Channel_Data { + float voltage; + float current; + uint8_t active; + uint8_t valid; +}; + +struct INA219_Data { + struct INA219_Channel_Data chan[INA219_MAX_COUNT]; + // The following multiplier is used to convert shunt voltage (in mV) to current (in A) + // Current_A = ShuntVoltage_mV / ShuntResistor_milliOhms = ShuntVoltage_mV * ina219_current_multiplier + // ina219_current_multiplier = 1 / ShuntResistor_milliOhms + float current_multiplier; + uint8_t count; +}; + +struct INA219_Data *Ina219Data = nullptr; + +const char *INA219_TYPE[] = { "INA219", "ISL28022" }; +const uint8_t INA219_ADDRESSES[] = { INA219_ADDRESS1, INA219_ADDRESS2, INA219_ADDRESS3, INA219_ADDRESS4 }; -uint8_t ina219_valid[4] = {0,0,0,0}; -float ina219_voltage[4] = {0,0,0,0}; -float ina219_current[4] = {0,0,0,0}; -char ina219_types[] = "INA219"; -uint8_t ina219_count = 0; /*********************************************************************************************\ * Calculate current multiplier depending on the selected mode @@ -128,8 +148,12 @@ uint8_t ina219_count = 0; * Note that some shunt values can be represented by 2 different encoded values such as * 11 or 100 both present 10 milliOhms * Because it is difficult to make a range check on such encoded value, none is performed + * + * Return 0 if configuration failed + * Return 1 if chip identified as INA219 + * Return 2 if chip identified as ISL28022 \*********************************************************************************************/ -bool Ina219SetCalibration(uint8_t mode, uint16_t addr) +uint8_t Ina219SetCalibration(uint8_t mode, uint16_t addr) { uint16_t config = 0; @@ -137,9 +161,9 @@ bool Ina219SetCalibration(uint8_t mode, uint16_t addr) if (mode < 5) { // All legacy modes 0..2 are handled the same and consider default 0.1 shunt resistor - ina219_current_multiplier = 1.0 / INA219_DEFAULT_SHUNT_RESISTOR_MILLIOHMS; + Ina219Data->current_multiplier = 1.0 / INA219_DEFAULT_SHUNT_RESISTOR_MILLIOHMS; #ifdef DEBUG_TASMOTA_SENSOR - dtostrfd(ina219_current_multiplier,5,__ina219_dbg1); + dtostrfd(Ina219Data->current_multiplier,5,__ina219_dbg1); DEBUG_SENSOR_LOG("Ina219SetCalibration: cur_mul=%s",__ina219_dbg1); #endif } @@ -149,61 +173,67 @@ bool Ina219SetCalibration(uint8_t mode, uint16_t addr) int shunt_milliOhms = mode / 10; for ( ; mult > 0 ; mult-- ) shunt_milliOhms *= 10; - ina219_current_multiplier = 1.0 / shunt_milliOhms; + Ina219Data->current_multiplier = 1.0 / shunt_milliOhms; #ifdef DEBUG_TASMOTA_SENSOR - dtostrfd(ina219_current_multiplier,5,__ina219_dbg1); + dtostrfd(Ina219Data->current_multiplier,5,__ina219_dbg1); DEBUG_SENSOR_LOG("Ina219SetCalibration: shunt=%dmO => cur_mul=%s",shunt_milliOhms,__ina219_dbg1); #endif } - config = INA219_CONFIG_BVOLTAGERANGE_32V + config = ISL28022_CONFIG_BVOLTAGERANGE_60V // If INA219 0..32V, If ISL28022 0..60V | INA219_CONFIG_GAIN_8_320MV // Use max scale | INA219_CONFIG_BADCRES_12BIT_16S_8510US // use averaging to improve accuracy | INA219_CONFIG_SADCRES_12BIT_16S_8510US // use averaging to improve accuracy | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + #ifdef DEBUG_TASMOTA_SENSOR + AddLog(LOG_LEVEL_DEBUG, PSTR("Ina219SetCalibration: Config=0x%04X (%d)"), config, config); + #endif // Set Config register to take into account the settings above - return I2cWrite16(addr, INA219_REG_CONFIG, config); + if (!I2cWrite16(addr, INA219_REG_CONFIG, config)) + return 0; + + uint16_t intr_reg = 0x0FFFF; + bool status = I2cValidRead16(&intr_reg, addr, ISL28022_REG_INTRSTATUS); + #ifdef DEBUG_TASMOTA_SENSOR + AddLog(LOG_LEVEL_DEBUG, PSTR("Ina219: IntrReg=0x%04X (%d)"), intr_reg, status); + #endif + + if (status && 0 == intr_reg) + return ISL28022_ACTIVE; // ISL28022 + return INA219_ACTIVE; // INA219 } float Ina219GetShuntVoltage_mV(uint16_t addr) { // raw shunt voltage (16-bit signed integer, so +-32767) - int16_t value = I2cReadS16(addr, INA219_REG_SHUNTVOLTAGE); - DEBUG_SENSOR_LOG("Ina219GetShuntVoltage_mV: ShReg = 0x%04X",value); + int16_t shunt_voltage = I2cReadS16(addr, INA219_REG_SHUNTVOLTAGE); + DEBUG_SENSOR_LOG("Ina219GetShuntVoltage_mV: ShReg = 0x%04X (%d)",shunt_voltage, shunt_voltage); // convert to shunt voltage in mV (so +-327mV) (LSB=10µV=0.01mV) - return value * 0.01; + return (float)shunt_voltage * 0.01; } -float Ina219GetBusVoltage_V(uint16_t addr) +float Ina219GetBusVoltage_V(uint16_t addr, uint8_t model) { - // Shift 3 to the right to drop CNVR and OVF as unsigned - uint16_t value = I2cRead16(addr, INA219_REG_BUSVOLTAGE) >> 3; - DEBUG_SENSOR_LOG("Ina219GetBusVoltage_V: BusReg = 0x%04X",value); + uint16_t bus_voltage = I2cRead16(addr, INA219_REG_BUSVOLTAGE); + if (ISL28022_ACTIVE == model) { + // ISL2802 LSB is bit 2 + bus_voltage >>= 2; + DEBUG_SENSOR_LOG("Isl28022GetBusVoltage_V: BusReg = 0x%04X (%d)",bus_voltage, bus_voltage); + } + else { + // INA219 LSB is bit 3 + bus_voltage >>= 3; + DEBUG_SENSOR_LOG("Ina219GetBusVoltage_V: BusReg = 0x%04X (%d)",bus_voltage, bus_voltage); + } // and multiply by LSB raw bus voltage to return bus voltage in volts (LSB=4mV=0.004V) - return value * 0.004; + return (float)bus_voltage * 0.004; } -/* Not used any more -float Ina219GetCurrent_mA(uint16_t addr) -{ - // Sometimes a sharp load will reset the INA219, which will reset the cal register, - // meaning CURRENT and POWER will not be available ... avoid this by always setting - // a cal value even if it's an unfortunate extra step - I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); - // Now we can safely read the CURRENT register! - // raw current value (16-bit signed integer, so +-32767) - float value = I2cReadS16(addr, INA219_REG_CURRENT); - value /= ina219_current_divider_ma; - // current value in mA, taking into account the config settings and current LSB - return value; -} -*/ - bool Ina219Read(void) { - for (int i=0; ichan[i].active) { continue; } + uint16_t addr = INA219_ADDRESSES[i]; + float bus_voltage_V = Ina219GetBusVoltage_V(addr, Ina219Data->chan[i].active); float shunt_voltage_mV = Ina219GetShuntVoltage_mV(addr); #ifdef DEBUG_TASMOTA_SENSOR dtostrfd(bus_voltage_V,5,__ina219_dbg1); @@ -211,16 +241,15 @@ bool Ina219Read(void) DEBUG_SENSOR_LOG("Ina219Read: bV=%sV, sV=%smV",__ina219_dbg1,__ina219_dbg2); #endif // we return the power-supply-side voltage (as bus_voltage register provides the load-side voltage) - ina219_voltage[i] = bus_voltage_V + (shunt_voltage_mV / 1000); + Ina219Data->chan[i].voltage = bus_voltage_V + (shunt_voltage_mV / 1000); // current is simply calculted from shunt voltage using pre-calculated multiplier - ina219_current[i] = shunt_voltage_mV * ina219_current_multiplier; + Ina219Data->chan[i].current = shunt_voltage_mV * Ina219Data->current_multiplier; #ifdef DEBUG_TASMOTA_SENSOR - dtostrfd(ina219_voltage[i],5,__ina219_dbg1); - dtostrfd(ina219_current[i],5,__ina219_dbg2); + dtostrfd(Ina219Data->chan[i].voltage,5,__ina219_dbg1); + dtostrfd(Ina219Data->chan[i].current,5,__ina219_dbg2); DEBUG_SENSOR_LOG("Ina219Read: V=%sV, I=%smA",__ina219_dbg1,__ina219_dbg2); #endif - ina219_valid[i] = SENSOR_MAX_MISS; - // AddLogMissed(ina219_types, ina219_valid); + Ina219Data->chan[i].valid = SENSOR_MAX_MISS; } return true; } @@ -244,13 +273,21 @@ bool Ina219CommandSensor(void) void Ina219Detect(void) { - for (uint32_t i = 0; i < sizeof(ina219_type); i++) { - uint16_t addr = ina219_addresses[i]; + for (uint32_t i = 0; i < INA219_MAX_COUNT; i++) { + uint16_t addr = INA219_ADDRESSES[i]; if (!I2cSetDevice(addr)) { continue; } - if (Ina219SetCalibration(Settings->ina219_mode, addr)) { - I2cSetActiveFound(addr, ina219_types); - ina219_type[i] = 1; - ina219_count++; + if (!Ina219Data) { + Ina219Data = (struct INA219_Data*)calloc(1,sizeof(struct INA219_Data)); + if (!Ina219Data) { + AddLog(LOG_LEVEL_ERROR,PSTR("INA219: Mem Error")); + return; + } + } + int model = Ina219SetCalibration(Settings->ina219_mode, addr); + if (model) { + I2cSetActiveFound(addr, INA219_TYPE[model-1]); + Ina219Data->chan[i].active = model; + Ina219Data->count++; } } } @@ -271,31 +308,31 @@ const char HTTP_SNS_INA219_DATA[] PROGMEM = void Ina219Show(bool json) { int num_found=0; - for (int i=0; ichan[i].active && Ina219Data->chan[i].valid) num_found++; int sensor_num = 0; - for (int i=0; ichan[i].active && !Ina219Data->chan[i].valid) continue; sensor_num++; char voltage[16]; - dtostrfd(ina219_voltage[i], Settings->flag2.voltage_resolution, voltage); + dtostrfd(Ina219Data->chan[i].voltage, Settings->flag2.voltage_resolution, voltage); char current[16]; - dtostrfd(ina219_current[i], Settings->flag2.current_resolution, current); + dtostrfd(Ina219Data->chan[i].current, Settings->flag2.current_resolution, current); char power[16]; - dtostrfd(ina219_voltage[i] * ina219_current[i], Settings->flag2.wattage_resolution, power); + dtostrfd(Ina219Data->chan[i].voltage * Ina219Data->chan[i].current, Settings->flag2.wattage_resolution, power); char name[16]; if (num_found>1) - snprintf_P(name, sizeof(name), PSTR("%s%c%d"), ina219_types, IndexSeparator(), sensor_num); + snprintf_P(name, sizeof(name), PSTR("%s%c%d"), INA219_TYPE[Ina219Data->chan[i].active-1], IndexSeparator(), sensor_num); else - snprintf_P(name, sizeof(name), PSTR("%s"), ina219_types); + snprintf_P(name, sizeof(name), PSTR("%s"), INA219_TYPE[Ina219Data->chan[i].active-1]); if (json) { ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%02x,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), - name, ina219_addresses[i], voltage, current, power); + name, INA219_ADDRESSES[i], voltage, current, power); #ifdef USE_DOMOTICZ if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_VOLTAGE, voltage); @@ -323,7 +360,7 @@ bool Xsns13(uint8_t function) if (FUNC_INIT == function) { Ina219Detect(); } - else if (ina219_count) { + else if (Ina219Data) { switch (function) { case FUNC_COMMAND_SENSOR: if (XSNS_13 == XdrvMailbox.index) { diff --git a/tasmota/xsns_22_sr04.ino b/tasmota/xsns_22_sr04.ino index d941b25c2..37c830e58 100644 --- a/tasmota/xsns_22_sr04.ino +++ b/tasmota/xsns_22_sr04.ino @@ -18,9 +18,6 @@ */ #ifdef USE_SR04 - -#include -#include /*********************************************************************************************\ * HC-SR04, HC-SR04+, JSN-SR04T - Ultrasonic distance sensor * @@ -35,52 +32,25 @@ #define SR04_MAX_SENSOR_DISTANCE 500 #endif -uint8_t sr04_type = 1; -real64_t distance; +enum Sr04CommsMode { SR04_MODE_NONE, // No hardware detected + SR04_MODE_TRIGGER_ECHO, // Mode 1 - Trigger and Echo connection + SR04_MODE_SER_RECEIVER, // Mode 2 - Serial receive only + SR04_MODE_SER_TRANSCEIVER, // Mode 3 - Serial transmit and receive + SR04_NOT_DETECTED }; // Not yet detected + +#include +#include + +struct { + float distance; + uint8_t valid; + uint8_t type = SR04_NOT_DETECTED; +} SR04; NewPing* sonar = nullptr; TasmotaSerial* sonar_serial = nullptr; -uint8_t Sr04TModeDetect(void) -{ - sr04_type = 0; - if (!PinUsed(GPIO_SR04_ECHO)) { return sr04_type; } - - int sr04_echo_pin = Pin(GPIO_SR04_ECHO); - int sr04_trig_pin = (PinUsed(GPIO_SR04_TRIG)) ? Pin(GPIO_SR04_TRIG) : Pin(GPIO_SR04_ECHO); // if GPIO_SR04_TRIG is not configured use single PIN mode with GPIO_SR04_ECHO only - sonar_serial = new TasmotaSerial(sr04_echo_pin, sr04_trig_pin, 1); - - if (sonar_serial->begin(9600,1)) { - DEBUG_SENSOR_LOG(PSTR("SR4: Detect mode")); - - if (sr04_trig_pin != -1) { - sr04_type = (Sr04TMiddleValue(Sr04TMode3Distance(), Sr04TMode3Distance(), Sr04TMode3Distance()) != NO_ECHO) ? 3 : 1; - } else { - sr04_type = 2; - } - } else { - sr04_type = 1; - } - - if (sr04_type < 2) { - delete sonar_serial; - sonar_serial = nullptr; - if (-1 == sr04_trig_pin) { - sr04_trig_pin = Pin(GPIO_SR04_ECHO); // if GPIO_SR04_TRIG is not configured use single PIN mode with GPIO_SR04_ECHO only - } - sonar = new NewPing(sr04_trig_pin, sr04_echo_pin, SR04_MAX_SENSOR_DISTANCE); - } else { - if (sonar_serial->hardwareSerial()) { - ClaimSerial(); - } - } - - AddLog(LOG_LEVEL_INFO,PSTR("SR4: Mode %d"), sr04_type); - return sr04_type; -} - -uint16_t Sr04TMiddleValue(uint16_t first, uint16_t second, uint16_t third) -{ +uint16_t Sr04TMiddleValue(uint16_t first, uint16_t second, uint16_t third) { uint16_t ret = first; if (first > second) { first = second; @@ -96,75 +66,126 @@ uint16_t Sr04TMiddleValue(uint16_t first, uint16_t second, uint16_t third) } } -uint16_t Sr04TMode3Distance() { - - sonar_serial->write(0x55); - sonar_serial->flush(); - - return Sr04TMode2Distance(); -} - -uint16_t Sr04TMode2Distance(void) -{ - sonar_serial->setTimeout(300); - const char startByte = 0xff; - - if (!sonar_serial->find(startByte)) { - //DEBUG_SENSOR_LOG(PSTR("SR4: No start byte")); - return NO_ECHO; +uint16_t Sr04TMode2Distance(void) { + uint8_t buffer[4]; // Accomodate either 2 or 3 bytes of data + uint32_t buffer_idx = 0; + uint32_t end = millis() + 100; + while (millis() < end) { + if (sonar_serial->available() && (buffer_idx < sizeof(buffer))) { + buffer[buffer_idx++] = sonar_serial->read(); + end = millis() + 10; + } + delay(1); + } + if (0 == SR04.type) { + AddLog(LOG_LEVEL_DEBUG, PSTR("SR4: Received '%*_H'"), buffer_idx, buffer); } - delay(5); + if (buffer_idx < 2) { return 0; } - uint8_t crc = sonar_serial->read(); - //read high byte + uint8_t crc = buffer[0]; // Read high byte uint16_t distance = ((uint16_t)crc) << 8; + distance += buffer[1]; // Read low byte - //read low byte - distance += sonar_serial->read(); - crc += distance & 0x00ff; - crc += 0x00FF; - - //check crc sum - if (crc != sonar_serial->read()) { - AddLog(LOG_LEVEL_ERROR,PSTR("SR4: Reading CRC error.")); - return NO_ECHO; + if (buffer_idx > 2) { // US-100 serial has no CRC + crc += distance & 0x00ff; + crc += 0x00FF; + if (crc != buffer[3]) { // Check crc sum + AddLog(LOG_LEVEL_ERROR, PSTR("SR4: Reading CRC error")); + return 0; + } } //DEBUG_SENSOR_LOG(PSTR("SR4: Distance: %d"), distance); return distance; } -void Sr04TReading(void) { +uint16_t Sr04TMode3Distance() { + sonar_serial->write(0x55); + sonar_serial->flush(); - if (sonar_serial==nullptr && sonar==nullptr) { - Sr04TModeDetect(); - } - - switch (sr04_type) { - case 3: - distance = (real64_t)(Sr04TMiddleValue(Sr04TMode3Distance(),Sr04TMode3Distance(),Sr04TMode3Distance()))/ 10; //convert to cm - break; - case 2: - //empty input buffer first - while(sonar_serial->available()) sonar_serial->read(); - distance = (real64_t)(Sr04TMiddleValue(Sr04TMode2Distance(),Sr04TMode2Distance(),Sr04TMode2Distance()))/10; - break; - case 1: - distance = (real64_t)(sonar->ping_median(5))/ US_ROUNDTRIP_CM; - break; - default: - distance = NO_ECHO; - } - - return; + return Sr04TMode2Distance(); } -void Sr04Show(bool json) -{ +/*********************************************************************************************/ - if (distance != 0) { // Check if read failed +void Sr04TModeDetect(void) { + SR04.type = SR04_MODE_NONE; + if (!PinUsed(GPIO_SR04_ECHO)) { return; } + + int sr04_echo_pin = Pin(GPIO_SR04_ECHO); + int sr04_trig_pin = (PinUsed(GPIO_SR04_TRIG)) ? Pin(GPIO_SR04_TRIG) : Pin(GPIO_SR04_ECHO); // if GPIO_SR04_TRIG is not configured use single PIN mode with GPIO_SR04_ECHO only + sonar_serial = new TasmotaSerial(sr04_echo_pin, sr04_trig_pin, 1); + + if (sonar_serial && sonar_serial->begin(9600)) { + DEBUG_SENSOR_LOG(PSTR("SR4: Detect mode")); + + if (PinUsed(GPIO_SR04_TRIG)) { + SR04.type = (Sr04TMiddleValue(Sr04TMode3Distance(), Sr04TMode3Distance(), Sr04TMode3Distance()) != 0) ? SR04_MODE_SER_TRANSCEIVER : SR04_MODE_TRIGGER_ECHO; + } else { + SR04.type = SR04_MODE_SER_RECEIVER; + } + } else { + SR04.type = SR04_MODE_TRIGGER_ECHO; + } + + if (SR04.type < SR04_MODE_SER_RECEIVER) { + if (sonar_serial) { + delete sonar_serial; + sonar_serial = nullptr; + } + sonar = new NewPing(sr04_trig_pin, sr04_echo_pin, SR04_MAX_SENSOR_DISTANCE); + if (!sonar || !sonar->ping_median(5)) { + SR04.type = SR04_MODE_NONE; + } + } else { + if (sonar_serial->hardwareSerial()) { + ClaimSerial(); + } + } + + AddLog(LOG_LEVEL_INFO,PSTR("SR4: Mode %d"), SR04.type); +} + +void Sr04TReading(void) { + if (TasmotaGlobal.uptime < 3) { return; } + + if (SR04.valid) { + SR04.valid--; + } else { + SR04.distance = 0; + } + + float distance; + switch (SR04.type) { + case SR04_NOT_DETECTED: + Sr04TModeDetect(); + SR04.valid = (SR04.type) ? SENSOR_MAX_MISS : 0; + break; + case SR04_MODE_SER_TRANSCEIVER: + distance = (float)(Sr04TMiddleValue(Sr04TMode3Distance(), Sr04TMode3Distance(), Sr04TMode3Distance())) / 10; // Convert to cm + break; + case SR04_MODE_SER_RECEIVER: + //empty input buffer first + while(sonar_serial->available()) { sonar_serial->read(); } + distance = (float)(Sr04TMiddleValue(Sr04TMode2Distance(), Sr04TMode2Distance(), Sr04TMode2Distance())) / 10; // Convert to cm + break; + case SR04_MODE_TRIGGER_ECHO: + distance = (float)(sonar->ping_median(5)) / US_ROUNDTRIP_CM; + break; + default: + distance = 0; + } + + if (distance) { + SR04.distance = distance; + SR04.valid = SENSOR_MAX_MISS; + } +} + +void Sr04Show(bool json) { + if (SR04.valid) { // Check if read failed char distance_chr[33]; - dtostrfd(distance, 3, distance_chr); + dtostrfd(SR04.distance, 3, distance_chr); if(json) { ResponseAppend_P(PSTR(",\"SR04\":{\"" D_JSON_DISTANCE "\":%s}"), distance_chr); @@ -185,15 +206,11 @@ void Sr04Show(bool json) * Interface \*********************************************************************************************/ -bool Xsns22(uint8_t function) -{ +bool Xsns22(uint8_t function) { bool result = false; - if (sr04_type) { + if (SR04.type) { switch (function) { - case FUNC_INIT: - result = (PinUsed(GPIO_SR04_ECHO)); - break; case FUNC_EVERY_SECOND: Sr04TReading(); result = true; diff --git a/tasmota/xsns_33_ds3231.ino b/tasmota/xsns_33_ds3231.ino index 6082bbe49..515ddee70 100644 --- a/tasmota/xsns_33_ds3231.ino +++ b/tasmota/xsns_33_ds3231.ino @@ -35,6 +35,9 @@ #define XSNS_33 33 #define XI2C_26 26 // See I2CDEVICES.md +#include "NTPServer.h" +#include "NTPPacket.h" + //DS3232 I2C Address #ifndef USE_RTC_ADDR #define USE_RTC_ADDR 0x68 @@ -67,6 +70,23 @@ bool ds3231ReadStatus = false; bool ds3231WriteStatus = false; //flag, we want to read/write to DS3231 only once bool DS3231chipDetected = false; +#define D_CMND_NTP "NTP" + +const char S_JSON_NTP_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_NTP "%s\":%d}"; + +const char kRTCTypes[] PROGMEM = "NTP"; + +#define NTP_MILLIS_OFFSET 50 + +NtpServer timeServer(PortUdp); + +struct NTP_t { + struct { + uint32_t init:1; + uint32_t runningNTP:1; + } mode; +} NTP; + /*----------------------------------------------------------------------* Detect the DS3231 Chip ----------------------------------------------------------------------*/ @@ -150,12 +170,45 @@ void DS3231EverySecond(void) TasmotaGlobal.rules_flag.time_set = 1; } } - else if (!ds3231WriteStatus && Rtc.utc_time > START_VALID_TIME && abs((int32_t)(Rtc.utc_time - ReadFromDS3231())) > 60) { // If time is valid and is drift from RTC in more that 60 second + else if (!ds3231WriteStatus && Rtc.utc_time > START_VALID_TIME && abs((int32_t)(Rtc.utc_time - ReadFromDS3231())) > 10) { // If time is valid and has drifted from RTC more than 10 seconds AddLog(LOG_LEVEL_INFO, PSTR("Write Time TO DS3231 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); SetDS3231Time (Rtc.utc_time); //update the DS3231 time ds3231WriteStatus = true; } + if (NTP.mode.runningNTP) { + timeServer.processOneRequest(Rtc.utc_time, NTP_MILLIS_OFFSET); + } +} + +/*********************************************************************************************\ + NTP functions + \*********************************************************************************************/ + +void NTPSelectMode(uint16_t mode) +{ + DEBUG_SENSOR_LOG(PSTR("RTC: NTP status %u"),mode); + switch(mode){ + case 0: + NTP.mode.runningNTP = false; + break; + case 1: + if (timeServer.beginListening()) { + NTP.mode.runningNTP = true; + } + break; + + } +} + +bool NTPCmd(void) +{ + bool serviced = true; + if (XdrvMailbox.data_len > 0) { + NTPSelectMode(XdrvMailbox.payload); + Response_P(S_JSON_NTP_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); + } + return serviced; } /*********************************************************************************************\ @@ -173,6 +226,11 @@ bool Xsns33(uint8_t function) } else if (DS3231chipDetected) { switch (function) { + case FUNC_COMMAND_SENSOR: + if (XSNS_33 == XdrvMailbox.index) { + result = NTPCmd(); + } + break; case FUNC_EVERY_SECOND: DS3231EverySecond(); break; diff --git a/tasmota/xsns_44_sps30.ino b/tasmota/xsns_44_sps30.ino index 569a821b3..1af0a7127 100644 --- a/tasmota/xsns_44_sps30.ino +++ b/tasmota/xsns_44_sps30.ino @@ -101,7 +101,8 @@ uint8_t twi_buff[64]; twi_readFrom(SPS30_ADDR,twi_buff,dlen,1); #endif // ESP8266 #ifdef ESP32 - Wire.readTransmission(SPS30_ADDR,twi_buff,dlen,1, NULL); + Wire.requestFrom((uint16_t)SPS30_ADDR, dlen, true); + Wire.readBytes(twi_buff, dlen); #endif // ESP32 uint8_t bind=0; diff --git a/tasmota/xsns_53_sml.ino b/tasmota/xsns_53_sml.ino index d001af112..974125946 100755 --- a/tasmota/xsns_53_sml.ino +++ b/tasmota/xsns_53_sml.ino @@ -79,7 +79,7 @@ #define DJ_COUNTER "Count" struct METER_DESC { - uint8_t srcpin; + int8_t srcpin; uint8_t type; uint16_t flag; int32_t params; @@ -499,9 +499,7 @@ uint16_t meter_spos[MAX_METERS]; #ifdef ESP8266 TasmotaSerial *meter_ss[MAX_METERS]; #endif // ESP8266 -#ifdef ESP32 -HardwareSerial *meter_ss[MAX_METERS]; -#endif // ESP32 + // serial buffers, may be made larger depending on telegram lenght #ifndef SML_BSIZ @@ -592,6 +590,229 @@ double sml_median(struct SML_MEDIAN_FILTER* mf, double in) { } #endif + +// ESP32 software serial read only +#ifdef ESP32 +#ifdef USE_ESP32_SW_SERIAL + +#ifndef ESP32_SWS_BUFFER_SIZE +#define ESP32_SWS_BUFFER_SIZE 256 +#endif + + +class SML_ESP32_SERIAL : public Stream { +public: + SML_ESP32_SERIAL(uint32_t uart_index); + virtual ~SML_ESP32_SERIAL(); + bool begin(uint32_t speed, uint32_t smode, int32_t recpin, int32_t trxpin); + int32_t peek(void); + int32_t read(void) override; + size_t write(uint8_t byte) override; + int32_t available(void) override; + void flush(void) override; + void setRxBufferSize(uint32_t size); + void updateBaudRate(uint32_t baud); + void rxRead(void); + using Print::write; +private: + // Member variables + void setbaud(uint32_t speed); + uint32_t uart_index; + int8_t m_rx_pin; + int8_t m_tx_pin; + uint32_t cfgmode; + uint32_t ss_byte; + uint32_t ss_bstart; + uint32_t ss_index; + uint32_t m_bit_time; + uint32_t m_in_pos; + uint32_t m_out_pos; + uint16_t serial_buffer_size; + bool m_valid; + uint8_t *m_buffer; + HardwareSerial *hws; +}; + + +void IRAM_ATTR sml_callRxRead(void *self) { ((SML_ESP32_SERIAL*)self)->rxRead(); }; + +SML_ESP32_SERIAL::SML_ESP32_SERIAL(uint32_t index) { + uart_index = index; + m_valid = true; +} + +SML_ESP32_SERIAL::~SML_ESP32_SERIAL(void) { + if (hws) { + hws->end(); + } else { + detachInterrupt(m_rx_pin); + if (m_buffer) { + free(m_buffer); + } + } +} + +void SML_ESP32_SERIAL::setbaud(uint32_t speed) { + m_bit_time = ESP.getCpuFreqMHz() * 1000000 / speed; +} + + +bool SML_ESP32_SERIAL::begin(uint32_t speed, uint32_t smode, int32_t recpin, int32_t trxpin) { + if (!m_valid) { return false; } + + m_buffer = 0; + if (recpin < 0) { + setbaud(speed); + m_rx_pin = -recpin; + serial_buffer_size = ESP32_SWS_BUFFER_SIZE; + m_buffer = (uint8_t*)malloc(serial_buffer_size); + if (m_buffer == NULL) return false; + pinMode(m_rx_pin, INPUT); + attachInterruptArg(m_rx_pin, sml_callRxRead, this, CHANGE); + m_in_pos = m_out_pos = 0; + hws = nullptr; + } else { + cfgmode = smode; + m_rx_pin = recpin; + m_tx_pin = trxpin; + hws = new HardwareSerial(uart_index); + if (hws) { + hws->begin(speed, cfgmode, m_rx_pin, m_tx_pin); + } + } + return true; +} + +void SML_ESP32_SERIAL::flush(void) { + if (hws) { + hws->flush(); + } else { + m_in_pos = m_out_pos = 0; + } +} + +int32_t SML_ESP32_SERIAL::peek(void) { + if (hws) { + return hws->peek(); + } else { + if (m_in_pos == m_out_pos) return -1; + return m_buffer[m_out_pos]; + } +} + +int32_t SML_ESP32_SERIAL::read(void) { + if (hws) { + return hws->read(); + } else { + if (m_in_pos == m_out_pos) return -1; + uint32_t ch = m_buffer[m_out_pos]; + m_out_pos = (m_out_pos +1) % serial_buffer_size; + return ch; + } +} + +int32_t SML_ESP32_SERIAL::available(void) { + if (hws) { + return hws->available(); + } else { + int avail = m_in_pos - m_out_pos; + if (avail < 0) avail += serial_buffer_size; + return avail; + } +} + +size_t SML_ESP32_SERIAL::write(uint8_t byte) { + if (hws) { + return hws->write(byte); + } + return 0; +} + +void SML_ESP32_SERIAL::setRxBufferSize(uint32_t size) { + if (hws) { + hws->setRxBufferSize(size); + } else { + if (m_buffer) { + free(m_buffer); + } + serial_buffer_size = size; + m_buffer = (uint8_t*)malloc(size); + } +} +void SML_ESP32_SERIAL::updateBaudRate(uint32_t baud) { + if (hws) { + hws->updateBaudRate(baud); + } else { + setbaud(baud); + } +} + +// no wait mode only 8N1 (or 7X1, obis only, ignoring parity) +void IRAM_ATTR SML_ESP32_SERIAL::rxRead(void) { + uint32_t diff; + uint32_t level; + +#define SML_LASTBIT 9 + + level = digitalRead(m_rx_pin); + + if (!level && !ss_index) { + // start condition + ss_bstart = ESP.getCycleCount() - (m_bit_time / 4); + ss_byte = 0; + ss_index++; + } else { + // now any bit changes go here + // calc bit number + diff = (ESP.getCycleCount() - ss_bstart) / m_bit_time; + + if (!level && diff > SML_LASTBIT) { + // start bit of next byte, store and restart + // leave irq at change + for (uint32_t i = ss_index; i <= SML_LASTBIT; i++) { + ss_byte |= (1 << i); + } + uint32_t next = (m_in_pos + 1) % serial_buffer_size; + if (next != (uint32_t)m_out_pos) { + m_buffer[m_in_pos] = ss_byte >> 1; + m_in_pos = next; + } + + ss_bstart = ESP.getCycleCount() - (m_bit_time / 4); + ss_byte = 0; + ss_index = 1; + return; + } + if (diff >= SML_LASTBIT) { + // bit zero was 0, + uint32_t next = (m_in_pos + 1) % serial_buffer_size; + if (next != (uint32_t)m_out_pos) { + m_buffer[m_in_pos] = ss_byte >> 1; + m_in_pos = next; + } + ss_byte = 0; + ss_index = 0; + } else { + // shift in + for (uint32_t i = ss_index; i < diff; i++) { + if (!level) ss_byte |= (1 << i); + } + ss_index = diff; + } + } +} +#endif // USE_ESP32_SW_SERIAL +#endif // ESP32 + +#ifdef ESP32 +#ifndef USE_ESP32_SW_SERIAL +HardwareSerial *meter_ss[MAX_METERS]; +#else +SML_ESP32_SERIAL *meter_ss[MAX_METERS]; +#endif +#endif // ESP32 + + #ifdef ANALOG_OPTO_SENSOR // sensor over ADS1115 with i2c Bus uint8_t ads1115_up; @@ -820,6 +1041,9 @@ void ADS1115_init(void) { char sml_start; uint8_t dump2log=0; +uint8_t ser_act_LED_pin=255; +uint8_t ser_act_meter_num=0; + #define SML_SAVAILABLE Serial_available() #define SML_SREAD Serial_read() #define SML_SPEAK Serial_peek() @@ -1398,12 +1622,15 @@ void sml_shift_in(uint32_t meters,uint32_t shard) { void SML_Poll(void) { uint32_t meters; - for (meters=0; metersavailable() && !digitalRead(ser_act_LED_pin)); // Invert LED, if queue is continuously full + } while (meter_ss[meters]->available()) { - sml_shift_in(meters,0); + sml_shift_in(meters, 0); } } } @@ -1755,7 +1982,7 @@ void SML_Decode(uint8_t index) { } else { // low word if (usign) ebus_dval = vbus_get_septet(cp) & 0xffff; - else (int16_t)(vbus_get_septet(cp) & 0xffff); + else ebus_dval = (int16_t)(vbus_get_septet(cp) & 0xffff); } break; case 'b': @@ -2124,7 +2351,7 @@ void SML_Show(boolean json) { } else { // web ui export //snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s{s}%s %s: {m}%s %s{e}", b_mqtt_data,meter_desc[mindex].prefix,name,tpowstr,unit); - if (strcmp(name,"*")) WSContentSend_PD(PSTR("{s}%s %s: {m}%s %s{e}"),meter_desc_p[mindex].prefix,name,tpowstr,unit); + if (strcmp(name,"*")) WSContentSend_PD(PSTR("{s}%s %s {m}%s %s{e}"),meter_desc_p[mindex].prefix,name,tpowstr,unit); } } } @@ -2311,7 +2538,7 @@ void SML_Init(void) { uint8_t *tp = 0; uint16_t index = 0; uint8_t section = 0; - uint8_t srcpin = 0; + int8_t srcpin = 0; uint8_t dec_line = 0; char *lp = glob_script_mem.scriptptr; sml_send_blocks = 0; @@ -2348,8 +2575,8 @@ void SML_Init(void) { } index--; srcpin = strtol(lp,&lp,10); - if (Gpio_used(srcpin)) { - AddLog(LOG_LEVEL_INFO, PSTR("gpio rx double define!")); + if (Gpio_used(abs(srcpin))) { + AddLog(LOG_LEVEL_INFO, PSTR("SML: Error: Duplicate GPIO %d defined. Not usable for RX in meter number %d"),abs(srcpin),index+1); dddef_exit: if (script_meter) free(script_meter); script_meter = 0; @@ -2404,7 +2631,7 @@ dddef_exit: lp++; script_meter_desc[index].trxpin = strtol(lp, &lp, 10); if (Gpio_used(script_meter_desc[index].trxpin)) { - AddLog(LOG_LEVEL_INFO, PSTR("gpio tx double define!")); + AddLog(LOG_LEVEL_INFO, PSTR("SML: Error: Duplicate GPIO %d defined. Not usable for TX in meter number %d"),script_meter_desc[index].trxpin,index+1); goto dddef_exit; } if (*lp != ',') goto next_line; @@ -2481,7 +2708,6 @@ dddef_exit: if (*lp == SCRIPT_EOL) lp--; goto next_line; } - #ifdef SML_REPLACE_VARS char dstbuf[SML_SRCBSIZE*2]; Replace_Cmd_Vars(lp, 1, dstbuf,sizeof(dstbuf)); @@ -2570,13 +2796,13 @@ init10: uint8_t cindex=0; // preloud counters for (byte i = 0; i < MAX_COUNTERS; i++) { - RtcSettings.pulse_counter[i]=Settings->pulse_counter[i]; + RtcSettings.pulse_counter[i] = Settings->pulse_counter[i]; sml_counters[i].sml_cnt_last_ts=millis(); } - uint32_t uart_index=2; - for (uint8_t meters=0; meters= 0) { + if (uart_index == 0) { ClaimSerial(); } + uart_index--; + if (uart_index < 0) uart_index = 0; + } +#else meter_ss[meters] = new HardwareSerial(uart_index); - if (uart_index==0) { ClaimSerial(); } + if (uart_index == 0) { ClaimSerial(); } uart_index--; - if (uart_index<0) uart_index=0; + if (uart_index < 0) uart_index = 0; meter_ss[meters]->setRxBufferSize(TMSBSIZ); +#endif // USE_ESP32_SW_SERIAL + #endif // ESP32 -#endif +#endif // SPECIAL_SS SerialConfig smode = SERIAL_8N1; @@ -2664,10 +2901,10 @@ init10: #endif // ESP8266 #ifdef ESP32 meter_ss[meters]->begin(meter_desc_p[meters].params, smode, meter_desc_p[meters].srcpin, meter_desc_p[meters].trxpin); + //meter_ss[meters]->setRxBufferSize(TMSBSIZ); #endif // ESP32 } } - } @@ -2685,7 +2922,7 @@ uint32_t sml_getv(uint32_t sel) { return sel; } uint32_t SML_SetBaud(uint32_t meter, uint32_t br) { - if (meter<1 || meter>meters_used) return 0; + if (meter < 1 || meter > meters_used) return 0; meter--; if (!meter_ss[meter]) return 0; #ifdef ESP8266 @@ -2762,10 +2999,14 @@ uint8_t hflg=0; } float SML_GetVal(uint32_t index) { - if (index<1 && index>SML_MAX_VARS) { index = 1;} + if (index < 1 || index > SML_MAX_VARS) { index = 1;} return meter_vars[index-1]; } +char *SML_GetSVal(uint32_t index) { + if (index < 1 || index > MAX_METERS) { index = 1;} + return &meter_id[index - 1][0]; +} #endif // USE_SML_SCRIPT_CMD @@ -3018,9 +3259,11 @@ uint8_t parity=0; // dump to log shows serial data on console // has to be off for normal use -// in console sensor53 d1,d2,d3 .. or. d0 for normal use +// in console sensor53 d1, d2, d3 ... or d0 for normal use // set counter => sensor53 c1 xxxx // restart driver => sensor53 r +// meter number for monitoring serial activity => sensor53 m1, m2, m3 ... or m0 for all (default) +// LED-GPIO for monitoring serial activity => sensor53 l2, l13, l15 ... or l255 for turn off (default) bool XSNS_53_cmd(void) { bool serviced = true; @@ -3037,7 +3280,7 @@ bool XSNS_53_cmd(void) { dump2log=index; ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"dump: %d\"}}"),dump2log); } else if (*cp=='c') { - // set ounter + // set counter cp++; uint8_t index=*cp&7; if (index<1 || index>MAX_COUNTERS) index=1; @@ -3061,6 +3304,31 @@ bool XSNS_53_cmd(void) { ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"restart\"}}")); SML_CounterSaveState(); SML_Init(); + } else if (*cp=='m') { + // meter number for serial activity + cp++; + if (!isdigit(*cp)) { + ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"ser_act_meter_num: %d\"}}"),ser_act_meter_num); + } else { + ser_act_meter_num=atoi(cp); + ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"ser_act_meter_num: %d\"}}"),ser_act_meter_num); + } + } else if (*cp=='l') { + // serial activity LED-GPIO + cp++; + if (!isdigit(*cp)) { + ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"ser_act_LED_pin: %d\"}}"),ser_act_LED_pin); + } else { + ser_act_LED_pin=atoi(cp); + if (Gpio_used(ser_act_LED_pin)) { + AddLog(LOG_LEVEL_INFO, PSTR("SML: Error: Duplicate GPIO %d defined. Not usable for LED."),ser_act_LED_pin); + ser_act_LED_pin=255; + } + if (ser_act_LED_pin!=255) { + pinMode(ser_act_LED_pin, OUTPUT); + } + ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"ser_act_LED_pin: %d\"}}"),ser_act_LED_pin); + } } else { serviced=false; } @@ -3095,7 +3363,9 @@ bool Xsns53(byte function) { case FUNC_LOOP: SML_Counter_Poll(); if (dump2log) Dump2log(); - else SML_Poll(); + else { + SML_Poll(); + } break; // case FUNC_EVERY_50_MSECOND: // if (dump2log) Dump2log(); diff --git a/tasmota/xsns_62_esp32_mi.h b/tasmota/xsns_62_esp32_mi.h new file mode 100644 index 000000000..3dd9bf89b --- /dev/null +++ b/tasmota/xsns_62_esp32_mi.h @@ -0,0 +1,512 @@ +/* + xsns_62_esp32_mi.h - MI-BLE-sensors via ESP32 support for Tasmota + + Copyright (C) 2021 Christian Baars and Theo Arends + + This program 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 . + +*/ +#ifdef USE_MI_ESP32 +/*********************************************************************************************\ + * structs and types +\*********************************************************************************************/ +#pragma pack(1) // byte-aligned structures to read the sensor data + +struct frame_crtl_t{ + uint16_t reserved1:1; + uint16_t reserved2:1; + uint16_t reserved3:1; + uint16_t isEncrypted:1; + uint16_t includesMAC:1; + uint16_t includesCapability:1; + uint16_t includesObj:1; + uint16_t MESH:1; + uint16_t registered:1; + uint16_t solicited:1; + uint16_t AuthMode:2; + uint16_t version:4; +}; + +struct mi_payload_t{ + uint8_t type; + uint8_t ten; + uint8_t size; + union { + struct{ //0d + int16_t temp; + uint16_t hum; + }HT; + uint8_t bat; //0a + int16_t temp; //04 + uint16_t hum; //06 + uint32_t lux; //07 + uint8_t moist; //08 + uint16_t fert; //09 + uint8_t leak; //14 + uint32_t NMT; //17 + uint8_t door; //19 + struct{ //01 + uint8_t num; + uint8_t value; + uint8_t type; + }Btn; + }; + uint8_t padding[12]; //for decryption +}; + +struct mi_beacon_t{ + frame_crtl_t frame; + uint16_t productID; + uint8_t counter; + uint8_t MAC[6]; + uint8_t capability; + mi_payload_t payload; +}; + + +struct cg_packet_t { + uint16_t frameID; + uint8_t MAC[6]; + uint16_t mode; + union { + struct { + int16_t temp; // -9 - 59 °C + uint16_t hum; + }; + uint8_t bat; + }; +}; + +struct encPacket_t{ + // the packet is longer, but this part is enough to decrypt + uint16_t PID; + uint8_t frameCnt; + uint8_t MAC[6]; + uint8_t payload[16]; // only a pointer to the address, size is variable +}; + +struct berryAdvPacket_t{ + uint8_t MAC[6]; + uint8_t addressType; + uint16_t svcUUID; + uint8_t RSSI; + uint8_t length; // length of svcData + uint8_t svcData[40]; // only a pointer to the address, size is variable + // the last array contains manufacturer data if present, if svcData is not present + // format: svcData[0] = length, svcData[1...length] = payload +}; + + +union mi_bindKey_t{ + struct{ + uint8_t key[16]; + uint8_t MAC[6]; + }; + uint8_t buf[22]; +}; + +struct ATCPacket_t{ //and PVVX + uint8_t MAC[6]; + union { + struct{ + uint16_t temp; //sadly this is in wrong endianess + uint8_t hum; + uint8_t batPer; + uint16_t batMV; + uint8_t frameCnt; + } A; //ATC + struct{ + int16_t temp; + uint16_t hum; // x 0.01 % + uint16_t batMV; + uint8_t batPer; + uint8_t frameCnt; + struct { + uint8_t reed:1; + uint8_t TRGval:1; + uint8_t TRGcrtl:1; + uint8_t tempTrig:1; + uint8_t humTrig:1; + uint8_t spare:3; + }; + }P; //PVVX + }; +}; + +#pragma pack(0) + + +struct MI32connectionContextBerry_t{ + NimBLEUUID serviceUUID; + NimBLEUUID charUUID; + uint8_t * MAC; + uint8_t * buffer; + uint8_t operation; + uint8_t addrType; + int error; + bool oneOp; +}; + +struct { + // uint32_t period; // set manually in addition to TELE-period, is set to TELE-period after start + TaskHandle_t ScanTask = nullptr; + TaskHandle_t ConnTask = nullptr; + MI32connectionContextBerry_t *conCtx = nullptr; + union { + struct { + uint32_t init:1; + uint32_t connected:1; + uint32_t autoScan:1; + uint32_t canScan:1; + uint32_t runningScan:1; + + uint32_t canConnect:1; + uint32_t willConnect:1; + uint32_t readingDone:1; + + uint32_t shallTriggerTele:1; + uint32_t triggeredTele:1; + uint32_t shallClearResults:1; // BLE scan results + uint32_t shallShowStatusInfo:1; // react to amount of found sensors via RULES + uint32_t didGetConfig:1; + uint32_t didStartHAP:1; + uint32_t triggerBerryAdvCB:1; + uint32_t triggerBerryConnCB:1; + }; + uint32_t all = 0; + } mode; + struct { + uint8_t sensor; // points to to the number 0...255 + } state; + struct { + uint32_t allwaysAggregate:1; // always show all known values of one sensor in brdigemode + uint32_t noSummary:1; // no sensor values at TELE-period + uint32_t directBridgeMode:1; // send every received BLE-packet as a MQTT-message in real-time + uint32_t showRSSI:1; + uint32_t ignoreBogusBattery:1; + uint32_t minimalSummary:1; // DEPRECATED!! + } option; +#ifdef USE_MI_EXT_GUI + uint32_t widgetSlot; +#ifdef USE_ENERGY_SENSOR + uint8_t *energy_history; +#endif //USE_ENERGY_SENSOR +#endif //USE_MI_EXT_GUI + +#ifdef USE_MI_HOMEKIT + void *outlet_hap_service[4]; //arbitrary chosen + int8_t HKconnectedControllers = 0; //should never be < 0 + uint8_t HKinfoMsg = 0; + char hk_setup_code[11]; +#endif //USE_MI_HOMEKIT + void *beConnCB; + void *beAdvCB; + uint8_t *beAdvBuf; + uint8_t infoMsg = 0; +} MI32; + +struct mi_sensor_t{ + uint8_t type; //Flora = 1; MI-HT_V1=2; LYWSD02=3; LYWSD03=4; CGG1=5; CGD1=6 + uint8_t lastCnt; //device generated counter of the packet + uint8_t shallSendMQTT; + uint8_t MAC[6]; + uint8_t *key; + uint32_t lastTimeSeen; + union { + struct { + uint32_t needsKey:1; + uint32_t temp:1; + uint32_t hum:1; + uint32_t tempHum:1; //every hum sensor has temp too, easier to use Tasmota dew point functions + uint32_t lux:1; + uint32_t moist:1; + uint32_t fert:1; + uint32_t bat:1; + uint32_t NMT:1; + uint32_t motion:1; + uint32_t Btn:1; + uint32_t door:1; + uint32_t leak:1; + }; + uint32_t raw; + } feature; + union { + struct { + uint32_t temp:1; + uint32_t hum:1; + uint32_t tempHum:1; //can be combined from the sensor + uint32_t lux:1; + uint32_t moist:1; + uint32_t fert:1; + uint32_t bat:1; + uint32_t NMT:1; + uint32_t motion:1; + uint32_t noMotion:1; + uint32_t Btn:1; + uint32_t door:1; + uint32_t leak:1; + }; + uint32_t raw; + } eventType; + union{ + struct{ + uint8_t hasWrongKey:1; + uint8_t isUnbounded:1; + }; + uint8_t raw; + } status; + + int RSSI; + uint32_t lastTime; + uint32_t lux; + uint8_t *lux_history; + float temp; //Flora, MJ_HT_V1, LYWSD0x, CGx + uint8_t *temp_history; + union { + struct { + uint8_t moisture; + uint16_t fertility; + char firmware[6]; // actually only for FLORA but hopefully we can add for more devices + }; // Flora + struct { + float hum; + uint8_t *hum_history; + }; // MJ_HT_V1, LYWSD0x + struct { + uint16_t events; //"alarms" since boot + uint32_t NMT; // no motion time in seconds for the MJYD2S + }; + struct { + uint16_t Btn; + uint8_t leak; + }; + uint8_t door; + }; + union { + uint8_t bat; // many values seem to be hard-coded garbage (LYWSD0x, GCD1) + }; +#ifdef USE_MI_HOMEKIT + //HAP handles + void *temp_hap_service; + void *hum_hap_service; + void *light_hap_service; + void *motion_hap_service; + void *door_sensor_hap_service; + void *button_hap_service[6]; + void *bat_hap_service; + void *leak_hap_service; +#endif //USE_MI_HOMEKIT +}; + +/*********************************************************************************************\ + * constants +\*********************************************************************************************/ + +#define D_CMND_MI32 "MI32" + +const char kMI32_Commands[] PROGMEM = D_CMND_MI32 "|Key|"/*Time|Battery|Unit|Beacon|*/"Cfg|Option"; + +void (*const MI32_Commands[])(void) PROGMEM = {&CmndMi32Key, /*&CmndMi32Time, &CmndMi32Battery, &CmndMi32Unit, &CmndMi32Beacon,*/ &CmndMi32Cfg, &CmndMi32Option }; + +#define FLORA 1 +#define MJ_HT_V1 2 +#define LYWSD02 3 +#define LYWSD03MMC 4 +#define CGG1 5 +#define CGD1 6 +#define NLIGHT 7 +#define MJYD2S 8 +#define YEERC 9 +#define MHOC401 10 +#define MHOC303 11 +#define ATC 12 +#define MCCGQ02 13 +#define SJWS01L 14 +#define PVVX 15 +#define YLKG08 16 + +#define MI32_TYPES 16 //count this manually + +const uint16_t kMI32DeviceID[MI32_TYPES]={ 0x0098, // Flora + 0x01aa, // MJ_HT_V1 + 0x045b, // LYWSD02 + 0x055b, // LYWSD03 + 0x0347, // CGG1 + 0x0576, // CGD1 + 0x03dd, // NLIGHT + 0x07f6, // MJYD2S + 0x0153, // yee-rc + 0x0387, // MHO-C401 + 0x06d3, // MHO-C303 + 0x0a1c, // ATC -> this is a fake ID + 0x098b, // MCCGQ02 + 0x0863, // SJWS01L + 0x944a, // PVVX -> this is a fake ID + 0x03b6 // YLKG08 and YLKG07 - version w/wo mains + }; + +const char kMI32DeviceType1[] PROGMEM = "Flora"; +const char kMI32DeviceType2[] PROGMEM = "MJ_HT_V1"; +const char kMI32DeviceType3[] PROGMEM = "LYWSD02"; +const char kMI32DeviceType4[] PROGMEM = "LYWSD03"; +const char kMI32DeviceType5[] PROGMEM = "CGG1"; +const char kMI32DeviceType6[] PROGMEM = "CGD1"; +const char kMI32DeviceType7[] PROGMEM = "NLIGHT"; +const char kMI32DeviceType8[] PROGMEM = "MJYD2S"; +const char kMI32DeviceType9[] PROGMEM = "YEERC"; +const char kMI32DeviceType10[] PROGMEM ="MHOC401"; +const char kMI32DeviceType11[] PROGMEM ="MHOC303"; +const char kMI32DeviceType12[] PROGMEM ="ATC"; +const char kMI32DeviceType13[] PROGMEM ="MCCGQ02"; +const char kMI32DeviceType14[] PROGMEM ="SJWS01L"; +const char kMI32DeviceType15[] PROGMEM ="PVVX"; +const char kMI32DeviceType16[] PROGMEM ="YLKG08"; +const char * kMI32DeviceType[] PROGMEM = {kMI32DeviceType1,kMI32DeviceType2,kMI32DeviceType3,kMI32DeviceType4, + kMI32DeviceType5,kMI32DeviceType6,kMI32DeviceType7,kMI32DeviceType8, + kMI32DeviceType9,kMI32DeviceType10,kMI32DeviceType11,kMI32DeviceType12, + kMI32DeviceType13,kMI32DeviceType14,kMI32DeviceType15,kMI32DeviceType16}; + +const char kMI32_ConnErrorMsg[] PROGMEM = "no Error|could not connect|got no service|got no characteristic|can not read|can not notify|can not write|did not write|notify time out"; + +const char kMI32_BLEInfoMsg[] PROGMEM = "Scan ended|Got Notification|Did connect|Did disconnect|Start scanning"; + +const char kMI32_HKInfoMsg[] PROGMEM = "HAP core started|HAP core did not start!!|HAP controller disconnected|HAP controller connected|HAP outlet added"; +/*********************************************************************************************\ + * enumerations +\*********************************************************************************************/ + +enum MI32_Commands { // commands useable in console or rules + CMND_MI32_KEY, // add bind key to a mac for packet decryption + CMND_MI32_CFG, // save config file as JSON with all sensors w/o keys to mi32cfg + CMND_MI32_OPTION // change driver options at runtime + }; + +enum MI32_TASK { + MI32_TASK_SCAN = 0, + MI32_TASK_CONN = 1, +}; + +enum MI32_ConnErrorMsg { + MI32_CONN_NO_ERROR = 0, + MI32_CONN_NO_CONNECT, + MI32_CONN_NO_SERVICE, + MI32_CONN_NO_CHARACTERISTIC, + MI32_CONN_CAN_NOT_READ, + MI32_CONN_CAN_NOT_NOTIFY, + MI32_CONN_CAN_NOT_WRITE, + MI32_CONN_DID_NOT_WRITE, + MI32_CONN_NOTIFY_TIMEOUT +}; + +enum MI32_BLEInfoMsg { + MI32_SCAN_ENDED = 1, + MI32_GOT_NOTIFICATION, + MI32_DID_CONNECT, + MI32_DID_DISCONNECT, + MI32_START_SCANNING +}; + +enum MI32_HKInfoMsg { + MI32_HAP_DID_START = 1, + MI32_HAP_DID_NOT_START, + MI32_HAP_CONTROLLER_DISCONNECTED, + MI32_HAP_CONTROLLER_CONNECTED, + MI32_HAP_OUTLET_ADDED +}; + +/*********************************************************************************************\ + * extended web gui +\*********************************************************************************************/ + +#ifdef USE_WEBSERVER +#ifdef USE_MI_EXT_GUI +const char HTTP_BTN_MENU_MI32[] PROGMEM = "

"; + +const char HTTP_MI32_SCRIPT_1[] PROGMEM = + "function setUp(){setInterval(countUp,1000); setInterval(update,100);}" + "function countUp(){let ti=document.querySelectorAll('.Ti');" + "for(const el of ti){var t=parseInt(el.innerText);el.innerText=t+1;}}" + "function update(){" //source, value + "var xr=new XMLHttpRequest();" + "xr.onreadystatechange=function(){" + "if(xr.readyState==4&&xr.status==200){" + "var r = xr.response;" // new widget + "if(r.length>2000){return;};if(r.length==0){return;}" + "var d = document.createElement('div');" + "d.innerHTML = r.trim();" + "var old = eb(d.firstChild.id);" + "old.parentNode.replaceChild(d.firstChild,old);" + "};" + "};" + "xr.open('GET','/m32?wi=1',true);" + "xr.send();" + "};" + ; + +const char HTTP_MI32_STYLE[] PROGMEM = + ""; + +const char HTTP_MI32_STYLE_SVG[] PROGMEM = + "" + "" + "" + ; + +const char HTTP_MI32_PARENT_START[] PROGMEM = + "
" + "

MI32 Bridge

" + "Observing %u devices
" + "Uptime: %u seconds
" +#ifdef USE_MI_HOMEKIT + "HomeKit setup code: %s
" + "HAP controller connections: %d
" +#else + "HomeKit not enabled%s
" +#endif //USE_MI_HOMEKIT + "Free Heap: %u kB" + "
"; + +const char HTTP_MI32_WIDGET[] PROGMEM = + "
MAC:%s RSSI:%d %s
" + "‌%s" + "

%s" + "" + "" + "" + "" + "

"; + +const char HTTP_MI32_GRAPH[] PROGMEM = + "" + "" + "" + ""; + //rgb(185, 124, 124) - red, rgb(185, 124, 124) - blue, rgb(242, 240, 176) - yellow + +#ifdef USE_MI_ESP32_ENERGY +const char HTTP_MI32_POWER_WIDGET[] PROGMEM = + "
" + "

Energy" + "

" + "

" D_VOLTAGE ": %.1f " D_UNIT_VOLT "

" + "

" D_CURRENT ": %.3f " D_UNIT_AMPERE "

"; +#endif //USE_MI_ESP32_ENERGY + +#endif //USE_MI_EXT_GUI +#endif // USE_WEBSERVER + +#endif //USE_MI_ESP32 diff --git a/tasmota/xsns_62_esp32_mi.ino b/tasmota/xsns_62_esp32_mi.ino index ecc9d228c..30fea697e 100644 --- a/tasmota/xsns_62_esp32_mi.ino +++ b/tasmota/xsns_62_esp32_mi.ino @@ -22,22 +22,12 @@ -------------------------------------------------------------------------------------------- Version yyyymmdd Action Description -------------------------------------------------------------------------------------------- + 0.9.5.0 20211016 changed - major rewrite, added mi32cfg (file and command), Homekit-Bridge, + extended GUI, + removed BLOCK, PERIOD, TIME, UNIT, BATTERY and PAGE -> replaced via Berry-Support + ------- 0.9.1.7 20201116 changed - small bugfixes, add BLOCK and OPTION command, send BLE scan via MQTT ------- - 0.9.1.6 20201022 changed - Beacon support, RSSI at TELEPERIOD, refactoring - ------- - 0.9.1.5 20201021 changed - HASS related ('null', hold back discovery), number of found sensors for RULES - ------- - 0.9.1.4 20201020 changed - use BearSSL for decryption, revert to old TELEPERIOD-cycle as default - ------- - 0.9.1.3 20200926 changed - Improve HA discovery, make key+MAC case insensitive - ------- - 0.9.1.3 20200916 changed - add ATC (custom FW for LYWSD03MMC), API adaption for NimBLE-Arduino 1.0.2 - ------- - 0.9.1.2 20200802 changed - add MHO-C303 - ------- - 0.9.1.1 20200715 changed - add MHO-C401, refactoring - ------- 0.9.1.0 20200712 changed - add lights and yeerc, add pure passive mode with decryption, lots of refactoring ------- @@ -53,334 +43,35 @@ #ifdef USE_MI_ESP32 +#ifdef USE_ENERGY_SENSOR +// #define USE_MI_ESP32_ENERGY //perpare for some GUI extensions +#endif + #define XSNS_62 62 -#define USE_MI_DECRYPTION #include #include -#ifdef USE_MI_DECRYPTION + #include -#endif //USE_MI_DECRYPTION + +#include "xsns_62_esp32_mi.h" + +#ifdef USE_MI_HOMEKIT +extern "C" void mi_homekit_main(void); +extern "C" void mi_homekit_update_value(void* handle, float value, uint32_t type); +extern "C" void mi_homekit_stop(); +void MI32getSetupCodeFromMAC(char* code); +#endif //USE_MI_HOMEKIT + void MI32scanEndedCB(NimBLEScanResults results); void MI32notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify); - -struct { - uint16_t perPage = 4; - uint32_t period; // set manually in addition to TELE-period, is set to TELE-period after start - union { - struct { - uint32_t init:1; - uint32_t connected:1; - uint32_t autoScan:1; - uint32_t canScan:1; - uint32_t runningScan:1; - uint32_t canConnect:1; - uint32_t willConnect:1; - uint32_t readingDone:1; - uint32_t shallSetTime:1; - uint32_t willSetTime:1; - uint32_t shallReadBatt:1; - uint32_t willReadBatt:1; - uint32_t shallSetUnit:1; - uint32_t willSetUnit:1; - uint32_t shallTriggerTele:1; - uint32_t triggeredTele:1; - uint32_t shallClearResults:1; // BLE scan results - uint32_t shallShowStatusInfo:1; // react to amount of found sensors via RULES - uint32_t firstAutodiscoveryDone:1; - uint32_t activeBeacon:1; - uint32_t shallShowScanResult:1; - uint32_t shallShowBlockList:1; - }; - uint32_t all = 0; - } mode; - struct { - uint8_t sensor; // points to to the number 0...255 - uint8_t beaconScanCounter; // countdown timer in seconds - } state; - struct { - uint32_t allwaysAggregate:1; // always show all known values of one sensor in brdigemode - uint32_t noSummary:1; // no sensor values at TELE-period - uint32_t directBridgeMode:1; // send every received BLE-packet as a MQTT-message in real-time - uint32_t holdBackFirstAutodiscovery:1; // allows to trigger it later - uint32_t showRSSI:1; - uint32_t ignoreBogusBattery:1; - uint32_t minimalSummary:1; // DEPRECATED!! - } option; -} MI32; - -#pragma pack(1) // byte-aligned structures to read the sensor data - - struct { - int16_t temp; - uint8_t hum; - uint16_t volt; // LYWSD03 only - } LYWSD0x_HT; - struct { - uint8_t spare; - int16_t temp; - uint16_t hum; - } CGD1_HT; - struct { - int16_t temp; - uint8_t spare; - uint32_t lux; - uint8_t moist; - uint16_t fert; - } Flora_TLMF; // temperature, lux, moisture, fertility - - -struct mi_beacon_t{ - uint16_t frame; - uint16_t productID; - uint8_t counter; - uint8_t MAC[6]; - uint8_t spare; - uint8_t type; - uint8_t ten; - uint8_t size; - union { - struct{ //0d - int16_t temp; - uint16_t hum; - }HT; - uint8_t bat; //0a - int16_t temp; //04 - uint16_t hum; //06 - uint32_t lux; //07 - uint8_t moist; //08 - uint16_t fert; //09 - uint32_t NMT; //17 - struct{ //01 - uint16_t num; - uint8_t longPress; - }Btn; - }; - uint8_t padding[12]; -}; - -struct cg_packet_t { - uint16_t frameID; - uint8_t MAC[6]; - uint16_t mode; - union { - struct { - int16_t temp; // -9 - 59 °C - uint16_t hum; - }; - uint8_t bat; - }; -}; - -struct encPacket_t{ - // the packet is longer, but this part is enough to decrypt - uint16_t PID; - uint8_t frameCnt; - uint8_t MAC[6]; - uint8_t payload[16]; // only a pointer to the address, size is variable -}; - -union mi_bindKey_t{ - struct{ - uint8_t key[16]; - uint8_t MAC[6]; - }; - uint8_t buf[22]; -}; - -struct ATCPacket_t{ - uint8_t MAC[6]; - uint16_t temp; //sadly this is in wrong endianess - uint8_t hum; - uint8_t batPer; - uint16_t batMV; - uint8_t frameCnt; -}; - -#pragma pack(0) - -struct mi_sensor_t{ - uint8_t type; //Flora = 1; MI-HT_V1=2; LYWSD02=3; LYWSD03=4; CGG1=5; CGD1=6 - uint8_t lastCnt; //device generated counter of the packet - uint8_t shallSendMQTT; - uint8_t MAC[6]; - union { - struct { - uint32_t temp:1; - uint32_t hum:1; - uint32_t tempHum:1; //every hum sensor has temp too, easier to use Tasmota dew point functions - uint32_t lux:1; - uint32_t moist:1; - uint32_t fert:1; - uint32_t bat:1; - uint32_t NMT:1; - uint32_t PIR:1; - uint32_t Btn:1; - }; - uint32_t raw; - } feature; - union { - struct { - uint32_t temp:1; - uint32_t hum:1; - uint32_t tempHum:1; //can be combined from the sensor - uint32_t lux:1; - uint32_t moist:1; - uint32_t fert:1; - uint32_t bat:1; - uint32_t NMT:1; - uint32_t motion:1; - uint32_t noMotion:1; - uint32_t Btn:1; - }; - uint32_t raw; - } eventType; - - int RSSI; - uint32_t lastTime; - uint32_t lux; - float temp; //Flora, MJ_HT_V1, LYWSD0x, CGx - union { - struct { - uint8_t moisture; - uint16_t fertility; - char firmware[6]; // actually only for FLORA but hopefully we can add for more devices - }; // Flora - struct { - float hum; - }; // MJ_HT_V1, LYWSD0x - struct { - uint16_t events; //"alarms" since boot - uint32_t NMT; // no motion time in seconds for the MJYD2S - }; - uint16_t Btn; - }; - union { - uint8_t bat; // many values seem to be hard-coded garbage (LYWSD0x, GCD1) - }; -}; - -struct scan_entry_t { - uint8_t MAC[6]; - uint16_t CID; - uint16_t SVC; - uint16_t UUID; - int32_t RSSI; -}; - -struct generic_beacon_t { - uint8_t MAC[6]; - uint32_t time; - int32_t RSSI; - uint16_t CID; // company identifier - uint16_t UUID; // the first, if more than one exists - uint16_t SVC; - bool active = false; -}; - -struct MAC_t { - uint8_t buf[6]; -}; +void MI32AddKey(mi_bindKey_t keyMAC); std::vector MIBLEsensors; -std::vector MIBLEbindKeys; -std::array MIBLEbeacons; // we support a fixed number -std::vector MIBLEscanResult; -std::vector MIBLEBlockList; static BLEScan* MI32Scan; -/*********************************************************************************************\ - * constants -\*********************************************************************************************/ - -#define D_CMND_MI32 "MI32" - -const char kMI32_Commands[] PROGMEM = D_CMND_MI32 "|" -#ifdef USE_MI_DECRYPTION - "Key|" -#endif // USE_MI_DECRYPTION - "Period|Time|Page|Battery|Unit|Beacon|Block|Option"; - -void (*const MI32_Commands[])(void) PROGMEM = { -#ifdef USE_MI_DECRYPTION - &CmndMi32Key, -#endif // USE_MI_DECRYPTION - &CmndMi32Period, &CmndMi32Time, &CmndMi32Page, &CmndMi32Battery, &CmndMi32Unit, &CmndMi32Beacon, &CmndMi32Block, &CmndMi32Option }; - -#define FLORA 1 -#define MJ_HT_V1 2 -#define LYWSD02 3 -#define LYWSD03MMC 4 -#define CGG1 5 -#define CGD1 6 -#define NLIGHT 7 -#define MJYD2S 8 -#define YEERC 9 -#define MHOC401 10 -#define MHOC303 11 -#define ATC 12 - -#define MI32_TYPES 12 //count this manually - -const uint16_t kMI32DeviceID[MI32_TYPES]={ 0x0098, // Flora - 0x01aa, // MJ_HT_V1 - 0x045b, // LYWSD02 - 0x055b, // LYWSD03 - 0x0347, // CGG1 - 0x0576, // CGD1 - 0x03dd, // NLIGHT - 0x07f6, // MJYD2S - 0x0153, // yee-rc - 0x0387, // MHO-C401 - 0x06d3, // MHO-C303 - 0x0a1c // ATC -> this is a fake ID - }; - -const char kMI32DeviceType1[] PROGMEM = "Flora"; -const char kMI32DeviceType2[] PROGMEM = "MJ_HT_V1"; -const char kMI32DeviceType3[] PROGMEM = "LYWSD02"; -const char kMI32DeviceType4[] PROGMEM = "LYWSD03"; -const char kMI32DeviceType5[] PROGMEM = "CGG1"; -const char kMI32DeviceType6[] PROGMEM = "CGD1"; -const char kMI32DeviceType7[] PROGMEM = "NLIGHT"; -const char kMI32DeviceType8[] PROGMEM = "MJYD2S"; -const char kMI32DeviceType9[] PROGMEM = "YEERC"; -const char kMI32DeviceType10[] PROGMEM ="MHOC401"; -const char kMI32DeviceType11[] PROGMEM ="MHOC303"; -const char kMI32DeviceType12[] PROGMEM ="ATC"; -const char * kMI32DeviceType[] PROGMEM = {kMI32DeviceType1,kMI32DeviceType2,kMI32DeviceType3,kMI32DeviceType4,kMI32DeviceType5,kMI32DeviceType6,kMI32DeviceType7,kMI32DeviceType8,kMI32DeviceType9,kMI32DeviceType10,kMI32DeviceType11,kMI32DeviceType12}; - -/*********************************************************************************************\ - * enumerations -\*********************************************************************************************/ - -enum MI32_Commands { // commands useable in console or rules - CMND_MI32_PERIOD, // set period like TELE-period in seconds between read-cycles - CMND_MI32_TIME, // set LYWSD02-Time from ESP8266-time - CMND_MI32_PAGE, // sensor entries per web page, which will be shown alternated - CMND_MI32_BATTERY, // read all battery levels - CMND_MI32_UNIT, // toggles the displayed unit between C/F (LYWSD02) - CMND_MI32_KEY, // add bind key to a mac for packet decryption - CMND_MI32_BEACON, // add up to 4 beacons defined by their MAC addresses - CMND_MI32_BLOCK, // block BLE sensors defined by their MAC addresses - CMND_MI32_OPTION // change driver options at runtime - }; - -enum MI32_TASK { - MI32_TASK_SCAN = 0, - MI32_TASK_CONN = 1, - MI32_TASK_TIME = 2, - MI32_TASK_BATT = 3, - MI32_TASK_UNIT = 4, -}; - -enum MI32_BEACON_CMND { - MI32_BEACON_ON = 0, - MI32_BEACON_OFF = 1, - MI32_BEACON_DEL = 2, -}; /*********************************************************************************************\ * Classes @@ -388,14 +79,15 @@ enum MI32_BEACON_CMND { class MI32SensorCallback : public NimBLEClientCallbacks { void onConnect(NimBLEClient* pclient) { - AddLog(LOG_LEVEL_DEBUG,PSTR("connected %s"), kMI32DeviceType[(MIBLEsensors[MI32.state.sensor].type)-1]); + // AddLog(LOG_LEVEL_DEBUG,PSTR("connected %s"), kMI32DeviceType[(MIBLEsensors[MI32.conCtx->slot].type)-1]); + MI32.infoMsg = MI32_DID_CONNECT; MI32.mode.willConnect = 0; MI32.mode.connected = 1; } void onDisconnect(NimBLEClient* pclient) { MI32.mode.connected = 0; - MI32.mode.willReadBatt = 0; - AddLog(LOG_LEVEL_DEBUG,PSTR("disconnected %s"), kMI32DeviceType[(MIBLEsensors[MI32.state.sensor].type)-1]); + MI32.infoMsg = MI32_DID_DISCONNECT; + //AddLog(LOG_LEVEL_DEBUG,PSTR("disconnected")); } bool onConnParamsUpdateRequest(NimBLEClient* MI32Client, const ble_gap_upd_params* params) { if(params->itvl_min < 24) { /** 1.25ms units */ @@ -413,46 +105,63 @@ class MI32SensorCallback : public NimBLEClientCallbacks { class MI32AdvCallbacks: public NimBLEAdvertisedDeviceCallbacks { void onResult(NimBLEAdvertisedDevice* advertisedDevice) { - // AddLog(LOG_LEVEL_DEBUG,PSTR("Advertised Device: %s Buffer: %u"),advertisedDevice->getAddress().toString().c_str(),advertisedDevice->getServiceData(0).length()); + static bool _mutex = false; + if(_mutex) return; + _mutex = true; + int RSSI = advertisedDevice->getRSSI(); uint8_t addr[6]; memcpy(addr,advertisedDevice->getAddress().getNative(),6); MI32_ReverseMAC(addr); - if (advertisedDevice->getServiceDataCount() == 0) { - // AddLog(LOG_LEVEL_DEBUG,PSTR("No Xiaomi Device: %s Buffer: %u"),advertisedDevice->getAddress().toString().c_str(),advertisedDevice->getServiceData(0).length()); - if(MI32.state.beaconScanCounter==0 && !MI32.mode.activeBeacon){ - MI32Scan->erase(advertisedDevice->getAddress()); - return; - } - else{ - MI32HandleGenericBeacon(advertisedDevice->getPayload(), advertisedDevice->getPayloadLength(), RSSI, addr); - return; - } + size_t ServiceDataLength = 0; + + if (advertisedDevice->getServiceDataCount() == 0) { + if(MI32.beAdvCB != nullptr && MI32.mode.triggerBerryAdvCB == 0){ + berryAdvPacket_t *_packet = (berryAdvPacket_t *)MI32.beAdvBuf; + memcpy(_packet->MAC,addr,6); + _packet->addressType = advertisedDevice->getAddressType(); + _packet->svcUUID = 0; + _packet->RSSI = (uint8_t)RSSI; + _packet->length = ServiceDataLength; + _packet->svcData[0] = 0; //guarantee it is zero!! + if(advertisedDevice->haveManufacturerData()){ + std::string _md = advertisedDevice->getManufacturerData(); + _packet->svcData[0] = _md.size(); + memcpy((_packet->svcData)+ServiceDataLength+1,_md.data(), _md.size()); + } + MI32.mode.triggerBerryAdvCB = 1; + } + _mutex = false; + return; } uint16_t UUID = advertisedDevice->getServiceDataUUID(0).getNative()->u16.value; - // AddLog(LOG_LEVEL_DEBUG,PSTR("UUID: %x"),UUID); - size_t ServiceDataLength = advertisedDevice->getServiceData(0).length(); + ServiceDataLength = advertisedDevice->getServiceData(0).length(); + if(MI32.beAdvCB != nullptr && MI32.mode.triggerBerryAdvCB == 0){ + berryAdvPacket_t *_packet = (berryAdvPacket_t *)MI32.beAdvBuf; + memcpy(_packet->MAC,addr,6); + _packet->addressType = advertisedDevice->getAddressType(); + _packet->svcUUID = UUID; + _packet->RSSI = (uint8_t)RSSI; + _packet->length = ServiceDataLength; + memcpy(_packet->svcData,advertisedDevice->getServiceData(0).data(),ServiceDataLength); + MI32.mode.triggerBerryAdvCB = 1; + } + if(UUID==0xfe95) { - if(MI32isInBlockList(addr) == true) return; MI32ParseResponse((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI); } else if(UUID==0xfdcd) { - if(MI32isInBlockList(addr) == true) return; MI32parseCGD1Packet((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI); } - else if(UUID==0x181a) { //ATC - if(MI32isInBlockList(addr) == true) return; + else if(UUID==0x181a) { //ATC and PVVX MI32ParseATCPacket((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI); } - else { - if(MI32.state.beaconScanCounter!=0 || MI32.mode.activeBeacon){ - MI32HandleGenericBeacon(advertisedDevice->getPayload(), advertisedDevice->getPayloadLength(), RSSI, addr); - } - // AddLog(LOG_LEVEL_DEBUG,PSTR("No Xiaomi Device: %x: %s Buffer: %u"), UUID, advertisedDevice->getAddress().toString().c_str(),advertisedDevice->getServiceData(0).length()); - MI32Scan->erase(advertisedDevice->getAddress()); - } + // else { + // MI32Scan->erase(advertisedDevice->getAddress()); + // } + _mutex = false; }; }; @@ -466,21 +175,16 @@ static NimBLEClient* MI32Client; \*********************************************************************************************/ void MI32scanEndedCB(NimBLEScanResults results){ - AddLog(LOG_LEVEL_DEBUG,PSTR("Scan ended")); + MI32.infoMsg = MI32_SCAN_ENDED; MI32.mode.runningScan = 0; } void MI32notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify){ - AddLog(LOG_LEVEL_DEBUG,PSTR("Notified length: %u"),length); - switch(MIBLEsensors[MI32.state.sensor].type){ - case LYWSD03MMC: case LYWSD02: case MHOC401: - MI32readHT_LY((char*)pData); - MI32.mode.readingDone = 1; - break; - default: - MI32.mode.readingDone = 1; - break; - } + MI32.infoMsg = MI32_GOT_NOTIFICATION; + MI32.conCtx->buffer[0] = (uint8_t)length; + memcpy(MI32.conCtx->buffer + 1, pData, length); + MI32.mode.triggerBerryConnCB = 1; + MI32.mode.readingDone = 1; } /*********************************************************************************************\ * Helper functions @@ -542,97 +246,125 @@ void MI32_ReverseMAC(uint8_t _mac[]){ memcpy(_mac,_reversedMAC, sizeof(_reversedMAC)); } -#ifdef USE_MI_DECRYPTION -void MI32AddKey(char* payload){ - mi_bindKey_t keyMAC; - MI32HexStringToBytes(payload,keyMAC.buf); - bool unknownKey = true; - for(uint32_t i=0; iMAC[i]; - } - memcpy((uint8_t*)&nonce+6,(uint8_t*)&packet->PID,2); - nonce[8] = packet->frameCnt; - memcpy((uint8_t*)&nonce+9,(uint8_t*)&_buf[_bufSize-9],3); - // AddLog(LOG_LEVEL_DEBUG,PSTR("nonceCnt1 and 2: %02x %02x %02x"),nonce[9],nonce[10],nonce[11]); - memcpy((uint8_t*)&tag,(uint8_t*)&_buf[_bufSize-6],4); - // AddLog(LOG_LEVEL_DEBUG,PSTR("tag: %02x %02x %02x %02x"),tag[0],tag[1],tag[2],tag[3]); - - MI32_ReverseMAC(packet->MAC); - uint8_t _bindkey[16] = {0x0}; - bool foundNoKey = true; - AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Search key for MAC: %02x %02x %02x %02x %02x %02x"), packet->MAC[0], packet->MAC[1], packet->MAC[2], packet->MAC[3], packet->MAC[4], packet->MAC[5]); - for(uint32_t i=0; iMAC,MIBLEbindKeys[i].MAC,sizeof(packet->MAC))==0){ - memcpy(_bindkey,MIBLEbindKeys[i].key,sizeof(_bindkey)); - AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Decryption Key found")); - foundNoKey = false; - break; - } - } - if(foundNoKey){ - AddLog(LOG_LEVEL_DEBUG,PSTR("M32: No Key found !!")); + if(MIBLEsensors[_slot].key == nullptr){ + // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: No Key found !!")); return -2; } + // uint8_t _testBuf[] = {0x58,0x30,0xb6,0x03,0x36,0x8b,0x98,0xc5,0x41,0x24,0xf8,0x8b,0xb8,0xf2,0x66,0x13,0x51,0x00,0x00,0x00,0xd6}; + // uint8_t _testKey[] = {0xb8,0x53,0x07,0x51,0x58,0x48,0x8d,0x3d,0x3c,0x97,0x7c,0xa3,0x9a,0x5b,0x5e,0xa9}; + // _beacon = (mi_beacon_t *)_testBuf; + // _bufSize = sizeof(_testBuf); + // dataLen = _bufSize - 11 ; // _bufsize - frame - type - frame.counter - MAC + + + uint32_t _version = (uint32_t)_beacon->frame.version; + // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: encrypted msg from %s with version:%u"),kMI32DeviceType[MIBLEsensors[_slot].type-1],_version); + + if(_version == 5){ + if(_beacon->frame.includesMAC){ + for (uint32_t i = 0; i<6; i++){ + nonce[i] = _beacon->MAC[i]; + } + // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: has MAC")); + memcpy(_payload,(uint8_t*)&_beacon->capability, dataLen); //special packet + dataLen -= 7; + } + else{ + // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: has no MAC")); + for (uint32_t i = 0; i<6; i++){ + nonce[i] = MIBLEsensors[_slot].MAC[5-i]; + } + dataLen = _bufSize -5 ; + memcpy(_payload,_beacon->MAC, dataLen); //special packet + dataLen -= 7; + // AddLogBuffer(LOG_LEVEL_DEBUG,(uint8_t*) _payload, dataLen); + } + // nonce: device MAC, device type, frame cnt, ext. cnt + memcpy((uint8_t*)&nonce+6,(uint8_t*)&_beacon->productID,2); + nonce[8] = _beacon->counter; + memcpy((uint8_t*)&nonce+9,(uint8_t*)&_payload[dataLen],3); + // memcpy((uint8_t*)&tag,(uint8_t*)&_payload[dataLen-4],4); + memcpy((uint8_t*)&tag,(uint8_t*)&_buf[_bufSize-4],4); + } + else if(_version == 3){ + // nonce: frame_ctrl, device type, ext. cnt, frame cnt, device MAC(only first 5 bytes) + memcpy(_payload,(uint8_t*)&_beacon->capability, dataLen); //special packet + nonceLen = 13; + memcpy((uint8_t*)&nonce,(uint8_t*)&_beacon->frame,2); + memcpy((uint8_t*)&nonce+2,(uint8_t*)&_beacon->productID,2); + nonce[4] = _beacon->counter; + memcpy((uint8_t*)&nonce+5,(uint8_t*)&_buf[_bufSize-4],3); + for (uint32_t i = 0; i<5; i++){ + nonce[i+8] = _beacon->MAC[i]; + } + tag[0] = _buf[_bufSize-1]; + // AddLogBuffer(LOG_LEVEL_DEBUG,(uint8_t*) nonce, 13); + dataLen -= 4; + } + else{ + AddLog(LOG_LEVEL_DEBUG,PSTR("M32: unexpected decryption version:%u"),_version); // should never happen + } + br_aes_small_ctrcbc_keys keyCtx; - br_aes_small_ctrcbc_init(&keyCtx, _bindkey, sizeof(_bindkey)); + br_aes_small_ctrcbc_init(&keyCtx, MIBLEsensors[_slot].key, 16); + // br_aes_small_ctrcbc_init(&keyCtx, _testKey, 16); br_ccm_context ctx; br_ccm_init(&ctx, &keyCtx.vtable); - br_ccm_reset(&ctx, nonce, sizeof(nonce), sizeof(authData), data_len, sizeof(tag)); + br_ccm_reset(&ctx, nonce, nonceLen, sizeof(authData), dataLen, sizeof(tag)); br_ccm_aad_inject(&ctx, authData, sizeof(authData)); br_ccm_flip(&ctx); + br_ccm_run(&ctx, 0, _payload, dataLen); + if(br_ccm_check_tag(&ctx, &tag)) return 0; - memcpy(payload,packet->payload,data_len); //we want to be sure about 4-byte alignement - br_ccm_run(&ctx, 0, payload, data_len); - memcpy((uint8_t*)packet->payload+1,payload,data_len); //back to the packet - - ret = br_ccm_check_tag(&ctx, &tag); - - AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Err:%i, Decrypted : %02x %02x %02x %02x %02x "), ret, packet->payload[1],packet->payload[2],packet->payload[3],packet->payload[4],packet->payload[5]); - return ret-1; + // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: decrypted in %.2f mSec"),enctime); + // AddLogBuffer(LOG_LEVEL_DEBUG,(uint8_t*) _payload, dataLen); + return -1; // wrong key ... maybe corrupt data packet too } -#endif // USE_MI_DECRYPTION /*********************************************************************************************\ * common functions \*********************************************************************************************/ - /** * @brief Return the slot number of a known sensor or return create new sensor slot * @@ -641,7 +373,6 @@ int MI32_decryptPacket(char *_buf, uint16_t _bufSize, uint32_t _type){ * @return uint32_t Known or new slot in the sensors-vector */ uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, uint8_t counter){ - DEBUG_SENSOR_LOG(PSTR("%s: will test ID-type: %x"),D_CMND_MI32, _type); bool _success = false; for (uint32_t i=0;i100.0f) value=100.0f; //clamp it for now + history[_hour] = (((uint8_t)(value/5.0f))+1) + 0b10000000; //lux + // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: history lux: %u in hour:%u"),history[_hour], _hour); + break; +#ifdef USE_MI_ESP32_ENERGY + case 100: // energy + if(value == 0.0f) value = 1.0f; + uint8_t _watt = ((uint8_t)(MI32ln(value))*2) + 0b10000000; //watt + history[_hour] = _watt; + // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: history energy: %u for value:%u"),history[_hour], value); //still playing with the mapping + break; +#endif //USE_MI_ESP32_ENERGY + } +} + +/** + * @brief Returns a value betwenn 0-21 for use as a data point in the history graph of the extended web UI + * + * @param history - pointer to uint8_t[23] + * @param hour - hour of datapoint + * @return uint8_t - value for the y-axis, should be between 0-21 + */ +uint8_t MI32fetchHistory(uint8_t *history, uint32_t hour){ + if(hour>23) { + return 0;} //should never happen + if(bitRead(history[hour],7) == 0) { + return 0; //invalidated data + } + return (history[hour]) - 0b10000000; +} + +/** + * @brief Invalidates the history data of the following hour by setting MSB to 0, should be called at FUNC_JSON_APPEND + * + */ +void Mi32invalidateOldHistory(){ + uint32_t _hour = (LocalTime()%SECS_PER_DAY)/SECS_PER_HOUR; + static uint32_t _lastInvalidatedHour = 99; + if (_lastInvalidatedHour == _hour){ + return; + } + uint32_t _nextHour = (_hour>22)?0:_hour+1; + for(auto _sensor:MIBLEsensors){ + if(_sensor.feature.temp == 1){ + bitClear(_sensor.temp_history[_nextHour],7); + } + if(_sensor.feature.hum == 1){ + bitClear(_sensor.hum_history[_nextHour],7); + } + if(_sensor.feature.lux == 1){ + bitClear(_sensor.lux_history[_nextHour],7); + } + } + _lastInvalidatedHour = _hour; +} + +#endif //USE_MI_EXT_GUI /*********************************************************************************************\ * init NimBLE \*********************************************************************************************/ void MI32PreInit(void) { - MIBLEsensors.reserve(10); - MIBLEbindKeys.reserve(10); - MIBLEscanResult.reserve(20); + MI32.mode.init = false; //test section for options @@ -758,7 +614,13 @@ void MI32PreInit(void) { MI32.option.directBridgeMode = 0; MI32.option.showRSSI = 1; MI32.option.ignoreBogusBattery = 1; // from advertisements - MI32.option.holdBackFirstAutodiscovery = 1; + + MI32loadCfg(); + if(MIBLEsensors.size()>0){ + MI32.mode.didGetConfig = 1; + } + + MI32.beAdvCB = nullptr; AddLog(LOG_LEVEL_INFO,PSTR("M32: pre-init")); } @@ -775,52 +637,370 @@ void MI32Init(void) { } } + if(MI32.mode.didGetConfig){ + MI32.mode.didStartHAP = 0; + #ifdef USE_MI_HOMEKIT + MI32getSetupCodeFromMAC(MI32.hk_setup_code); + AddLog(LOG_LEVEL_INFO,PSTR("M32: Init HAP core")); + mi_homekit_main(); + #else + MI32.mode.didStartHAP = 1; + #endif //USE_MI_HOMEKIT + } + if (!MI32.mode.init) { - NimBLEDevice::init(""); + NimBLEDevice::init("MI32"); AddLog(LOG_LEVEL_INFO,PSTR("M32: Init BLE device")); - MI32.mode.canScan = 1; MI32.mode.init = 1; - MI32.period = Settings->tele_period; MI32StartScanTask(); // Let's get started !! } +#ifdef USE_MI_EXT_GUI +#ifdef USE_MI_ESP32_ENERGY + MI32.energy_history = (uint8_t*) calloc(24,1); +#endif //USE_MI_ESP32_ENERGY +#endif //USE_MI_EXT_GUI return; } +/*********************************************************************************************\ + * Berry section - partly used by HomeKit too +\*********************************************************************************************/ +extern "C" { + + bool MI32runBerryConnection(uint8_t operation){ + if(MI32.conCtx != nullptr){ + MI32.conCtx->operation = operation%100; + AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Berry connection op: %d, addrType: %d"),MI32.conCtx->operation, MI32.conCtx->addrType); + MI32StartConnectionTask(); + return true; + } + return false; + } + + void MI32setBerryConnCB(void* function, uint8_t *buffer){ + if(MI32.conCtx == nullptr){ + MI32.conCtx = new MI32connectionContextBerry_t; + } + MI32.conCtx->buffer = buffer; + MI32.beConnCB = function; + AddLog(LOG_LEVEL_INFO,PSTR("M32: Connection Ctx created")); + } + + bool MI32setBerryCtxSvc(const char *Svc){ + if(MI32.conCtx != nullptr){ + MI32.conCtx->serviceUUID = NimBLEUUID(Svc); + AddLog(LOG_LEVEL_INFO,PSTR("M32: SVC: %s"),MI32.conCtx->serviceUUID.toString().c_str()); + // AddLog(LOG_LEVEL_INFO,PSTR("M32: SVC: %s"),Svc); + return true; + } + return false; + } + + bool MI32setBerryCtxChr(const char *Chr){ + if(MI32.conCtx != nullptr){ + MI32.conCtx->charUUID = NimBLEUUID(Chr); + AddLog(LOG_LEVEL_INFO,PSTR("M32: CHR: %s"),MI32.conCtx->charUUID.toString().c_str()); + // AddLog(LOG_LEVEL_INFO,PSTR("M32: CHR: %s"),Chr); + return true; + } + return false; + } + + bool MI32setBerryCtxMAC(uint8_t *MAC, uint8_t type){ + if(MI32.conCtx != nullptr){ + MI32.conCtx->MAC = MAC; + if(type<4) MI32.conCtx->addrType = type; + else MI32.conCtx->addrType = 0; + return true; + } + return false; + } + + void MI32setBerryAdvCB(void* function, uint8_t *buffer){ + MI32.beAdvCB = function; + MI32.beAdvBuf = buffer; + } + + void MI32setBatteryForSlot(uint32_t slot, uint8_t value){ + if(slot>MIBLEsensors.size()-1) return; + if(MIBLEsensors[slot].feature.bat){ + MIBLEsensors[slot].bat = value; + } + } + + void MI32setHumidityForSlot(uint32_t slot, float value){ + if(slot>MIBLEsensors.size()-1) return; + if(MIBLEsensors[slot].feature.hum){ + MIBLEsensors[slot].hum = value; + } + } + + void MI32setTemperatureForSlot(uint32_t slot, float value){ + if(slot>MIBLEsensors.size()-1) return; + if(MIBLEsensors[slot].feature.temp){ + MIBLEsensors[slot].temp = value; + } + } + + uint32_t MI32numberOfDevices(){ + return MIBLEsensors.size(); + } + + uint8_t * MI32getDeviceMAC(uint32_t slot){ + if(slot>MIBLEsensors.size()-1) return NULL; + return MIBLEsensors[slot].MAC; + } + + const char * MI32getDeviceName(uint32_t slot){ + if(slot>MIBLEsensors.size()-1) return ""; + return kMI32DeviceType[MIBLEsensors[slot].type-1]; + } + +} //extern "C" +/*********************************************************************************************\ + * Homekit section +\*********************************************************************************************/ +#ifdef USE_MI_HOMEKIT +extern "C" { + + const char * MI32getSetupCode(){ + return (const char*)MI32.hk_setup_code; + } + + uint32_t MI32numOfRelays(){ + if(TasmotaGlobal.devices_present>0) MI32.HKinfoMsg = MI32_HAP_OUTLET_ADDED; + return TasmotaGlobal.devices_present; + } + + void MI32setRelayFromHK(uint32_t relay, bool onOff){ + ExecuteCommandPower(relay, onOff, SRC_IGNORE); + } + + uint32_t MI32getDeviceType(uint32_t slot){ + return MIBLEsensors[slot].type; + } + +/** + * @brief Get at least a bit of the status of the HAP core, i.e. to reduce the activy of the driver while doing the pairing + * + * @param event + */ + void MI32passHapEvent(uint32_t event){ + switch(event){ + case 5: //HAP_EVENT_PAIRING_STARTED + MI32suspendScanTask(); + default: + vTaskResume(MI32.ScanTask); + } + if(event==4){ + MI32.HKinfoMsg = MI32_HAP_CONTROLLER_DISCONNECTED; + MI32.HKconnectedControllers--; + } + if(event==3){ + MI32.HKinfoMsg = MI32_HAP_CONTROLLER_CONNECTED; + MI32.HKconnectedControllers++; + } + } + + void MI32didStartHAP(bool HAPdidStart){ + if(HAPdidStart) { + MI32.mode.didStartHAP = 1; + MI32.HKinfoMsg = MI32_HAP_DID_START; + } + else{ + MI32.HKinfoMsg = MI32_HAP_DID_NOT_START; + } + } + +/** + * @brief Simply store the writeable HAP characteristics as void pointers in the "main" driver for updates of the values + * + * @param slot - sensor slot in MIBLEsensors + * @param type - sensors type, except for the buttons this is equal to the mibeacon types + * @param handle - a void ponter to a characteristic + */ + void MI32saveHAPhandles(uint32_t slot, uint32_t type, void* handle){ + // AddLog(LOG_LEVEL_INFO,PSTR("M32: pass ptr to hap service, type:%u"), type); + switch(type){ + case 1000: case 1001: case 1002: case 1003: case 1004: case 1005: + MIBLEsensors[slot].button_hap_service[type-1000] = handle; + break; + case 0x04: + MIBLEsensors[slot].temp_hap_service = handle; + break; + case 0x06: + MIBLEsensors[slot].hum_hap_service = handle; + break; + case 0x0a: + MIBLEsensors[slot].bat_hap_service = handle; + break; + case 0x07: + MIBLEsensors[slot].light_hap_service = handle; + break; + case 0x0f: + MIBLEsensors[slot].motion_hap_service = handle; + break; + case 0x14: + MIBLEsensors[slot].leak_hap_service = handle; + break; + case 0x19: + MIBLEsensors[slot].door_sensor_hap_service = handle; + break; + case 0xf0: + if(slot>3) break; //support only 4 for now + MI32.outlet_hap_service[slot] = handle; + break; + } + } +} + +/** + * @brief Creates a simplified setup code from the Wifi MAC for HomeKit by converting every ascii-converted byte to 1, if it not 2-9 + * Example: AABBCC1234f2 + * -> 111-11-234 + * This is no security feature, only for convenience + * * @param setupcode + */ + void MI32getSetupCodeFromMAC(char *setupcode){ + uint8_t _mac[6]; + char _macStr[13] = { 0 }; + WiFi.macAddress(_mac); + ToHex_P(_mac,6,_macStr,13); + AddLog(LOG_LEVEL_INFO,PSTR("M32: Wifi MAC: %s"), _macStr); + for(int i = 0; i<10; i++){ + if(_macStr[i]>'9' || _macStr[i]<'1') setupcode[i]='1'; + else setupcode[i] = _macStr[i]; + } + setupcode[3] = '-'; + setupcode[6] = '-'; + setupcode[10] = 0; + AddLog(LOG_LEVEL_INFO,PSTR("M32: HK setup code: %s"), setupcode); + return; + } + +#endif //USE_MI_HOMEKIT +/*********************************************************************************************\ + * Config section +\*********************************************************************************************/ + +void MI32loadCfg(){ + if (TfsFileExists("/mi32cfg")){ + MIBLEsensors.reserve(10); + const size_t _buf_size = 2048; + char * _filebuf = (char*)calloc(_buf_size,1); + AddLog(LOG_LEVEL_INFO,PSTR("M32: found config file")); + if(TfsLoadFile("/mi32cfg",(uint8_t*)_filebuf,_buf_size)){ + AddLog(LOG_LEVEL_INFO,PSTR("M32: %s"),_filebuf); + JsonParser parser(_filebuf); + JsonParserToken root = parser.getRoot(); + if (!root) {AddLog(LOG_LEVEL_INFO,PSTR("M32: invalid root "));} + JsonParserArray arr = root.getArray(); + if (!arr) {AddLog(LOG_LEVEL_INFO,PSTR("M32: invalid array object"));; } + bool _error; + int32_t _numberOfDevices; + for (auto _dev : arr) { + AddLog(LOG_LEVEL_INFO,PSTR("M32: found device in config file")); + JsonParserObject _device = _dev.getObject(); + uint8_t _mac[6]; + JsonParserToken _val = _device[PSTR("MAC")]; + _error = true; + if (_val) { + char *_macStr = (char *)_val.getStr(); + AddLog(LOG_LEVEL_INFO,PSTR("M32: found MAC: %s"), _macStr); + if(strlen(_macStr)!=12){ + AddLog(LOG_LEVEL_INFO,PSTR("M32: wrong MAC length: %u"), strlen(_macStr)); + break; + } + MI32HexStringToBytes(_macStr,_mac); + _val = _device[PSTR("PID")]; + if(_val){ + uint8_t _pid[2]; + char *_pidStr = (char *)_val.getStr(); + AddLog(LOG_LEVEL_INFO,PSTR("M32: found PID: %s"), _pidStr); + if(strlen(_pidStr)!=4){ + AddLog(LOG_LEVEL_INFO,PSTR("M32: wrong PID length: %u"), strlen(_pidStr)); + break; + } + MI32HexStringToBytes(_pidStr,_pid); + uint16_t _pid16 = _pid[0]*256 + _pid[1]; + _numberOfDevices = MIBLEgetSensorSlot(_mac,_pid16,0); + _error = false; + } + } + _val = _device[PSTR("key")]; + if (_val) { + mi_bindKey_t _keyMAC; + uint8_t *_key = (uint8_t*) malloc(16); + char *_keyStr = (char *)_val.getStr(); + if(strlen(_keyStr)==0){ + continue; + } + if(strlen(_keyStr)!=32){ + _error = true; + break; + } + MI32HexStringToBytes(_keyStr,_key); + MIBLEsensors[_numberOfDevices].key = _key; + } + } + if(!_error){ + AddLog(LOG_LEVEL_INFO,PSTR("M32: added %u devices from config file"), _numberOfDevices + 1); + } + } + free(_filebuf); + } +} + +void MI32saveConfig(){ + const size_t _buf_size = 2048; + char * _filebuf = (char*) malloc(_buf_size); + _filebuf[0] = '['; + uint32_t _pos = 1; + for(auto _sensor: MIBLEsensors){ + char _MAC[13]; + ToHex_P(_sensor.MAC,6,_MAC,13); + char _key[33]; + _key[0] = 0; + if(_sensor.key != nullptr){ + ToHex_P(_sensor.key,16,_key,33); + } + uint32_t _inc = snprintf_P(_filebuf+_pos,200,PSTR("{\"MAC\":\"%s\",\"PID\":\"%04x\",\"key\":\"%s\"},"),_MAC,kMI32DeviceID[_sensor.type - 1],_key); + _pos += _inc; + } + _filebuf[_pos-1] = ']'; + _filebuf[_pos] = '\0'; + if (_pos>2){ + AddLog(LOG_LEVEL_INFO,PSTR("M32: %s"), _filebuf); + if (TfsSaveFile("/mi32cfg",(uint8_t*)_filebuf,_pos+1)) { + AddLog(LOG_LEVEL_INFO,PSTR("M32: %u bytes written to config"), _pos+1); + } + } + else{ + AddLog(LOG_LEVEL_ERROR,PSTR("M32: nothing written to config")); + } + free(_filebuf); +} + /*********************************************************************************************\ * Task section \*********************************************************************************************/ +void MI32suspendScanTask(void){ + if (MI32.ScanTask != nullptr) vTaskSuspend(MI32.ScanTask); +} + void MI32StartTask(uint32_t task){ switch(task){ case MI32_TASK_SCAN: - if (MI32.mode.canScan == 0 || MI32.mode.willConnect == 1) return; + if (MI32.mode.willConnect == 1) return; if (MI32.mode.runningScan == 1 || MI32.mode.connected == 1) return; MI32StartScanTask(); break; case MI32_TASK_CONN: if (MI32.mode.canConnect == 0 || MI32.mode.willConnect == 1 ) return; if (MI32.mode.connected == 1) return; - MI32StartSensorTask(); - break; - case MI32_TASK_TIME: - if (MI32.mode.shallSetTime == 0) return; - MI32StartTimeTask(); - break; - case MI32_TASK_BATT: - if (MI32.mode.willReadBatt == 1) return; - switch(MIBLEsensors[MI32.state.sensor].type) { - case LYWSD03MMC: case MHOC401: // the "original" battery value is crap ... - MI32.mode.willReadBatt = 1; - MI32StartSensorTask(); // ... but the part of the temp/hum-message is good! - break; - default: - MI32StartBatteryTask(); - } - break; - case MI32_TASK_UNIT: - if (MI32.mode.shallSetUnit == 0) return; - MI32StartUnitTask(); + MI32StartConnectionTask(); break; default: break; @@ -828,49 +1008,27 @@ void MI32StartTask(uint32_t task){ } bool MI32ConnectActiveSensor(){ // only use inside a task !! - MI32.mode.connected = 0; - - NimBLEAddress _address = NimBLEAddress(MIBLEsensors[MI32.state.sensor].MAC); + NimBLEAddress _address = NimBLEAddress(MI32.conCtx->MAC, MI32.conCtx->addrType); + MI32Client = nullptr; if(NimBLEDevice::getClientListSize()) { - // AddLog(LOG_LEVEL_DEBUG,PSTR("%s: found any clients in the list"),D_CMND_MI32); MI32Client = NimBLEDevice::getClientByPeerAddress(_address); - if(MI32Client){ - // Should be impossible - // AddLog(LOG_LEVEL_DEBUG,PSTR("%s: got connected client"),D_CMND_MI32); - } - else { - // Should be the norm after the first iteration - MI32Client = NimBLEDevice::getDisconnectedClient(); - // AddLog(LOG_LEVEL_DEBUG,PSTR("%s: got disconnected client"),D_CMND_MI32); - } } - - if(NimBLEDevice::getClientListSize() >= NIMBLE_MAX_CONNECTIONS) { - MI32.mode.willConnect = 0; - DEBUG_SENSOR_LOG(PSTR("%s: max connection already reached"),D_CMND_MI32); - return false; - } - if(!MI32Client) { - // AddLog(LOG_LEVEL_DEBUG,PSTR("%s: will create client"),D_CMND_MI32); - MI32Client = NimBLEDevice::createClient(); + if (!MI32Client){ + MI32Client = NimBLEDevice::createClient(_address); MI32Client->setClientCallbacks(&MI32SensorCB , false); - MI32Client->setConnectionParams(12,12,0,48); - MI32Client->setConnectTimeout(30); - // AddLog(LOG_LEVEL_DEBUG,PSTR("%s: did create new client"),D_CMND_MI32); } - vTaskDelay(300/ portTICK_PERIOD_MS); - if (!MI32Client->connect(_address,false)) { + if (!MI32Client->connect(false)) { MI32.mode.willConnect = 0; - // NimBLEDevice::deleteClient(MI32Client); - // AddLog(LOG_LEVEL_DEBUG,PSTR("%s: did not connect client"),D_CMND_MI32); + NimBLEDevice::deleteClient(MI32Client); + // AddLog(LOG_LEVEL_ERROR,PSTR("M32: did not connect client")); return false; } return true; - // } } void MI32StartScanTask(){ if (MI32.mode.connected) return; + if(MI32.ScanTask!=nullptr) vTaskDelete(MI32.ScanTask); MI32.mode.runningScan = 1; xTaskCreatePinnedToCore( MI32ScanTask, /* Function to implement the task */ @@ -878,447 +1036,284 @@ void MI32StartScanTask(){ 2048, /* Stack size in words */ NULL, /* Task input parameter */ 0, /* Priority of the task */ - NULL, /* Task handle. */ + &MI32.ScanTask, /* Task handle. */ 0); /* Core where the task should run */ - AddLog(LOG_LEVEL_DEBUG,PSTR("%s: Start scanning"),D_CMND_MI32); } void MI32ScanTask(void *pvParameters){ + if(MI32.mode.didGetConfig){ + vTaskDelay(5000/ portTICK_PERIOD_MS); + } if (MI32Scan == nullptr) MI32Scan = NimBLEDevice::getScan(); - // DEBUG_SENSOR_LOG(PSTR("%s: Scan Cache Length: %u"),D_CMND_MI32, MI32Scan->getResults().getCount()); + MI32Scan->setInterval(70); MI32Scan->setWindow(50); MI32Scan->setAdvertisedDeviceCallbacks(&MI32ScanCallbacks,true); MI32Scan->setActiveScan(false); + MI32Scan->setMaxResults(0); MI32Scan->start(0, MI32scanEndedCB, true); // never stop scanning, will pause automatically while connecting - + MI32.infoMsg = MI32_START_SCANNING; + uint32_t timer = 0; for(;;){ - if(MI32.mode.shallClearResults){ - MI32Scan->clearResults(); - MI32.mode.shallClearResults=0; - } vTaskDelay(10000/ portTICK_PERIOD_MS); } vTaskDelete( NULL ); } -void MI32StartSensorTask(){ - MI32.mode.willConnect = 1; - switch(MIBLEsensors[MI32.state.sensor].type){ - case LYWSD03MMC: case MHOC401: - break; - default: - MI32.mode.willConnect = 0; - return; - } +bool MI32StartConnectionTask(){ + if(MI32.conCtx == nullptr) return false; + if(MI32.conCtx->buffer == nullptr) return false; + MI32.mode.willConnect = 1; + MI32Scan->stop(); + MI32suspendScanTask(); xTaskCreatePinnedToCore( - MI32SensorTask, /* Function to implement the task */ - "MI32SensorTask", /* Name of the task */ + MI32ConnectionTask, /* Function to implement the task */ + "MI32ConnectionTask", /* Name of the task */ 4096, /* Stack size in words */ NULL, /* Task input parameter */ - 15, /* Priority of the task */ - NULL, /* Task handle. */ + 2, /* Priority of the task */ + &MI32.ConnTask, /* Task handle. */ 0); /* Core where the task should run */ - AddLog(LOG_LEVEL_DEBUG,PSTR("%s: Start sensor connections"),D_CMND_MI32); - AddLog(LOG_LEVEL_DEBUG,PSTR("%s: with sensor: %u"),D_CMND_MI32, MI32.state.sensor); + return true; } -void MI32SensorTask(void *pvParameters){ +void MI32ConnectionTask(void *pvParameters){ + MI32.mode.connected = 0; + MI32.conCtx->error = MI32_CONN_NO_ERROR; if (MI32ConnectActiveSensor()){ + MI32.mode.readingDone = 0; uint32_t timer = 0; while (MI32.mode.connected == 0){ if (timer>1000){ MI32Client->disconnect(); - // NimBLEDevice::deleteClient(MI32Client); + NimBLEDevice::deleteClient(MI32Client); MI32.mode.willConnect = 0; - MI32.mode.willReadBatt = 0; //could be a "battery task" for LYWSD03MMC or MHO-C401 + MI32.mode.triggerBerryConnCB = 1; + MI32.conCtx->error = MI32_CONN_NO_CONNECT; // not connected + MI32StartTask(MI32_TASK_SCAN); vTaskDelay(100/ portTICK_PERIOD_MS); vTaskDelete( NULL ); } timer++; vTaskDelay(10/ portTICK_PERIOD_MS); } + NimBLERemoteService* pSvc = nullptr; + NimBLERemoteCharacteristic* pChr = nullptr; - timer = 150; - switch(MIBLEsensors[MI32.state.sensor].type){ - case LYWSD03MMC: case MHOC401: - MI32.mode.readingDone = 0; - if(MI32connectLYWSD03forNotification()) timer=0; - break; - default: - break; + pSvc = MI32Client->getService(MI32.conCtx->serviceUUID); + if(pSvc) { + pChr = pSvc->getCharacteristic(MI32.conCtx->charUUID); } + else{ + MI32.conCtx->error = MI32_CONN_NO_SERVICE; + } + if (pChr){ + switch(MI32.conCtx->operation){ + case 11: + if(pChr->canRead()) { + std::string _val = pChr->readValue(); + MI32.conCtx->buffer[0] = (uint8_t)_val.size(); + const char *_c_val = _val.c_str(); + memcpy( MI32.conCtx->buffer + 1,_c_val,MI32.conCtx->buffer[0]); + } + else{ + MI32.conCtx->error = MI32_CONN_CAN_NOT_READ; + } + break; + case 13: + if(pChr->canNotify()) { + if(pChr->subscribe(true,MI32notifyCB,false)) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: subscribe")); + } + else{ + MI32.conCtx->error = MI32_CONN_CAN_NOT_NOTIFY; + } + break; + case 12: + if(pChr->canWrite()) { + uint8_t len = MI32.conCtx->buffer[0]; + if(pChr->writeValue(MI32.conCtx->buffer + 1,len,true)) { // true is important ! + // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: write op done")); + } + else{ + MI32.conCtx->error = MI32_CONN_DID_NOT_WRITE; + } + } + else{ + MI32.conCtx->error = MI32_CONN_CAN_NOT_WRITE; + } + MI32.mode.readingDone = 1; + break; + default: + break; + } + } + else{ + MI32.conCtx->error = MI32_CONN_NO_CHARACTERISTIC; + } + timer = 0; - while (!MI32.mode.readingDone){ - if (timer>150){ + while (timer<150){ + if (MI32.mode.readingDone){ break; } + else{ + MI32.conCtx->error = MI32_CONN_NOTIFY_TIMEOUT; //did not read on notify - timeout + } timer++; vTaskDelay(100/ portTICK_PERIOD_MS); - } - MI32Client->disconnect(); - DEBUG_SENSOR_LOG(PSTR("%s: requested disconnect"),D_CMND_MI32); + } - - MI32.mode.connected = 0; - vTaskDelete( NULL ); -} - -bool MI32connectLYWSD03forNotification(){ - NimBLERemoteService* pSvc = nullptr; - NimBLERemoteCharacteristic* pChr = nullptr; - static BLEUUID serviceUUID(0xebe0ccb0,0x7a0a,0x4b0c,0x8a1a6ff2997da3a6); - static BLEUUID charUUID(0xebe0ccc1,0x7a0a,0x4b0c,0x8a1a6ff2997da3a6); - pSvc = MI32Client->getService(serviceUUID); - if(pSvc) { - pChr = pSvc->getCharacteristic(charUUID); + MI32Client->disconnect(); + DEBUG_SENSOR_LOG(PSTR("M32: requested disconnect")); } - if (pChr){ - if(pChr->canNotify()) { - if(pChr->subscribe(true,MI32notifyCB,false)) { - return true; - } - } + else{ + MI32.conCtx->error = MI32_CONN_NO_CONNECT; // not connected } - return false; -} - -void MI32StartTimeTask(){ - MI32.mode.willConnect = 1; - xTaskCreatePinnedToCore( - MI32TimeTask, /* Function to implement the task */ - "MI32TimeTask", /* Name of the task */ - 4096, /* Stack size in words */ - NULL, /* Task input parameter */ - 15, /* Priority of the task */ - NULL, /* Task handle. */ - 0); /* Core where the task should run */ - // AddLog(LOG_LEVEL_DEBUG,PSTR("%s: Start time set"),D_CMND_MI32); - // AddLog(LOG_LEVEL_DEBUG,PSTR("%s: with sensor: %u"),D_CMND_MI32, MI32.state.sensor); -} - -void MI32TimeTask(void *pvParameters){ - if (MIBLEsensors[MI32.state.sensor].type != LYWSD02 && MIBLEsensors[MI32.state.sensor].type != MHOC303) { - MI32.mode.shallSetTime = 0; - vTaskDelete( NULL ); - } - if(MI32ConnectActiveSensor()){ - uint32_t timer = 0; - while (MI32.mode.connected == 0){ - if (timer>1000){ - break; - } - timer++; - vTaskDelay(10/ portTICK_PERIOD_MS); - } - - NimBLERemoteService* pSvc = nullptr; - NimBLERemoteCharacteristic* pChr = nullptr; - static BLEUUID serviceUUID(0xEBE0CCB0,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); - static BLEUUID charUUID(0xEBE0CCB7,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); - pSvc = MI32Client->getService(serviceUUID); - if(pSvc) { - pChr = pSvc->getCharacteristic(charUUID); - - } - if (pChr){ - if(pChr->canWrite()) { - union { - uint8_t buf[5]; - uint32_t time; - } _utc; - _utc.time = Rtc.utc_time; - _utc.buf[4] = Rtc.time_timezone / 60; - - if(!pChr->writeValue(_utc.buf,sizeof(_utc.buf),true)) { // true is important ! - MI32.mode.willConnect = 0; - MI32Client->disconnect(); - } - else { - MI32.mode.shallSetTime = 0; - MI32.mode.willSetTime = 0; - } - } - } - MI32Client->disconnect(); - } - MI32.mode.connected = 0; - MI32.mode.canScan = 1; + MI32.mode.triggerBerryConnCB = 1; + MI32StartTask(MI32_TASK_SCAN); vTaskDelete( NULL ); } -void MI32StartUnitTask(){ - MI32.mode.willConnect = 1; - xTaskCreatePinnedToCore( - MI32UnitTask, /* Function to implement the task */ - "MI32UnitTask", /* Name of the task */ - 4096, /* Stack size in words */ - NULL, /* Task input parameter */ - 15, /* Priority of the task */ - NULL, /* Task handle. */ - 0); /* Core where the task should run */ - // AddLog(LOG_LEVEL_DEBUG,PSTR("%s: Start unit set"),D_CMND_MI32); - // AddLog(LOG_LEVEL_DEBUG,PSTR("%s: with sensor: %u"),D_CMND_MI32, MI32.state.sensor); -} - -void MI32UnitTask(void *pvParameters){ - if (MIBLEsensors[MI32.state.sensor].type != LYWSD02 && MIBLEsensors[MI32.state.sensor].type != MHOC303) { - MI32.mode.shallSetUnit = 0; - vTaskDelete( NULL ); - } - - if(MI32ConnectActiveSensor()){ - uint32_t timer = 0; - while (MI32.mode.connected == 0){ - if (timer>1000){ - break; - } - timer++; - vTaskDelay(10/ portTICK_PERIOD_MS); - } - - NimBLERemoteService* pSvc = nullptr; - NimBLERemoteCharacteristic* pChr = nullptr; - static BLEUUID serviceUUID(0xEBE0CCB0,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); - static BLEUUID charUUID(0xEBE0CCBE,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); - pSvc = MI32Client->getService(serviceUUID); - if(pSvc) { - pChr = pSvc->getCharacteristic(charUUID); - } - - if(pChr->canRead()){ - uint8_t curUnit; - const char *buf = pChr->readValue().c_str(); - if( buf[0] != 0 && buf[0]<101 ){ - curUnit = buf[0]; - } - - if(pChr->canWrite()) { - curUnit = curUnit == 0x01?0xFF:0x01; // C/F - - if(!pChr->writeValue(&curUnit,sizeof(curUnit),true)) { // true is important ! - MI32.mode.willConnect = 0; - MI32Client->disconnect(); - } - else { - MI32.mode.shallSetUnit = 0; - MI32.mode.willSetUnit = 0; - } - } - } - MI32Client->disconnect(); - } - - MI32.mode.connected = 0; - MI32.mode.canScan = 1; - vTaskDelete( NULL ); -} - -void MI32StartBatteryTask(){ - if (MI32.mode.connected) return; - MI32.mode.willReadBatt = 1; - MI32.mode.willConnect = 1; - MI32.mode.canScan = 0; - - switch (MIBLEsensors[MI32.state.sensor].type){ - case LYWSD03MMC: case MJ_HT_V1: case CGG1: case NLIGHT: case MJYD2S: case YEERC: case MHOC401: - MI32.mode.willConnect = 0; - MI32.mode.willReadBatt = 0; - return; - } - - xTaskCreatePinnedToCore( - MI32BatteryTask, /* Function to implement the task */ - "MI32BatteryTask", /* Name of the task */ - 4096, /* Stack size in words */ - NULL, /* Task input parameter */ - 15, /* Priority of the task */ - NULL, /* Task handle. */ - 0); /* Core where the task should run */ -} - -void MI32BatteryTask(void *pvParameters){ - // all reported battery values are probably crap, but we allow the reading on demand - - MI32.mode.connected = 0; - if(MI32ConnectActiveSensor()){ - uint32_t timer = 0; - while (MI32.mode.connected == 0){ - if (timer>1000){ - break; - } - timer++; - vTaskDelay(30/ portTICK_PERIOD_MS); - } - - switch(MIBLEsensors[MI32.state.sensor].type){ - case FLORA: case LYWSD02: case CGD1: - MI32batteryRead(MIBLEsensors[MI32.state.sensor].type); - break; - } - MI32Client->disconnect(); - } - MI32.mode.willReadBatt = 0; - MI32.mode.connected = 0; - vTaskDelete( NULL ); -} - -void MI32batteryRead(uint32_t _type){ - uint32_t timer = 0; - while (!MI32.mode.connected){ - if (timer>1000){ - break; - } - timer++; - vTaskDelay(10/ portTICK_PERIOD_MS); - } - DEBUG_SENSOR_LOG(PSTR("%s connected for battery"),kMI32DeviceType[MIBLEsensors[MI32.state.sensor].type-1] ); - NimBLERemoteService* pSvc = nullptr; - NimBLERemoteCharacteristic* pChr = nullptr; - - switch(_type){ - case FLORA: - { - static BLEUUID _serviceUUID(0x00001204,0x0000,0x1000,0x800000805f9b34fb); - static BLEUUID _charUUID(0x00001a02,0x0000,0x1000,0x800000805f9b34fb); - pSvc = MI32Client->getService(_serviceUUID); - if(pSvc) { - pChr = pSvc->getCharacteristic(_charUUID); - } - } - break; - case LYWSD02: - { - static BLEUUID _serviceUUID(0xEBE0CCB0,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); - static BLEUUID _charUUID(0xEBE0CCC4,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); - pSvc = MI32Client->getService(_serviceUUID); - if(pSvc) { - pChr = pSvc->getCharacteristic(_charUUID); - } - } - break; - case CGD1: - { - static BLEUUID _serviceUUID((uint16_t)0x180F); - static BLEUUID _charUUID((uint16_t)0x2A19); - pSvc = MI32Client->getService(_serviceUUID); - if(pSvc) { - pChr = pSvc->getCharacteristic(_charUUID); - } - } - break; - } - - if (pChr){ - DEBUG_SENSOR_LOG(PSTR("%s: got %s char %s"),D_CMND_MI32, kMI32DeviceType[MIBLEsensors[MI32.state.sensor].type-1], pChr->getUUID().toString().c_str()); - if(pChr->canRead()) { - const char *buf = pChr->readValue().c_str(); - MI32readBat((char*)buf); - } - } - MI32.mode.readingDone = 1; -} - /*********************************************************************************************\ * parse the response from advertisements \*********************************************************************************************/ void MI32parseMiBeacon(char * _buf, uint32_t _slot, uint16_t _bufSize){ + float _tempFloat; - mi_beacon_t _beacon; + mi_beacon_t* _beacon = (mi_beacon_t*)_buf; + mi_payload_t _payload; - if (MIBLEsensors[_slot].type==MJ_HT_V1 || MIBLEsensors[_slot].type==CGG1 || MIBLEsensors[_slot].type==YEERC){ - memcpy((uint8_t*)&_beacon+1,(uint8_t*)_buf, sizeof(_beacon)-1); // shift by one byte for the MJ_HT_V1 DANGER!!! - memcpy((uint8_t*)&_beacon.MAC,(uint8_t*)&_beacon.MAC+1,6); // but shift back the MAC - _beacon.counter = _buf[4]; // restore the counter - } - else{ - memcpy((char *)&_beacon, _buf, _bufSize); - } + MIBLEsensors[_slot].lastCnt = _beacon->counter; - MIBLEsensors[_slot].lastCnt = _beacon.counter; -#ifdef USE_MI_DECRYPTION - int decryptRet = 0; - switch(MIBLEsensors[_slot].type){ - case LYWSD03MMC: case MHOC401: - if (_beacon.frame == 0x5858){ - decryptRet = MI32_decryptPacket((char*)&_beacon.productID,_bufSize, LYWSD03MMC); //start with PID - // AddLogBuffer(LOG_LEVEL_DEBUG,(uint8_t*)&_beacon.productID,_bufSize); +#ifdef USE_MI_EXT_GUI + bitSet(MI32.widgetSlot,_slot); +#endif //USE_MI_EXT_GUI +if(_beacon->frame.includesObj == 0){ + if(_beacon->capability == 0x28) MIBLEsensors[_slot].status.isUnbounded = 1; + return; //nothing to parse +} + +int decryptRet = 0; +if(_beacon->frame.isEncrypted){ + MIBLEsensors[_slot].feature.needsKey = 1; + decryptRet = MI32_decryptPacket(_buf,_bufSize, (uint8_t*)&_payload,_slot); + // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: decryptRet: %d"),decryptRet); + } +else{ + uint32_t _offset = (_beacon->frame.includesCapability)?0:1; + uint32_t _payloadSize = (_beacon->frame.includesCapability)?_beacon->payload.size:_beacon->payload.ten; + if(_beacon->frame.includesMAC && _beacon->frame.includesObj) { + // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: offset %u, size: %u"),_offset,_payloadSize); + memcpy((uint8_t*)&_payload,(uint8_t*)(&_beacon->payload)-_offset, _payloadSize + 3); + // AddLogBuffer(LOG_LEVEL_DEBUG,(uint8_t*)&_payload,_payloadSize + 3); } - else return; // 0x3058 holds no data, TODO: check for unpaired devices, that need connections - break; - case MJYD2S: - AddLog(LOG_LEVEL_DEBUG,PSTR("MJYD2S: %x"),_beacon.frame); - if (_beacon.frame == 0x5948){ // Now let's build/recreate a special MiBeacon - memmove((uint8_t*)&_beacon.MAC+6,(uint8_t*)&_beacon.MAC, _bufSize); // shift payload by the size of the MAC = 6 bytes - memcpy((uint8_t*)&_beacon.MAC,MIBLEsensors[_slot].MAC,6); // now insert the real MAC from our internal vector - _bufSize+=6; // the packet has grown - MI32_ReverseMAC(_beacon.MAC); // payload MAC is always reversed - AddLog(LOG_LEVEL_DEBUG,PSTR("MJYD2S: special packet")); - } - if (_beacon.frame != 0x5910){ - decryptRet = MI32_decryptPacket((char*)&_beacon.productID,_bufSize,MJYD2S); //start with PID - } - break; } if(decryptRet!=0){ AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Decryption failed with error: %d"),decryptRet); + if (decryptRet == -1) MIBLEsensors[_slot].status.hasWrongKey = 1; return; } -#endif //USE_MI_DECRYPTION - if(MIBLEsensors[_slot].type==6){ - DEBUG_SENSOR_LOG(PSTR("CGD1 no support for MiBeacon, type %u"),MIBLEsensors[_slot].type); - return; - } - AddLog(LOG_LEVEL_DEBUG,PSTR("%s at slot %u with payload type: %02x"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot,_beacon.type); - switch(_beacon.type){ + // AddLog(LOG_LEVEL_DEBUG,PSTR("%s at slot %u with payload type: %02x"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot,_payload.type); + MIBLEsensors[_slot].lastTime = millis(); + switch(_payload.type){ case 0x01: - MIBLEsensors[_slot].Btn=_beacon.Btn.num + (_beacon.Btn.longPress/2)*6; + if(_payload.Btn.type == 4){ //knob dimmer + if(_payload.Btn.num == 0){ + if(_payload.Btn.value<128){ + AddLog(LOG_LEVEL_DEBUG,PSTR("Rotate right: %u"),_payload.Btn.value); + } + else{ + AddLog(LOG_LEVEL_DEBUG,PSTR("Rotate left: %u"),256 - _payload.Btn.value); + } + } + else if(_payload.Btn.num<128){ + AddLog(LOG_LEVEL_DEBUG,PSTR("Rotate right: %u"),_payload.Btn.num); + } + else{ + AddLog(LOG_LEVEL_DEBUG,PSTR("Rotate left: %u"),256 - _payload.Btn.num); + } + return; //TODO: implement MQTT later + } + MIBLEsensors[_slot].Btn=_payload.Btn.num + (_payload.Btn.type/2)*6; MIBLEsensors[_slot].eventType.Btn = 1; MI32.mode.shallTriggerTele = 1; +#ifdef USE_MI_HOMEKIT + { + // {uint32_t _button = _payload.Btn.num + (_payload.Btn.type/2)*6; + uint32_t _singleLong = 0; + if(MIBLEsensors[_slot].Btn>5){ + MIBLEsensors[_slot].Btn = MIBLEsensors[_slot].Btn - 6; + _singleLong = 2; + } + if(MIBLEsensors[_slot].Btn>5) break; // + if((void**)MIBLEsensors[_slot].button_hap_service[MIBLEsensors[_slot].Btn] != nullptr){ + // AddLog(LOG_LEVEL_DEBUG,PSTR("Send Button %u: SingleLong:%u, pointer: %x"), MIBLEsensors[_slot].Btn,_singleLong,MIBLEsensors[_slot].button_hap_service[MIBLEsensors[_slot].Btn] ); + mi_homekit_update_value(MIBLEsensors[_slot].button_hap_service[MIBLEsensors[_slot].Btn], (float)_singleLong, 0x01); + } + } +#endif //USE_MI_HOMEKIT // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode 1: U16: %u Button"), MIBLEsensors[_slot].Btn ); break; case 0x04: - _tempFloat=(float)(_beacon.temp)/10.0f; + _tempFloat=(float)(_payload.temp)/10.0f; if(_tempFloat<60){ MIBLEsensors[_slot].temp=_tempFloat; MIBLEsensors[_slot].eventType.temp = 1; DEBUG_SENSOR_LOG(PSTR("Mode 4: temp updated")); } - // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode 4: U16: %u Temp"), _beacon.temp ); +#ifdef USE_MI_HOMEKIT + mi_homekit_update_value(MIBLEsensors[_slot].temp_hap_service, _tempFloat, 0x04); +#endif //USE_MI_HOMEKIT +#ifdef USE_MI_EXT_GUI + MI32addHistory(MIBLEsensors[_slot].temp_history, _tempFloat, 0); +#endif //USE_MI_EXT_GUI + // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode 4: U16: %u Temp"), _payload.temp ); break; case 0x06: - _tempFloat=(float)(_beacon.hum)/10.0f; + _tempFloat=(float)(_payload.hum)/10.0f; if(_tempFloat<101){ MIBLEsensors[_slot].hum=_tempFloat; MIBLEsensors[_slot].eventType.hum = 1; DEBUG_SENSOR_LOG(PSTR("Mode 6: hum updated")); } - // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode 6: U16: %u Hum"), _beacon.hum); +#ifdef USE_MI_HOMEKIT + mi_homekit_update_value(MIBLEsensors[_slot].hum_hap_service, _tempFloat,0x06); +#endif //USE_MI_HOMEKIT +#ifdef USE_MI_EXT_GUI + MI32addHistory(MIBLEsensors[_slot].hum_history, _tempFloat, 1); +#endif //USE_MI_EXT_GUI + // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode 6: U16: %u Hum"), _payload.hum); break; case 0x07: - MIBLEsensors[_slot].lux=_beacon.lux & 0x00ffffff; + MIBLEsensors[_slot].lux=_payload.lux & 0x00ffffff; if(MIBLEsensors[_slot].type==MJYD2S){ MIBLEsensors[_slot].eventType.noMotion = 1; } MIBLEsensors[_slot].eventType.lux = 1; - // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode 7: U24: %u Lux"), _beacon.lux & 0x00ffffff); +#ifdef USE_MI_HOMEKIT + mi_homekit_update_value(MIBLEsensors[_slot].light_hap_service, (float)MIBLEsensors[_slot].lux,0x07); +#endif //USE_MI_HOMEKIT +#ifdef USE_MI_EXT_GUI + MI32addHistory(MIBLEsensors[_slot].lux_history, (float)MIBLEsensors[_slot].lux, 2); +#endif //USE_MI_EXT_GUI + // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode 7: U24: %u Lux"), _payload.lux & 0x00ffffff); break; case 0x08: - MIBLEsensors[_slot].moisture=_beacon.moist; + MIBLEsensors[_slot].moisture=_payload.moist; MIBLEsensors[_slot].eventType.moist = 1; DEBUG_SENSOR_LOG(PSTR("Mode 8: moisture updated")); - // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode 8: U8: %u Moisture"), _beacon.moist); + // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode 8: U8: %u Moisture"), _payload.moist); break; case 0x09: - MIBLEsensors[_slot].fertility=_beacon.fert; + MIBLEsensors[_slot].fertility=_payload.fert; MIBLEsensors[_slot].eventType.fert = 1; DEBUG_SENSOR_LOG(PSTR("Mode 9: fertility updated")); - // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode 9: U16: %u Fertility"), _beacon.fert); + // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode 9: U16: %u Fertility"), _payload.fert); break; case 0x0a: if(MI32.option.ignoreBogusBattery){ @@ -1326,56 +1321,85 @@ if(decryptRet!=0){ break; } } - if(_beacon.bat<101){ - MIBLEsensors[_slot].bat = _beacon.bat; + if(_payload.bat<101){ + MIBLEsensors[_slot].bat = _payload.bat; MIBLEsensors[_slot].eventType.bat = 1; DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated")); - } - // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode a: U8: %u %%"), _beacon.bat); +#ifdef USE_MI_HOMEKIT + mi_homekit_update_value(MIBLEsensors[_slot].bat_hap_service, (float)_payload.bat,0xa); +#endif //USE_MI_HOMEKIT + } + // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode a: U8: %u %%"), _payload.bat); break; case 0x0d: - _tempFloat=(float)(_beacon.HT.temp)/10.0f; + _tempFloat=(float)(_payload.HT.temp)/10.0f; if(_tempFloat<60){ MIBLEsensors[_slot].temp = _tempFloat; DEBUG_SENSOR_LOG(PSTR("Mode d: temp updated")); } - _tempFloat=(float)(_beacon.HT.hum)/10.0f; + _tempFloat=(float)(_payload.HT.hum)/10.0f; if(_tempFloat<100){ MIBLEsensors[_slot].hum = _tempFloat; DEBUG_SENSOR_LOG(PSTR("Mode d: hum updated")); } MIBLEsensors[_slot].eventType.tempHum = 1; - // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode d: U16: %x Temp U16: %x Hum"), _beacon.HT.temp, _beacon.HT.hum); + // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode d: U16: %x Temp U16: %x Hum"), _payload.HT.temp, _payload.HT.hum); break; -#ifdef USE_MI_DECRYPTION + case 0x0f: - if (_beacon.ten!=0) break; + if (_payload.ten!=0) break; MIBLEsensors[_slot].eventType.motion = 1; - MIBLEsensors[_slot].lastTime = millis(); MIBLEsensors[_slot].events++; - MIBLEsensors[_slot].lux = _beacon.lux; + MIBLEsensors[_slot].lux = _payload.lux & 0x00ffffff; MIBLEsensors[_slot].eventType.lux = 1; MIBLEsensors[_slot].NMT = 0; MI32.mode.shallTriggerTele = 1; - // AddLog(LOG_LEVEL_DEBUG,PSTR("PIR: primary"),MIBLEsensors[_slot].lux ); +#ifdef USE_MI_HOMEKIT + mi_homekit_update_value(MIBLEsensors[_slot].motion_hap_service, (float)1,0x0f); + mi_homekit_update_value(MIBLEsensors[_slot].light_hap_service, (float)_payload.lux,0x07); +#endif //USE_MI_HOMEKIT +#ifdef USE_MI_EXT_GUI + MI32addHistory(MIBLEsensors[_slot].lux_history, (float)MIBLEsensors[_slot].lux, 2); +#endif //USE_MI_EXT_GUI + // AddLog(LOG_LEVEL_DEBUG,PSTR("motion: primary"),MIBLEsensors[_slot].lux ); break; + case 0x14: + MIBLEsensors[_slot].leak = _payload.leak; + MIBLEsensors[_slot].eventType.leak = 1; + if(_payload.leak>0) MI32.mode.shallTriggerTele = 1; +#ifdef USE_MI_HOMEKIT + mi_homekit_update_value(MIBLEsensors[_slot].leak_hap_service, (float)_payload.leak,0x14); +#endif //USE_MI_HOMEKIT + break; case 0x17: - MIBLEsensors[_slot].NMT = _beacon.NMT; + MIBLEsensors[_slot].NMT = _payload.NMT; MIBLEsensors[_slot].eventType.NMT = 1; MI32.mode.shallTriggerTele = 1; - // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode 17: NMT: %u seconds"), _beacon.NMT); + // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode 17: NMT: %u seconds"), _payload.NMT); break; -#endif //USE_MI_DECRYPTION + case 0x19: + MIBLEsensors[_slot].door = _payload.door; + MIBLEsensors[_slot].eventType.door = 1; + MIBLEsensors[_slot].events++; + MI32.mode.shallTriggerTele = 1; +#ifdef USE_MI_HOMEKIT + mi_homekit_update_value(MIBLEsensors[_slot].door_sensor_hap_service, (float)_payload.door,0x19); +#endif //USE_MI_HOMEKIT + // AddLog(LOG_LEVEL_DEBUG,PSTR("Mode 19: %u"), _payload.door); + break; + default: if (MIBLEsensors[_slot].type==NLIGHT){ - MIBLEsensors[_slot].eventType.motion = 1; //PIR + MIBLEsensors[_slot].eventType.motion = 1; //motion MIBLEsensors[_slot].events++; MIBLEsensors[_slot].NMT = 0; - MIBLEsensors[_slot].lastTime = millis(); MI32.mode.shallTriggerTele = 1; - // AddLog(LOG_LEVEL_DEBUG,PSTR("PIR: primary"),MIBLEsensors[_slot].lux ); +#ifdef USE_MI_HOMEKIT + mi_homekit_update_value(MIBLEsensors[_slot].motion_hap_service, (float)1,0x0f); +#endif //USE_MI_HOMEKIT } else{ + //unknown payload AddLogBuffer(LOG_LEVEL_DEBUG,(uint8_t*)_buf,_bufSize); } break; @@ -1387,18 +1411,41 @@ if(decryptRet!=0){ void MI32ParseATCPacket(char * _buf, uint32_t length, uint8_t addr[6], int RSSI){ ATCPacket_t *_packet = (ATCPacket_t*)_buf; - uint32_t _slot = MIBLEgetSensorSlot(_packet->MAC, 0x0a1c, _packet->frameCnt); // This must be a hard-coded fake ID - AddLog(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot); + bool isATC = (length == 0x0d); + uint32_t _slot; + if (isATC) _slot = MIBLEgetSensorSlot(_packet->MAC, 0x0a1c, _packet->A.frameCnt); // This must be a hard-coded fake ID + else { + MI32_ReverseMAC(_packet->MAC); + _slot = MIBLEgetSensorSlot(_packet->MAC, 0x944a, _packet->P.frameCnt); // ... and again + } if(_slot==0xff) return; + // AddLog(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot); MIBLEsensors[_slot].RSSI=RSSI; + MIBLEsensors[_slot].lastTime = millis(); + if(isATC){ + MIBLEsensors[_slot].temp = (float)(int16_t(__builtin_bswap16(_packet->A.temp)))/10.0f; + MIBLEsensors[_slot].hum = (float)_packet->A.hum; + MIBLEsensors[_slot].bat = _packet->A.batPer; + } + else{ + MIBLEsensors[_slot].temp = (float)(_packet->P.temp)/100.0f; + MIBLEsensors[_slot].hum = (float)_packet->P.hum/100.0f; + MIBLEsensors[_slot].bat = _packet->P.batPer; + } - MIBLEsensors.at(_slot).temp = (float)(int16_t(__builtin_bswap16(_packet->temp)))/10.0f; - MIBLEsensors.at(_slot).hum = (float)_packet->hum; MIBLEsensors[_slot].eventType.tempHum = 1; - MIBLEsensors.at(_slot).bat = _packet->batPer; MIBLEsensors[_slot].eventType.bat = 1; - +#ifdef USE_MI_HOMEKIT + mi_homekit_update_value(MIBLEsensors[_slot].temp_hap_service, MIBLEsensors.at(_slot).temp,0x04); + mi_homekit_update_value(MIBLEsensors[_slot].hum_hap_service, MIBLEsensors.at(_slot).hum,0x06); + mi_homekit_update_value(MIBLEsensors[_slot].bat_hap_service, (float)MIBLEsensors.at(_slot).bat,0x0a); +#endif //USE_MI_HOMEKIT +#ifdef USE_MI_EXT_GUI + bitSet(MI32.widgetSlot,_slot); + MI32addHistory(MIBLEsensors[_slot].temp_history, (float)MIBLEsensors[_slot].temp, 0); + MI32addHistory(MIBLEsensors[_slot].hum_history, (float)MIBLEsensors[_slot].hum, 1); +#endif //USE_MI_EXT_GUI MIBLEsensors[_slot].shallSendMQTT = 1; if(MI32.option.directBridgeMode) MI32.mode.shallTriggerTele = 1; @@ -1408,9 +1455,10 @@ void MI32parseCGD1Packet(char * _buf, uint32_t length, uint8_t addr[6], int RSSI uint8_t _addr[6]; memcpy(_addr,addr,6); uint32_t _slot = MIBLEgetSensorSlot(_addr, 0x0576, 0); // This must be hard-coded, no object-id in Cleargrass-packet, we have no packet counter too - AddLog(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot); if(_slot==0xff) return; + // AddLog(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot); MIBLEsensors[_slot].RSSI=RSSI; + MIBLEsensors[_slot].lastTime = millis(); cg_packet_t _packet; memcpy((char*)&_packet,_buf,sizeof(_packet)); switch (_packet.mode){ @@ -1418,21 +1466,33 @@ void MI32parseCGD1Packet(char * _buf, uint32_t length, uint8_t addr[6], int RSSI float _tempFloat; _tempFloat=(float)(_packet.temp)/10.0f; if(_tempFloat<60){ - MIBLEsensors.at(_slot).temp = _tempFloat; + MIBLEsensors[_slot].temp = _tempFloat; MIBLEsensors[_slot].eventType.temp = 1; DEBUG_SENSOR_LOG(PSTR("CGD1: temp updated")); +#ifdef USE_MI_HOMEKIT + mi_homekit_update_value(MIBLEsensors[_slot].temp_hap_service, _tempFloat,0x04); +#endif //USE_MI_HOMEKIT +#ifdef USE_MI_EXT_GUI + MI32addHistory(MIBLEsensors[_slot].temp_history, (float)MIBLEsensors[_slot].temp, 0); +#endif //USE_MI_EXT_GUI } _tempFloat=(float)(_packet.hum)/10.0f; if(_tempFloat<100){ - MIBLEsensors.at(_slot).hum = _tempFloat; + MIBLEsensors[_slot].hum = _tempFloat; MIBLEsensors[_slot].eventType.hum = 1; DEBUG_SENSOR_LOG(PSTR("CGD1: hum updated")); +#ifdef USE_MI_HOMEKIT + mi_homekit_update_value(MIBLEsensors[_slot].hum_hap_service, _tempFloat,0x06); +#endif //USE_MI_HOMEKIT +#ifdef USE_MI_EXT_GUI + MI32addHistory(MIBLEsensors[_slot].hum_history, (float)MIBLEsensors[_slot].hum, 1); +#endif //USE_MI_EXT_GUI } DEBUG_SENSOR_LOG(PSTR("CGD1: U16: %x Temp U16: %x Hum"), _packet.temp, _packet.hum); break; case 0x0102: if(_packet.bat<101){ - MIBLEsensors.at(_slot).bat = _packet.bat; + MIBLEsensors[_slot].bat = _packet.bat; MIBLEsensors[_slot].eventType.bat = 1; DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated")); } @@ -1443,6 +1503,9 @@ void MI32parseCGD1Packet(char * _buf, uint32_t length, uint8_t addr[6], int RSSI if(MIBLEsensors[_slot].eventType.raw == 0) return; MIBLEsensors[_slot].shallSendMQTT = 1; if(MI32.option.directBridgeMode) MI32.mode.shallTriggerTele = 1; +#ifdef USE_MI_EXT_GUI + bitSet(MI32.widgetSlot,_slot); +#endif //USE_MI_EXT_GUI } void MI32ParseResponse(char *buf, uint16_t bufsize, uint8_t addr[6], int RSSI) { @@ -1460,221 +1523,6 @@ void MI32ParseResponse(char *buf, uint16_t bufsize, uint8_t addr[6], int RSSI) { } } -/** - * @brief Parse a BLE advertisement packet - * - * @param payload - * @param payloadLength - * @param CID - * @param SVC - * @param UUID - */ -void MI32ParseGenericBeacon(uint8_t* payload, size_t payloadLength, uint16_t* CID, uint16_t*SVC, uint16_t* UUID){ - AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Beacon:____________")); - for (uint32_t i = 0; i19) { - AddLog(LOG_LEVEL_INFO,PSTR("M32: Scan buffer full")); - MI32.state.beaconScanCounter = 1; - return; - } - for(auto _scanResult : MIBLEscanResult){ - if(memcmp(addr,_scanResult.MAC,6)==0){ - // AddLog(LOG_LEVEL_INFO,PSTR("M32: known device")); - return; - } - } - scan_entry_t _new; - _new.RSSI = RSSI; - _new.CID = 0; - _new.SVC = 0; - _new.UUID = 0; - memcpy(_new.MAC,addr,sizeof(_new.MAC)); - MI32ParseGenericBeacon(payload,payloadLength,&_new.CID,&_new.SVC,&_new.UUID); - MIBLEscanResult.push_back(_new); -} - - -/** - * @brief Add a beacon defined by its MAC-address, if only zeros are given, the beacon will be deactivated - * - * @param index 1-4 beacons are currently supported - * @param data null terminated char array representing a MAC-address in hex - */ -void MI32addBeacon(uint8_t index, char* data){ - auto &_new = MIBLEbeacons[index-1]; //TODO: check - MI32HexStringToBytes(data,_new.MAC); - char _MAC[18]; - ToHex_P(MIBLEbeacons[index-1].MAC,6,_MAC,18,':'); - char _empty[6] = {0}; - _new.time = 0; - if(memcmp(_empty,_new.MAC,6) == 0){ - _new.active = false; - AddLog(LOG_LEVEL_INFO,PSTR("M32: Beacon%u deactivated"), index); - } - else{ - _new.active = true; - MI32.mode.activeBeacon = 1; - AddLog(LOG_LEVEL_INFO,PSTR("M32: Beacon added with MAC: %s"), _MAC); - } -} - -/** - * @brief Present BLE scan in the console, after that deleting the scan data - * - */ -void MI32showScanResults(){ - size_t _size = MIBLEscanResult.size(); - ResponseAppend_P(PSTR(",\"BLEScan\":{\"Found\":%u,\"Devices\":["), _size); - bool add_comma = false; - for(auto _scanResult : MIBLEscanResult){ - char _MAC[18]; - ToHex_P(_scanResult.MAC,6,_MAC,18,':'); - ResponseAppend_P(PSTR("%s{\"MAC\":\"%s\",\"CID\":\"0x%04x\",\"SVC\":\"0x%04x\",\"UUID\":\"0x%04x\",\"RSSI\":%d}"), - (add_comma)?",":"", _MAC, _scanResult.CID, _scanResult.SVC, _scanResult.UUID, _scanResult.RSSI); - add_comma = true; - } - ResponseAppend_P(PSTR("]}")); - MIBLEscanResult.clear(); - MI32.mode.shallShowScanResult = 0; -} - -void MI32showBlockList(){ - ResponseAppend_P(PSTR(",\"Block\":[")); - bool add_comma = false; - for(auto _scanResult : MIBLEBlockList){ - char _MAC[18]; - ToHex_P(_scanResult.buf,6,_MAC,18,':'); - ResponseAppend_P(PSTR("%s\"%s\""), (add_comma)?",":"", _MAC); - add_comma = true; - } - ResponseAppend_P(PSTR("]")); - MI32.mode.shallShowBlockList = 0; -} - -bool MI32isInBlockList(uint8_t* MAC){ - bool isBlocked = false; - for(auto &_blockedMAC : MIBLEBlockList){ - if(memcmp(_blockedMAC.buf,MAC,6) == 0) isBlocked = true; - } - return isBlocked; -} - -void MI32removeMIBLEsensor(uint8_t* MAC){ - MIBLEsensors.erase( std::remove_if( MIBLEsensors.begin() , MIBLEsensors.end(), [MAC]( mi_sensor_t _sensor )->bool - { return (memcmp(_sensor.MAC,MAC,6) == 0); } - ), end( MIBLEsensors ) ); -} -/***********************************************************************\ - * Read data from connections -\***********************************************************************/ - -void MI32readHT_LY(char *_buf){ - DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_MI32,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); - if(_buf[0] != 0 && _buf[1] != 0){ - memcpy(&LYWSD0x_HT,(void *)_buf,sizeof(LYWSD0x_HT)); - AddLog(LOG_LEVEL_DEBUG, PSTR("%s: T * 100: %u, H: %u, V: %u"),D_CMND_MI32,LYWSD0x_HT.temp,LYWSD0x_HT.hum, LYWSD0x_HT.volt); - uint32_t _slot = MI32.state.sensor; - - DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); - static float _tempFloat; - _tempFloat=(float)(LYWSD0x_HT.temp)/100.0f; - if(_tempFloat<60){ - MIBLEsensors[_slot].temp=_tempFloat; - // MIBLEsensors[_slot].showedUp=255; // this sensor is real - } - _tempFloat=(float)LYWSD0x_HT.hum; - if(_tempFloat<100){ - MIBLEsensors[_slot].hum = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("LYWSD0x: hum updated")); - } - MIBLEsensors[_slot].eventType.tempHum = 1; - if (MIBLEsensors[_slot].type == LYWSD03MMC || MIBLEsensors[_slot].type == MHOC401){ - MIBLEsensors[_slot].bat = ((float)LYWSD0x_HT.volt-2100.0f)/12.0f; - MI32.mode.willReadBatt = 0; - MIBLEsensors[_slot].eventType.bat = 1; - } - MIBLEsensors[_slot].shallSendMQTT = 1; - MI32.mode.shallTriggerTele = 1; - } -} - -bool MI32readBat(char *_buf){ - DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_MI32,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); - if(_buf[0] != 0){ - AddLog(LOG_LEVEL_DEBUG,PSTR("%s: Battery: %u"),D_CMND_MI32,_buf[0]); - uint32_t _slot = MI32.state.sensor; - DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); - if(_buf[0]<101){ - MIBLEsensors[_slot].bat=_buf[0]; - if(MIBLEsensors[_slot].type==FLORA){ - memcpy(MIBLEsensors[_slot].firmware, _buf+2, 5); - MIBLEsensors[_slot].firmware[5] = '\0'; - AddLog(LOG_LEVEL_DEBUG,PSTR("%s: Firmware: %s"),D_CMND_MI32,MIBLEsensors[_slot].firmware); - } - MIBLEsensors[_slot].eventType.bat = 1; - MIBLEsensors[_slot].shallSendMQTT = 1; - MI32.mode.shallTriggerTele = 1; - return true; - } - } - return false; -} - /** * @brief Launch functions from Core 1 to make race conditions less likely * @@ -1685,6 +1533,37 @@ void MI32Every50mSecond(){ MI32.mode.shallTriggerTele = 0; MI32triggerTele(); } + if(MI32.mode.triggerBerryAdvCB == 1){ + if(MI32.beAdvCB != nullptr){ + void (*func_ptr)(void) = (void (*)(void))MI32.beAdvCB; + func_ptr(); + } + MI32.mode.triggerBerryAdvCB = 0; + } + if(MI32.mode.triggerBerryConnCB == 1){ + if(MI32.beConnCB != nullptr){ + void (*func_ptr)(int) = (void (*)(int))MI32.beConnCB; + char _message[32]; + GetTextIndexed(_message, sizeof(_message), MI32.conCtx->error, kMI32_ConnErrorMsg); + AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s"),_message); + func_ptr(MI32.conCtx->error); + } + MI32.mode.triggerBerryConnCB = 0; + } + if(MI32.infoMsg > 0){ + char _message[32]; + GetTextIndexed(_message, sizeof(_message), MI32.infoMsg-1, kMI32_BLEInfoMsg); + AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s"),_message); + MI32.infoMsg = 0; + } +#ifdef USE_MI_HOMEKIT + if(MI32.HKinfoMsg > 0){ + char _message[32]; + GetTextIndexed(_message, sizeof(_message), MI32.HKinfoMsg-1, kMI32_HKInfoMsg); + AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s"),_message); + MI32.HKinfoMsg = 0; + } +#endif //USE_MI_HOMEKIT } /** @@ -1693,256 +1572,52 @@ void MI32Every50mSecond(){ */ void MI32EverySecond(bool restart){ - static uint32_t _counter = MI32.period - 15; - static uint32_t _nextSensorSlot = 0; + +#ifdef USE_MI_HOMEKIT + if(TasmotaGlobal.devices_present>0){ + for(uint32_t i=0;iMI32.period) { - _counter = 0; - MI32.mode.canScan = 0; - MI32.mode.canConnect = 1; - } - - if(MI32.mode.connected == 1 || MI32.mode.willConnect == 1) return; - - if(MIBLEsensors.size()==0) { - if (MI32.mode.runningScan == 0 && MI32.mode.canScan == 1) MI32StartTask(MI32_TASK_SCAN); - return; - } - - if(_counter==0) { - - MI32.state.sensor = _nextSensorSlot; - MI32.mode.canScan = 0; - // if (MI32.mode.runningScan|| MI32.mode.connected || MI32.mode.willConnect) return; - if (MI32.mode.connected || MI32.mode.willConnect) return; - _nextSensorSlot++; - MI32.mode.canConnect = 1; - if(MI32.mode.connected == 0) { - if (MI32.mode.shallReadBatt) { - //TODO: decide automatically, which sensor can not work without connections - AddLog(LOG_LEVEL_DEBUG,PSTR("%s: active sensor now: %u of %u"),D_CMND_MI32, MI32.state.sensor, MIBLEsensors.size()-1); - AddLog(LOG_LEVEL_DEBUG, PSTR("will connect to %s"),kMI32DeviceType[MIBLEsensors[MI32.state.sensor].type-1] ); - - MI32StartTask(MI32_TASK_BATT); +#ifdef USE_MI_HOMEKIT + if(MIBLEsensors[i].NMT > 20){ //TODO: Make a choosable timeout later + mi_homekit_update_value(MIBLEsensors[i].motion_hap_service,0.0f,0x0f); } -#ifndef USE_MI_DECRYPTION // turn off connections, because we only listen to advertisements - else{ - MI32StartTask(MI32_TASK_CONN); - } -#endif //USE_MI_DECRYPTION - } - if (_nextSensorSlot>(MIBLEsensors.size()-1)) { - _nextSensorSlot= 0; - _counter++; - if (MI32.mode.shallReadBatt){ - MI32.mode.shallReadBatt = 0; - } - MI32.mode.canConnect = 0; - MI32.mode.canScan = 1; +#endif //USE_MI_HOMEKIT } } - else _counter++; - if (MI32.state.sensor>MIBLEsensors.size()-1) { - _nextSensorSlot = 0; - MI32.mode.canScan = 1; - } - MI32StartTask(MI32_TASK_SCAN); } /*********************************************************************************************\ * Commands \*********************************************************************************************/ -void CmndMi32Period(void) { - if (XdrvMailbox.data_len > 0) { - if (1 == XdrvMailbox.payload) { - MI32EverySecond(true); - } else { - MI32.period = XdrvMailbox.payload; - } - } - ResponseCmndNumber(MI32.period); -} - -void CmndMi32Time(void) { - if (XdrvMailbox.data_len > 0) { - if (MIBLEsensors.size() > XdrvMailbox.payload) { - if ((LYWSD02 == MIBLEsensors[XdrvMailbox.payload].type) || (MHOC303 == MIBLEsensors[XdrvMailbox.payload].type)) { - AddLog(LOG_LEVEL_DEBUG, PSTR("M32: Will set Time")); - MI32.state.sensor = XdrvMailbox.payload; - MI32.mode.canScan = 0; - MI32.mode.canConnect = 0; - MI32.mode.shallSetTime = 1; - MI32.mode.willSetTime = 0; - ResponseCmndNumber(XdrvMailbox.payload); - } - } - } -} - -void CmndMi32Page(void) { - if (XdrvMailbox.payload > 0) { - MI32.perPage = XdrvMailbox.payload; - } - ResponseCmndNumber(MI32.perPage); -} - -void CmndMi32Battery(void) { - MI32EverySecond(true); - MI32.mode.shallReadBatt = 1; - MI32.mode.canConnect = 1; - ResponseCmndDone(); -} - -void CmndMi32Unit(void) { - if (XdrvMailbox.data_len > 0) { - if (MIBLEsensors.size() > XdrvMailbox.payload) { - if ((LYWSD02 == MIBLEsensors[XdrvMailbox.payload].type) || (MHOC303 == MIBLEsensors[XdrvMailbox.payload].type)) { - AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Will set Unit")); - MI32.state.sensor = XdrvMailbox.payload; - MI32.mode.canScan = 0; - MI32.mode.canConnect = 0; - MI32.mode.shallSetUnit = 1; - MI32.mode.willSetUnit = 0; - ResponseCmndNumber(XdrvMailbox.payload); - } - } - } -} - -#ifdef USE_MI_DECRYPTION void CmndMi32Key(void) { - if (44 == XdrvMailbox.data_len) { // a KEY-MAC-string - MI32AddKey(XdrvMailbox.data); + if (44 == XdrvMailbox.data_len || 36 == XdrvMailbox.data_len) { // a KEY-MAC-string + mi_bindKey_t keyMAC; + MI32HexStringToBytes(XdrvMailbox.data,keyMAC.buf); + if(36 == XdrvMailbox.data_len){ + memmove(keyMAC.buf + 10, keyMAC.buf + 6, 12); + const uint8_t _fillbytes[4] = {0x8d,0x3d,0x3c,0x97}; // only valid for YLKG08 and YLKG07 ?? + memcpy(keyMAC.buf + 6,_fillbytes,4); + AddLogBuffer(LOG_LEVEL_DEBUG,(uint8_t*) keyMAC.buf, 16); + } + MI32AddKey(keyMAC); ResponseCmndDone(); } } -#endif // USE_MI_DECRYPTION -void CmndMi32Beacon(void) { - if (XdrvMailbox.data_len == 0) { - switch (XdrvMailbox.index) { - case 0: - MI32.state.beaconScanCounter = 8; - ResponseCmndIdxChar(PSTR("Scanning...")); - break; - case 1: case 2: case 3: case 4: - char _MAC[18]; - ResponseCmndIdxChar(ToHex_P(MIBLEbeacons[XdrvMailbox.index-1].MAC, 6, _MAC, 18, ':')); - break; - } - } else { - if ((12 == XdrvMailbox.data_len) || (17 == XdrvMailbox.data_len)) { // MAC-string without or with colons - switch (XdrvMailbox.index) { - case 1: case 2: case 3: case 4: - MI32addBeacon(XdrvMailbox.index, XdrvMailbox.data); - break; - } - } - ResponseCmndIdxChar(XdrvMailbox.data); - } -} - -void CmndMi32Block(void){ - if (XdrvMailbox.data_len == 0) { - switch (XdrvMailbox.index) { - case 0: - MIBLEBlockList.clear(); - // AddLog(LOG_LEVEL_INFO,PSTR("M32: Size of ilist: %u"), MIBLEBlockList.size()); - ResponseCmndIdxChar(PSTR("Block list cleared")); - break; - case 1: - ResponseCmndIdxChar(PSTR("Show block list")); - break; - } - } - else { - MAC_t _MACasBytes; - MI32HexStringToBytes(XdrvMailbox.data,_MACasBytes.buf); - switch (XdrvMailbox.index) { - case 0: - MIBLEBlockList.erase( std::remove_if( begin( MIBLEBlockList ), end( MIBLEBlockList ), [_MACasBytes]( MAC_t& _entry )->bool - { return (memcmp(_entry.buf,_MACasBytes.buf,6) == 0); } - ), end( MIBLEBlockList ) ); - ResponseCmndIdxChar(PSTR("MAC not blocked anymore")); - break; - case 1: - bool _notYetInList = true; - for (auto &_entry : MIBLEBlockList) { - if (memcmp(_entry.buf,_MACasBytes.buf,6) == 0){ - _notYetInList = false; - } - } - if (_notYetInList) { - MIBLEBlockList.push_back(_MACasBytes); - ResponseCmndIdxChar(XdrvMailbox.data); - MI32removeMIBLEsensor(_MACasBytes.buf); - } - // AddLog(LOG_LEVEL_INFO,PSTR("M32: Size of ilist: %u"), MIBLEBlockList.size()); - break; - } - } - MI32.mode.shallShowBlockList = 1; - MI32triggerTele(); +void CmndMi32Cfg(void) { + MI32saveConfig(); + ResponseCmndDone(); } void CmndMi32Option(void){ @@ -1957,6 +1632,9 @@ void CmndMi32Option(void){ case 2: MI32.option.directBridgeMode = onOff; break; + case 3: + MI32.mode.didGetConfig = onOff; + break; } ResponseCmndDone(); } @@ -1964,16 +1642,216 @@ void CmndMi32Option(void){ /*********************************************************************************************\ * Presentation \*********************************************************************************************/ +#ifdef USE_MI_EXT_GUI +bool MI32HandleWebGUIResponse(void){ + char tmp[16]; + WebGetArg(PSTR("wi"), tmp, sizeof(tmp)); + if (strlen(tmp)) { + WSContentBegin(200, CT_PLAIN); + if(MI32.widgetSlot==0) {WSContentEnd();return true;} + for(uint32_t i=0;i<32;i++){ + if(bitRead(MI32.widgetSlot,i)){ + MI32sendWidget(i); + WSContentEnd(); + bitClear(MI32.widgetSlot,i); + return true; + } + } + WSContentEnd(); + return true; + } + return false; +} -const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 v0917a{m}%u%s / %u{e}"; -const char HTTP_MI32_MAC[] PROGMEM = "{s}%s %s{m}%s{e}"; -const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}"; +#ifdef USE_MI_ESP32_ENERGY +//https://gist.github.com/LingDong-/7e4c4cae5cbbc44400a05fba65f06f23 +// used for logarithmic mapping of 0 - 3600 watts to 0-20 pixel - TaylorLog did not work as expected +float MI32ln(float x) { + unsigned int bx = * (unsigned int *) (&x); + unsigned int ex = bx >> 23; + signed int t = (signed int)ex-(signed int)127; + unsigned int s = (t < 0) ? (-t) : t; + bx = 1065353216 | (bx & 8388607); + x = * (float *) (&bx); + return -1.49278+(2.11263+(-0.729104+0.10969*x)*x)*x+0.6931471806*t; +} +#endif //USE_MI_ESP32_ENERGY + +void MI32createPolyline(char *polyline, uint8_t *history){ + uint32_t _pos = 0; + uint32_t _inc = 0; + for (uint32_t i = 0; i<24;i++){ + uint32_t y = 21-MI32fetchHistory(history,i); + if (y>20){ + y = 150; //create a big gap in the graph to represent invalidated data + } + _inc = snprintf_P(polyline+_pos,10,PSTR("%u,%u "),i*6,y); + _pos+=_inc; + } + // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: polyline: %s"),polyline); +} + +#ifdef USE_MI_ESP32_ENERGY +void MI32sendEnergyWidget(){ + if (Energy.current_available && Energy.voltage_available) { + WSContentSend_P(HTTP_MI32_POWER_WIDGET,MIBLEsensors.size()+1, Energy.voltage,Energy.current[1]); + char _polyline[176]; + MI32createPolyline(_polyline,MI32.energy_history); + WSContentSend_P(PSTR("

" D_POWERUSAGE ": %.1f " D_UNIT_WATT ""),Energy.active_power); + WSContentSend_P(HTTP_MI32_GRAPH,_polyline,185,124,124,_polyline,1); + WSContentSend_P(PSTR("

")); + } +} +#endif //USE_MI_ESP32_ENERGY + +void MI32sendWidget(uint32_t slot){ + auto _sensor = MIBLEsensors[slot]; + char _MAC[13]; + ToHex_P(_sensor.MAC,6,_MAC,13); + uint32_t _opacity = 1; + if(_sensor.RSSI == 0){ + _opacity=0; + } + char _key[33] ={0}; + if(_sensor.key!=nullptr){ + ToHex_P(_sensor.key,16,_key,33); + } + else if(_sensor.feature.needsKey == 1){ + snprintf_P(_key,32,PSTR("!! needs key !!")); + _opacity=0; + } + if (_sensor.status.hasWrongKey == 1){ + snprintf_P(_key,32,PSTR("!! wrong key !!")); + _opacity=0; + } + if (_sensor.status.isUnbounded == 1){ + if(_sensor.type != CGD1){ //only exception atm + snprintf_P(_key,32,PSTR("!! not paired !!")); + _opacity=0; + } + } + + char _bat[24]; + snprintf_P(_bat,24,PSTR("🔋%u%%"), _sensor.bat); + if(!_sensor.feature.bat) _bat[0] = 0; + if (_sensor.bat == 0) _bat[9] = 0; + WSContentSend_P(HTTP_MI32_WIDGET,slot+1,_opacity,_MAC,_sensor.RSSI,_bat,_key,kMI32DeviceType[_sensor.type-1]); + + if(_sensor.feature.tempHum){ + if(!isnan(_sensor.temp)){ + char _polyline[176]; + MI32createPolyline(_polyline,_sensor.temp_history); + WSContentSend_P(PSTR("

" D_JSON_TEMPERATURE ": %.1f °C"),_sensor.temp); + WSContentSend_P(HTTP_MI32_GRAPH,_polyline,185,124,124,_polyline,1); + WSContentSend_P(PSTR("

")); + } + if(!isnan(_sensor.hum)){ + char _polyline[176]; + MI32createPolyline(_polyline,_sensor.hum_history); + WSContentSend_P(PSTR("

" D_JSON_HUMIDITY ": %.1f %%"),_sensor.hum); + WSContentSend_P(HTTP_MI32_GRAPH,_polyline,151,190,216,_polyline,2); + WSContentSend_P(PSTR("

")); + } + if(!isnan(_sensor.temp) && !isnan(_sensor.hum)){ + WSContentSend_P(PSTR("" D_JSON_DEWPOINT ": %.1f °C"),CalcTempHumToDew(_sensor.temp,_sensor.hum)); + } + } + else if(_sensor.feature.temp){ + if(!isnan(_sensor.temp)){ + char _polyline[176]; + MI32createPolyline(_polyline,_sensor.temp_history); + WSContentSend_P(PSTR("

" D_JSON_TEMPERATURE ": %.1f °C"),_sensor.temp); + WSContentSend_P(HTTP_MI32_GRAPH,_polyline,185,124,124,_polyline,1); + WSContentSend_P(PSTR("

")); + } + } + if(_sensor.feature.lux){ + if(_sensor.lux!=0x00ffffff){ + char _polyline[176]; + MI32createPolyline(_polyline,_sensor.lux_history); + WSContentSend_P(PSTR("

" D_JSON_ILLUMINANCE ": %d Lux"),_sensor.lux); + WSContentSend_P(HTTP_MI32_GRAPH,_polyline,242,240,176,_polyline,3); + WSContentSend_P(PSTR("

")); + } + } + if(_sensor.feature.Btn){ + if(_sensor.Btn<12) WSContentSend_P(PSTR("

Last Button: %u

"),_sensor.Btn); + } + if(_sensor.feature.motion){ + WSContentSend_P(PSTR("

Events: %u

"),_sensor.events); + WSContentSend_P(PSTR("

No motion for > %u seconds

"),_sensor.NMT); + } + if(_sensor.feature.door){ + if(_sensor.door!=255){ + if(_sensor.door==1){ + WSContentSend_P(PSTR("

Contact open

")); + } + else{ + WSContentSend_P(PSTR("

Contact closed

")); + } + WSContentSend_P(PSTR("

Events: %u

"),_sensor.events); + } + } + if(_sensor.feature.leak){ + if(_sensor.leak==1){ + WSContentSend_P(PSTR("

Leak !!!

")); + } + else{ + WSContentSend_P(PSTR("

no leak

")); + } + } + WSContentSend_P(PSTR("
")); +} + +void MI32InitGUI(void){ + MI32suspendScanTask(); + MI32.widgetSlot=0; + WSContentStart_P("m32"); + WSContentSend_P(HTTP_MI32_SCRIPT_1); + // WSContentSend_P(HTTP_MI32_SCRIPT_1); + WSContentSendStyle(); + WSContentSend_P(HTTP_MI32_STYLE); + WSContentSend_P(HTTP_MI32_STYLE_SVG,1,185,124,124,185,124,124); + WSContentSend_P(HTTP_MI32_STYLE_SVG,2,151,190,216,151,190,216); + WSContentSend_P(HTTP_MI32_STYLE_SVG,3,242,240,176,242,240,176); +#ifdef USE_MI_HOMEKIT + WSContentSend_P((HTTP_MI32_PARENT_START),MIBLEsensors.size(),UpTime(),MI32.hk_setup_code,MI32.HKconnectedControllers,ESP.getFreeHeap()/1024); +#else + const char _setupCode[1] = {0}; + WSContentSend_P((HTTP_MI32_PARENT_START),MIBLEsensors.size(),UpTime(),_setupCode,ESP.getFreeHeap()/1024); +#endif //USE_MI_HOMEKIT + for(uint32_t _slot = 0;_slot")); + WSContentSpaceButton(BUTTON_MAIN); + WSContentStop(); + vTaskResume(MI32.ScanTask); +} + +void MI32HandleWebGUI(void){ + if (!HttpCheckPriviledgedAccess()) { return; } + if (MI32HandleWebGUIResponse()) { return; } + MI32InitGUI(); +} +#endif //USE_MI_EXT_GUI + +const char HTTP_MI32[] PROGMEM = "{s}Mi ESP32 {m} %u devices{e}"; + +#ifndef USE_MI_EXT_GUI const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u %%{e}"; const char HTTP_LASTBUTTON[] PROGMEM = "{s}%s Last Button{m}%u {e}"; const char HTTP_EVENTS[] PROGMEM = "{s}%s Events{m}%u {e}"; const char HTTP_NMT[] PROGMEM = "{s}%s No motion{m}> %u seconds{e}"; +const char HTTP_DOOR[] PROGMEM = "{s}%s Door{m}> %u open/closed{e}"; const char HTTP_MI32_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%u us/cm{e}"; +#endif //USE_MI_EXT_GUI +const char HTTP_MI32_MAC[] PROGMEM = "{s}%s %s{m}%s{e}"; const char HTTP_MI32_HL[] PROGMEM = "{s}
{m}
{e}"; +const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}"; void MI32ShowContinuation(bool *commaflg) { if (*commaflg) { @@ -1986,32 +1864,20 @@ void MI32ShowContinuation(bool *commaflg) { void MI32Show(bool json) { if (json) { - if(MI32.mode.shallShowScanResult) { - return MI32showScanResults(); - } - else if(MI32.mode.shallShowBlockList) { - return MI32showBlockList(); - } #ifdef USE_HOME_ASSISTANT bool _noSummarySave = MI32.option.noSummary; bool _minimalSummarySave = MI32.option.minimalSummary; if(hass_mode==2){ - if(MI32.option.holdBackFirstAutodiscovery){ - if(!MI32.mode.firstAutodiscoveryDone){ - MI32.mode.firstAutodiscoveryDone = 1; - return; - } - } MI32.option.noSummary = false; MI32.option.minimalSummary = false; } #endif //USE_HOME_ASSISTANT if(!MI32.mode.triggeredTele){ - MI32.mode.shallClearResults=1; + // MI32.mode.shallClearResults=1; if(MI32.option.noSummary) return; // no message at TELEPERIOD } - + MI32suspendScanTask(); for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { if(MI32.mode.triggeredTele && MIBLEsensors[i].eventType.raw == 0) continue; if(MI32.mode.triggeredTele && MIBLEsensors[i].shallSendMQTT==0) continue; @@ -2128,18 +1994,29 @@ void MI32Show(bool json) } } } // minimal summary - if (MIBLEsensors[i].feature.PIR){ + if (MIBLEsensors[i].feature.motion){ if(MIBLEsensors[i].eventType.motion || !MI32.mode.triggeredTele){ if(MI32.mode.triggeredTele) { MI32ShowContinuation(&commaflg); - ResponseAppend_P(PSTR("\"PIR\":1")); // only real-time + ResponseAppend_P(PSTR("\"motion\":1")); // only real-time } MI32ShowContinuation(&commaflg); ResponseAppend_P(PSTR("\"Events\":%u"),MIBLEsensors[i].events); } else if(MIBLEsensors[i].eventType.noMotion && MI32.mode.triggeredTele){ MI32ShowContinuation(&commaflg); - ResponseAppend_P(PSTR("\"PIR\":0")); + ResponseAppend_P(PSTR("\"motion\":0")); + } + } + + if (MIBLEsensors[i].feature.door){ + if(MIBLEsensors[i].eventType.door || !MI32.mode.triggeredTele){ + if(MI32.mode.triggeredTele) { + MI32ShowContinuation(&commaflg); + ResponseAppend_P(PSTR("\"DOOR\":%u"),MIBLEsensors[i].door); // only real-time + } + MI32ShowContinuation(&commaflg); + ResponseAppend_P(PSTR("\"Events\":%u"),MIBLEsensors[i].events); } } @@ -2187,40 +2064,31 @@ void MI32Show(bool json) } } MI32.mode.triggeredTele = 0; -// add beacons - uint32_t _idx = 0; - for (auto _beacon : MIBLEbeacons){ - _idx++; - if(!_beacon.active) continue; - char _MAC[18]; - ToHex_P(_beacon.MAC,6,_MAC,18,':'); - ResponseAppend_P(PSTR(",\"Beacon%u\":{\"MAC\":\"%s\",\"CID\":\"0x%04x\",\"SVC\":\"0x%04x\"," - "\"UUID\":\"0x%04x\",\"Time\":%u,\"RSSI\":%d}"), - _idx,_MAC,_beacon.CID,_beacon.SVC,_beacon.UUID,_beacon.time,_beacon.RSSI); - } #ifdef USE_HOME_ASSISTANT if(hass_mode==2){ MI32.option.noSummary = _noSummarySave; MI32.option.minimalSummary = _minimalSummarySave; } #endif //USE_HOME_ASSISTANT +#ifdef USE_MI_EXT_GUI + Mi32invalidateOldHistory(); +#ifdef USE_MI_ESP32_ENERGY + MI32addHistory(MI32.energy_history,Energy.active_power[0],100); //TODO: which value?? +#endif //USE_MI_ESP32_ENERGY +#endif //USE_MI_EXT_GUI + vTaskResume(MI32.ScanTask); #ifdef USE_WEBSERVER } else { - static uint16_t _page = 0; - static uint16_t _counter = 0; - int32_t i = _page * MI32.perPage; - uint32_t j = i + MI32.perPage; - if (j+1>MIBLEsensors.size()){ - j = MIBLEsensors.size(); - } - char stemp[5] ={0}; - if (MIBLEsensors.size()-(_page*MI32.perPage)>1 && MI32.perPage!=1) { - sprintf_P(stemp,"-%u",j); - } - if (MIBLEsensors.size()==0) i=-1; // only for the GUI + MI32suspendScanTask(); - WSContentSend_PD(HTTP_MI32, i+1,stemp,MIBLEsensors.size()); - for (i; i0) WSContentSend_PD(HTTP_NMT, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].NMT); } + if(MIBLEsensors[i].door != 255 && MIBLEsensors[i].type==MCCGQ02){ + WSContentSend_PD(HTTP_DOOR, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].door); + } if (MIBLEsensors[i].lux!=0x00ffffff) { // this is the error code -> no valid value WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].lux); } @@ -2260,36 +2135,26 @@ void MI32Show(bool json) WSContentSend_PD(HTTP_LASTBUTTON, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].Btn); } } - _counter++; - if(_counter>3) { - _page++; - _counter=0; - } - if (MIBLEsensors.size()%MI32.perPage==0 && _page==MIBLEsensors.size()/MI32.perPage) { _page = 0; } - if (_page>MIBLEsensors.size()/MI32.perPage) { _page = 0; } - - //always at the bottom of the page - uint32_t _idx=0; - if(MI32.mode.activeBeacon){ - WSContentSend_PD(HTTP_MI32_HL); - char _sbeacon[] = "Beacon1"; - for (auto &_beacon : MIBLEbeacons){ - _idx++; - if(!_beacon.active) continue; - WSContentSend_PD(HTTP_MI32_HL); - _sbeacon[6] = _idx + 0x30; - char _MAC[18]; - ToHex_P(_beacon.MAC,6,_MAC,18,':'); - WSContentSend_PD(HTTP_MI32_MAC, _sbeacon, D_MAC_ADDRESS, _MAC); - WSContentSend_PD(HTTP_RSSI, _sbeacon, _beacon.RSSI); - if(_beacon.CID!=0) WSContentSend_PD(PSTR("{s}Beacon%u CID{m}0x%04X{e}"),_idx, _beacon.CID); - if(_beacon.SVC!=0) WSContentSend_PD(PSTR("{s}Beacon%u SVC{m}0x%04X{e}"),_idx, _beacon.SVC); - if(_beacon.UUID!=0) WSContentSend_PD(PSTR("{s}Beacon%u UUID{m}0x%04X{e}"),_idx, _beacon.UUID); - WSContentSend_PD(PSTR("{s}Beacon%u Time{m}%u seconds{e}"),_idx, _beacon.time); - } - } +#endif //USE_MI_EXT_GUI #endif // USE_WEBSERVER } + vTaskResume(MI32.ScanTask); +} + +int ExtStopBLE(){ + if(Settings->flag5.mi32_enable == 0) return 0; + if (MI32.ScanTask != nullptr){ + MI32Scan->stop(); + vTaskDelete(MI32.ScanTask); + AddLog(LOG_LEVEL_INFO,PSTR("M32: stop BLE")); + } +#ifdef USE_MI_HOMEKIT + if(MI32.mode.didStartHAP) { + AddLog(LOG_LEVEL_INFO,PSTR("M32: stop Homebridge")); + mi_homekit_stop(); + } +#endif //USE_MI_HOMEKIT + return 0; } /*********************************************************************************************\ @@ -2319,6 +2184,9 @@ bool Xsns62(uint8_t function) case FUNC_EVERY_SECOND: MI32EverySecond(false); break; + case FUNC_SAVE_BEFORE_RESTART: + ExtStopBLE(); + break; case FUNC_COMMAND: result = DecodeCommand(kMI32_Commands, MI32_Commands); break; @@ -2329,6 +2197,14 @@ bool Xsns62(uint8_t function) case FUNC_WEB_SENSOR: MI32Show(0); break; +#ifdef USE_MI_EXT_GUI + case FUNC_WEB_ADD_MAIN_BUTTON: + if (MI32.mode.didGetConfig) WSContentSend_P(HTTP_BTN_MENU_MI32); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer_on(PSTR("/m32"), MI32HandleWebGUI); + break; +#endif //USE_MI_EXT_GUI #endif // USE_WEBSERVER } return result; diff --git a/tasmota/xsns_62_esp32_mi_homekit.c b/tasmota/xsns_62_esp32_mi_homekit.c new file mode 100644 index 000000000..7e6c92ff3 --- /dev/null +++ b/tasmota/xsns_62_esp32_mi_homekit.c @@ -0,0 +1,333 @@ +#if(USE_MI_HOMEKIT==1) + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +//Homekit +static int MI32_bridge_identify(hap_acc_t *ha); +static int MI32_accessory_identify(hap_acc_t *ha); +static void MI32_bridge_thread_entry(void *p); + +extern uint32_t MI32numberOfDevices(); +extern const char *MI32getDeviceName(uint32_t slot); +extern uint32_t MI32getDeviceType(uint32_t slot); +extern void MI32saveHAPhandles(uint32_t slot, uint32_t type, void* handle); +extern void MI32passHapEvent(uint32_t event); +extern void MI32didStartHAP(); +extern const char * MI32getSetupCode(); +extern uint32_t MI32numOfRelays(); +extern void MI32setRelayFromHK(uint32_t relay, bool onOff); + +// static const char *TAG = "Mi Bridge"; +static bool MIBridgeWasNeverConnected = true; + +#define CONFIG_EXAMPLE_SETUP_ID "MI32" + +#define FLORA 1 +#define MJ_HT_V1 2 +#define LYWSD02 3 +#define LYWSD03MMC 4 +#define CGG1 5 +#define CGD1 6 +#define NLIGHT 7 +#define MJYD2S 8 +#define YEERC 9 +#define MHOC401 10 +#define MHOC303 11 +#define ATC 12 +#define MCCGQ02 13 +#define SJWS01L 14 +#define PVVX 15 +#define YLKG08 16 + +/*********************************************************************************************\ + * Homekit +\*********************************************************************************************/ +/* Mandatory identify routine for the bridge. + * In a real accessory, something like LED blink should be implemented + * got visual identification + */ +static int MI32_bridge_identify(hap_acc_t *ha) +{ + return HAP_SUCCESS; +} + +void mi_hap_event_handler(hap_event_t event, void *data) +{ + MI32passHapEvent((uint32_t)event); + if(event == HAP_EVENT_CTRL_CONNECTED) MIBridgeWasNeverConnected = false; +} + +static int MI32_bridge_read_callback(hap_read_data_t read_data[], int count, + void *serv_priv, void *read_priv) +{ + return HAP_SUCCESS; +} + +static int MI32_outlets_write_callback(hap_write_data_t write_data[], int count, + void *serv_priv, void *write_priv) +{ + uint8_t _relay = ((uint8_t*)serv_priv)[0]; + int i, ret = HAP_SUCCESS; + hap_write_data_t *write; + for (i = 0; i < count; i++) { + write = &write_data[i]; + if (!strcmp(hap_char_get_type_uuid(write->hc), HAP_CHAR_UUID_ON)) { + MI32setRelayFromHK(_relay-48, write->val.b); + hap_char_update_val(write->hc, &(write->val)); + *(write->status) = HAP_STATUS_SUCCESS; + } else { + *(write->status) = HAP_STATUS_RES_ABSENT; + } + } + return ret; +} + +/* Mandatory identify routine for the bridged accessory + * In a real bridge, the actual accessory must be sent some request to + * identify itself visually + */ +static int MI32_accessory_identify(hap_acc_t *ha) +{ + return HAP_SUCCESS; +} + +/*The main thread for handling the Smart Outlet Accessory */ +static void MI32_bridge_thread_entry(void *p) +{ + // esp_log_level_set("*", ESP_LOG_NONE); + hap_acc_t *accessory; + hap_serv_t *service; + + /* Initialize the HAP core */ + hap_init(HAP_TRANSPORT_WIFI); + + /* Initialise the mandatory parameters for Accessory which will be added as + * the mandatory services internally + */ + hap_acc_cfg_t cfg = { + .name = "Mi-Home-Bridge", + .manufacturer = "Tasmota", + .model = "ESP32", + .serial_num = "9600", + .fw_rev = "0.9.5", + .hw_rev = NULL, + .pv = "1.1.0", + .cid = HAP_CID_BRIDGE, + .identify_routine = MI32_bridge_identify + }; + /* Create accessory object */ + accessory = hap_acc_create(&cfg); + + /* Add a dummy Product Data */ + uint8_t product_data[] = {'T','M','H'}; + hap_acc_add_product_data(accessory, product_data, sizeof(product_data)); + + /* Add the Accessory to the HomeKit Database */ + hap_add_accessory(accessory); + +#define NUM_BRIDGED_ACCESSORIES 1 + /* Create and add the Accessory to the Bridge object*/ + uint32_t _numDevices = MI32numberOfDevices(); + for (uint32_t i = 0; i < _numDevices; i++) { + char *accessory_name = (char*)MI32getDeviceName(i); + char _serialNum[4] = {0}; + snprintf(_serialNum,sizeof(_serialNum),"%u", i); + + hap_acc_cfg_t bridge_cfg = { + .name = accessory_name, + .manufacturer = "Xiaomi", + .model = accessory_name, + .serial_num = _serialNum, + .fw_rev = "0.9.1", + .hw_rev = NULL, + .pv = "1.1.0", + .cid = HAP_CID_SENSOR, + .identify_routine = MI32_accessory_identify, + }; + + /* Create accessory object */ + accessory = hap_acc_create(&bridge_cfg); + + switch (MI32getDeviceType(i)){ + case LYWSD02: case LYWSD03MMC: case CGG1: case CGD1: case MHOC303: case MHOC401: case ATC: case PVVX: + { + service = hap_serv_humidity_sensor_create(50.0f); + hap_serv_set_bulk_read_cb(service, MI32_bridge_read_callback); + hap_acc_add_serv(accessory, service); + MI32saveHAPhandles(i,0x06,(void *)hap_serv_get_char_by_uuid(service, HAP_CHAR_UUID_CURRENT_RELATIVE_HUMIDITY)); + + service = hap_serv_temperature_sensor_create(22.5f); + hap_serv_set_bulk_read_cb(service, MI32_bridge_read_callback); + hap_acc_add_serv(accessory, service); + MI32saveHAPhandles(i,0x04,hap_serv_get_char_by_uuid(service, HAP_CHAR_UUID_CURRENT_TEMPERATURE)); + + service = hap_serv_battery_service_create(99,0,0); + hap_serv_set_bulk_read_cb(service, MI32_bridge_read_callback); + hap_acc_add_serv(accessory, service); + MI32saveHAPhandles(i,0x0a,hap_serv_get_char_by_uuid(service, HAP_CHAR_UUID_BATTERY_LEVEL)); + } + break; + case FLORA: case MJYD2S: + { + service = hap_serv_light_sensor_create(100.0f); + hap_serv_set_bulk_read_cb(service, MI32_bridge_read_callback); + hap_acc_add_serv(accessory, service); + MI32saveHAPhandles(i,0x07,hap_serv_get_char_by_uuid(service, HAP_CHAR_UUID_CURRENT_AMBIENT_LIGHT_LEVEL)); + service = hap_serv_battery_service_create(50,0,0); + hap_serv_set_bulk_read_cb(service, MI32_bridge_read_callback); + hap_acc_add_serv(accessory, service); + MI32saveHAPhandles(i,0x0a,hap_serv_get_char_by_uuid(service, HAP_CHAR_UUID_BATTERY_LEVEL)); + if(MI32getDeviceType(i) == MJYD2S){ + service = hap_serv_motion_sensor_create(false); + hap_serv_set_bulk_read_cb(service, MI32_bridge_read_callback); + hap_acc_add_serv(accessory, service); + MI32saveHAPhandles(i,0x0f,hap_serv_get_char_by_uuid(service, HAP_CHAR_UUID_MOTION_DETECTED)); + } + break; + } + case NLIGHT: + { + service = hap_serv_motion_sensor_create(false); + hap_serv_set_bulk_read_cb(service, MI32_bridge_read_callback); + hap_acc_add_serv(accessory, service); + MI32saveHAPhandles(i,0x0f,hap_serv_get_char_by_uuid(service, HAP_CHAR_UUID_MOTION_DETECTED)); + + service = hap_serv_battery_service_create(50,0,0); + hap_serv_set_bulk_read_cb(service, MI32_bridge_read_callback); + hap_acc_add_serv(accessory, service); + MI32saveHAPhandles(i,0x0a,hap_serv_get_char_by_uuid(service, HAP_CHAR_UUID_BATTERY_LEVEL)); + break; + //motion 0x0f + } + case MCCGQ02: + { + service = hap_serv_contact_sensor_create(0); + hap_serv_set_bulk_read_cb(service, MI32_bridge_read_callback); + hap_acc_add_serv(accessory, service); + MI32saveHAPhandles(i,0x19,hap_serv_get_char_by_uuid(service, HAP_CHAR_UUID_CONTACT_SENSOR_STATE)); + service = hap_serv_battery_service_create(50,0,0); + hap_serv_set_bulk_read_cb(service, MI32_bridge_read_callback); + hap_acc_add_serv(accessory, service); + MI32saveHAPhandles(i,0x0a,hap_serv_get_char_by_uuid(service, HAP_CHAR_UUID_BATTERY_LEVEL)); + break; + } + case YEERC: + { + bridge_cfg.cid = HAP_CID_PROGRAMMABLE_SWITCH; + hap_serv_t * _label = hap_serv_service_label_create(1); + hap_acc_add_serv(accessory, _label); + for(uint8_t _but=0;_but<6;_but++){ + hap_serv_t * _newSwitch = hap_serv_stateless_programmable_switch_create(0); + const uint8_t _validVals[] = {0,2}; + hap_char_add_valid_vals(hap_serv_get_char_by_uuid(_newSwitch, HAP_CHAR_UUID_PROGRAMMABLE_SWITCH_EVENT), _validVals, 2); + hap_char_t *_index = hap_char_service_label_index_create(_but+1); + hap_serv_add_char(_newSwitch,_index); + hap_acc_add_serv(accessory, _newSwitch); + MI32saveHAPhandles(i,_but+1000,hap_serv_get_char_by_uuid(_newSwitch, HAP_CHAR_UUID_PROGRAMMABLE_SWITCH_EVENT)); + } + } + break; + case SJWS01L: + service = hap_serv_leak_sensor_create(0); + hap_serv_set_bulk_read_cb(service, MI32_bridge_read_callback); + hap_acc_add_serv(accessory, service); + MI32saveHAPhandles(i,0x14,hap_serv_get_char_by_uuid(service, HAP_CHAR_UUID_LEAK_DETECTED)); + hap_serv_t * _newSwitch = hap_serv_stateless_programmable_switch_create(0); + const uint8_t _validVals[] = {0,2}; + hap_char_add_valid_vals(hap_serv_get_char_by_uuid(_newSwitch, HAP_CHAR_UUID_PROGRAMMABLE_SWITCH_EVENT), _validVals, 2); + hap_acc_add_serv(accessory, _newSwitch); + MI32saveHAPhandles(i,1000,hap_serv_get_char_by_uuid(_newSwitch, HAP_CHAR_UUID_PROGRAMMABLE_SWITCH_EVENT)); + service = hap_serv_battery_service_create(50,0,0); + hap_serv_set_bulk_read_cb(service, MI32_bridge_read_callback); + hap_acc_add_serv(accessory, service); + MI32saveHAPhandles(i,0x0a,hap_serv_get_char_by_uuid(service, HAP_CHAR_UUID_BATTERY_LEVEL)); + break; + default: + break; + } + /* Add the Accessory to the HomeKit Database */ + hap_add_bridged_accessory(accessory, hap_get_unique_aid(accessory_name)); + } + // add internal Tasmota devices + for(uint32_t i = 0;i 0.0f); + break; + default: + new_val.f = value; + } + int ret = hap_char_update_val((hap_char_t *)handle, &new_val); + // if(ret!= HAP_SUCCESS){ + // ESP_LOGE(TAG,"error:",ret); + // } +} + +void mi_homekit_stop(){ + hap_stop(); +} + +#endif //USE_MI_ESP32 + diff --git a/tasmota/xsns_65_hdc1080.ino b/tasmota/xsns_65_hdc1080.ino index cdeb6eaae..381f1a48a 100644 --- a/tasmota/xsns_65_hdc1080.ino +++ b/tasmota/xsns_65_hdc1080.ino @@ -213,7 +213,7 @@ bool HdcRead(void) { temp_data = (uint16_t) ((sensor_data[0] << 8) | sensor_data[1]); rh_data = (uint16_t) ((sensor_data[2] << 8) | sensor_data[3]); - AddLog(LOG_LEVEL_DEBUG, PSTR("HdcRead: temperature raw data: 0x%04x; humidity raw data: 0x%04x"), temp_data, rh_data); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("HdcRead: temperature raw data: 0x%04x; humidity raw data: 0x%04x"), temp_data, rh_data); // read the temperature from the first 16 bits of the result diff --git a/tasmota/xsns_69_opentherm.ino b/tasmota/xsns_69_opentherm.ino index cfcc0384d..e8960de76 100644 --- a/tasmota/xsns_69_opentherm.ino +++ b/tasmota/xsns_69_opentherm.ino @@ -24,13 +24,25 @@ #include // Hot water and boiler parameter ranges +#ifndef OT_HOT_WATER_MIN #define OT_HOT_WATER_MIN 23 +#endif +#ifndef OT_HOT_WATER_MAX #define OT_HOT_WATER_MAX 55 +#endif +#ifndef OT_BOILER_MIN #define OT_BOILER_MIN 40 +#endif +#ifndef OT_BOILER_MAX #define OT_BOILER_MAX 85 +#endif +#ifndef OT_HOT_WATER_DEFAULT #define OT_HOT_WATER_DEFAULT 36; +#endif +#ifndef OT_BOILER_DEFAULT #define OT_BOILER_DEFAULT 85; +#endif // Seconds before OT will make an attempt to connect to the boiler after connection error #define SNS_OT_DISCONNECT_COOLDOWN_SECONDS 4 @@ -467,8 +479,11 @@ uint8_t sns_opentherm_read_flags(char *data, uint32_t len) // flag value, however, this command does not update the settings. #define D_CMND_SET_HOT_WATER_ENABLED "dhw" +// BLOR - Reset boiler +#define D_CMND_BLLOR "blor" + const char kOpenThermCommands[] PROGMEM = D_PRFX_OTHERM "|" D_CMND_OTHERM_BOILER_SETPOINT "|" D_CMND_OTHERM_DHW_SETPOINT - "|" D_CMND_OTHERM_SAVE_SETTINGS "|" D_CMND_OTHERM_FLAGS "|" D_CMND_SET_CENTRAL_HEATING_ENABLED "|" D_CMND_SET_HOT_WATER_ENABLED; + "|" D_CMND_OTHERM_SAVE_SETTINGS "|" D_CMND_OTHERM_FLAGS "|" D_CMND_SET_CENTRAL_HEATING_ENABLED "|" D_CMND_SET_HOT_WATER_ENABLED "|" D_CMND_BLLOR; void (*const OpenThermCommands[])(void) PROGMEM = { &sns_opentherm_boiler_setpoint_cmd, @@ -476,7 +491,8 @@ void (*const OpenThermCommands[])(void) PROGMEM = { &sns_opentherm_save_settings_cmd, &sns_opentherm_flags_cmd, &sns_opentherm_set_central_heating_cmd, - &sns_opentherm_set_hot_water_cmd}; + &sns_opentherm_set_hot_water_cmd, + &sns_opentherm_blor_cmd,}; void sns_opentherm_cmd(void) { } void sns_opentherm_boiler_setpoint_cmd(void) @@ -550,6 +566,17 @@ void sns_opentherm_set_hot_water_cmd(void) ResponseCmndNumber(sns_ot_boiler_status.m_enableHotWater ? 1 : 0); } +void sns_opentherm_blor_cmd(void) +{ + bool query = strlen(XdrvMailbox.data) == 0; + bool retval = false; + if (!query) + { + if (atoi(XdrvMailbox.data)) retval = sns_opentherm_call_blor(); + } + ResponseCmndNumber(retval); +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ diff --git a/tasmota/xsns_69_opentherm_protocol.ino b/tasmota/xsns_69_opentherm_protocol.ino index bc821640a..b281f4781 100644 --- a/tasmota/xsns_69_opentherm_protocol.ino +++ b/tasmota/xsns_69_opentherm_protocol.ino @@ -32,6 +32,7 @@ typedef union { uint8_t notSupported : 1; // If set, boiler does not support this command uint8_t supported : 1; // Set if at least one response were successfull uint8_t retryCount : 2; // Retry counter before notSupported flag being set + uint8_t skip : 1; // Only manual call }; } OpenThermParamFlags; @@ -243,7 +244,16 @@ OpenThermCommand sns_opentherm_commands[] = { .m_ot_make_request = sns_opentherm_get_generic_u16, .m_ot_parse_response = sns_opentherm_parse_generic_u16, .m_ot_appent_telemetry = sns_opentherm_tele_generic_u16}, + {// Boiler Lock-out Reset command + .m_command_name = "BLOR", + .m_command_code = (uint8_t)OpenThermMessageID::Command, + .m_flags = {.skip = 1}, + .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, + .m_ot_make_request = sns_opentherm_send_blor, + .m_ot_parse_response = sns_opentherm_parse_generic_u16, + .m_ot_appent_telemetry = sns_opentherm_tele_u8_u8}, }; +#define SNS_OT_COMMANDS_COUNT (sizeof(sns_opentherm_commands) / sizeof(OpenThermCommand)) /////////////////////////////////// Process Slave Status Flags & Control ////////////////////////////////////////////////// unsigned long sns_opentherm_set_slave_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status) @@ -431,6 +441,32 @@ void sns_opentherm_tele_oem_diag(struct OpenThermCommandT *self) ResponseAppend_P(PSTR("%d"), (int)self->m_results[0].m_u16); } +/////////////////////////////////// Boiler Boiler Lock-out Reset ////////////////////////////////////////////////// +unsigned long sns_opentherm_send_blor(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status) +{ + AddLog(LOG_LEVEL_ERROR, PSTR("[OTH]: Call Boiler Lock-out Reset")); + + self->m_flags.skip = true; // Disable future calls of this command + + unsigned int data = 1; //1 : “BLOR”= Boiler Lock-out Reset command + data <<= 8; + return OpenTherm::buildRequest(OpenThermMessageType::OPTH_WRITE_DATA, OpenThermMessageID::Command, data); +} + +bool sns_opentherm_call_blor() +{ + for (int i = 0; i < SNS_OT_COMMANDS_COUNT; ++i) + { + struct OpenThermCommandT *cmd = &sns_opentherm_commands[i]; + if (!strcmp(cmd->m_command_name, "BLOR") && cmd->m_flags.skip) { + cmd->m_flags.skip = false; + return true; + } + } + + return false; +} + /////////////////////////////////// Generic Single Float ///////////////////////////////////////////////// unsigned long sns_opentherm_get_generic_float(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *) { @@ -488,7 +524,6 @@ void sns_opentherm_parse_boiler_temperature(struct OpenThermCommandT *self, stru //////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////// -#define SNS_OT_COMMANDS_COUNT (sizeof(sns_opentherm_commands) / sizeof(OpenThermCommand)) int sns_opentherm_current_command = SNS_OT_COMMANDS_COUNT; unsigned long sns_opentherm_get_next_request(struct OT_BOILER_STATUS_T *boilerStatus) @@ -552,7 +587,7 @@ void sns_opentherm_dump_telemetry() for (int i = 0; i < SNS_OT_COMMANDS_COUNT; ++i) { struct OpenThermCommandT *cmd = &sns_opentherm_commands[i]; - if (!cmd->m_flags.supported) + if (!cmd->m_flags.supported || cmd->m_flags.skip) { continue; } @@ -568,7 +603,9 @@ void sns_opentherm_protocol_reset() for (int i = 0; i < SNS_OT_COMMANDS_COUNT; ++i) { struct OpenThermCommandT *cmd = &sns_opentherm_commands[i]; + int skip = cmd->m_flags.skip; cmd->m_flags.m_flags = 0; + cmd->m_flags.skip = skip; memset(cmd->m_results, 0, sizeof(OpenThermCommandT::m_results)); } } diff --git a/tasmota/xsns_90_hrg15.ino b/tasmota/xsns_90_hrg15.ino index f7ba63721..0743d8902 100644 --- a/tasmota/xsns_90_hrg15.ino +++ b/tasmota/xsns_90_hrg15.ino @@ -21,6 +21,12 @@ /*********************************************************************************************\ * Hydreon RG-15 * See https://rainsensors.com/products/rg-15/ + * https://rainsensors.com/rg-9-15-protocol/ + * + * Rule for Domoticz Rain sensor index 418: + * on tele-rg-15#flowrate do var1 %value% endon + * on tele-rg-15#event do backlog var2 %value%; mult1 100; event sendrain endon + * on event#sendrain do dzsend1 418,%var1%;%var2% endon \*********************************************************************************************/ #define XSNS_90 90 @@ -29,6 +35,7 @@ #define RG15_BAUDRATE 9600 #define RG15_READ_TIMEOUT 500 #define RG15_EVENT_TIMEOUT 60 +#define RG15_BUFFER_SIZE 150 #include @@ -41,192 +48,202 @@ const char HTTP_RG15[] PROGMEM = "{s}" RG15_NAME " " D_JSON_FLOWRATE "{m}%2_f " D_UNIT_MILLIMETER "/" D_UNIT_HOUR "{e}"; #endif // USE_WEBSERVER -TasmotaSerial *HydreonSerial; +TasmotaSerial *HydreonSerial = nullptr; struct RG15 { + float acc; + float event; + float total; + float rate; uint16_t time = RG15_EVENT_TIMEOUT; - uint8_t ready = 1; - uint8_t received = 0; - float acc = 0.0f; - float event = 0.0f; - float total = 0.0f; - float rate = 0.0f; + uint8_t init_step; } Rg15; -void Rg15Init(void) -{ - Rg15.ready = 0; - if (PinUsed(GPIO_HRG15_RX) && PinUsed(GPIO_HRG15_TX)) { - HydreonSerial = new TasmotaSerial(Pin(GPIO_HRG15_RX), Pin(GPIO_HRG15_TX)); - if (HydreonSerial->begin(RG15_BAUDRATE)) { - if (HydreonSerial->hardwareSerial()) { ClaimSerial(); } +/*********************************************************************************************/ - HydreonSerial->println('R'); - - Rg15.ready = 1; - } - } -} - -bool Rg15Poll(void) { - - // Trigger the first update - if (! Rg15.received) { - HydreonSerial->println('R'); - } - - if (! HydreonSerial->available()) { - - // Check if the rain event has timed out, reset rate to 0 - if (++Rg15.time == RG15_EVENT_TIMEOUT) { - Rg15.acc = 0; - Rg15.rate = 0; - MqttPublishSensor(); - } - - return false; - } - - // Now read what's available - char rg15_buffer[255]; - - while (HydreonSerial->available()) { - Rg15ReadLine(rg15_buffer); - AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("%s:" D_JSON_SERIALRECEIVED " = %s"),"HRG", rg15_buffer); - - Rg15Process(rg15_buffer); - } - - MqttPublishSensor(); - - return true; -} - -bool Rg15ReadLine(char* buffer) -{ - char c; - uint8_t i = 0; +bool Rg15ReadLine(char* buffer) { + // All lines are terminated with a carriage return (\r or 13) followed by a new line (\n or 10) + uint32_t i = 0; uint32_t cmillis = millis(); + while (HydreonSerial->available() ) { + char c = HydreonSerial->read(); + if (c == 10) { break; } // New line ends the message - while (1) { - if (HydreonSerial->available()) { - c = HydreonSerial->read(); - buffer[i++] = c; + if ((c >= 32) && (c < 127)) { // Accept only valid characters + buffer[i++] = c; + if (i == RG15_BUFFER_SIZE -1) { break; } // Overflow + } - if (c == 10) { break; } // New line ends the message - if (i == 254) { break; } // Overflow - } - - if ((millis() - cmillis) > RG15_READ_TIMEOUT) { - return false; - } + if ((millis() - cmillis) > RG15_READ_TIMEOUT) { + AddLog(LOG_LEVEL_DEBUG, PSTR("HRG: Timeout")); + return false; + } } + buffer[i] = '\0'; + + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("HRG: Read '%s'"), buffer); - buffer[i-2] = '\0'; return true; } -void Rg15Process(char* buffer) { - - // Process payload, example: Acc 0.01 mm, EventAcc 2.07 mm, TotalAcc 54.85 mm, RInt 2.89 mmph - Rg15.received = 1; - Rg15.acc = Rg15Parse(buffer, "Acc"); - Rg15.event = Rg15Parse(buffer, "EventAcc"); - Rg15.total = Rg15Parse(buffer, "TotalAcc"); - Rg15.rate = Rg15Parse(buffer, "RInt"); - - if (Rg15.acc > 0.0f) { - Rg15.time = 0; // We have some data, so the rain event is on-going - } -} - -float Rg15Parse(char* buffer, const char* item) { - char* start = strstr(buffer, item); - if (start != nullptr) { - char* end = strstr(start, " mm"); +bool Rg15Parse(char* buffer, const char* item, float* result) { + char* start = strstr(buffer, item); + if (start != nullptr) { + char* end = strstr(start, " mm"); // Metric (mm or mmph) + if (end == nullptr) { + end = strstr(start, " i"); // Imperial (in or iph) + } + if (end != nullptr) { char tmp = end[0]; end[0] = '\0'; - float result = CharToFloat (start + strlen(item)); + *result = CharToFloat(start + strlen(item)); end[0] = tmp; - return result; - } else { - return 0.0f; + return true; } + } + return false; } +bool Rg15Process(char* buffer) { + // Process payloads like: + // Acc 0.01 mm, EventAcc 2.07 mm, TotalAcc 54.85 mm, RInt 2.89 mmph + // Acc 0.001 in, EventAcc 0.002 in, TotalAcc 0.003 in, RInt 0.004 iph + // Acc 0.001 mm, EventAcc 0.002 mm, TotalAcc 0.003 mm, RInt 0.004 mmph, XTBTips 0, XTBAcc 0.01 mm, XTBEventAcc 0.02 mm, XTBTotalAcc 0.03 mm + if (buffer[0] == 'A' && buffer[1] == 'c' && buffer[2] == 'c') { + Rg15Parse(buffer, "Acc", &Rg15.acc); + Rg15Parse(buffer, "EventAcc", &Rg15.event); + Rg15Parse(buffer, "TotalAcc", &Rg15.total); + Rg15Parse(buffer, "RInt", &Rg15.rate); + + if (Rg15.acc > 0.0f) { + Rg15.time = RG15_EVENT_TIMEOUT; // We have some data, so the rain event is on-going + } + return true; + } + return false; +} + +/*********************************************************************************************/ + +void Rg15Init(void) { + if (PinUsed(GPIO_HRG15_RX) && PinUsed(GPIO_HRG15_TX)) { + // Max size message: + // Acc 0.001 mm, EventAcc 0.002 mm, TotalAcc 0.003 mm, RInt 0.004 mmph, XTBTips 0, XTBAcc 0.01 mm, XTBEventAcc 0.02 mm, XTBTotalAcc 0.03 mm + HydreonSerial = new TasmotaSerial(Pin(GPIO_HRG15_RX), Pin(GPIO_HRG15_TX), 2, 0, RG15_BUFFER_SIZE); + if (HydreonSerial) { + if (HydreonSerial->begin(RG15_BAUDRATE)) { + if (HydreonSerial->hardwareSerial()) { ClaimSerial(); } + Rg15.init_step = 5; // Perform RG-15 init + } + } + } +} + +void Rg15Poll(void) { + bool publish = false; + + if (!HydreonSerial->available()) { + if (Rg15.time) { // Check if the rain event has timed out, reset rate to 0 + Rg15.time--; + if (!Rg15.time) { + Rg15.acc = 0; + Rg15.rate = 0; + publish = true; + } + } + } else { + char rg15_buffer[RG15_BUFFER_SIZE]; // Read what's available + while (HydreonSerial->available()) { + Rg15ReadLine(rg15_buffer); + if (Rg15Process(rg15_buffer)) { // Do NOT use "publish = Rg15Process(rg15_buffer)" + publish = true; + } + } + } + + if (publish && !TasmotaGlobal.global_state.mqtt_down) { + MqttPublishSensor(); + } + +// Units: I = Imperial (in) or M = Metric (mm) +// Resolution: H = High (0.001) or L = Low (0.01) +// Mode: P = Request mode (Polling) or C = Continuous mode - report any change +// Request: R = Read available data once + char init_commands[] = "R CLM "; // Indexed by Rg15.init_step + + if (Rg15.init_step) { + Rg15.init_step--; + + char cmnd = init_commands[Rg15.init_step]; + if (cmnd != ' ') { + HydreonSerial->println(cmnd); + } + } +} + +void Rg15Show(bool json) { + if (json) { + ResponseAppend_P(PSTR(",\"" RG15_NAME "\":{\"" D_JSON_ACTIVE "\":%2_f,\"" D_JSON_EVENT "\":%2_f,\"" D_JSON_TOTAL "\":%2_f,\"" D_JSON_FLOWRATE "\":%2_f}"), + &Rg15.acc, &Rg15.event, &Rg15.total, &Rg15.rate); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_RG15, &Rg15.acc, &Rg15.event, &Rg15.total, &Rg15.rate); +#endif // USE_WEBSERVER + } +} + +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ + bool Rg15Command(void) { bool serviced = true; if (XdrvMailbox.data_len == 1) { - char *send = XdrvMailbox.data; + char send = XdrvMailbox.data[0] & 0xDF; // Make uppercase + HydreonSerial->flush(); // Flush receive buffer HydreonSerial->println(send); - HydreonSerial->flush(); - if (send[0] == 'k' || send[0] == 'K' || send[0] == 'o' || send[0] == 'O') { - ResponseCmndDone(); - return serviced; + if ('K' == send) { // Restart RG-15 reading DIP switches + Rg15.init_step = 5; // Perform RG-15 init } - char rg15_buffer[255]; - if (Rg15ReadLine(rg15_buffer)) { - Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":%s\"}"), rg15_buffer); - Rg15Process(rg15_buffer); - } + ResponseCmndDone(); } return serviced; } -void Rg15Show(bool json) -{ - if (!Rg15.received) { - return; - } - - if (json) { - ResponseAppend_P(PSTR(",\"" RG15_NAME "\":{\"" D_JSON_ACTIVE "\":%2_f, \"" D_JSON_EVENT "\":%2_f, \"" D_JSON_TOTAL "\":%2_f, \"" D_JSON_FLOWRATE "\":%2_f}"), &Rg15.acc, &Rg15.event, &Rg15.total, &Rg15.rate); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_RG15, &Rg15.acc, &Rg15.event, &Rg15.total, &Rg15.rate); -#endif // USE_WEBSERVER - } -} - /*********************************************************************************************\ * Interface \*********************************************************************************************/ -bool Xsns90(uint8_t function) -{ - +bool Xsns90(uint8_t function) { bool result = false; - if (Rg15.ready) - { - switch (function) - { - case FUNC_INIT: - Rg15Init(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_90 == XdrvMailbox.index) { - Rg15Command(); - } - break; - case FUNC_EVERY_SECOND: - Rg15Poll(); - break; - case FUNC_JSON_APPEND: - Rg15Show(1); - break; + if (FUNC_INIT == function) { + Rg15Init(); + } + else if (HydreonSerial) { + switch (function) { + case FUNC_EVERY_SECOND: + Rg15Poll(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_90 == XdrvMailbox.index) { + result = Rg15Command(); + } + break; + case FUNC_JSON_APPEND: + Rg15Show(1); + break; #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Rg15Show(0); - break; + case FUNC_WEB_SENSOR: + Rg15Show(0); + break; #endif // USE_WEBSERVER } } - return result; } diff --git a/tools/Esptool/ESP32/boot_app0.bin b/tools/Esptool/ESP32/boot_app0.bin deleted file mode 100644 index 13562cabb..000000000 Binary files a/tools/Esptool/ESP32/boot_app0.bin and /dev/null differ diff --git a/tools/Esptool/ESP32/bootloader_dout_40m.bin b/tools/Esptool/ESP32/bootloader_dout_40m.bin deleted file mode 100644 index eab1e96d1..000000000 Binary files a/tools/Esptool/ESP32/bootloader_dout_40m.bin and /dev/null differ diff --git a/tools/Esptool/ESP32/partitions.bin b/tools/Esptool/ESP32/partitions.bin deleted file mode 100644 index f1e66d048..000000000 Binary files a/tools/Esptool/ESP32/partitions.bin and /dev/null differ diff --git a/tools/Esptool/ESP32/readme.txt b/tools/Esptool/ESP32/readme.txt deleted file mode 100644 index bdedc87de..000000000 --- a/tools/Esptool/ESP32/readme.txt +++ /dev/null @@ -1,5 +0,0 @@ -These files are needed for flashing Tasmota32 with esptool.py to an ESP32. - -Command syntax for flashing Tasmota32 firmware on ESP32 via Esptool (replace COM Port Number!): - -esptool.py --chip esp32 --port COM5 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dout --flash_freq 40m --flash_size detect 0x1000 bootloader_dout_40m.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 tasmota32.bin diff --git a/tools/Esptool/EraseFlash.bat b/tools/Esptool/EraseFlash.bat deleted file mode 100644 index 96bab0259..000000000 --- a/tools/Esptool/EraseFlash.bat +++ /dev/null @@ -1 +0,0 @@ -esptool.py --baud 115200 erase_flash diff --git a/tools/Esptool/Odroid_go_and_core2/Core2_flash_10M.bat b/tools/Esptool/Odroid_go_and_core2/Core2_flash_10M.bat deleted file mode 100644 index 7f978acb2..000000000 --- a/tools/Esptool/Odroid_go_and_core2/Core2_flash_10M.bat +++ /dev/null @@ -1 +0,0 @@ -esptool.py --chip esp32 --baud 2000000 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0x1000 bootloader_qio_80m.bin 0x8000 partitions_spiffs_10M.bin 0xe000 boot_app0.bin 0x10000 tasmota32-core2.bin diff --git a/tools/Esptool/Odroid_go_and_core2/Odroid_flash_10M.bat b/tools/Esptool/Odroid_go_and_core2/Odroid_flash_10M.bat deleted file mode 100644 index fde9850e0..000000000 --- a/tools/Esptool/Odroid_go_and_core2/Odroid_flash_10M.bat +++ /dev/null @@ -1 +0,0 @@ -esptool.py --chip esp32 --baud 2000000 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0x1000 bootloader_qio_80m.bin 0x8000 partitions_spiffs_10M.bin 0xe000 boot_app0.bin 0x10000 tasmota32-odroid.bin diff --git a/tools/Esptool/Odroid_go_and_core2/boot_app0.bin b/tools/Esptool/Odroid_go_and_core2/boot_app0.bin deleted file mode 100644 index 13562cabb..000000000 Binary files a/tools/Esptool/Odroid_go_and_core2/boot_app0.bin and /dev/null differ diff --git a/tools/Esptool/Odroid_go_and_core2/bootloader_qio_80m.bin b/tools/Esptool/Odroid_go_and_core2/bootloader_qio_80m.bin deleted file mode 100644 index d0a5182b9..000000000 Binary files a/tools/Esptool/Odroid_go_and_core2/bootloader_qio_80m.bin and /dev/null differ diff --git a/tools/Esptool/Odroid_go_and_core2/partitions_spiffs_10M.bin b/tools/Esptool/Odroid_go_and_core2/partitions_spiffs_10M.bin deleted file mode 100644 index 08781f13a..000000000 Binary files a/tools/Esptool/Odroid_go_and_core2/partitions_spiffs_10M.bin and /dev/null differ diff --git a/tools/Esptool/ReadFlash.bat b/tools/Esptool/ReadFlash.bat deleted file mode 100644 index be3bfe24b..000000000 --- a/tools/Esptool/ReadFlash.bat +++ /dev/null @@ -1 +0,0 @@ -esptool.py --baud 115200 read_flash 0x000000 0x100000 backup.bin diff --git a/tools/Esptool/VerifyFlash.bat b/tools/Esptool/VerifyFlash.bat deleted file mode 100644 index d5865d3a6..000000000 --- a/tools/Esptool/VerifyFlash.bat +++ /dev/null @@ -1 +0,0 @@ -esptool.py --baud 115200 verify_flash -fs 1MB -fm dout 0x000000 firmware.bin diff --git a/tools/Esptool/WriteFlash.bat b/tools/Esptool/WriteFlash.bat deleted file mode 100644 index 8adc4192e..000000000 --- a/tools/Esptool/WriteFlash.bat +++ /dev/null @@ -1 +0,0 @@ -esptool.py --baud 115200 write_flash -fs 1MB -fm dout 0x000000 firmware.bin diff --git a/tools/decode-status.py b/tools/decode-status.py index c234f8911..6eae490bb 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -205,8 +205,8 @@ a_features = [[ ],[ "USE_CONFIG_OVERRIDE","FIRMWARE_MINIMAL","FIRMWARE_SENSORS","FIRMWARE_CLASSIC", "FIRMWARE_KNX_NO_EMULATION","USE_DISPLAY_MODES1TO5","USE_DISPLAY_GRAPH","USE_DISPLAY_LCD", - "USE_DISPLAY_SSD1306","USE_DISPLAY_MATRIX","USE_DISPLAY_ILI9341","USE_DISPLAY_EPAPER", - "USE_DISPLAY_SH1106","USE_MP3_PLAYER","USE_PCA9685","USE_TUYA_DIMMER", + "USE_DISPLAY_SSD1306","USE_DISPLAY_MATRIX","USE_DISPLAY_ILI9341","USE_DISPLAY_EPAPER_29", + "USE_DISPLAY_SH1106","USE_MP3_PLAYER","USE_PCA9685","USE_TUYA_MCU", "USE_RC_SWITCH","USE_ARMTRONIX_DIMMERS","USE_SM16716","USE_SCRIPT", "USE_EMULATION_WEMO","USE_SONOFF_IFAN","USE_ZIGBEE","NO_EXTRA_4K_HEAP", "VTABLES_IN_IRAM","VTABLES_IN_DRAM","VTABLES_IN_FLASH","PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH", @@ -214,7 +214,7 @@ a_features = [[ ],[ "USE_COUNTER","USE_ADC_VCC","USE_ENERGY_SENSOR","USE_PZEM004T", "USE_DS18B20","USE_DS18x20_LEGACY","USE_DS18x20","USE_DHT", - "USE_SHT","USE_HTU","USE_BMP","USE_BME680", + "USE_SHT","USE_HTU","USE_BMP","USE_BME68X", "USE_BH1750","USE_VEML6070","USE_ADS1115_I2CDEV","USE_ADS1115", "USE_INA219","USE_SHT3X","USE_MHZ19","USE_TSL2561", "USE_SENSEAIR","USE_PMS5003","USE_MGS","USE_NOVA_SDS", @@ -226,7 +226,7 @@ a_features = [[ "USE_MCP39F501","USE_PZEM_AC","USE_DS3231","USE_HX711", "USE_PZEM_DC","USE_TX20_WIND_SENSOR","USE_MGC3130","USE_RF_SENSOR", "USE_THEO_V2","USE_ALECTO_V2","USE_AZ7798","USE_MAX31855", - "USE_PN532_I2C","USE_MAX44009","USE_SCD30","USE_HRE", + "USE_PN532_HSU","USE_MAX44009","USE_SCD30","USE_HRE", "USE_ADE7953","USE_SPS30","USE_VL53L0X","USE_MLX90614", "USE_MAX31865","USE_CHIRP","USE_SOLAX_X1","USE_PAJ7620" ],[ @@ -234,7 +234,7 @@ a_features = [[ "USE_INA226","USE_A4988_STEPPER","USE_DDS2382","USE_SM2135", "USE_SHUTTER","USE_PCF8574","USE_DDSU666","USE_DEEPSLEEP", "USE_SONOFF_SC","USE_SONOFF_RF","USE_SONOFF_L1","USE_EXS_DIMMER", - "USE_TASMOTA_SLAVE","USE_HIH6","USE_HPMA","USE_TSL2591", + "USE_TASMOTA_CLIENT","USE_HIH6","USE_HPMA","USE_TSL2591", "USE_DHT12","USE_DS1624","USE_GPS","USE_HOTPLUG", "USE_NRF24","USE_MIBLE","USE_HM10","USE_LE01MR", "USE_AHT1x","USE_WEMOS_MOTOR_V1","USE_DEVICE_GROUPS","USE_PWM_DIMMER" @@ -262,7 +262,7 @@ a_features = [[ "USE_MCP2515","USE_TASMESH","USE_WIFI_RANGE_EXTENDER","USE_INFLUXDB", "USE_HRG15","USE_VINDRIKTNING","USE_SCD40","USE_HM330X", "USE_HDC2010","USE_LSC_MCSL","USE_SONOFF_SPM","USE_SHIFT595", - "","","","", + "USE_SDM230","","","", "","","","", "","","","" ]] @@ -292,7 +292,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v20211205 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v20220115 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj)) diff --git a/tools/logo/favicon.ico b/tools/logo/favicon.ico new file mode 100644 index 000000000..82fb66dea Binary files /dev/null and b/tools/logo/favicon.ico differ diff --git a/tools/lv_berry/lv_symbol.h b/tools/lv_berry/lv_symbol.h deleted file mode 100644 index 8006c215c..000000000 --- a/tools/lv_berry/lv_symbol.h +++ /dev/null @@ -1,62 +0,0 @@ - -SYMBOL_AUDIO="\xef\x80\x81" -SYMBOL_VIDEO="\xef\x80\x88" -SYMBOL_LIST="\xef\x80\x8b" -SYMBOL_OK="\xef\x80\x8c" -SYMBOL_CLOSE="\xef\x80\x8d" -SYMBOL_POWER="\xef\x80\x91" -SYMBOL_SETTINGS="\xef\x80\x93" -SYMBOL_HOME="\xef\x80\x95" -SYMBOL_DOWNLOAD="\xef\x80\x99" -SYMBOL_DRIVE="\xef\x80\x9c" -SYMBOL_REFRESH="\xef\x80\xa1" -SYMBOL_MUTE="\xef\x80\xa6" -SYMBOL_VOLUME_MID="\xef\x80\xa7" -SYMBOL_VOLUME_MAX="\xef\x80\xa8" -SYMBOL_IMAGE="\xef\x80\xbe" -SYMBOL_EDIT="\xef\x8C\x84" -SYMBOL_PREV="\xef\x81\x88" -SYMBOL_PLAY="\xef\x81\x8b" -SYMBOL_PAUSE="\xef\x81\x8c" -SYMBOL_STOP="\xef\x81\x8d" -SYMBOL_NEXT="\xef\x81\x91" -SYMBOL_EJECT="\xef\x81\x92" -SYMBOL_LEFT="\xef\x81\x93" -SYMBOL_RIGHT="\xef\x81\x94" -SYMBOL_PLUS="\xef\x81\xa7" -SYMBOL_MINUS="\xef\x81\xa8" -SYMBOL_EYE_OPEN="\xef\x81\xae" -SYMBOL_EYE_CLOSE="\xef\x81\xb0" -SYMBOL_WARNING="\xef\x81\xb1" -SYMBOL_SHUFFLE="\xef\x81\xb4" -SYMBOL_UP="\xef\x81\xb7" -SYMBOL_DOWN="\xef\x81\xb8" -SYMBOL_LOOP="\xef\x81\xb9" -SYMBOL_DIRECTORY="\xef\x81\xbb" -SYMBOL_UPLOAD="\xef\x82\x93" -SYMBOL_CALL="\xef\x82\x95" -SYMBOL_CUT="\xef\x83\x84" -SYMBOL_COPY="\xef\x83\x85" -SYMBOL_SAVE="\xef\x83\x87" -SYMBOL_CHARGE="\xef\x83\xa7" -SYMBOL_PASTE="\xef\x83\xAA" -SYMBOL_BELL="\xef\x83\xb3" -SYMBOL_KEYBOARD="\xef\x84\x9c" -SYMBOL_GPS="\xef\x84\xa4" -SYMBOL_FILE="\xef\x85\x9b" -SYMBOL_WIFI="\xef\x87\xab" -SYMBOL_BATTERY_FULL="\xef\x89\x80" -SYMBOL_BATTERY_3="\xef\x89\x81" -SYMBOL_BATTERY_2="\xef\x89\x82" -SYMBOL_BATTERY_1="\xef\x89\x83" -SYMBOL_BATTERY_EMPTY="\xef\x89\x84" -SYMBOL_USB="\xef\x8a\x87" -SYMBOL_BLUETOOTH="\xef\x8a\x93" -SYMBOL_TRASH="\xef\x8B\xAD" -SYMBOL_BACKSPACE="\xef\x95\x9A" -SYMBOL_SD_CARD="\xef\x9F\x82" -SYMBOL_NEW_LINE="\xef\xA2\xA2" - -SYMBOL_DUMMY="\xEF\xA3\xBF" - -SYMBOL_BULLET="\xE2\x80\xA2" \ No newline at end of file diff --git a/tools/lv_berry/lv_symbols.h b/tools/lv_berry/lv_symbols.h deleted file mode 100644 index cce4f230a..000000000 --- a/tools/lv_berry/lv_symbols.h +++ /dev/null @@ -1,61 +0,0 @@ -SYMBOL_AUDIO "\\xef\\x80\\x81" -SYMBOL_VIDEO "\\xef\\x80\\x88" -SYMBOL_LIST "\\xef\\x80\\x8b" -SYMBOL_OK "\\xef\\x80\\x8c" -SYMBOL_CLOSE "\\xef\\x80\\x8d" -SYMBOL_POWER "\\xef\\x80\\x91" -SYMBOL_SETTINGS "\\xef\\x80\\x93" -SYMBOL_HOME "\\xef\\x80\\x95" -SYMBOL_DOWNLOAD "\\xef\\x80\\x99" -SYMBOL_DRIVE "\\xef\\x80\\x9c" -SYMBOL_REFRESH "\\xef\\x80\\xa1" -SYMBOL_MUTE "\\xef\\x80\\xa6" -SYMBOL_VOLUME_MID "\\xef\\x80\\xa7" -SYMBOL_VOLUME_MAX "\\xef\\x80\\xa8" -SYMBOL_IMAGE "\\xef\\x80\\xbe" -SYMBOL_EDIT "\\xef\\x8C\\x84" -SYMBOL_PREV "\\xef\\x81\\x88" -SYMBOL_PLAY "\\xef\\x81\\x8b" -SYMBOL_PAUSE "\\xef\\x81\\x8c" -SYMBOL_STOP "\\xef\\x81\\x8d" -SYMBOL_NEXT "\\xef\\x81\\x91" -SYMBOL_EJECT "\\xef\\x81\\x92" -SYMBOL_LEFT "\\xef\\x81\\x93" -SYMBOL_RIGHT "\\xef\\x81\\x94" -SYMBOL_PLUS "\\xef\\x81\\xa7" -SYMBOL_MINUS "\\xef\\x81\\xa8" -SYMBOL_EYE_OPEN "\\xef\\x81\\xae" -SYMBOL_EYE_CLOSE "\\xef\\x81\\xb0" -SYMBOL_WARNING "\\xef\\x81\\xb1" -SYMBOL_SHUFFLE "\\xef\\x81\\xb4" -SYMBOL_UP "\\xef\\x81\\xb7" -SYMBOL_DOWN "\\xef\\x81\\xb8" -SYMBOL_LOOP "\\xef\\x81\\xb9" -SYMBOL_DIRECTORY "\\xef\\x81\\xbb" -SYMBOL_UPLOAD "\\xef\\x82\\x93" -SYMBOL_CALL "\\xef\\x82\\x95" -SYMBOL_CUT "\\xef\\x83\\x84" -SYMBOL_COPY "\\xef\\x83\\x85" -SYMBOL_SAVE "\\xef\\x83\\x87" -SYMBOL_CHARGE "\\xef\\x83\\xa7" -SYMBOL_PASTE "\\xef\\x83\\xAA" -SYMBOL_BELL "\\xef\\x83\\xb3" -SYMBOL_KEYBOARD "\\xef\\x84\\x9c" -SYMBOL_GPS "\\xef\\x84\\xa4" -SYMBOL_FILE "\\xef\\x85\\x9b" -SYMBOL_WIFI "\\xef\\x87\\xab" -SYMBOL_BATTERY_FULL "\\xef\\x89\\x80" -SYMBOL_BATTERY_3 "\\xef\\x89\\x81" -SYMBOL_BATTERY_2 "\\xef\\x89\\x82" -SYMBOL_BATTERY_1 "\\xef\\x89\\x83" -SYMBOL_BATTERY_EMPTY "\\xef\\x89\\x84" -SYMBOL_USB "\\xef\\x8a\\x87" -SYMBOL_BLUETOOTH "\\xef\\x8a\\x93" -SYMBOL_TRASH "\\xef\\x8B\\xAD" -SYMBOL_BACKSPACE "\\xef\\x95\\x9A" -SYMBOL_SD_CARD "\\xef\\x9F\\x82" -SYMBOL_NEW_LINE "\\xef\\xA2\\xA2" - -SYMBOL_DUMMY "\\xEF\\xA3\\xBF" - -SYMBOL_BULLET "\\xE2\\x80\\xA2" diff --git a/tools/lv_gpio/gpio_convert.py b/tools/lv_gpio/gpio_convert.py index dfa3d78f0..6232fd287 100644 --- a/tools/lv_gpio/gpio_convert.py +++ b/tools/lv_gpio/gpio_convert.py @@ -56,7 +56,7 @@ print(" * Generated code, don't edit") print(" *******************************************************************/") print(""" -const be_constint_t lv_gpio_constants[] = { +const be_const_member_t lv_gpio_constants[] = { """) lv_module2 = {} diff --git a/tools/unishox/compress-html-uncompressed.py b/tools/unishox/compress-html-uncompressed.py index f5e8619bb..5a58528fe 100644 --- a/tools/unishox/compress-html-uncompressed.py +++ b/tools/unishox/compress-html-uncompressed.py @@ -4,11 +4,11 @@ # Instructions: # open a console, e.g. in vscode, open a 'terminal' # cd .\tools\unishox -# run: +# run: # python compress-html-uncompressed.py # # The intent it to commit both uncompressed and compressed to the repo -# else this script would need to be run at build. +# else this script would need to be run at build. # # Example Tasmota code: # #ifdef USE_UNISHOX_COMPRESSION @@ -24,6 +24,30 @@ from os import listdir from os import path from datetime import datetime +def extract_c_string(s: str) -> str: + state = 0 + escape = False + out = "" + for c in s: + if state == 0: # before string + if c == '"': # entering string + out = '"' + state = 1 + elif c == '/': # start of comment before entering string + state = 99 # we're done + elif state == 1: # in string + if escape: # escaped char + out += '\\' + c + escape = False + elif c == '\\': # escaped char + escape = True + elif c == '"': # end of string + out += '"' + state = 99 # we're done + else: + out += c + return out + path_compressed = path.join('..','..','tasmota','html_compressed') path_uncompressed = path.join('..','..','tasmota','html_uncompressed') @@ -56,10 +80,9 @@ for file in files: const_name = el[:-2] #extract the "const char" variable name line_list.pop(line_number) else: # remove line comments - line_el = line.rsplit("//") - # print('Splitted line list by //' % line_el) - # print(line_el[0]) - text = text + line_el[0] + line_el = extract_c_string(line) + # print(line_el) + text = text + line_el line_number = line_number +1 # print const_name @@ -86,9 +109,9 @@ for file in files: # print(text[lastel+1:pos:]) lastel = pos - print("####### Parsing input from " + path_uncompressed + path.sep + file) + print("####### Parsing input from " + path_uncompressed + path.sep + file) print(" Const char name: "+const_name) - #print('####### Cleaned input:') + #print('####### Cleaned input:') #print(input) #construct output (taken from shadinger) @@ -121,7 +144,7 @@ for file in files: print(" the optimal case would be raw bytes + 8, real difference: "+str(in_real - out_real)+ "bytes") # https://www.geeksforgeeks.org/break-list-chunks-size-n-python/ def chunked(my_list, n): - return [my_list[i * n:(i + 1) * n] for i in range((len(my_list) + n - 1) // n )] + return [my_list[i * n:(i + 1) * n] for i in range((len(my_list) + n - 1) // n )] # split in chunks of 20 characters chunks = chunked(out_bytes, 20) @@ -130,7 +153,7 @@ for file in files: line_complete = "const char " + const_name + "_COMPRESSED" +"[] PROGMEM = " + ("\n" + " "*29).join(lines_raw) + ";" lines = "\nconst size_t " + const_name +"_SIZE = {size};\n{lines}\n\n".format(size=in_len, lines=line_complete) - #print('####### Final output:') + #print('####### Final output:') #print(lines) definition = "#define " + const_name + " Decompress(" + const_name + "_COMPRESSED" + "," + const_name +"_SIZE" + ").c_str()" @@ -148,6 +171,6 @@ for file in files: f = open(path_compressed + path.sep + file, "w") f.write(comment + lines + definition) f.close() - print("####### Wrote output to " + path_compressed + path.sep + file) + print("####### Wrote output to " + path_compressed + path.sep + file) print("If all files are in use, total saving was "+str(totalSaved)+" out of "+str(totalIn))