diff --git a/.github/workflows/check-arduino.yml b/.github/workflows/check-arduino.yml index 0d969f6..adb330f 100644 --- a/.github/workflows/check-arduino.yml +++ b/.github/workflows/check-arduino.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Arduino Lint uses: arduino/arduino-lint-action@v1 diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 93383bb..38999da 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -34,7 +34,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Compile example sketches uses: arduino/compile-sketches@v1 @@ -53,7 +53,7 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} - name: Save memory usage change report as artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: if-no-files-found: error path: ${{ env.SKETCHES_REPORTS_PATH }} diff --git a/.github/workflows/spell-check.yml b/.github/workflows/spell-check.yml index 01bee87..ef7d894 100644 --- a/.github/workflows/spell-check.yml +++ b/.github/workflows/spell-check.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Spell check uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml new file mode 100644 index 0000000..9cde1ac --- /dev/null +++ b/.github/workflows/sync-labels.yml @@ -0,0 +1,138 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/sync-labels.md +name: Sync Labels + +# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows +on: + push: + paths: + - ".github/workflows/sync-labels.ya?ml" + - ".github/label-configuration-files/*.ya?ml" + pull_request: + paths: + - ".github/workflows/sync-labels.ya?ml" + - ".github/label-configuration-files/*.ya?ml" + schedule: + # Run daily at 8 AM UTC to sync with changes to shared label configurations. + - cron: "0 8 * * *" + workflow_dispatch: + repository_dispatch: + +env: + CONFIGURATIONS_FOLDER: .github/label-configuration-files + CONFIGURATIONS_ARTIFACT: label-configuration-files + +jobs: + check: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Download JSON schema for labels configuration file + id: download-schema + uses: carlosperate/download-file-action@v2 + with: + file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json + location: ${{ runner.temp }}/label-configuration-schema + + - name: Install JSON schema validator + run: | + sudo npm install \ + --global \ + ajv-cli \ + ajv-formats + + - name: Validate local labels configuration + run: | + # See: https://github.com/ajv-validator/ajv-cli#readme + ajv validate \ + --all-errors \ + -c ajv-formats \ + -s "${{ steps.download-schema.outputs.file-path }}" \ + -d "${{ env.CONFIGURATIONS_FOLDER }}/*.{yml,yaml}" + + download: + needs: check + runs-on: ubuntu-latest + + strategy: + matrix: + filename: + # Filenames of the shared configurations to apply to the repository in addition to the local configuration. + # https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/sync-labels + - universal.yml + + steps: + - name: Download + uses: carlosperate/download-file-action@v2 + with: + file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }} + + - name: Pass configuration files to next job via workflow artifact + uses: actions/upload-artifact@v3 + with: + path: | + *.yaml + *.yml + if-no-files-found: error + name: ${{ env.CONFIGURATIONS_ARTIFACT }} + + sync: + needs: download + runs-on: ubuntu-latest + + steps: + - name: Set environment variables + run: | + # See: https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable + echo "MERGED_CONFIGURATION_PATH=${{ runner.temp }}/labels.yml" >> "$GITHUB_ENV" + + - name: Determine whether to dry run + id: dry-run + if: > + github.event_name == 'pull_request' || + ( + ( + github.event_name == 'push' || + github.event_name == 'workflow_dispatch' + ) && + github.ref != format('refs/heads/{0}', github.event.repository.default_branch) + ) + run: | + # Use of this flag in the github-label-sync command will cause it to only check the validity of the + # configuration. + echo "::set-output name=flag::--dry-run" + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Download configuration files artifact + uses: actions/download-artifact@v3 + with: + name: ${{ env.CONFIGURATIONS_ARTIFACT }} + path: ${{ env.CONFIGURATIONS_FOLDER }} + + - name: Remove unneeded artifact + uses: geekyeggo/delete-artifact@v2 + with: + name: ${{ env.CONFIGURATIONS_ARTIFACT }} + + - name: Merge label configuration files + run: | + # Merge all configuration files + shopt -s extglob + cat "${{ env.CONFIGURATIONS_FOLDER }}"/*.@(yml|yaml) > "${{ env.MERGED_CONFIGURATION_PATH }}" + + - name: Install github-label-sync + run: sudo npm install --global github-label-sync + + - name: Sync labels + env: + GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # See: https://github.com/Financial-Times/github-label-sync + github-label-sync \ + --labels "${{ env.MERGED_CONFIGURATION_PATH }}" \ + ${{ steps.dry-run.outputs.flag }} \ + ${{ github.repository }} diff --git a/README.md b/README.md index 1cf6533..1672e27 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,11 @@ -# Portenta Machine Control Library for Arduino +# [Deprecated] Portenta Machine Control Library for Arduino + +> [!WARNING] +> This library is deprecated and no longer actively maintained. +> +> We recommend transitioning to the [Arduino_PortentaMachineControl](https://github.com/arduino-libraries/Arduino_PortentaMachineControl) library for ongoing support, new features and contributions. If you need assistance with migration, refer to the [migration guide](https://docs.arduino.cc/tutorials/portenta-machine-control/pmc-arduino-library). +> +> Please note that the [examples](./examples/) provided with this library are not compatible with the new library. [![Check Arduino status](https://github.com/arduino-libraries/Arduino_MachineControl/actions/workflows/check-arduino.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_MachineControl/actions/workflows/check-arduino.yml) [![Compile Examples status](https://github.com/arduino-libraries/Arduino_MachineControl/actions/workflows/compile-examples.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_MachineControl/actions/workflows/compile-examples.yml) diff --git a/examples/Analog_Out/Analog_Out.ino b/examples/Analog_Out/Analog_Out.ino index 89110e7..1e77034 100644 --- a/examples/Analog_Out/Analog_Out.ino +++ b/examples/Analog_Out/Analog_Out.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* Machine Control - Analog out Example diff --git a/examples/Analog_input/Analog_input_0_10V/Analog_input_0_10V.ino b/examples/Analog_input/Analog_input_0_10V/Analog_input_0_10V.ino index 9305875..21634d8 100644 --- a/examples/Analog_input/Analog_input_0_10V/Analog_input_0_10V.ino +++ b/examples/Analog_input/Analog_input_0_10V/Analog_input_0_10V.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* Machine Control - Analog in 0 - 10 V Example @@ -20,7 +32,7 @@ using namespace machinecontrol; float res_divider = 0.28057; -float reference = 3.3; +float reference = 3.0; void setup() { analogReadResolution(16); diff --git a/examples/Analog_input/Analog_input_4_20mA/Analog_input_4_20mA.ino b/examples/Analog_input/Analog_input_4_20mA/Analog_input_4_20mA.ino index 167de2d..cae68fb 100644 --- a/examples/Analog_input/Analog_input_4_20mA/Analog_input_4_20mA.ino +++ b/examples/Analog_input/Analog_input_4_20mA/Analog_input_4_20mA.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* Machine Control - Analog in 4 - 20 mA Example @@ -21,7 +33,7 @@ using namespace machinecontrol; #define SENSE_RES 120 -float reference = 3.3; +float reference = 3.0; void setup() { analogReadResolution(16); diff --git a/examples/Analog_input/Analog_input_NTC/Analog_input_NTC.ino b/examples/Analog_input/Analog_input_NTC/Analog_input_NTC.ino index d15149c..7628f1f 100644 --- a/examples/Analog_input/Analog_input_NTC/Analog_input_NTC.ino +++ b/examples/Analog_input/Analog_input_NTC/Analog_input_NTC.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* Machine Control - Analog in NTC Example @@ -26,7 +38,7 @@ using namespace machinecontrol; #define REFERENCE_RES 100000 -float reference = 3.3; +float reference = 3.0; float lowest_voltage = 2.7; void setup() { diff --git a/examples/CAN/ReadCan/ReadCan.ino b/examples/CAN/ReadCan/ReadCan.ino index c7273f7..50d96a1 100644 --- a/examples/CAN/ReadCan/ReadCan.ino +++ b/examples/CAN/ReadCan/ReadCan.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* CAN Read Example diff --git a/examples/CAN/WriteCan/WriteCan.ino b/examples/CAN/WriteCan/WriteCan.ino index 6250cfd..7471de7 100644 --- a/examples/CAN/WriteCan/WriteCan.ino +++ b/examples/CAN/WriteCan/WriteCan.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* CAN Write Example diff --git a/examples/Digital_output/Digital_output.ino b/examples/Digital_output/Digital_output.ino index 5bf6b51..c391ceb 100644 --- a/examples/Digital_output/Digital_output.ino +++ b/examples/Digital_output/Digital_output.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* Machine Control - Digital Output Example diff --git a/examples/Digital_programmable/CombinedIOExpander/CombinedIOExpander.ino b/examples/Digital_programmable/CombinedIOExpander/CombinedIOExpander.ino index c76ad3d..afcc4d6 100644 --- a/examples/Digital_programmable/CombinedIOExpander/CombinedIOExpander.ino +++ b/examples/Digital_programmable/CombinedIOExpander/CombinedIOExpander.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* Machine Control - IOExpander Read And Write Example @@ -53,14 +65,14 @@ void loop() { Serial.println(); // Write the status value to On to all the Output Pins - setAll(SWITCH_ON); + digital_programmables.writeAll(SWITCH_ON_ALL); // Reads from all Input Pins readAll(); delay(1000); // Write the status value to Off all to all the Output Pins - setAll(SWITCH_OFF); + digital_programmables.writeAll(SWITCH_OFF_ALL); // Reads from all Input Pins readAll(); @@ -69,43 +81,30 @@ void loop() { } -void setAll(PinStatus status) { - // Write the status value to each Pin - digital_programmables.set(IO_WRITE_CH_PIN_00, status); - digital_programmables.set(IO_WRITE_CH_PIN_01, status); - digital_programmables.set(IO_WRITE_CH_PIN_02, status); - digital_programmables.set(IO_WRITE_CH_PIN_03, status); - digital_programmables.set(IO_WRITE_CH_PIN_04, status); - digital_programmables.set(IO_WRITE_CH_PIN_05, status); - digital_programmables.set(IO_WRITE_CH_PIN_06, status); - digital_programmables.set(IO_WRITE_CH_PIN_07, status); - digital_programmables.set(IO_WRITE_CH_PIN_08, status); - digital_programmables.set(IO_WRITE_CH_PIN_09, status); - digital_programmables.set(IO_WRITE_CH_PIN_10, status); - digital_programmables.set(IO_WRITE_CH_PIN_11, status); -} void readAll() { - // Reads from input pins. This API returns -1 if you try to read from a write channel. - Serial.println("IO Pin 00: " + String(digital_programmables.read(IO_READ_CH_PIN_00))); - Serial.println("IO Pin 01: " + String(digital_programmables.read(IO_READ_CH_PIN_01))); - Serial.println("IO Pin 02: " + String(digital_programmables.read(IO_READ_CH_PIN_02))); - Serial.println("IO Pin 03: " + String(digital_programmables.read(IO_READ_CH_PIN_03))); - Serial.println("IO Pin 04: " + String(digital_programmables.read(IO_READ_CH_PIN_04))); - Serial.println("IO Pin 05: " + String(digital_programmables.read(IO_READ_CH_PIN_05))); - Serial.println("IO Pin 06: " + String(digital_programmables.read(IO_READ_CH_PIN_06))); - Serial.println("IO Pin 07: " + String(digital_programmables.read(IO_READ_CH_PIN_07))); - Serial.println("IO Pin 08: " + String(digital_programmables.read(IO_READ_CH_PIN_08))); - Serial.println("IO Pin 09: " + String(digital_programmables.read(IO_READ_CH_PIN_09))); - Serial.println("IO Pin 10: " + String(digital_programmables.read(IO_READ_CH_PIN_10))); - Serial.println("IO Pin 11: " + String(digital_programmables.read(IO_READ_CH_PIN_11))); + uint32_t inputs = digital_programmables.readAll(); + Serial.println("CH00: " + String((inputs & (1 << IO_READ_CH_PIN_00)) >> IO_READ_CH_PIN_00)); + Serial.println("CH01: " + String((inputs & (1 << IO_READ_CH_PIN_01)) >> IO_READ_CH_PIN_01)); + Serial.println("CH02: " + String((inputs & (1 << IO_READ_CH_PIN_02)) >> IO_READ_CH_PIN_02)); + Serial.println("CH03: " + String((inputs & (1 << IO_READ_CH_PIN_03)) >> IO_READ_CH_PIN_03)); + Serial.println("CH04: " + String((inputs & (1 << IO_READ_CH_PIN_04)) >> IO_READ_CH_PIN_04)); + Serial.println("CH05: " + String((inputs & (1 << IO_READ_CH_PIN_05)) >> IO_READ_CH_PIN_05)); + Serial.println("CH06: " + String((inputs & (1 << IO_READ_CH_PIN_06)) >> IO_READ_CH_PIN_06)); + Serial.println("CH07: " + String((inputs & (1 << IO_READ_CH_PIN_07)) >> IO_READ_CH_PIN_07)); + Serial.println("CH08: " + String((inputs & (1 << IO_READ_CH_PIN_08)) >> IO_READ_CH_PIN_08)); + Serial.println("CH09: " + String((inputs & (1 << IO_READ_CH_PIN_09)) >> IO_READ_CH_PIN_09)); + Serial.println("CH10: " + String((inputs & (1 << IO_READ_CH_PIN_10)) >> IO_READ_CH_PIN_10)); + Serial.println("CH11: " + String((inputs & (1 << IO_READ_CH_PIN_11)) >> IO_READ_CH_PIN_11)); + Serial.println(); + inputs = digital_inputs.readAll(); + Serial.println("CH00: " + String((inputs & (1 << DIN_READ_CH_PIN_00)) >> DIN_READ_CH_PIN_00)); + Serial.println("CH01: " + String((inputs & (1 << DIN_READ_CH_PIN_01)) >> DIN_READ_CH_PIN_01)); + Serial.println("CH02: " + String((inputs & (1 << DIN_READ_CH_PIN_02)) >> DIN_READ_CH_PIN_02)); + Serial.println("CH03: " + String((inputs & (1 << DIN_READ_CH_PIN_03)) >> DIN_READ_CH_PIN_03)); + Serial.println("CH04: " + String((inputs & (1 << DIN_READ_CH_PIN_04)) >> DIN_READ_CH_PIN_04)); + Serial.println("CH05: " + String((inputs & (1 << DIN_READ_CH_PIN_05)) >> DIN_READ_CH_PIN_05)); + Serial.println("CH06: " + String((inputs & (1 << DIN_READ_CH_PIN_06)) >> DIN_READ_CH_PIN_06)); + Serial.println("CH07: " + String((inputs & (1 << DIN_READ_CH_PIN_07)) >> DIN_READ_CH_PIN_07)); Serial.println(); - Serial.println("DIN Pin 00: " + String(digital_inputs.read(DIN_READ_CH_PIN_00))); - Serial.println("DIN Pin 01: " + String(digital_inputs.read(DIN_READ_CH_PIN_01))); - Serial.println("DIN Pin 02: " + String(digital_inputs.read(DIN_READ_CH_PIN_02))); - Serial.println("DIN Pin 03: " + String(digital_inputs.read(DIN_READ_CH_PIN_03))); - Serial.println("DIN Pin 04: " + String(digital_inputs.read(DIN_READ_CH_PIN_04))); - Serial.println("DIN Pin 05: " + String(digital_inputs.read(DIN_READ_CH_PIN_05))); - Serial.println("DIN Pin 06: " + String(digital_inputs.read(DIN_READ_CH_PIN_06))); - Serial.println("DIN Pin 07: " + String(digital_inputs.read(DIN_READ_CH_PIN_07))); } diff --git a/examples/Digital_programmable/Digital_input/Digital_input.ino b/examples/Digital_programmable/Digital_input/Digital_input.ino index c94e1a9..beb5ecb 100644 --- a/examples/Digital_programmable/Digital_input/Digital_input.ino +++ b/examples/Digital_programmable/Digital_input/Digital_input.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* Machine Control - Digital Input Example @@ -28,7 +40,7 @@ void setup() { } void loop() { - //Reads and Prints all channels and + //Reads and Prints all channels (in a single operation) readAll(); //Read one-by-one each channel and print them one-by-one @@ -62,13 +74,14 @@ void loop() { } uint8_t readAll() { - Serial.println("CH00: " + String(digital_inputs.read(DIN_READ_CH_PIN_00))); - Serial.println("CH01: " + String(digital_inputs.read(DIN_READ_CH_PIN_01))); - Serial.println("CH02: " + String(digital_inputs.read(DIN_READ_CH_PIN_02))); - Serial.println("CH03: " + String(digital_inputs.read(DIN_READ_CH_PIN_03))); - Serial.println("CH04: " + String(digital_inputs.read(DIN_READ_CH_PIN_04))); - Serial.println("CH05: " + String(digital_inputs.read(DIN_READ_CH_PIN_05))); - Serial.println("CH06: " + String(digital_inputs.read(DIN_READ_CH_PIN_06))); - Serial.println("CH07: " + String(digital_inputs.read(DIN_READ_CH_PIN_07))); + uint32_t inputs = digital_inputs.readAll(); + Serial.println("CH00: " + String((inputs & (1 << DIN_READ_CH_PIN_00)) >> DIN_READ_CH_PIN_00)); + Serial.println("CH01: " + String((inputs & (1 << DIN_READ_CH_PIN_01)) >> DIN_READ_CH_PIN_01)); + Serial.println("CH02: " + String((inputs & (1 << DIN_READ_CH_PIN_02)) >> DIN_READ_CH_PIN_02)); + Serial.println("CH03: " + String((inputs & (1 << DIN_READ_CH_PIN_03)) >> DIN_READ_CH_PIN_03)); + Serial.println("CH04: " + String((inputs & (1 << DIN_READ_CH_PIN_04)) >> DIN_READ_CH_PIN_04)); + Serial.println("CH05: " + String((inputs & (1 << DIN_READ_CH_PIN_05)) >> DIN_READ_CH_PIN_05)); + Serial.println("CH06: " + String((inputs & (1 << DIN_READ_CH_PIN_06)) >> DIN_READ_CH_PIN_06)); + Serial.println("CH07: " + String((inputs & (1 << DIN_READ_CH_PIN_07)) >> DIN_READ_CH_PIN_07)); Serial.println(); } diff --git a/examples/Digital_programmable/GPIO_programmable/GPIO_programmable.ino b/examples/Digital_programmable/GPIO_programmable/GPIO_programmable.ino index ce9558a..c7d34ba 100644 --- a/examples/Digital_programmable/GPIO_programmable/GPIO_programmable.ino +++ b/examples/Digital_programmable/GPIO_programmable/GPIO_programmable.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* Machine Control - IOExpander Read And Write Example @@ -12,7 +24,7 @@ This example code is in the public domain. */ - + #include #include "Wire.h" using namespace machinecontrol; @@ -42,52 +54,47 @@ void loop() { digital_programmables.set(IO_WRITE_CH_PIN_03, SWITCH_OFF); delay(1000); + Serial.println(); + // Sets all the status Pins Values to On in one single operation + uint32_t status = ON_VALUE_PIN_10 | ON_VALUE_PIN_08 | ON_VALUE_PIN_06 | ON_VALUE_PIN_04 | ON_VALUE_PIN_02 | ON_VALUE_PIN_00; + digital_programmables.writeAll(status); + delay(1000); + + // Toggles the actual status values of all digital programmables Pins + digital_programmables.toggle(); + delay(1000); + Serial.println(); // Write the status value to On to all the Output Pins - setAll(SWITCH_ON); + digital_programmables.writeAll(SWITCH_ON_ALL); // Reads from all Input Pins readAll(); delay(1000); // Write the status value to Off all to all the Output Pins - setAll(SWITCH_OFF); + digital_programmables.writeAll(SWITCH_OFF_ALL); // Reads from all Input Pins readAll(); Serial.println(); delay(1000); - } -void setAll(PinStatus status) { - // Write the status value to each Pin - digital_programmables.set(IO_WRITE_CH_PIN_00, status); - digital_programmables.set(IO_WRITE_CH_PIN_01, status); - digital_programmables.set(IO_WRITE_CH_PIN_02, status); - digital_programmables.set(IO_WRITE_CH_PIN_03, status); - digital_programmables.set(IO_WRITE_CH_PIN_04, status); - digital_programmables.set(IO_WRITE_CH_PIN_05, status); - digital_programmables.set(IO_WRITE_CH_PIN_06, status); - digital_programmables.set(IO_WRITE_CH_PIN_07, status); - digital_programmables.set(IO_WRITE_CH_PIN_08, status); - digital_programmables.set(IO_WRITE_CH_PIN_09, status); - digital_programmables.set(IO_WRITE_CH_PIN_10, status); - digital_programmables.set(IO_WRITE_CH_PIN_11, status); +uint8_t readAll() { + uint32_t inputs = digital_programmables.readAll(); + Serial.println("CH00: " + String((inputs & (1 << IO_READ_CH_PIN_00)) >> IO_READ_CH_PIN_00)); + Serial.println("CH01: " + String((inputs & (1 << IO_READ_CH_PIN_01)) >> IO_READ_CH_PIN_01)); + Serial.println("CH02: " + String((inputs & (1 << IO_READ_CH_PIN_02)) >> IO_READ_CH_PIN_02)); + Serial.println("CH03: " + String((inputs & (1 << IO_READ_CH_PIN_03)) >> IO_READ_CH_PIN_03)); + Serial.println("CH04: " + String((inputs & (1 << IO_READ_CH_PIN_04)) >> IO_READ_CH_PIN_04)); + Serial.println("CH05: " + String((inputs & (1 << IO_READ_CH_PIN_05)) >> IO_READ_CH_PIN_05)); + Serial.println("CH06: " + String((inputs & (1 << IO_READ_CH_PIN_06)) >> IO_READ_CH_PIN_06)); + Serial.println("CH07: " + String((inputs & (1 << IO_READ_CH_PIN_07)) >> IO_READ_CH_PIN_07)); + Serial.println("CH08: " + String((inputs & (1 << IO_READ_CH_PIN_08)) >> IO_READ_CH_PIN_08)); + Serial.println("CH09: " + String((inputs & (1 << IO_READ_CH_PIN_09)) >> IO_READ_CH_PIN_09)); + Serial.println("CH10: " + String((inputs & (1 << IO_READ_CH_PIN_10)) >> IO_READ_CH_PIN_10)); + Serial.println("CH11: " + String((inputs & (1 << IO_READ_CH_PIN_11)) >> IO_READ_CH_PIN_11)); + Serial.println(); } -void readAll() { - // Reads from input pins. This API returns -1 if you try to read from a write channel. - Serial.println("Pin 00: " + String(digital_programmables.read(IO_READ_CH_PIN_00))); - Serial.println("Pin 01: " + String(digital_programmables.read(IO_READ_CH_PIN_01))); - Serial.println("Pin 02: " + String(digital_programmables.read(IO_READ_CH_PIN_02))); - Serial.println("Pin 03: " + String(digital_programmables.read(IO_READ_CH_PIN_03))); - Serial.println("Pin 04: " + String(digital_programmables.read(IO_READ_CH_PIN_04))); - Serial.println("Pin 05: " + String(digital_programmables.read(IO_READ_CH_PIN_05))); - Serial.println("Pin 06: " + String(digital_programmables.read(IO_READ_CH_PIN_06))); - Serial.println("Pin 07: " + String(digital_programmables.read(IO_READ_CH_PIN_07))); - Serial.println("Pin 08: " + String(digital_programmables.read(IO_READ_CH_PIN_08))); - Serial.println("Pin 09: " + String(digital_programmables.read(IO_READ_CH_PIN_09))); - Serial.println("Pin 10: " + String(digital_programmables.read(IO_READ_CH_PIN_10))); - Serial.println("Pin 11: " + String(digital_programmables.read(IO_READ_CH_PIN_11))); -} diff --git a/examples/Encoders/Encoders.ino b/examples/Encoders/Encoders.ino index 0e91d45..67a4d4c 100644 --- a/examples/Encoders/Encoders.ino +++ b/examples/Encoders/Encoders.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + #include using namespace machinecontrol; diff --git a/examples/RS232/RS232.ino b/examples/RS232/RS232.ino index 97b4a0b..1f44fc6 100644 --- a/examples/RS232/RS232.ino +++ b/examples/RS232/RS232.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* RS232 communication diff --git a/examples/RS485_fullduplex/RS485_fullduplex.ino b/examples/RS485_fullduplex/RS485_fullduplex.ino index 4c1a04a..1f13922 100644 --- a/examples/RS485_fullduplex/RS485_fullduplex.ino +++ b/examples/RS485_fullduplex/RS485_fullduplex.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* RS485 Full duplex communication diff --git a/examples/RS485_halfduplex/RS485_halfduplex.ino b/examples/RS485_halfduplex/RS485_halfduplex.ino index 3e5de9d..0291e1a 100644 --- a/examples/RS485_halfduplex/RS485_halfduplex.ino +++ b/examples/RS485_halfduplex/RS485_halfduplex.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* RS485 Half Duplex communication diff --git a/examples/RTC/RTC.ino b/examples/RTC/RTC.ino index 954e237..7edf77f 100644 --- a/examples/RTC/RTC.ino +++ b/examples/RTC/RTC.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* Machine Control - RTC Example diff --git a/examples/RTC_Alarm/RTC_Alarm.ino b/examples/RTC_Alarm/RTC_Alarm.ino index c455af6..f5c4325 100644 --- a/examples/RTC_Alarm/RTC_Alarm.ino +++ b/examples/RTC_Alarm/RTC_Alarm.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* Machine Control - RTC Alarm Example diff --git a/examples/Temp_probes_RTD/Temp_probes_RTD.ino b/examples/Temp_probes_RTD/Temp_probes_RTD.ino index 2899dc6..b2c1edb 100644 --- a/examples/Temp_probes_RTD/Temp_probes_RTD.ino +++ b/examples/Temp_probes_RTD/Temp_probes_RTD.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* Machine Control - Temperature probes RTD example diff --git a/examples/Temp_probes_Thermocouples/Temp_probes_Thermocouples.ino b/examples/Temp_probes_Thermocouples/Temp_probes_Thermocouples.ino index 5fef867..a224288 100644 --- a/examples/Temp_probes_Thermocouples/Temp_probes_Thermocouples.ino +++ b/examples/Temp_probes_Thermocouples/Temp_probes_Thermocouples.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + /* Machine Control - Thermocouples Read Sensors diff --git a/examples/USB_host/USB_host.ino b/examples/USB_host/USB_host.ino index 69cc975..0fa9695 100644 --- a/examples/USB_host/USB_host.ino +++ b/examples/USB_host/USB_host.ino @@ -1,3 +1,15 @@ +/* + * IMPORTANT NOTE: + * + * This example is associated with the deprecated Arduino_MachineControl library. + * We have introduced a new and improved library called Arduino_PortentaMachineControl, which offers enhanced features + * and ongoing support. + * We encourage you to update your projects to use the new library. + * + * The functions and syntax in this example are not compatible with Arduino_PortentaMachineControl. + * Please refer to the migration guide for necessary adjustments. + */ + #include #include diff --git a/library.properties b/library.properties index f58e0ad..4f5ea82 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=Arduino_MachineControl -version=1.1.0 +version=1.1.2 author=Arduino maintainer=Arduino -sentence=Arduino Library for Portenta Machine Control - PMC -paragraph= +sentence=DEPRECATED. Arduino Library for Portenta Machine Control - PMC +paragraph=This library is no longer actively maintained and is deprecated. Consider migrating to the Arduino_PortentaMachineControl library. category=Communication url=https://github.com/arduino-libraries/Arduino_MachineControl architectures=mbed, mbed_portenta diff --git a/src/Arduino_MachineControl.h b/src/Arduino_MachineControl.h index e5aba58..d7088c2 100644 --- a/src/Arduino_MachineControl.h +++ b/src/Arduino_MachineControl.h @@ -9,9 +9,16 @@ #include "utility/RTC/PCF8563T.h" #include "utility/RTC/PCF8563T.h" -#include "Arduino.h" -#include "pinDefinitions.h" -#include "mbed.h" +#include +#include +#include + +#if __has_include("portenta_info.h") +#include "portenta_info.h" +#define TRY_REV2_RECOGNITION +uint8_t* boardInfo(); +#define PMC_R2_SKU (24 << 8 | 3) +#endif namespace machinecontrol { @@ -28,6 +35,26 @@ class RTDClass { * @param channel (0-2) */ void selectChannel(int channel) { + +#ifdef TRY_REV2_RECOGNITION + // check if OTP data is present AND the board is mounted on a r2 carrier + auto info = (PortentaBoardInfo*)boardInfo(); + if (info->magic == 0xB5 && info->carrier == PMC_R2_SKU) { + // reverse channels 0 and 2 + switch (channel) { + case 0: + channel = 2; + break; + case 2: + channel = 0; + break; + default: + break; + } + } +#endif +#undef TRY_REV2_RECOGNITION + for (int i=0; i<3; i++) { ch_sel[i] = (i == channel ? 1 : 0); } @@ -74,9 +101,6 @@ class RTDClass { extern RTDClass temp_probes; -static mbed::CAN _can(PB_8, PH_13); - - /** * The COMMClass is used to initialize the CAN and RS485 LEDs and * establish the power mode of the CAN bus. @@ -124,10 +148,10 @@ class COMMClass { can_disable = 1; } - UART _UART4_ = arduino::UART(PA_0, PI_9, NC, NC); - mbed::CAN& can = _can; + arduino::UART _UART4_ {PA_0, PI_9, NC, NC}; + mbed::CAN can {PB_8, PH_13}; - RS485Class rs485 = RS485Class(_UART4_, PinNameToIndex(PA_0), PinNameToIndex(PI_13), PinNameToIndex(PI_10)); + RS485Class rs485 {_UART4_, PinNameToIndex(PA_0), PinNameToIndex(PI_13), PinNameToIndex(PI_10)}; void rs485Enable(bool enable) { digitalWrite(PinNameToIndex(PG_9), enable ? HIGH : LOW); } void rs485ModeRS232(bool enable) { digitalWrite(PinNameToIndex(PA_10), enable ? LOW : HIGH); } diff --git a/src/utility/QEI/QEI.cpp b/src/utility/QEI/QEI.cpp index 22f32e4..db767db 100644 --- a/src/utility/QEI/QEI.cpp +++ b/src/utility/QEI/QEI.cpp @@ -152,7 +152,9 @@ QEI::QEI(PinName channelA, //X4 encoding uses interrupts on channel A, //and on channel B. channelA_.rise(mbed::callback(this, &QEI::encode)); - channelA_.fall(mbed::callback(this, &QEI::encode)); + if(encoding != X1_ENCODING){ + channelA_.fall(mbed::callback(this, &QEI::encode)); + } //If we're using X4 encoding, then attach interrupts to channel B too. if (encoding == X4_ENCODING) { @@ -191,6 +193,20 @@ int QEI::getRevolutions(void) { } +// +-------------+ +// | X1 Encoding | +// +-------------+ +// +// When observing states two patterns will appear: +// +// Counter clockwise rotation: +// +// 10 -> 10 -> 10 -> 10 -> ... +// +// Clockwise rotation: +// +// 11 -> 11 -> 11 -> ... +// // +-------------+ // | X2 Encoding | // +-------------+ @@ -243,8 +259,15 @@ void QEI::encode(void) { //2-bit state. currState_ = (chanA << 1) | (chanB); - - if (encoding_ == X2_ENCODING) { + + if(encoding_ == X1_ENCODING){ + if(currState_ == 0x3){ + pulses_++; + } + if(currState_ == 0x2){ + pulses_--; + } + } else if (encoding_ == X2_ENCODING) { //11->00->11->00 is counter clockwise rotation or "forward". if ((prevState_ == 0x3 && currState_ == 0x0) || diff --git a/src/utility/QEI/QEI.h b/src/utility/QEI/QEI.h index 5ab79d2..8e6fba0 100644 --- a/src/utility/QEI/QEI.h +++ b/src/utility/QEI/QEI.h @@ -148,7 +148,7 @@ class QEI { public: typedef enum Encoding { - + X1_ENCODING, X2_ENCODING, X4_ENCODING diff --git a/src/utility/RTC/PCF8563T.cpp b/src/utility/RTC/PCF8563T.cpp index c7c6f76..a21b36a 100644 --- a/src/utility/RTC/PCF8563T.cpp +++ b/src/utility/RTC/PCF8563T.cpp @@ -172,7 +172,7 @@ uint8_t PCF8563TClass::getMonths() { * @return byte with Day(s) value */ uint8_t PCF8563TClass::getDays() { - uint8_t days = readByte(PCF8563T_DAYS_REG); + uint8_t days = readByte(PCF8563T_DAYS_REG) & 0x3F; return (days & 0x0F) + ((days >> 4)*10); } @@ -347,7 +347,7 @@ void PCF8563TClass::setHourAlarm(uint8_t hours) { uint8_t dec = hours / 10; uint8_t unit = hours - (dec * 10); uint8_t hour_alarm = PCF8563T_HOUR_ALARM_AE_H_MASK & ((dec << 4) + unit); - writeByte(PCF8563T_HOURS_REG, hour_alarm); //check formula on datasheet val + 6 * (val / 10) + writeByte(PCF8563T_HOUR_ALARM_REG, hour_alarm); //check formula on datasheet val + 6 * (val / 10) } /** diff --git a/src/utility/THERMOCOUPLE/MAX31855.cpp b/src/utility/THERMOCOUPLE/MAX31855.cpp index 6053867..4e86718 100644 --- a/src/utility/THERMOCOUPLE/MAX31855.cpp +++ b/src/utility/THERMOCOUPLE/MAX31855.cpp @@ -19,10 +19,30 @@ #include "MAX31855.h" +const double MAX31855Class::Jm210_760[] ; +const double MAX31855Class::J760_1200[] ; +const double MAX31855Class::Km270_0[] ; +const double MAX31855Class::K0_1372[] ; + +const double MAX31855Class::InvJ_neg[] ; +const double MAX31855Class::InvJ0_760[] ; +const double MAX31855Class::InvJ760_1200[] ; + +const double MAX31855Class::InvK_neg[] ; +const double MAX31855Class::InvK0_500[] ; +const double MAX31855Class::InvK500_1372[] ; + +const MAX31855Class::coefftable MAX31855Class::CoeffJ[]; +const MAX31855Class::coefftable MAX31855Class::CoeffK[]; + +const MAX31855Class::coefftable MAX31855Class::InvCoeffJ[]; +const MAX31855Class::coefftable MAX31855Class::InvCoeffK[]; + MAX31855Class::MAX31855Class(int cs, SPIClass& spi) : _cs(cs), _spi(&spi), - _spiSettings(4000000, MSBFIRST, SPI_MODE0) + _spiSettings(4000000, MSBFIRST, SPI_MODE0), + _coldOffset(2.10f) { } @@ -72,10 +92,78 @@ uint32_t MAX31855Class::readSensor() return read; } +double MAX31855Class::polynomial(double value, int tableEntries, coefftable const (*table) ) +{ + double output = 0; + double valuePower = 1; + for (int i=0;i0) { + voltage += 0.118597600000E+00 * exp( -0.118343200000E-03 * pow(temp-0.126968600000E+03, 2)); + } + return voltage; +} + +double MAX31855Class::mvtoTemp(int type, double voltage) { + coefftable const (*table); + int tableEntries; + + switch (type) { + case PROBE_J: + table = InvCoeffJ; + tableEntries = sizeof(InvCoeffJ)/sizeof(coefftable); + break; + case PROBE_K: + table = InvCoeffK; + tableEntries = sizeof(InvCoeffJ)/sizeof(coefftable); + break; + } + return polynomial(voltage, tableEntries, table); +} + float MAX31855Class::readTemperature(int type) { uint32_t rawword; - float celsius; + int32_t measuredTempInt; + int32_t measuredColdInt; + double measuredTemp; + double measuredCold; + double measuredVolt; rawword = readSensor(); @@ -83,23 +171,48 @@ float MAX31855Class::readTemperature(int type) if (rawword & 0x7) { return NAN; } - // The temperature is stored in the last 14 word's bits + // The cold junction temperature is stored in the last 14 word's bits + // whereas the ttermocouple temperature (non linearized) is in the topmost 18 bits // sent by the Thermocouple-to-Digital Converter + + // sign extend thermocouple value if (rawword & 0x80000000) { // Negative value, drop the lower 18 bits and explicitly extend sign bits. - rawword = 0xFFFFC000 | ((rawword >> 18) & 0x00003FFFF); + measuredTempInt = 0xFFFC0000 | ((rawword >> 18) & 0x00003FFFF); } else { // Positive value, just drop the lower 18 bits. - rawword >>= 18; + measuredTempInt = rawword>>18; } - // multiply for the LSB value - celsius = rawword * 0.25f; - if (type == PROBE_J) { - // conversion factor from K type to J type - celsius = celsius * 4/5; + // convert it to degrees + measuredTemp = measuredTempInt * 0.25f; + + // sign extend cold junction temperature + measuredColdInt = (rawword>>4)&0xfff; + if (measuredColdInt&0x800) { + // Negative value, sign extend + measuredColdInt |= 0xfffff000; } - return celsius; + + // convert it to degrees + measuredCold = (measuredColdInt/16.0f); + // now the tricky part... since MAX31855K is considering a linear response + // and is trimemd for K thermocouples, we have to convert the reading back + // to mV and then use NIST polynomial approximation to determine temperature + // we know that reading from chip is calculated as: + // temp = chip_temperature + thermocouple_voltage/0.041276f + // + // convert temperature to mV is accomplished converting the chip temperature + // to mV using NIST polynomial and then by adding the measured voltage + // calculated inverting the function above + // this way we calculate the voltage we would have measured if cold junction + // was at 0 degrees celsius + + measuredVolt = coldTempTomv(type, measuredCold - _coldOffset)+(measuredTemp - measuredCold) * 0.041276f; + + // finally from the cold junction compensated voltage we calculate the temperature + // using NIST polynomial approximation for the thermocouple type we are using + return mvtoTemp(type,measuredVolt); } float MAX31855Class::readReferenceTemperature(int type) @@ -126,4 +239,9 @@ float MAX31855Class::readReferenceTemperature(int type) return ref; } +void MAX31855Class::setColdOffset(float offset) +{ + _coldOffset = offset; +} + MAX31855Class THERM; diff --git a/src/utility/THERMOCOUPLE/MAX31855.h b/src/utility/THERMOCOUPLE/MAX31855.h index f5c2b3a..c2c5380 100644 --- a/src/utility/THERMOCOUPLE/MAX31855.h +++ b/src/utility/THERMOCOUPLE/MAX31855.h @@ -36,13 +36,66 @@ class MAX31855Class { float readTemperature(int type = PROBE_K); float readReferenceTemperature(int type = PROBE_K); + void setColdOffset(float offset); private: uint32_t readSensor(); - + float _coldOffset; int _cs; SPIClass* _spi; SPISettings _spiSettings; + + // NIST coefficient tables + static constexpr double Jm210_760[] = { 0.000000000000E+00, 0.503811878150E-01, 0.304758369300E-04,-0.856810657200E-07, 0.132281952950E-09,-0.170529583370E-12, 0.209480906970E-15,-0.125383953360E-18, 0.156317256970E-22 }; + static constexpr double J760_1200[] = { 0.296456256810E+03,-0.149761277860E+01, 0.317871039240E-02,-0.318476867010E-05, 0.157208190040E-08,-0.306913690560E-12 }; + + static constexpr double Km270_0[] = { 0.000000000000E+00, 0.394501280250E-01, 0.236223735980E-04,-0.328589067840E-06,-0.499048287770E-08,-0.675090591730E-10,-0.574103274280E-12,-0.310888728940E-14,-0.104516093650E-16,-0.198892668780E-19,-0.163226974860E-22 }; + static constexpr double K0_1372[] = { -0.176004136860E-01, 0.389212049750E-01, 0.185587700320E-04,-0.994575928740E-07, 0.318409457190E-09,-0.560728448890E-12, 0.560750590590E-15,-0.320207200030E-18, 0.971511471520E-22,-0.121047212750E-25 }; + + static constexpr double InvJ_neg[] = { 0.0000000E+00, 1.9528268E+01, -1.2286185E+00, -1.0752178E+00, -5.9086933E-01, -1.7256713E-01, -2.8131513E-02,-2.3963370E-03,-8.3823321E-05}; + static constexpr double InvJ0_760[] = { 0.000000E+00, 1.978425E+01, -2.001204E-01, 1.036969E-02, -2.549687E-04, 3.585153E-06, -5.344285E-08, 5.099890E-10 }; + static constexpr double InvJ760_1200[] = { -3.11358187E+03, 3.00543684E+02, -9.94773230E+00, 1.70276630E-01, -1.43033468E-03, 4.73886084E-06 }; + + static constexpr double InvK_neg[] = { 0.0000000E+00, 2.5173462E+01, 1.1662878E+00, 1.0833638E+00, 8.9773540E-01, 3.7342377E-01, 8.6632643E-02, 1.0450598E-02, 5.1920577E-04 }; + static constexpr double InvK0_500[] = { 0.000000E+00, 2.508355E+01, 7.860106E-02, -2.503131E-01, 8.315270E-02, -1.228034E-02, 9.804036E-04, -4.413030E-05, 1.057734E-06, -1.052755E-08 }; + static constexpr double InvK500_1372[] = { -1.318058E+02, 4.830222E+01, -1.646031E+00, 5.464731E-02, -9.650715E-04, 8.802193E-06, -3.110810E-08 }; + + typedef struct { + int size; + double max; + const double *coeffs; + } coefftable; + + static constexpr coefftable CoeffJ []= { + {0,-210, NULL}, + {sizeof(Jm210_760) / sizeof(double), 760.0f, &Jm210_760[0]}, + {sizeof(J760_1200) / sizeof(double), 1200.0f, &J760_1200[0]} + }; + + static constexpr coefftable CoeffK []= { + {0,-270, NULL}, + {sizeof(Jm210_760) / sizeof(double), 0.0f, &Km270_0[0]}, + {sizeof(K0_1372) / sizeof(double), 1200.0f, &K0_1372[0]} + }; + + static constexpr coefftable InvCoeffJ []= { + {0,-0.895, NULL}, + {sizeof(InvJ_neg) / sizeof(double), 0.0f, &InvJ_neg[0]}, + {sizeof(InvJ0_760) / sizeof(double), 42.919f, &InvJ0_760[0]}, + {sizeof(InvJ760_1200) / sizeof(double), 69.533f, &InvJ760_1200[0]} + }; + + static constexpr coefftable InvCoeffK []= { + {0,-5.891, NULL}, + {sizeof(InvK_neg) / sizeof(double), 0.0f, &InvK_neg[0]}, + {sizeof(InvK0_500) / sizeof(double), 20.644f, &InvK0_500[0]}, + {sizeof(InvK500_1372) / sizeof(double), 54.886f, &InvK500_1372[0]}, + }; + + double mvtoTemp(int type, double voltage); + double coldTempTomv(int type, double temp); + double polynomial(double value, int tableEntries, coefftable const (*table) ); + }; extern MAX31855Class THERM; diff --git a/src/utility/ioexpander/ArduinoIOExpander.cpp b/src/utility/ioexpander/ArduinoIOExpander.cpp index 3dc1be0..461e72e 100644 --- a/src/utility/ioexpander/ArduinoIOExpander.cpp +++ b/src/utility/ioexpander/ArduinoIOExpander.cpp @@ -83,11 +83,40 @@ int ArduinoIOExpanderClass::read(int pin) return -1; } +void ArduinoIOExpanderClass::writeAll(uint32_t banks) { + _tca.writeAll(banks & 0xFF, (banks >> 8) & 0xFF, 0x00); +} + +uint32_t ArduinoIOExpanderClass::readAll() +{ + uint8_t banks[3]; + _tca.readAll(banks); + return *(uint32_t*)banks; +} + + +void ArduinoIOExpanderClass::toggle(){ + writeAll(~(readAll())); +} + void ArduinoIOExpanderClass::initPins() { if (_tca.getAddress() == IO_ADD) { PinStatus status = SWITCH_OFF; + set(IO_WRITE_CH_PIN_00, status); + set(IO_WRITE_CH_PIN_01, status); + set(IO_WRITE_CH_PIN_02, status); + set(IO_WRITE_CH_PIN_03, status); + set(IO_WRITE_CH_PIN_04, status); + set(IO_WRITE_CH_PIN_05, status); + set(IO_WRITE_CH_PIN_06, status); + set(IO_WRITE_CH_PIN_07, status); + set(IO_WRITE_CH_PIN_08, status); + set(IO_WRITE_CH_PIN_09, status); + set(IO_WRITE_CH_PIN_10, status); + set(IO_WRITE_CH_PIN_11, status); + pinMode(IO_WRITE_CH_PIN_00, OUTPUT); pinMode(IO_WRITE_CH_PIN_01, OUTPUT); pinMode(IO_WRITE_CH_PIN_02, OUTPUT); @@ -113,18 +142,7 @@ void ArduinoIOExpanderClass::initPins() pinMode(IO_READ_CH_PIN_10, INPUT); pinMode(IO_READ_CH_PIN_11, INPUT); - set(IO_WRITE_CH_PIN_00, status); - set(IO_WRITE_CH_PIN_01, status); - set(IO_WRITE_CH_PIN_02, status); - set(IO_WRITE_CH_PIN_03, status); - set(IO_WRITE_CH_PIN_04, status); - set(IO_WRITE_CH_PIN_05, status); - set(IO_WRITE_CH_PIN_06, status); - set(IO_WRITE_CH_PIN_07, status); - set(IO_WRITE_CH_PIN_08, status); - set(IO_WRITE_CH_PIN_09, status); - set(IO_WRITE_CH_PIN_10, status); - set(IO_WRITE_CH_PIN_11, status); + writeAll(SWITCH_OFF_ALL); } else { pinMode(DIN_READ_CH_PIN_00, INPUT); pinMode(DIN_READ_CH_PIN_01, INPUT); diff --git a/src/utility/ioexpander/ArduinoIOExpander.h b/src/utility/ioexpander/ArduinoIOExpander.h index 28993d1..e7cd402 100644 --- a/src/utility/ioexpander/ArduinoIOExpander.h +++ b/src/utility/ioexpander/ArduinoIOExpander.h @@ -25,6 +25,24 @@ #define SWITCH_ON HIGH #define SWITCH_OFF LOW +#define SWITCH_ON_ALL 0x0000FFFF +#define SWITCH_OFF_ALL 0x00000000 + +enum { + ON_VALUE_PIN_00 = 0x01, + ON_VALUE_PIN_01 = 0x02, + ON_VALUE_PIN_02 = 0x04, + ON_VALUE_PIN_03 = 0x08, + ON_VALUE_PIN_04 = 0x80, + ON_VALUE_PIN_05 = 0x40, + ON_VALUE_PIN_06 = 0x20, + ON_VALUE_PIN_07 = 0x10, + ON_VALUE_PIN_08 = 0x100, + ON_VALUE_PIN_09 = 0x200, + ON_VALUE_PIN_10 = 0x400, + ON_VALUE_PIN_11 = 0x800, +}; + enum { IO_WRITE_CH_PIN_00 = TCA6424A_P00, IO_WRITE_CH_PIN_01 = TCA6424A_P01, @@ -77,8 +95,10 @@ class ArduinoIOExpanderClass { void setAddress(uint8_t address); bool set(int pin, PinStatus status); bool set(int pin, int status) { return set( pin, (PinStatus)status); }; - + void writeAll(uint32_t banks); int read(int pin); + uint32_t readAll(); + void toggle(); bool pinMode(int pin, PinMode direction); private: diff --git a/src/utility/ioexpander/I2Cdev.cpp b/src/utility/ioexpander/I2Cdev.cpp index 5525624..40b5dfc 100644 --- a/src/utility/ioexpander/I2Cdev.cpp +++ b/src/utility/ioexpander/I2Cdev.cpp @@ -3,6 +3,9 @@ // 2013-06-05 by Jeff Rowberg // // Changelog: +// 2021-09-28 - allow custom Wire object as transaction function argument +// 2020-01-20 - hardija : complete support for Teensy 3.x +// 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1 // 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications // 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) // 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire @@ -87,11 +90,6 @@ THE SOFTWARE. #endif -#ifndef BUFFER_LENGTH -// band-aid fix for platforms without Wire-defined BUFFER_LENGTH (removed from some official implementations) -#define BUFFER_LENGTH 32 -#endif - /** Default constructor. */ I2Cdev::I2Cdev() { @@ -105,9 +103,9 @@ I2Cdev::I2Cdev() { * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout) { +int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout, void *wireObj) { uint8_t b; - uint8_t count = readByte(devAddr, regAddr, &b, timeout); + uint8_t count = readByte(devAddr, regAddr, &b, timeout, wireObj); *data = b & (1 << bitNum); return count; } @@ -120,9 +118,9 @@ int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout) { +int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout, void *wireObj) { uint16_t b; - uint8_t count = readWord(devAddr, regAddr, &b, timeout); + uint8_t count = readWord(devAddr, regAddr, &b, timeout, wireObj); *data = b & (1 << bitNum); return count; } @@ -136,14 +134,14 @@ int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16 * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout) { +int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout, void *wireObj) { // 01101001 read byte // 76543210 bit numbers // xxx args: bitStart=4, length=3 // 010 masked // -> 010 shifted uint8_t count, b; - if ((count = readByte(devAddr, regAddr, &b, timeout)) != 0) { + if ((count = readByte(devAddr, regAddr, &b, timeout, wireObj)) != 0) { uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); b &= mask; b >>= (bitStart - length + 1); @@ -161,7 +159,7 @@ int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (1 = success, 0 = failure, -1 = timeout) */ -int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout) { +int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout, void *wireObj) { // 1101011001101001 read byte // fedcba9876543210 bit numbers // xxx args: bitStart=12, length=3 @@ -169,7 +167,7 @@ int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uin // -> 010 shifted uint8_t count; uint16_t w; - if ((count = readWord(devAddr, regAddr, &w, timeout)) != 0) { + if ((count = readWord(devAddr, regAddr, &w, timeout, wireObj)) != 0) { uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); w &= mask; w >>= (bitStart - length + 1); @@ -185,8 +183,8 @@ int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uin * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout) { - return readBytes(devAddr, regAddr, 1, data, timeout); +int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout, void *wireObj) { + return readBytes(devAddr, regAddr, 1, data, timeout, wireObj); } /** Read single word from a 16-bit device register. @@ -196,8 +194,8 @@ int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout) { - return readWords(devAddr, regAddr, 1, data, timeout); +int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout, void *wireObj) { + return readWords(devAddr, regAddr, 1, data, timeout, wireObj); } /** Read multiple bytes from an 8-bit device register. @@ -208,7 +206,7 @@ int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16 * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Number of bytes read (-1 indicates failure) */ -int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout) { +int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout, void *wireObj) { #ifdef I2CDEV_SERIAL_DEBUG Serial.print("I2C (0x"); Serial.print(devAddr, HEX); @@ -219,74 +217,66 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 Serial.print("..."); #endif - int8_t count = 0; + uint8_t count = 0; uint32_t t1 = millis(); #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; #if (ARDUINO < 100) // Arduino v00xx (before v1.0), Wire library // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min((int)length, BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.send(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); - - for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { - data[count] = Wire.receive(); + for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->send(regAddr); + useWire->endTransmission(); + useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = useWire->receive(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); #endif } - - Wire.endTransmission(); } #elif (ARDUINO == 100) // Arduino v1.0.0, Wire library // Adds standardized write() and read() stream methods instead of send() and receive() // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min((int)length, BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.write(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); - - for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { - data[count] = Wire.read(); + for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = useWire->read(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); #endif } - - Wire.endTransmission(); } #elif (ARDUINO > 100) // Arduino v1.0.1+, Wire library // Adds official support for repeated start condition, yay! // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min((int)length, BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.write(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); - - for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { - data[count] = Wire.read(); + for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = useWire->read(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); @@ -328,7 +318,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Number of words read (-1 indicates failure) */ -int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout) { +int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout, void *wireObj) { #ifdef I2CDEV_SERIAL_DEBUG Serial.print("I2C (0x"); Serial.print(devAddr, HEX); @@ -339,32 +329,33 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 Serial.print("..."); #endif - int8_t count = 0; + uint8_t count = 0; uint32_t t1 = millis(); #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; #if (ARDUINO < 100) // Arduino v00xx (before v1.0), Wire library // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.send(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->send(regAddr); + useWire->endTransmission(); + useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes bool msb = true; // starts with MSB, then LSB - for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + for (; useWire->available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { if (msb) { // first byte is bits 15-8 (MSb=15) - data[count] = Wire.receive() << 8; + data[count] = useWire->receive() << 8; } else { // second byte is bits 7-0 (LSb=0) - data[count] |= Wire.receive(); + data[count] |= useWire->receive(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); @@ -373,31 +364,28 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 } msb = !msb; } - - Wire.endTransmission(); } #elif (ARDUINO == 100) // Arduino v1.0.0, Wire library // Adds standardized write() and read() stream methods instead of send() and receive() // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.write(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes bool msb = true; // starts with MSB, then LSB - for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + for (; useWire->available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { if (msb) { // first byte is bits 15-8 (MSb=15) - data[count] = Wire.read() << 8; + data[count] = useWire->read() << 8; } else { // second byte is bits 7-0 (LSb=0) - data[count] |= Wire.read(); + data[count] |= useWire->read(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); @@ -406,31 +394,28 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 } msb = !msb; } - - Wire.endTransmission(); } #elif (ARDUINO > 100) // Arduino v1.0.1+, Wire library // Adds official support for repeated start condition, yay! // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.write(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes bool msb = true; // starts with MSB, then LSB - for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + for (; useWire->available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { if (msb) { // first byte is bits 15-8 (MSb=15) - data[count] = Wire.read() << 8; + data[count] = useWire->read() << 8; } else { // second byte is bits 7-0 (LSb=0) - data[count] |= Wire.read(); + data[count] |= useWire->read(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); @@ -439,8 +424,6 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 } msb = !msb; } - - Wire.endTransmission(); } #endif @@ -479,11 +462,11 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 * @param value New bit value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) { +bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data, void *wireObj) { uint8_t b; - readByte(devAddr, regAddr, &b); + readByte(devAddr, regAddr, &b, I2Cdev::readTimeout, wireObj); b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); - return writeByte(devAddr, regAddr, b); + return writeByte(devAddr, regAddr, b, wireObj); } /** write a single bit in a 16-bit device register. @@ -493,11 +476,11 @@ bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t * @param value New bit value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data) { +bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data, void *wireObj) { uint16_t w; - readWord(devAddr, regAddr, &w); + readWord(devAddr, regAddr, &w, I2Cdev::readTimeout, wireObj); w = (data != 0) ? (w | (1 << bitNum)) : (w & ~(1 << bitNum)); - return writeWord(devAddr, regAddr, w); + return writeWord(devAddr, regAddr, w, wireObj); } /** Write multiple bits in an 8-bit device register. @@ -508,7 +491,7 @@ bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_ * @param data Right-aligned value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) { +bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data, void *wireObj) { // 010 value to write // 76543210 bit numbers // xxx args: bitStart=4, length=3 @@ -517,13 +500,13 @@ bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8 // 10100011 original & ~mask // 10101011 masked | value uint8_t b; - if (readByte(devAddr, regAddr, &b) != 0) { + if (readByte(devAddr, regAddr, &b, I2Cdev::readTimeout, wireObj) != 0) { uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); data <<= (bitStart - length + 1); // shift data into correct position data &= mask; // zero all non-important bits in data b &= ~(mask); // zero all important bits in existing byte b |= data; // combine data with existing byte - return writeByte(devAddr, regAddr, b); + return writeByte(devAddr, regAddr, b, wireObj); } else { return false; } @@ -537,7 +520,7 @@ bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8 * @param data Right-aligned value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data) { +bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data, void *wireObj) { // 010 value to write // fedcba9876543210 bit numbers // xxx args: bitStart=12, length=3 @@ -546,13 +529,13 @@ bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint // 1010001110010110 original & ~mask // 1010101110010110 masked | value uint16_t w; - if (readWord(devAddr, regAddr, &w) != 0) { + if (readWord(devAddr, regAddr, &w, I2Cdev::readTimeout, wireObj) != 0) { uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); data <<= (bitStart - length + 1); // shift data into correct position data &= mask; // zero all non-important bits in data w &= ~(mask); // zero all important bits in existing word w |= data; // combine data with existing word - return writeWord(devAddr, regAddr, w); + return writeWord(devAddr, regAddr, w, wireObj); } else { return false; } @@ -564,8 +547,8 @@ bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint * @param data New byte value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { - return writeBytes(devAddr, regAddr, 1, &data); +bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data, void *wireObj) { + return writeBytes(devAddr, regAddr, 1, &data, wireObj); } /** Write single word to a 16-bit device register. @@ -574,8 +557,8 @@ bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { * @param data New word value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) { - return writeWords(devAddr, regAddr, 1, &data); +bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data, void *wireObj) { + return writeWords(devAddr, regAddr, 1, &data, wireObj); } /** Write multiple bytes to an 8-bit device register. @@ -585,7 +568,7 @@ bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) { * @param data Buffer to copy new data from * @return Status of operation (true = success) */ -bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) { +bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data, void *wireObj) { #ifdef I2CDEV_SERIAL_DEBUG Serial.print("I2C (0x"); Serial.print(devAddr, HEX); @@ -596,14 +579,20 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ Serial.print("..."); #endif uint8_t status = 0; + +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; +#endif + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.beginTransmission(devAddr); - Wire.send((uint8_t) regAddr); // send address + useWire->beginTransmission(devAddr); + useWire->send((uint8_t) regAddr); // send address #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - Wire.beginTransmission(devAddr); - Wire.write((uint8_t) regAddr); // send address + useWire->beginTransmission(devAddr); + useWire->write((uint8_t) regAddr); // send address #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::beginTransmission(devAddr); Fastwire::write(regAddr); @@ -614,21 +603,21 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ if (i + 1 < length) Serial.print(" "); #endif #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.send((uint8_t) data[i]); + useWire->send((uint8_t) data[i]); #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - Wire.write((uint8_t) data[i]); + useWire->write((uint8_t) data[i]); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::write((uint8_t) data[i]); #endif } #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.endTransmission(); + useWire->endTransmission(); #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - status = Wire.endTransmission(); + status = useWire->endTransmission(); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::stop(); //status = Fastwire::endTransmission(); @@ -646,7 +635,7 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ * @param data Buffer to copy new data from * @return Status of operation (true = success) */ -bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) { +bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data, void *wireObj) { #ifdef I2CDEV_SERIAL_DEBUG Serial.print("I2C (0x"); Serial.print(devAddr, HEX); @@ -657,14 +646,20 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 Serial.print("..."); #endif uint8_t status = 0; + +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; +#endif + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.beginTransmission(devAddr); - Wire.send(regAddr); // send address + useWire->beginTransmission(devAddr); + useWire->send(regAddr); // send address #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - Wire.beginTransmission(devAddr); - Wire.write(regAddr); // send address + useWire->beginTransmission(devAddr); + useWire->write(regAddr); // send address #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::beginTransmission(devAddr); Fastwire::write(regAddr); @@ -675,13 +670,13 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 if (i + 1 < length) Serial.print(" "); #endif #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.send((uint8_t)(data[i] >> 8)); // send MSB - Wire.send((uint8_t)data[i]); // send LSB + useWire->send((uint8_t)(data[i] >> 8)); // send MSB + useWire->send((uint8_t)data[i]); // send LSB #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - Wire.write((uint8_t)(data[i] >> 8)); // send MSB - Wire.write((uint8_t)data[i]); // send LSB + useWire->write((uint8_t)(data[i] >> 8)); // send MSB + useWire->write((uint8_t)data[i]); // send LSB #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::write((uint8_t)(data[i] >> 8)); // send MSB status = Fastwire::write((uint8_t)data[i]); // send LSB @@ -689,11 +684,11 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 #endif } #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.endTransmission(); + useWire->endTransmission(); #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - status = Wire.endTransmission(); + status = useWire->endTransmission(); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::stop(); //status = Fastwire::endTransmission(); @@ -753,7 +748,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; #endif TWSR = 0; // no prescaler => prescaler = 1 - TWBR = ((16000L / khz) - 16) / 2; // change the I2C clock rate + TWBR = F_CPU / 2000 / khz - 8; // change the I2C clock rate TWCR = 1 << TWEN; // enable twi module, no interrupt } @@ -993,7 +988,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2; // bitrate register // enable twi module, acks, and twi interrupt - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA); /* TWEN - TWI Enable Bit TWIE - TWI Interrupt Enable @@ -1062,7 +1057,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; } void twii_SetStart() { - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWSTA); } void twi_write01() { @@ -1145,19 +1140,19 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; void twi_reply(uint8_t ack) { // transmit master read ready signal, with or without ack if (ack){ - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT) | (1 << TWEA); } else { - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT); } } void twi_stop(void) { // send stop condition - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWSTO); // wait for stop condition to be exectued on bus // TWINT is not set after a stop condition! - while (TWCR & _BV(TWSTO)) { + while (TWCR & (1 << TWSTO)) { continue; } @@ -1167,7 +1162,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; void twi_releaseBus(void) { // release bus - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT); // update twi state twi_state = TWI_READY; diff --git a/src/utility/ioexpander/I2Cdev.h b/src/utility/ioexpander/I2Cdev.h index 60c3195..5b59c56 100644 --- a/src/utility/ioexpander/I2Cdev.h +++ b/src/utility/ioexpander/I2Cdev.h @@ -3,6 +3,7 @@ // 2013-06-05 by Jeff Rowberg // // Changelog: +// 2021-09-28 - allow custom Wire object as transaction function argument // 2020-01-20 - hardija : complete support for Teensy 3.x // 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1 // 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications @@ -48,6 +49,11 @@ THE SOFTWARE. #ifndef _I2CDEV_H_ #define _I2CDEV_H_ +// ----------------------------------------------------------------------------- +// Enable deprecated pgmspace typedefs in avr-libc +// ----------------------------------------------------------------------------- +#define __PROG_TYPES_COMPAT__ + // ----------------------------------------------------------------------------- // I2C interface implementation setting // ----------------------------------------------------------------------------- @@ -99,10 +105,26 @@ THE SOFTWARE. #endif #ifdef SPARK - #include + #include "application.h" #define ARDUINO 101 + #define BUFFER_LENGTH 32 #endif +#ifndef I2CDEVLIB_WIRE_BUFFER_LENGTH + #if defined(I2C_BUFFER_LENGTH) + // Arduino ESP32 core Wire uses this + #define I2CDEVLIB_WIRE_BUFFER_LENGTH I2C_BUFFER_LENGTH + #elif defined(BUFFER_LENGTH) + // Arduino AVR core Wire and many others use this + #define I2CDEVLIB_WIRE_BUFFER_LENGTH BUFFER_LENGTH + #elif defined(SERIAL_BUFFER_SIZE) + // Arduino SAMD core Wire uses this + #define I2CDEVLIB_WIRE_BUFFER_LENGTH SERIAL_BUFFER_SIZE + #else + // should be a safe fallback, though possibly inefficient + #define I2CDEVLIB_WIRE_BUFFER_LENGTH 32 + #endif +#endif // 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];") #define I2CDEV_DEFAULT_READ_TIMEOUT 1000 @@ -111,23 +133,23 @@ class I2Cdev { public: I2Cdev(); - static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); - - static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data); - static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data); - static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data); - static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data); - static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data); - static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data); - static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); - static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + + static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data, void *wireObj=0); + static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data, void *wireObj=0); + static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data, void *wireObj=0); + static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data, void *wireObj=0); + static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data, void *wireObj=0); + static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data, void *wireObj=0); + static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, void *wireObj=0); + static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, void *wireObj=0); static uint16_t readTimeout; }; @@ -240,7 +262,7 @@ class I2Cdev { /* TWI Status is in TWSR, in the top 5 bits: TWS7 - TWS3 */ - #define TW_STATUS_MASK (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|_BV(TWS3)) + #define TW_STATUS_MASK ((1 << TWS7)|(1 << TWS6)|(1 << TWS5)|(1 << TWS4)|(1 << TWS3)) #define TW_STATUS (TWSR & TW_STATUS_MASK) #define TW_START 0x08 #define TW_REP_START 0x10 @@ -275,11 +297,11 @@ class I2Cdev { //#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr)) #ifndef sbi // set bit - #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) + #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= (1 << bit)) #endif // sbi #ifndef cbi // clear bit - #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) + #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~(1 << bit)) #endif // cbi extern TwoWire Wire; diff --git a/src/utility/ioexpander/TCA6424A.cpp b/src/utility/ioexpander/TCA6424A.cpp index 6c63e73..550e237 100644 --- a/src/utility/ioexpander/TCA6424A.cpp +++ b/src/utility/ioexpander/TCA6424A.cpp @@ -87,7 +87,7 @@ uint8_t TCA6424A::readBank(uint8_t bank) { * @param banks Container for all bank's pin values (P00-P27) */ void TCA6424A::readAll(uint8_t *banks) { - I2Cdev::readBytes(devAddr, TCA6424A_RA_INPUT0, 3, banks); + I2Cdev::readBytes(devAddr, TCA6424A_RA_INPUT0 | TCA6424A_AUTO_INCREMENT, 3, banks); } /** Get all pin logic levels from all banks. * Reads into individual 1-byte containers. @@ -96,7 +96,7 @@ void TCA6424A::readAll(uint8_t *banks) { * @param bank2 Container for Bank 2's pin values (P20-P27) */ void TCA6424A::readAll(uint8_t *bank0, uint8_t *bank1, uint8_t *bank2) { - I2Cdev::readBytes(devAddr, TCA6424A_RA_INPUT0, 3, buffer); + I2Cdev::readBytes(devAddr, TCA6424A_RA_INPUT0 | TCA6424A_AUTO_INCREMENT, 3, buffer); *bank0 = buffer[0]; *bank1 = buffer[1]; *bank2 = buffer[2];