Added SensorLib

This commit is contained in:
lewisxhe 2024-05-15 11:38:17 +08:00
parent b0a5ecd796
commit f864b5ea47
138 changed files with 43016 additions and 0 deletions

1
lib/SensorLib/.piopm Normal file
View File

@ -0,0 +1 @@
{"type": "library", "name": "SensorLib", "version": "0.2.0", "spec": {"owner": "lewisxhe", "id": 15035, "name": "SensorLib", "requirements": null, "uri": null}}

21
lib/SensorLib/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 lewis he
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.

73
lib/SensorLib/README.md Normal file
View File

@ -0,0 +1,73 @@
```
_____ _ _ _
/ ___| | | (_)| |
\ `--. ___ _ __ ___ ___ _ __ | | _ | |__
`--. \ / _ \| '_ \ / __| / _ \ | '__|| | | || '_ \
/\__/ /| __/| | | |\__ \| (_) || | | |____| || |_) |
\____/ \___||_| |_||___/ \___/ |_| \_____/|_||_.__/
··· ···
> Commonly used I2C , SPI device multi-platform libraries
```
[![Build esp-idf](https://github.com/lewisxhe/SensorLib/actions/workflows/esp-idf.yml/badge.svg)](https://github.com/lewisxhe/SensorLib/actions/workflows/esp-idf.yml)
[![Arduino CI](https://github.com/lewisxhe/SensorLib/actions/workflows/arduino_ci.yml/badge.svg)](https://github.com/lewisxhe/SensorLib/actions/workflows/arduino_ci.yml)
[![PlatformIO CI](https://github.com/lewisxhe/SensorLib/actions/workflows/pio.yml/badge.svg)](https://github.com/lewisxhe/SensorLib/actions/workflows/pio.yml)
[![arduino-library-badge](https://www.ardu-badge.com/badge/SensorLib.svg?)](https://www.ardu-badge.com/SensorLib)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/lewisxhe/library/SensorLib.svg)](https://registry.platformio.org/libraries/lewisxhe/SensorLib)
[![LICENSE](https://img.shields.io/github/license/lewisxhe/SensorLib)](https://github.com/lewisxhe/SensorLib/blob/master/LICENSE)
[![ISSUES](https://img.shields.io/github/issues/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorsLib/issues)
[![FROK](https://img.shields.io/github/forks/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorsLib/graphs/contributors)
[![STAR](https://img.shields.io/github/stars/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorsLib/stargazers)
[![releases](https://img.shields.io/github/release/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorLib/releases)
![PCF8563](https://img.shields.io/badge/PCB8563-GREEN)
![PCF85063](https://img.shields.io/badge/PCF85063-GREEN)
![HYM8563](https://img.shields.io/badge/HYM8563-GREEN)
![QMI8658](https://img.shields.io/badge/QMI8658-blue)
![BMM150](https://img.shields.io/badge/BMM150-blue)
![QMC6310](https://img.shields.io/badge/QMC6310-blue)
![BMA423](https://img.shields.io/badge/BMA423-blue)
![BHI260AP](https://img.shields.io/badge/BHI260AP-blue)
![XL9555](https://img.shields.io/badge/XL9555-yellow)
![DRV2605](https://img.shields.io/badge/DRV2605-teal)
![CM32181](https://img.shields.io/badge/CM32181-brown)
![LTR553](https://img.shields.io/badge/LTR553-brown)
![FT5206](https://img.shields.io/badge/FT5206-red)
![FT6206](https://img.shields.io/badge/FT6206-red)
![FT6236](https://img.shields.io/badge/FT6236-red)
![FT3267](https://img.shields.io/badge/FT3267-red)
![CST816S](https://img.shields.io/badge/CST816S-red)
![CST816D](https://img.shields.io/badge/CST816D-red)
![CST816T](https://img.shields.io/badge/CST816T-red)
![CST820](https://img.shields.io/badge/CST820-red)
![CST226SE](https://img.shields.io/badge/CST226SE-red)
![CHSC5816](https://img.shields.io/badge/CHSC5816-red)
![GT911](https://img.shields.io/badge/GT911-red)
Support list:
| Sensor | Description | I2C | SPI |
| --------------- | ------------------------ | --- | --- |
| PCF8563/HYM8563 | Real-time clock | ✔️ | ❌ |
| PCF85063 | Real-time clock | ✔️ | ❌ |
| QMI8658 | IMU | ✔️ | ✔️ |
| BHI260AP | IMU | ✔️ | ✔️ |
| QMC6310 | Magnetic Sensor | ✔️ | ❌ |
| BMM150 | Magnetic Sensor | ✔️ | ❌ |
| XL9555 | I/O expander | ✔️ | ❌ |
| BMA423 | Accelerometer | ✔️ | ❌ |
| DRV2605 | Haptic Driver | ✔️ | ❌ |
| CM32181 | Ambient Light Sensor | ✔️ | ❌ |
| LTR553 | Light & Proximity Sensor | ✔️ | ❌ |
| FT3267 | Capacitive touch | ✔️ | ❌ |
| FT5206 | Capacitive touch | ✔️ | ❌ |
| FT6206 | Capacitive touch | ✔️ | ❌ |
| FT6236 | Capacitive touch | ✔️ | ❌ |
| CST820 | Capacitive touch | ✔️ | ❌ |
| CST816S/T/D | Capacitive touch | ✔️ | ❌ |
| CST226SE | Capacitive touch | ✔️ | ❌ |
| CHSC5816 | Capacitive touch | ✔️ | ❌ |
| GT911 | Capacitive touch | ✔️ | ❌ |

View File

@ -0,0 +1,88 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file BAM423_Accelerometer.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-01
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBMA423.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 21
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 22
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 39
#endif
SensorBMA423 accel;
uint32_t lastMillis;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT);
if (!accel.begin(Wire, BMA423_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find BMA423 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init BAM423 Sensor success!");
//Default 4G ,200HZ
accel.configAccelerometer();
accel.enableAccelerometer();
}
void loop()
{
int16_t x, y, z;
accel.getAccelerometer(x, y, z);
Serial.print("X:");
Serial.print(x); Serial.print(" ");
Serial.print("Y:");
Serial.print(y); Serial.print(" ");
Serial.print("Z:");
Serial.print(z);
Serial.println();
delay(50);
}

View File

@ -0,0 +1,142 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file BAM423_Orientation.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-03
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBMA423.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 21
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 22
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 39
#endif
SensorBMA423 accel;
char report[256];
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT);
if (!accel.begin(Wire, BMA423_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find BMA423 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init BAM423 Sensor success!");
//Default 4G ,200HZ
accel.configAccelerometer();
accel.enableAccelerometer();
Serial.println("Output ...");
}
void loop()
{
uint8_t direction = accel.direction();
switch (direction) {
case SensorBMA423::DIRECTION_BOTTOM_LEFT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | * | " \
"\r\n |________________| \r\n" );
break;
case SensorBMA423::DIRECTION_TOP_RIGHT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | * | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n |________________| \r\n" );
break;
case SensorBMA423::DIRECTION_TOP_LEFT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | * | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n |________________| \r\n" );
break;
case SensorBMA423::DIRECTION_BOTTOM_RIGHT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | * | " \
"\r\n |________________| \r\n" );
break;
case SensorBMA423::DIRECTION_BOTTOM:
sprintf( report, "\r\n ________________ " \
"\r\n |________________| " \
"\r\n * \r\n" );
break;
case SensorBMA423::DIRECTION_TOP:
sprintf( report, "\r\n __*_____________ " \
"\r\n |________________| \r\n" );
break;
default:
sprintf( report, "None of the 3D orientation axes is set in BMA423 - accelerometer.\r\n" );
break;
}
Serial.println(direction);
Serial.println(report);
delay(1000);
}

View File

@ -0,0 +1,77 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file BAM423_Temperature.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-01
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBMA423.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 21
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 22
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 39
#endif
SensorBMA423 accel;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT);
if (!accel.begin(Wire, BMA423_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find BMA423 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init BAM423 Sensor success!");
}
void loop()
{
Serial.print("getTemperature:");
Serial.print(accel.getTemperature(SensorBMA423::TEMP_DEG));
Serial.print("*C ");
Serial.print(accel.getTemperature(SensorBMA423::TEMP_FAHREN));
Serial.print("*F");
delay(1000);
}

View File

@ -0,0 +1,140 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* 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.
*
* @file BHI260AP_6DoF.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-06
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBHI260AP.hpp"
#ifdef BHY2_USE_I2C
#define BHI260AP_SDA 21
#define BHI260AP_SCL 22
#define BHI260AP_IRQ 39
#define BHI260AP_RST -1
#else
#define BHI260AP_MOSI 33
#define BHI260AP_MISO 34
#define BHI260AP_SCK 35
#define BHI260AP_CS 36
#define BHI260AP_IRQ 37
#define BHI260AP_RST 47
#endif
SensorBHI260AP bhy;
void accel_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len)
{
struct bhy2_data_xyz data;
float scaling_factor = get_sensor_default_scaling(sensor_id);
bhy2_parse_xyz(data_ptr, &data);
Serial.print(bhy.getSensorName(sensor_id));
Serial.print(":");
Serial.printf("x: %f, y: %f, z: %f;\r\n",
data.x * scaling_factor,
data.y * scaling_factor,
data.z * scaling_factor
);
}
void gyro_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len)
{
struct bhy2_data_xyz data;
float scaling_factor = get_sensor_default_scaling(sensor_id);
bhy2_parse_xyz(data_ptr, &data);
Serial.print(bhy.getSensorName(sensor_id));
Serial.print(":");
Serial.printf("x: %f, y: %f, z: %f;\r\n",
data.x * scaling_factor,
data.y * scaling_factor,
data.z * scaling_factor
);
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin and interrupt pin, if any
bhy.setPins(BHI260AP_RST, BHI260AP_IRQ);
#ifdef BHY2_USE_I2C
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.init(Wire, BHI260AP_SDA, BHI260AP_SCL, BHI260AP_SLAVE_ADDRESS_L)) {
Serial.print("Failed to init BHI260AP - ");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#else
// Using SPI interface
if (!bhy.init(SPI, BHI260AP_CS, BHI260AP_MOSI, BHI260AP_MISO, BHI260AP_SCK)) {
Serial.print("Failed to init BHI260AP - ");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Init BHI260AP Sensor success!");
// Output all available sensors to Serial
bhy.printSensors(Serial);
float sample_rate = 100.0; /* Read out hintr_ctrl measured at 100Hz */
uint32_t report_latency_ms = 0; /* Report immediately */
// Enable acceleration
bhy.configure(SENSOR_ID_ACC_PASS, sample_rate, report_latency_ms);
// Enable gyroscope
bhy.configure(SENSOR_ID_GYRO_PASS, sample_rate, report_latency_ms);
// Set the acceleration sensor result callback function
bhy.onResultEvent(SENSOR_ID_ACC_PASS, accel_process_callback);
// Set the gyroscope sensor result callback function
bhy.onResultEvent(SENSOR_ID_GYRO_PASS, gyro_process_callback);
}
void loop()
{
// Update sensor fifo
bhy.update();
delay(50);
}

View File

@ -0,0 +1,107 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* 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.
*
* @file BHI260AP_DebugInfo.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-10-08
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBHI260AP.hpp"
#ifdef BHY2_USE_I2C
#define BHI260AP_SDA 21
#define BHI260AP_SCL 22
#define BHI260AP_IRQ 39
#define BHI260AP_RST -1
#else
#define BHI260AP_MOSI 33
#define BHI260AP_MISO 34
#define BHI260AP_SCK 35
#define BHI260AP_CS 36
#define BHI260AP_IRQ 37
#define BHI260AP_RST 47
#endif
SensorBHI260AP bhy;
void quaternion_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len)
{
Serial.println(bhy.getSensorName(sensor_id));
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin and interrupt pin, if any
bhy.setPins(BHI260AP_RST, BHI260AP_IRQ);
#ifdef BHY2_USE_I2C
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.init(Wire, BHI260AP_SDA, BHI260AP_SCL, BHI260AP_SLAVE_ADDRESS_L)) {
Serial.print("Failed to init BHI260AP - ");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#else
// Using SPI interface
if (!bhy.init(SPI, BHI260AP_CS, BHI260AP_MOSI, BHI260AP_MISO, BHI260AP_SCK)) {
Serial.print("Failed to init BHI260AP - ");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Init BHI260AP Sensor success!");
// Output all current sensor information
bhy.printInfo(Serial);
// Output interrupt configuration information to Serial
bhy.printInterruptCtrl(Serial);
}
void loop()
{
// Update sensor fifo
bhy.update();
delay(50);
}

View File

@ -0,0 +1,163 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* 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.
*
* @file BHI260AP_Orientation.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-10-07
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBHI260AP.hpp"
#ifdef BHY2_USE_I2C
#define BHI260AP_SDA 21
#define BHI260AP_SCL 22
#define BHI260AP_IRQ 39
#define BHI260AP_RST -1
#else
#define BHI260AP_MOSI 33
#define BHI260AP_MISO 34
#define BHI260AP_SCK 35
#define BHI260AP_CS 36
#define BHI260AP_IRQ 37
#define BHI260AP_RST 47
#endif
void orientation_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len);
SensorBHI260AP bhy;
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin and interrupt pin, if any
bhy.setPins(BHI260AP_RST, BHI260AP_IRQ);
#ifdef BHY2_USE_I2C
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.init(Wire, BHI260AP_SDA, BHI260AP_SCL, BHI260AP_SLAVE_ADDRESS_L)) {
Serial.print("Failed to init BHI260AP - ");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#else
// Using SPI interface
if (!bhy.init(SPI, BHI260AP_CS, BHI260AP_MOSI, BHI260AP_MISO, BHI260AP_SCK)) {
Serial.print("Failed to init BHI260AP - ");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Init BHI260AP Sensor success!");
// Output all available sensors to Serial
bhy.printSensors(Serial);
float sample_rate = 100.0; /* Read out hintr_ctrl measured at 100Hz */
uint32_t report_latency_ms = 0; /* Report immediately */
// Direction detection relies on the accelerometer, and the accelerometer needs to be turned on first.
bhy.configure(SENSOR_ID_ACC_PASS, sample_rate, report_latency_ms);
// Enable direction detection
bhy.configure(SENSOR_ID_DEVICE_ORI, sample_rate, report_latency_ms);
// Set the direction detection result output processing function
bhy.onResultEvent(SENSOR_ID_DEVICE_ORI, orientation_process_callback);
}
void loop()
{
// Update sensor fifo
bhy.update();
delay(50);
}
void orientation_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len)
{
char report[256];
uint8_t direction = *data_ptr;
switch (direction) {
case BHY2_DIRECTION_BOTTOM_LEFT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | * | " \
"\r\n |________________| \r\n" );
break;
case BHY2_DIRECTION_TOP_RIGHT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | * | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n |________________| \r\n" );
break;
case BHY2_DIRECTION_TOP_LEFT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | * | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n |________________| \r\n" );
break;
case BHY2_DIRECTION_BOTTOM_RIGHT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | * | " \
"\r\n |________________| \r\n" );
break;
default:
sprintf( report, "None of the 3D orientation axes is set in BHI260 - accelerometer.\r\n" );
break;
}
Serial.print(bhy.getSensorName(sensor_id));
Serial.print(":");
Serial.println(direction);
Serial.println(report);
}

View File

@ -0,0 +1,125 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* 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.
*
* @file BHI260AP_StepCounter.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-10-08
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBHI260AP.hpp"
#ifdef BHY2_USE_I2C
#define BHI260AP_SDA 21
#define BHI260AP_SCL 22
#define BHI260AP_IRQ 39
#define BHI260AP_RST -1
#else
#define BHI260AP_MOSI 33
#define BHI260AP_MISO 34
#define BHI260AP_SCK 35
#define BHI260AP_CS 36
#define BHI260AP_IRQ 37
#define BHI260AP_RST 47
#endif
SensorBHI260AP bhy;
void step_detector_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len)
{
Serial.print(bhy.getSensorName(sensor_id));
Serial.println(" detected.");
}
void step_counter_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len)
{
Serial.print(bhy.getSensorName(sensor_id));
Serial.print(":");
Serial.println(bhy2_parse_step_counter(data_ptr));
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin and interrupt pin, if any
bhy.setPins(BHI260AP_RST, BHI260AP_IRQ);
#ifdef BHY2_USE_I2C
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.init(Wire, BHI260AP_SDA, BHI260AP_SCL, BHI260AP_SLAVE_ADDRESS_L)) {
Serial.print("Failed to init BHI260AP - ");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#else
// Using SPI interface
if (!bhy.init(SPI, BHI260AP_CS, BHI260AP_MOSI, BHI260AP_MISO, BHI260AP_SCK)) {
Serial.print("Failed to init BHI260AP - ");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Init BHI260AP Sensor success!");
// Output all available sensors to Serial
bhy.printSensors(Serial);
float sample_rate = 100.0; /* Read out hintr_ctrl measured at 100Hz */
uint32_t report_latency_ms = 0; /* Report immediately */
// Direction Step count relies on the accelerometer, and the accelerometer needs to be turned on first.
bhy.configure(SENSOR_ID_ACC_PASS, sample_rate, report_latency_ms);
// Enable Step detector
bhy.configure(SENSOR_ID_STD, sample_rate, report_latency_ms);
// Enable Step counter
bhy.configure(SENSOR_ID_STC, sample_rate, report_latency_ms);
// Set the number of steps to detect the callback function
bhy.onResultEvent(SENSOR_ID_STD, step_detector_process_callback);
bhy.onResultEvent(SENSOR_ID_STC, step_counter_process_callback);
}
void loop()
{
// Update sensor fifo
bhy.update();
delay(50);
}

View File

@ -0,0 +1,140 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file BMA423_Feature.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-03
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBMA423.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 21
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 22
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 39
#endif
SensorBMA423 accel;
uint32_t lastMillis;
bool sensorIRQ = false;
void setFlag()
{
sensorIRQ = true;
}
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT);
attachInterrupt(SENSOR_IRQ, setFlag, RISING);
if (!accel.begin(Wire, BMA423_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find BMA423 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init BAM423 Sensor success!");
//Default 4G ,200HZ
accel.configAccelerometer();
// Enable acceleration sensor
accel.enableAccelerometer();
// Enable pedometer steps
accel.enablePedometer();
// Emptying the pedometer steps
accel.resetPedometer();
// Enable sensor features
accel.enableFeature(SensorBMA423::FEATURE_STEP_CNTR |
SensorBMA423::FEATURE_ANY_MOTION |
SensorBMA423::FEATURE_ACTIVITY |
SensorBMA423::FEATURE_TILT |
SensorBMA423::FEATURE_WAKEUP,
true);
// Pedometer interrupt enable
accel.enablePedometerIRQ();
// Tilt interrupt enable
accel.enableTiltIRQ();
// DoubleTap interrupt enable
accel.enableWakeupIRQ();
// Any motion / no motion interrupt enable
accel.enableAnyNoMotionIRQ();
// Activity interruption enable
accel.enableActivityIRQ();
// Chip interrupt function enable
accel.configInterrupt();
}
void loop()
{
int16_t x, y, z;
if (sensorIRQ) {
sensorIRQ = false;
// The interrupt status must be read after an interrupt is detected
uint16_t status = accel.readIrqStatus();
Serial.printf("Accelerometer interrupt mask : 0x%x\n", status);
if (accel.isPedometer()) {
uint32_t stepCounter = accel.getPedometerCounter();
Serial.printf("Step count interrupt,step Counter:%u\n", stepCounter);
}
if (accel.isActivity()) {
Serial.println("Activity interrupt");
}
if (accel.isTilt()) {
Serial.println("Tilt interrupt");
}
if (accel.isDoubleTap()) {
Serial.println("DoubleTap interrupt");
}
if (accel.isAnyNoMotion()) {
Serial.println("Any motion / no motion interrupt");
}
}
delay(50);
}

View File

@ -0,0 +1,102 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* 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.
*
* @file BMM150_GetDataExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-10-10
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBMM150.hpp"
#include "SensorWireHelper.h"
#ifndef SENSOR_SDA
#define SENSOR_SDA 33
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 35
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
#ifndef SENSOR_RST
#define SENSOR_RST -1
#endif
SensorBMM150 bmm;
void setup()
{
Serial.begin(115200);
while (!Serial);
// Using I2C interface
if (!bmm.init(Wire, SENSOR_SDA, SENSOR_SCL, BMM150_I2C_ADDRESS_CSB_HIGH_SDO_LOW)) {
Serial.print("Failed to init BMM150 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init BMM150 Sensor success!");
/* Set magnetometer run mode */
/**
* * POWERMODE_NORMAL,
* * POWERMODE_FORCED,
* * POWERMODE_SLEEP,
* * POWERMODE_SUSPEND,
*/
bmm.setMode(SensorBMM150::POWERMODE_NORMAL);
}
void loop()
{
int16_t x, y, z;
/* Read mag data */
/* Unit for magnetometer data is microtesla(uT) */
if (bmm.getMag(x, y, z)) {
Serial.print("X:");
Serial.print(x);
Serial.print("uT,");
Serial.print("Y:");
Serial.print(y);
Serial.print("uT,");
Serial.print("Z:");
Serial.print(z);
Serial.println("uT");
}
delay(50);
}

View File

@ -0,0 +1,97 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file CM32181_LightSensor.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-14
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorCM32181.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 39
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 40
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 1
#endif
SensorCM32181 light;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT_PULLUP);
if (!light.begin(Wire, CM32181_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find CM32181 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init CM32181 Sensor success!");
int id = light.getChipID();
Serial.print("CM32181 ID = "); Serial.println(id);
/*
Sensitivity mode selection
SAMPLING_X1
SAMPLING_X2
SAMPLING_X1_8
SAMPLING_X1_4
*/
light.setSampling(SensorCM32181::SAMPLING_X2);
//Power On sensor
light.powerOn();
}
void loop()
{
// Get raw data
uint16_t raw = light.getRaw();
// Get conversion data , The manual does not provide information on how to obtain the
// calibration value, now use the calibration value 0.28 provided by the manual
float lux = light.getLux();
Serial.printf("RAW:%u Lux:%.2f\n", raw, lux);
delay(500);
}

View File

@ -0,0 +1,134 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* 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.
*
* @file CM32181_LightSensorInterrupt.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-13
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorCM32181.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 39
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 40
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 1
#endif
SensorCM32181 light;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT_PULLUP);
if (!light.begin(Wire, CM32181_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find CM32181 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init CM32181 Sensor success!");
int id = light.getChipID();
Serial.print("CM32181 ID = "); Serial.println(id);
/*
Sensitivity mode selection
SAMPLING_X1
SAMPLING_X2
SAMPLING_X1_8
SAMPLING_X1_4
*/
light.setSampling(SensorCM32181::SAMPLING_X2,
SensorCM32181::INTEGRATION_TIME_400MS
);
// Set high and low thresholds. If the threshold is higher or lower than the set threshold, an interrupt will be triggered.
uint16_t lowThresholdRaw = 100;
uint16_t highThresholdRaw = 250;
light.setIntThreshold(lowThresholdRaw, highThresholdRaw);
//Power On sensor
light.powerOn();
// Turn on interrupt
light.enableINT();
}
void loop()
{
int pinVal = digitalRead(SENSOR_IRQ) ;
if (pinVal == LOW) {
// After triggering the interrupt, the interrupt status must be read
SensorCM32181::InterruptEvent event = light.getIrqStatus();
// Turn off interrupts
light.disableINT();
// Get Status
switch (event) {
case SensorCM32181::ALS_EVENT_LOW_TRIGGER:
Serial.println("Low interrupt event");
break;
case SensorCM32181::ALS_EVENT_HIGH_TRIGGER:
Serial.println("High interrupt event");
break;
default:
Serial.println("This is an impossible place to reach");
break;
}
// Get raw data
uint16_t raw = light.getRaw();
// Get conversion data , The manual does not provide information on how to obtain the
// calibration value, now use the calibration value 0.28 provided by the manual
float lux = light.getLux();
Serial.printf("IRQ:%d RAW:%u Lux:%.2f\n", pinVal, raw, lux);
// Turn on interrupts
light.enableINT();
}
delay(800);
}

View File

@ -0,0 +1,468 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file DRV2605_Basic.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-03
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorDRV2605.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 21
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 22
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 39
#endif
SensorDRV2605 drv;
uint8_t effect = 1;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT);
if (!drv.begin(Wire, DRV2605_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find DRV2605 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init DRV2605 Sensor success!");
drv.selectLibrary(1);
// I2C trigger by sending 'run' command
// default, internal trigger when sending RUN command
drv.setMode(DRV2605_MODE_INTTRIG);
}
void loop()
{
Serial.print("Effect #"); Serial.println(effect);
if (effect == 1) {
Serial.println("11.2 Waveform Library Effects List");
}
if (effect == 1) {
Serial.println(F("1 - Strong Click - 100%"));
}
if (effect == 2) {
Serial.println(F("2 - Strong Click - 60%"));
}
if (effect == 3) {
Serial.println(F("3 - Strong Click - 30%"));
}
if (effect == 4) {
Serial.println(F("4 - Sharp Click - 100%"));
}
if (effect == 5) {
Serial.println(F("5 - Sharp Click - 60%"));
}
if (effect == 6) {
Serial.println(F("6 - Sharp Click - 30%"));
}
if (effect == 7) {
Serial.println(F("7 - Soft Bump - 100%"));
}
if (effect == 8) {
Serial.println(F("8 - Soft Bump - 60%"));
}
if (effect == 9) {
Serial.println(F("9 - Soft Bump - 30%"));
}
if (effect == 10) {
Serial.println(F("10 - Double Click - 100%"));
}
if (effect == 11) {
Serial.println(F("11 - Double Click - 60%"));
}
if (effect == 12) {
Serial.println(F("12 - Triple Click - 100%"));
}
if (effect == 13) {
Serial.println(F("13 - Soft Fuzz - 60%"));
}
if (effect == 14) {
Serial.println(F("14 - Strong Buzz - 100%"));
}
if (effect == 15) {
Serial.println(F("15 - 750 ms Alert 100%"));
}
if (effect == 16) {
Serial.println(F("16 - 1000 ms Alert 100%"));
}
if (effect == 17) {
Serial.println(F("17 - Strong Click 1 - 100%"));
}
if (effect == 18) {
Serial.println(F("18 - Strong Click 2 - 80%"));
}
if (effect == 19) {
Serial.println(F("19 - Strong Click 3 - 60%"));
}
if (effect == 20) {
Serial.println(F("20 - Strong Click 4 - 30%"));
}
if (effect == 21) {
Serial.println(F("21 - Medium Click 1 - 100%"));
}
if (effect == 22) {
Serial.println(F("22 - Medium Click 2 - 80%"));
}
if (effect == 23) {
Serial.println(F("23 - Medium Click 3 - 60%"));
}
if (effect == 24) {
Serial.println(F("24 - Sharp Tick 1 - 100%"));
}
if (effect == 25) {
Serial.println(F("25 - Sharp Tick 2 - 80%"));
}
if (effect == 26) {
Serial.println(F("26 - Sharp Tick 3 - 60%"));
}
if (effect == 27) {
Serial.println(F("27 - Short Double Click Strong 1 - 100%"));
}
if (effect == 28) {
Serial.println(F("28 - Short Double Click Strong 2 - 80%"));
}
if (effect == 29) {
Serial.println(F("29 - Short Double Click Strong 3 - 60%"));
}
if (effect == 30) {
Serial.println(F("30 - Short Double Click Strong 4 - 30%"));
}
if (effect == 31) {
Serial.println(F("31 - Short Double Click Medium 1 - 100%"));
}
if (effect == 32) {
Serial.println(F("32 - Short Double Click Medium 2 - 80%"));
}
if (effect == 33) {
Serial.println(F("33 - Short Double Click Medium 3 - 60%"));
}
if (effect == 34) {
Serial.println(F("34 - Short Double Sharp Tick 1 - 100%"));
}
if (effect == 35) {
Serial.println(F("35 - Short Double Sharp Tick 2 - 80%"));
}
if (effect == 36) {
Serial.println(F("36 - Short Double Sharp Tick 3 - 60%"));
}
if (effect == 37) {
Serial.println(F("37 - Long Double Sharp Click Strong 1 - 100%"));
}
if (effect == 38) {
Serial.println(F("38 - Long Double Sharp Click Strong 2 - 80%"));
}
if (effect == 39) {
Serial.println(F("39 - Long Double Sharp Click Strong 3 - 60%"));
}
if (effect == 40) {
Serial.println(F("40 - Long Double Sharp Click Strong 4 - 30%"));
}
if (effect == 41) {
Serial.println(F("41 - Long Double Sharp Click Medium 1 - 100%"));
}
if (effect == 42) {
Serial.println(F("42 - Long Double Sharp Click Medium 2 - 80%"));
}
if (effect == 43) {
Serial.println(F("43 - Long Double Sharp Click Medium 3 - 60%"));
}
if (effect == 44) {
Serial.println(F("44 - Long Double Sharp Tick 1 - 100%"));
}
if (effect == 45) {
Serial.println(F("45 - Long Double Sharp Tick 2 - 80%"));
}
if (effect == 46) {
Serial.println(F("46 - Long Double Sharp Tick 3 - 60%"));
}
if (effect == 47) {
Serial.println(F("47 - Buzz 1 - 100%"));
}
if (effect == 48) {
Serial.println(F("48 - Buzz 2 - 80%"));
}
if (effect == 49) {
Serial.println(F("49 - Buzz 3 - 60%"));
}
if (effect == 50) {
Serial.println(F("50 - Buzz 4 - 40%"));
}
if (effect == 51) {
Serial.println(F("51 - Buzz 5 - 20%"));
}
if (effect == 52) {
Serial.println(F("52 - Pulsing Strong 1 - 100%"));
}
if (effect == 53) {
Serial.println(F("53 - Pulsing Strong 2 - 60%"));
}
if (effect == 54) {
Serial.println(F("54 - Pulsing Medium 1 - 100%"));
}
if (effect == 55) {
Serial.println(F("55 - Pulsing Medium 2 - 60%"));
}
if (effect == 56) {
Serial.println(F("56 - Pulsing Sharp 1 - 100%"));
}
if (effect == 57) {
Serial.println(F("57 - Pulsing Sharp 2 - 60%"));
}
if (effect == 58) {
Serial.println(F("58 - Transition Click 1 - 100%"));
}
if (effect == 59) {
Serial.println(F("59 - Transition Click 2 - 80%"));
}
if (effect == 60) {
Serial.println(F("60 - Transition Click 3 - 60%"));
}
if (effect == 61) {
Serial.println(F("61 - Transition Click 4 - 40%"));
}
if (effect == 62) {
Serial.println(F("62 - Transition Click 5 - 20%"));
}
if (effect == 63) {
Serial.println(F("63 - Transition Click 6 - 10%"));
}
if (effect == 64) {
Serial.println(F("64 - Transition Hum 1 - 100%"));
}
if (effect == 65) {
Serial.println(F("65 - Transition Hum 2 - 80%"));
}
if (effect == 66) {
Serial.println(F("66 - Transition Hum 3 - 60%"));
}
if (effect == 67) {
Serial.println(F("67 - Transition Hum 4 - 40%"));
}
if (effect == 68) {
Serial.println(F("68 - Transition Hum 5 - 20%"));
}
if (effect == 69) {
Serial.println(F("69 - Transition Hum 6 - 10%"));
}
if (effect == 70) {
Serial.println(F("70 - Transition Ramp Down Long Smooth 1 - 100 to 0%"));
}
if (effect == 71) {
Serial.println(F("71 - Transition Ramp Down Long Smooth 2 - 100 to 0%"));
}
if (effect == 72) {
Serial.println(F("72 - Transition Ramp Down Medium Smooth 1 - 100 to 0%"));
}
if (effect == 73) {
Serial.println(F("73 - Transition Ramp Down Medium Smooth 2 - 100 to 0%"));
}
if (effect == 74) {
Serial.println(F("74 - Transition Ramp Down Short Smooth 1 - 100 to 0%"));
}
if (effect == 75) {
Serial.println(F("75 - Transition Ramp Down Short Smooth 2 - 100 to 0%"));
}
if (effect == 76) {
Serial.println(F("76 - Transition Ramp Down Long Sharp 1 - 100 to 0%"));
}
if (effect == 77) {
Serial.println(F("77 - Transition Ramp Down Long Sharp 2 - 100 to 0%"));
}
if (effect == 78) {
Serial.println(F("78 - Transition Ramp Down Medium Sharp 1 - 100 to 0%"));
}
if (effect == 79) {
Serial.println(F("79 - Transition Ramp Down Medium Sharp 2 - 100 to 0%"));
}
if (effect == 80) {
Serial.println(F("80 - Transition Ramp Down Short Sharp 1 - 100 to 0%"));
}
if (effect == 81) {
Serial.println(F("81 - Transition Ramp Down Short Sharp 2 - 100 to 0%"));
}
if (effect == 82) {
Serial.println(F("82 - Transition Ramp Up Long Smooth 1 - 0 to 100%"));
}
if (effect == 83) {
Serial.println(F("83 - Transition Ramp Up Long Smooth 2 - 0 to 100%"));
}
if (effect == 84) {
Serial.println(F("84 - Transition Ramp Up Medium Smooth 1 - 0 to 100%"));
}
if (effect == 85) {
Serial.println(F("85 - Transition Ramp Up Medium Smooth 2 - 0 to 100%"));
}
if (effect == 86) {
Serial.println(F("86 - Transition Ramp Up Short Smooth 1 - 0 to 100%"));
}
if (effect == 87) {
Serial.println(F("87 - Transition Ramp Up Short Smooth 2 - 0 to 100%"));
}
if (effect == 88) {
Serial.println(F("88 - Transition Ramp Up Long Sharp 1 - 0 to 100%"));
}
if (effect == 89) {
Serial.println(F("89 - Transition Ramp Up Long Sharp 2 - 0 to 100%"));
}
if (effect == 90) {
Serial.println(F("90 - Transition Ramp Up Medium Sharp 1 - 0 to 100%"));
}
if (effect == 91) {
Serial.println(F("91 - Transition Ramp Up Medium Sharp 2 - 0 to 100%"));
}
if (effect == 92) {
Serial.println(F("92 - Transition Ramp Up Short Sharp 1 - 0 to 100%"));
}
if (effect == 93) {
Serial.println(F("93 - Transition Ramp Up Short Sharp 2 - 0 to 100%"));
}
if (effect == 94) {
Serial.println(F("94 - Transition Ramp Down Long Smooth 1 - 50 to 0%"));
}
if (effect == 95) {
Serial.println(F("95 - Transition Ramp Down Long Smooth 2 - 50 to 0%"));
}
if (effect == 96) {
Serial.println(F("96 - Transition Ramp Down Medium Smooth 1 - 50 to 0%"));
}
if (effect == 97) {
Serial.println(F("97 - Transition Ramp Down Medium Smooth 2 - 50 to 0%"));
}
if (effect == 98) {
Serial.println(F("98 - Transition Ramp Down Short Smooth 1 - 50 to 0%"));
}
if (effect == 99) {
Serial.println(F("99 - Transition Ramp Down Short Smooth 2 - 50 to 0%"));
}
if (effect == 100) {
Serial.println(F("100 - Transition Ramp Down Long Sharp 1 - 50 to 0%"));
}
if (effect == 101) {
Serial.println(F("101 - Transition Ramp Down Long Sharp 2 - 50 to 0%"));
}
if (effect == 102) {
Serial.println(F("102 - Transition Ramp Down Medium Sharp 1 - 50 to 0%"));
}
if (effect == 103) {
Serial.println(F("103 - Transition Ramp Down Medium Sharp 2 - 50 to 0%"));
}
if (effect == 104) {
Serial.println(F("104 - Transition Ramp Down Short Sharp 1 - 50 to 0%"));
}
if (effect == 105) {
Serial.println(F("105 - Transition Ramp Down Short Sharp 2 - 50 to 0%"));
}
if (effect == 106) {
Serial.println(F("106 - Transition Ramp Up Long Smooth 1 - 0 to 50%"));
}
if (effect == 107) {
Serial.println(F("107 - Transition Ramp Up Long Smooth 2 - 0 to 50%"));
}
if (effect == 108) {
Serial.println(F("108 - Transition Ramp Up Medium Smooth 1 - 0 to 50%"));
}
if (effect == 109) {
Serial.println(F("109 - Transition Ramp Up Medium Smooth 2 - 0 to 50%"));
}
if (effect == 110) {
Serial.println(F("110 - Transition Ramp Up Short Smooth 1 - 0 to 50%"));
}
if (effect == 111) {
Serial.println(F("111 - Transition Ramp Up Short Smooth 2 - 0 to 50%"));
}
if (effect == 112) {
Serial.println(F("112 - Transition Ramp Up Long Sharp 1 - 0 to 50%"));
}
if (effect == 113) {
Serial.println(F("113 - Transition Ramp Up Long Sharp 2 - 0 to 50%"));
}
if (effect == 114) {
Serial.println(F("114 - Transition Ramp Up Medium Sharp 1 - 0 to 50%"));
}
if (effect == 115) {
Serial.println(F("115 - Transition Ramp Up Medium Sharp 2 - 0 to 50%"));
}
if (effect == 116) {
Serial.println(F("116 - Transition Ramp Up Short Sharp 1 - 0 to 50%"));
}
if (effect == 117) {
Serial.println(F("117 - Transition Ramp Up Short Sharp 2 - 0 to 50%"));
}
if (effect == 118) {
Serial.println(F("118 - Long buzz for programmatic stopping - 100%"));
}
if (effect == 119) {
Serial.println(F("119 - Smooth Hum 1 (No kick or brake pulse) - 50%"));
}
if (effect == 120) {
Serial.println(F("120 - Smooth Hum 2 (No kick or brake pulse) - 40%"));
}
if (effect == 121) {
Serial.println(F("121 - Smooth Hum 3 (No kick or brake pulse) - 30%"));
}
if (effect == 122) {
Serial.println(F("122 - Smooth Hum 4 (No kick or brake pulse) - 20%"));
}
if (effect == 123) {
Serial.println(F("123 - Smooth Hum 5 (No kick or brake pulse) - 10%"));
}
// set the effect to play
drv.setWaveform(0, effect); // play effect
drv.setWaveform(1, 0); // end waveform
// play the effect!
drv.run();
// wait a bit
delay(500);
effect++;
if (effect > 117) effect = 1;
}

View File

@ -0,0 +1,8 @@
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS ../../../SensorLib)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(ESP_IDF_TouchDrv_Example)

View File

@ -0,0 +1,10 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := ESP_IDF_TouchDrv_Example
EXTRA_COMPONENT_DIRS = ../../../SensorLib
include $(IDF_PATH)/make/project.mk

View File

@ -0,0 +1,181 @@
# ESP_IDF_TouchDrv_Example
```
The current example only writes the CSTxxx series touch application.
The other sensors have not been added, but the methods are the same.
```
### Configure the Project
Open the project configuration menu (`idf.py menuconfig`).
In the `SensorLib Example Configuration` menu:
* Select the PMU Type in the `SensorLib read and write methods` optionChoose according to the situation
1. Implemented using built-in read and write methods (Read and write methods are provided internally by SensorLib, supporting high version esp-idf >= 5.0, and low version methods (< 5.0))
2. Implemented using read and write callback methods (Implemented using externally provided methods, suitable for multiple platforms)
* In `Sensor SCL GPIO Num` select the clock pin to connect to the PMU,the default is 17
* In `Sensor SDA GPIO Num` select the data pin connected to the PMU,the default is 18
* Select the interrupt pin connected to the PMU in `Sensor Interrupt Pin`, the default is 16
* Select `Sensor reset Pin` , the default is 21
* `Master Frequency` The maximum communication frequency defaults to 100000HZ, and you can decide whether to change it according to the situation.
## How to Use Example
Before project configuration and build, be sure to set the correct chip target using `idf.py set-target <chip_name>`. default use **esp32s3**
### Build and Flash
Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
## Example Output
The output information is to configure the output voltage and enable status of the PMU
```
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x15 (USB_UART_CHIP_RESET),boot:0xa (SPI_FAST_FLASH_BOOT)
Saved PC:0x403788f6
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3810,len:0x178c
load:0x403c9700,len:0x4
load:0x403c9704,len:0xbfc
load:0x403cc700,len:0x2d64
entry 0x403c9900
I (26) boot: ESP-IDF v5.3-dev-1288-g5524b692ee 2nd stage bootloader
I (27) boot: compile time Jan 10 2024 22:49:17
I (27) boot: Multicore bootloader
I (31) boot: chip revision: v0.2
I (35) boot.esp32s3: Boot SPI Speed : 80MHz
I (40) boot.esp32s3: SPI Mode : DIO
I (45) boot.esp32s3: SPI Flash Size : 2MB
I (49) boot: Enabling RNG early entropy source...
I (55) boot: Partition Table:
I (58) boot: ## Label Usage Type ST Offset Length
I (66) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (73) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (81) boot: 2 factory factory app 00 00 00010000 00100000
I (88) boot: End of partition table
I (92) esp_image: segment 0: paddr=00010020 vaddr=3c020020 size=0e0dch ( 57564) map
I (111) esp_image: segment 1: paddr=0001e104 vaddr=3fc93100 size=01f14h ( 7956) load
I (113) esp_image: segment 2: paddr=00020020 vaddr=42000020 size=1acb0h (109744) map
I (137) esp_image: segment 3: paddr=0003acd8 vaddr=3fc95014 size=00994h ( 2452) load
I (138) esp_image: segment 4: paddr=0003b674 vaddr=40374000 size=0f0e0h ( 61664) load
I (163) boot: Loaded app from partition at offset 0x10000
I (163) boot: Disabling RNG early entropy source...
I (163) cpu_start: Multicore app
I (176) cpu_start: Pro cpu start user code
I (176) cpu_start: cpu freq: 240000000 Hz
I (177) cpu_start: Application information:
I (177) cpu_start: Project name: ESP_IDF_TouchDrv_Example
I (177) cpu_start: App version: v0.1.4-6-gfeaf675-dirty
I (177) cpu_start: Compile time: Jan 11 2024 14:01:31
I (177) cpu_start: ELF file SHA256: 3ce1527fc...
I (178) cpu_start: ESP-IDF: v5.3-dev-1288-g5524b692ee
I (178) cpu_start: Min chip rev: v0.0
I (178) cpu_start: Max chip rev: v0.99
I (178) cpu_start: Chip rev: v0.2
I (178) heap_init: Initializing. RAM available for dynamic allocation:
I (179) heap_init: At 3FC96290 len 00053480 (333 KiB): RAM
I (179) heap_init: At 3FCE9710 len 00005724 (21 KiB): RAM
I (179) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
I (180) heap_init: At 600FE010 len 00001FD8 (7 KiB): RTCRAM
I (181) spi_flash: detected chip: winbond
I (181) spi_flash: flash io: dio
W (181) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
W (181) i2c: This driver is an old driver, please migrate your application code to adapt `driver/i2c_master.h`
I (182) sleep: Configure to isolate all GPIO pins in sleep state
I (182) sleep: Enable automatic switching of GPIO sleep configuration
I (183) main_task: Started on CPU0
I (193) main_task: Calling app_main()
I (193) gpio: GPIO[16]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:2
I (193) I2C: Implemented using read and write callback methods (Use lower version < 5.0 API)
I (193) mian: I2C initialized successfully
I (193) TOUCH: ----touch_drv_init----
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- 15 -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
I (303) TOUCH: Find touch address 0x15
I (303) TOUCH: Find touch address 0x15
I (303) TOUCH: Implemented using built-in read and write methods (Use lower version < 5.0 API)
Using ESP-IDF Driver interface.
E (303) i2c: i2c driver install error
I (303) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (303) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
Chip ID:0xb5
Version :0x2
Touch type:CST816T
I (383) TOUCH: Init touch SUCCESS!
I (383) TOUCH: Some CST816 will automatically enter sleep,can use the touch.disableAutoSleep() to turn off
I (383) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (513) mian: Run...
I (513) main_task: Returned from app_main()
X[0]:143 Y[0]:127
X[0]:143 Y[0]:127
X[0]:142 Y[0]:127
X[0]:141 Y[0]:126
X[0]:138 Y[0]:125
X[0]:135 Y[0]:123
X[0]:131 Y[0]:121
X[0]:126 Y[0]:119
X[0]:121 Y[0]:117
X[0]:84 Y[0]:146
X[0]:85 Y[0]:146
X[0]:86 Y[0]:145
X[0]:87 Y[0]:143
X[0]:88 Y[0]:140
X[0]:89 Y[0]:136
X[0]:90 Y[0]:132
X[0]:91 Y[0]:127
X[0]:92 Y[0]:123
X[0]:93 Y[0]:119
X[0]:94 Y[0]:115
X[0]:95 Y[0]:111
I (513563) TOUCH: Touch Home button pressed!
I (513573) TOUCH: Touch Home button pressed!
I (513583) TOUCH: Touch Home button pressed!
I (513603) TOUCH: Touch Home button pressed!
I (513613) TOUCH: Touch Home button pressed!
I (513633) TOUCH: Touch Home button pressed!
I (513643) TOUCH: Touch Home button pressed!
```
## Build process example
Assuming you don't have esp-idf yet
```
mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
git clone https://github.com/lewisxhe/XPowersLib.git
cd esp-idf
./install.sh
. ./export.sh
cd ..
cd SensorLib/examples/ESP_IDF_Example
Configure SDA,SCL,INT,RST,Pin
...
idf.py menuconfig
idf.py build
idf.py -b 921600 flash
idf.py monitor
```

View File

@ -0,0 +1,5 @@
idf_component_register(SRCS
"touch_drv.cpp"
"i2c_driver.cpp"
"main.cpp"
INCLUDE_DIRS ".")

View File

@ -0,0 +1,52 @@
menu "SensorLib Example Configuration"
choice I2C_COMMUNICATION_METHOD
prompt "SensorLib read and write methods"
default I2C_COMMUNICATION_METHOD_BUILTIN_RW
help
Define SensorLib read and write methods
config I2C_COMMUNICATION_METHOD_BUILTIN_RW
bool "Implemented using built-in read and write methods"
config I2C_COMMUNICATION_METHOD_CALLBACK_RW
bool "Implemented using read and write callback methods"
endchoice
config I2C_MASTER_PORT_NUM
int "Sensor I2C Port Number"
default 1
help
Port number for I2C Master device.
config I2C_MASTER_FREQUENCY
int "Master Frequency"
default 100000
help
I2C Speed of Master device.
config SENSOR_SCL
int "Sensor SCL GPIO Num"
default 17
help
GPIO number for I2C clock line.
config SENSOR_SDA
int "Sensor SDA GPIO Num"
default 18
help
GPIO number for I2C data line.
config SENSOR_IRQ
int "Sensor Interrupt Pin"
default 16
help
Sensor interrupt pin.
config SENSOR_RST
int "Sensor reset Pin"
default 21
help
Sensor reset pin.
endmenu

View File

@ -0,0 +1,4 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

View File

@ -0,0 +1,253 @@
/**
* @file port_i2c.cpp
* @author Lewis He (lewishe@outlook.com)
* @license MIT
* @copyright Copyright (c) 2024 Shenzhen Xinyuan Electronic Technology Co., Ltd
* @date 2024-01-10
*
*/
#include <cstring>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "i2c_driver.h"
static const char *TAG = "I2C";
#define I2C_MASTER_NUM (i2c_port_t)CONFIG_I2C_MASTER_PORT_NUM
#define I2C_MASTER_SDA_IO (gpio_num_t)CONFIG_SENSOR_SDA
#define I2C_MASTER_SCL_IO (gpio_num_t)CONFIG_SENSOR_SCL
#define I2C_MASTER_FREQ_HZ CONFIG_I2C_MASTER_FREQUENCY /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
#include "soc/clk_tree_defs.h"
i2c_master_dev_handle_t i2c_device;
// * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle,
// * which is useful when the bus shares multiple devices.
i2c_master_bus_handle_t bus_handle;
#endif
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
/**
* @brief Read a sequence of bytes from a pmu registers
*/
int i2c_read_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len)
{
esp_err_t ret;
if (len == 0) {
return ESP_OK;
}
if (data == NULL) {
return ESP_FAIL;
}
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
ret = i2c_master_transmit_receive(
i2c_device,
(const uint8_t *)&regAddr,
1,
data,
len,
-1);
#else
i2c_cmd_handle_t cmd;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, regAddr, true);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000));
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "PMU i2c_master_cmd_begin FAILED! > ");
return ESP_FAIL;
}
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_READ, true);
if (len > 1) {
i2c_master_read(cmd, data, len - 1, I2C_MASTER_ACK);
}
i2c_master_read_byte(cmd, &data[len - 1], I2C_MASTER_NACK);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000));
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "i2c_read_error.");
}
#endif
return ret == ESP_OK ? 0 : -1;
}
/**
* @brief Write a byte to a pmu register
*/
int i2c_write_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len)
{
esp_err_t ret;
if (data == NULL) {
return ESP_FAIL;
}
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
uint8_t *write_buffer = (uint8_t *)malloc(sizeof(uint8_t) * (len + 1));
if (!write_buffer) {
return -1;
}
write_buffer[0] = regAddr;
memcpy(write_buffer + 1, data, len);
ret = i2c_master_transmit(
i2c_device,
write_buffer,
len + 1,
-1);
free(write_buffer);
#else
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, regAddr, true);
i2c_master_write(cmd, data, len, true);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000));
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "i2c_write_error.");
}
#endif
return ret == ESP_OK ? 0 : -1;
}
esp_err_t i2c_drv_device_init(uint8_t address)
{
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
i2c_device_config_t i2c_dev_conf = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = address,
.scl_speed_hz = I2C_MASTER_FREQ_HZ,
};
return i2c_master_bus_add_device(bus_handle, &i2c_dev_conf, &i2c_device);
#else
return ESP_OK;
#endif
}
#endif //CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
/**
* @brief i2c master initialization
*/
esp_err_t i2c_drv_init(void)
{
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
ESP_LOGI(TAG, "Implemented using read and write callback methods (Use higher version >= 5.0 API)");
i2c_master_bus_config_t i2c_bus_config;
memset(&i2c_bus_config, 0, sizeof(i2c_bus_config));
i2c_bus_config.clk_source = I2C_CLK_SRC_DEFAULT;
i2c_bus_config.i2c_port = I2C_MASTER_NUM;
i2c_bus_config.scl_io_num = (gpio_num_t)I2C_MASTER_SCL_IO;
i2c_bus_config.sda_io_num = (gpio_num_t)I2C_MASTER_SDA_IO;
i2c_bus_config.glitch_ignore_cnt = 7;
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &bus_handle));
return ESP_OK;
#else
ESP_LOGI(TAG, "Implemented using read and write callback methods (Use lower version < 5.0 API)");
i2c_config_t i2c_conf ;
memset(&i2c_conf, 0, sizeof(i2c_conf));
i2c_conf.mode = I2C_MODE_MASTER;
i2c_conf.sda_io_num = I2C_MASTER_SDA_IO;
i2c_conf.scl_io_num = I2C_MASTER_SCL_IO;
i2c_conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
i2c_conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
i2c_conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
i2c_param_config(I2C_MASTER_NUM, &i2c_conf);
return i2c_driver_install(I2C_MASTER_NUM, i2c_conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
#endif
}
void i2c_drv_scan()
{
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
esp_err_t err = ESP_OK;
uint8_t address = 0x00;
printf("Scand I2C Devices:\n");
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n");
for (int i = 0; i < 128; i += 16) {
printf("%02x: ", i);
for (int j = 0; j < 16; j++) {
fflush(stdout);
address = i + j;
err = i2c_master_probe(bus_handle, address, 1000);
if (err == ESP_OK) {
printf("%02x ", address);
} else if (err == ESP_ERR_TIMEOUT) {
printf("UU ");
} else {
printf("-- ");
}
}
printf("\r\n");
}
printf("\n\n\n");
#else
uint8_t address;
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n");
for (int i = 0; i < 128; i += 16) {
printf("%02x: ", i);
for (int j = 0; j < 16; j++) {
fflush(stdout);
address = i + j;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, true);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 50 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if (ret == ESP_OK) {
printf("%02x ", address);
} else if (ret == ESP_ERR_TIMEOUT) {
printf("UU ");
} else {
printf("-- ");
}
}
printf("\r\n");
}
#endif
}
bool i2c_drv_probe(uint8_t devAddr)
{
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
return ESP_OK == i2c_master_probe(bus_handle, devAddr, 1000);
#else
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_WRITE, true);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 50 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
return (ret == ESP_OK);
#endif //ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)
}

View File

@ -0,0 +1,32 @@
/**
* @file i2c_driver.h
* @author Lewis He (lewishe@outlook.com)
* @license MIT
* @copyright Copyright (c) 2024 Shenzhen Xinyuan Electronic Technology Co., Ltd
* @date 2024-01-10
*
*/
#pragma once
#include "esp_err.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "esp_idf_version.h"
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
#include "driver/i2c_master.h"
#else
#include "driver/i2c.h"
#endif //ESP_IDF_VERSION
esp_err_t i2c_drv_init(void);
void i2c_drv_scan();
bool i2c_drv_probe(uint8_t devAddr);
int i2c_read_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len);
int i2c_write_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len);
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
esp_err_t i2c_drv_device_init(uint8_t address);
#endif

View File

@ -0,0 +1,83 @@
/**
* @file main.cpp
* @author Lewis He (lewishe@outlook.com)
* @license MIT
* @copyright Copyright (c) 2024 Shenzhen Xinyuan Electronic Technology Co., Ltd
* @date 2024-01-10
*
*/
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "freertos/queue.h"
#include "i2c_driver.h"
#define SENSOR_INPUT_PIN (gpio_num_t)CONFIG_SENSOR_IRQ /*!< axp power chip interrupt Pin*/
#define SENSOR_INPUT_PIN_SEL (1ULL<<SENSOR_INPUT_PIN)
static const char *TAG = "mian";
extern esp_err_t sensor_drv_init();
extern esp_err_t touch_drv_init();
extern void touch_drv_isr_handler();
static void sensor_hander_task(void *);
static QueueHandle_t gpio_evt_queue = NULL;
static void IRAM_ATTR sensor_irq_handler(void *arg)
{
uint32_t gpio_num = (uint32_t) arg;
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
static void irq_init()
{
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_NEGEDGE;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pin_bit_mask = SENSOR_INPUT_PIN_SEL;
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
gpio_config(&io_conf);
gpio_set_intr_type(SENSOR_INPUT_PIN, GPIO_INTR_NEGEDGE);
//install gpio isr service
gpio_install_isr_service(0);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(SENSOR_INPUT_PIN, sensor_irq_handler, (void *) SENSOR_INPUT_PIN);
}
extern "C" void app_main(void)
{
//create a queue to handle gpio event from isr
gpio_evt_queue = xQueueCreate(5, sizeof(uint32_t));
// Register Sensor interrupt pins
irq_init();
ESP_ERROR_CHECK(i2c_drv_init());
ESP_LOGI(TAG, "I2C initialized successfully");
ESP_ERROR_CHECK(touch_drv_init());
xTaskCreate(sensor_hander_task, "App/sen", 4 * 1024, NULL, 10, NULL);
ESP_LOGI(TAG, "Run...");
}
static void sensor_hander_task(void *args)
{
uint32_t io_num;
while (1) {
if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
touch_drv_isr_handler();
}
}
}

View File

@ -0,0 +1,166 @@
/**
* @file touch_drv.cpp
* @author Lewis He (lewishe@outlook.com)
* @license MIT
* @copyright Copyright (c) 2024 Shenzhen Xinyuan Electronic Technology Co., Ltd
* @date 2024-01-10
*
*/
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_err.h"
#include "i2c_driver.h"
#include "freertos/FreeRTOS.h"
#include "TouchDrvCSTXXX.hpp"
static const char *TAG = "TOUCH";
TouchDrvCSTXXX touch;
static void touch_home_button_callback(void *user_data);
esp_err_t touch_drv_init()
{
uint8_t address = 0xFF;
ESP_LOGI(TAG, "----touch_drv_init----");
/*
* CST816, CST328 Some chips have automatic sleep function.
* If you want to scan the device address,
* must reset the chip first. If the reset pin is not connected,
* you may not be able to obtain the device address by scanning the bus.
*/
gpio_num_t gpio_num = (gpio_num_t)CONFIG_SENSOR_RST;
ESP_ERROR_CHECK(gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT));
gpio_set_level(gpio_num, 0);
vTaskDelay(pdMS_TO_TICKS(15));
gpio_set_level(gpio_num, 1);
vTaskDelay(pdMS_TO_TICKS(80));
// Run bus scan
i2c_drv_scan();
// Get known address
if (i2c_drv_probe(CST816_SLAVE_ADDRESS)) {
address = CST816_SLAVE_ADDRESS;
ESP_LOGI(TAG, "Find touch address 0x%X", address);
}
if (i2c_drv_probe(CST226SE_SLAVE_ADDRESS)) {
address = CST226SE_SLAVE_ADDRESS;
ESP_LOGI(TAG, "Find touch address 0x%X", address);
}
if (i2c_drv_probe(CST328_SLAVE_ADDRESS)) {
address = CST328_SLAVE_ADDRESS;
ESP_LOGI(TAG, "Find touch address 0x%X", address);
}
if (address == 0xFF) {
ESP_LOGE(TAG, "Could't find touch chip!"); return ESP_FAIL;
}
ESP_LOGI(TAG, "Find touch address 0x%X", address);
// Set reset and interrupt pin
touch.setPins(CONFIG_SENSOR_RST, CONFIG_SENSOR_IRQ);
//* Implemented using read and write callback methods, applicable to other platforms
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
// * Provide the device address to the callback function
i2c_drv_device_init(address);
ESP_LOGI(TAG, "Implemented using read and write callback methods");
if (touch.begin(address, i2c_read_callback, i2c_write_callback)) {
ESP_LOGI(TAG, "Init touch SUCCESS!");
} else {
ESP_LOGE(TAG, "Init touch FAILED!");
return ESP_FAIL;
}
#endif
//* Use the built-in esp-idf communication method
#if CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use higher version >= 5.0 API)");
// * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle,
// * which is useful when the bus shares multiple devices.
extern i2c_master_bus_handle_t bus_handle;
if (touch.begin(bus_handle, address)) {
ESP_LOGI(TAG, "Init touch SUCCESS!");
} else {
ESP_LOGE(TAG, "Init touch FAILED!");
return false;
}
#else
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use lower version < 5.0 API)");
if (touch.begin((i2c_port_t)CONFIG_I2C_MASTER_PORT_NUM, address, CONFIG_SENSOR_SDA, CONFIG_SENSOR_SCL)) {
ESP_LOGI(TAG, "Init touch SUCCESS!");
} else {
ESP_LOGE(TAG, "Init touch FAILED!");
return false;
}
#endif //ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)
#endif //CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
const char *model = touch.getModelName();
if (strncmp(model, "CST8", 3) == 0) {
ESP_LOGI(TAG, "Some CST816 will automatically enter sleep,can use the touch.disableAutoSleep() to turn off");
// Some CST816 will automatically enter sleep,
// can use the touch.disableAutoSleep() to turn off
touch.disableAutoSleep();
/**
* Some touch screens have touch buttons,
* and the touch coordinates need to be given
* before the touch button callback function can be used.
*/
// Example touch coordinates using T-Display-S3 touch
touch.setCenterButtonCoordinate(85, 360);
touch.setHomeButtonCallback(touch_home_button_callback);
}
// Set the maximum valid coordinates
// touch.setMaxCoordinates(320, 170);
// Swap XY coordinates
// touch.setSwapXY(true);
// Mirror XY coordinates
// touch.setMirrorXY(false, true);
return ESP_OK;
}
static void touch_home_button_callback(void *user_data)
{
ESP_LOGI(TAG, "Touch Home button pressed!");
}
void touch_drv_isr_handler()
{
int16_t x[5], y[5];
uint8_t touched = touch.getPoint(x, y, touch.getSupportTouchPoint());
if (touched) {
for (int i = 0; i < touched; ++i) {
printf("X[");
printf("%d", i);
printf("]:");
printf("%d", x[i]);
printf(" ");
printf(" Y[");
printf("%d", i);
printf("]:");
printf("%d", y[i]);
printf(" ");
}
printf("\n");
}
}

View File

@ -0,0 +1,6 @@
CONFIG_IDF_TARGET="esp32s3"
CONFIG_IDF_TARGET_ESP32S3=y
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240

View File

@ -0,0 +1,193 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* 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.
*
* @file LTR553ALS_Sensor.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-09
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorLTR553.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 5
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 6
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 21
#endif
SensorLTR553 als;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT_PULLUP);
if (!als.begin(Wire, LTR553_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find LTR553 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init LTR553 Sensor success!");
// Set the ambient light high and low thresholds.
// If the value exceeds or falls below the set value, an interrupt will be triggered.
als.setLightSensorThreshold(10, 200);
// Set the high and low thresholds of the proximity sensor.
// If the value exceeds or falls below the set value, an interrupt will be triggered.
als.setProximityThreshold(10, 30);
// Controls the Light Sensor N number of times the measurement data is outside the range
// defined by the upper and lower threshold limits before asserting the interrupt.
als.setLightSensorPersists(5);
// Controls the Proximity N number of times the measurement data is outside the range
// defined by the upper and lower threshold limits before asserting the interrupt.
als.setProximityPersists(5);
/*
* ALS_IRQ_ACTIVE_LOW, // INT pin is considered active when it is a logic 0 (default)
* ALS_IRQ_ACTIVE_HIGH // INT pin is considered active when it is a logic 1
* * */
als.setIRQLevel(SensorLTR553::ALS_IRQ_ACTIVE_LOW);
/*
* ALS_IRQ_ONLY_PS, // Only PS measurement can trigger interrupt
* ALS_IRQ_ONLY_ALS, // Only ALS measurement can trigger interrupt
* ALS_IRQ_BOTH, // Both ALS and PS measurement can trigger interrupt
* * * */
als.enableIRQ(SensorLTR553::ALS_IRQ_BOTH);
/*
* ALS_GAIN_1X , -> 1 lux to 64k lux (default)
* ALS_GAIN_2X , -> 0.5 lux to 32k lux
* ALS_GAIN_4X , -> 0.25 lux to 16k lux
* ALS_GAIN_8X , -> 0.125 lux to 8k lux
* ALS_GAIN_48X , -> 0.02 lux to 1.3k lux
* ALS_GAIN_96X , -> 0.01 lux to 600 lux
* */
als.setLightSensorGain(SensorLTR553::ALS_GAIN_8X);
/*
* PS_LED_PLUSE_30KHZ,
* PS_LED_PLUSE_40KHZ,
* PS_LED_PLUSE_50KHZ,
* PS_LED_PLUSE_60KHZ,
* PS_LED_PLUSE_70KHZ,
* PS_LED_PLUSE_80KHZ,
* PS_LED_PLUSE_90KHZ,
* PS_LED_PLUSE_100KHZ,
* * * * * * * * * * */
als.setPsLedPulsePeriod(SensorLTR553::PS_LED_PLUSE_100KHZ);
/*
* PS_LED_DUTY_25,
* PS_LED_DUTY_50,
* PS_LED_DUTY_75,
* PS_LED_DUTY_100,
* * * */
als.setPsLedDutyCycle(SensorLTR553::PS_LED_DUTY_100);
/*
* PS_LED_CUR_5MA,
* PS_LED_CUR_10MA,
* PS_LED_CUR_20MA,
* PS_LED_CUR_50MA,
* PS_LED_CUR_100MA,
* * * * * * * */
als.setPsLedCurrnet(SensorLTR553::PS_LED_CUR_50MA);
/*
* PS_MEAS_RATE_50MS,
* PS_MEAS_RATE_70MS,
* PS_MEAS_RATE_100MS,
* PS_MEAS_RATE_200MS,
* PS_MEAS_RATE_500MS,
* PS_MEAS_RATE_1000MS,
* PS_MEAS_RATE_2000MS,
* PS_MEAS_RATE_10MS
* * * * * * * */
als.setProximityRate(SensorLTR553::PS_MEAS_RATE_200MS);
// Number of pulses
als.setPsLedPulses(1);
// Enable proximity sensor saturation indication
als.enablePsIndicator();
// Enable ambient light sensor
als.enableLightSensor();
// Enable proximity sensor
als.enableProximity();
}
bool canRead()
{
#if SENSOR_IRQ != -1
return digitalRead(SENSOR_IRQ) == LOW;
#else
static uint32_t lastReadMillis;
if (millis() > lastReadMillis) {
lastReadMillis = millis() + 500;
return true;
}
return false;
#endif
}
void loop()
{
/*
* PS Saturation Flag is used for monitoring the internal IC saturation.
* It will be flagged when the IC has reached saturation
* and not able to perform any further PS measurement
* */
bool saturated = false;
if (canRead()) {
Serial.print(" ALS: CH1:"); Serial.print(als.getLightSensor(1));
Serial.print(" - CH0:"); Serial.print(als.getLightSensor(0));
Serial.print(" - PS:"); Serial.print(als.getProximity(&saturated));
Serial.print(" - "); Serial.println(saturated ? "PS saturated" : "PS not saturated");
}
delay(5);
}

View File

@ -0,0 +1,214 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file PCF85063_AlarmByUnits.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-12-11
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <time.h>
#include "SensorPCF85063.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 4
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 5
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 14
#endif
SensorPCF85063 rtc;
uint32_t lastMillis = 0;
uint8_t nextHour = 22;
uint8_t nextMonth = 1;
uint8_t nextDay = 1;
uint8_t nextMinute = 59;
uint8_t nextSecond = 20;
void setup()
{
Serial.begin(115200);
while (!Serial);
if (!rtc.begin(Wire, PCF85063_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find PCF8563 - check your wiring!");
while (1) {
delay(1000);
}
}
pinMode(SENSOR_IRQ, INPUT_PULLUP);
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
nextSecond = 55;
// First test alarm seconds
rtc.setAlarmBySecond(30);
rtc.enableAlarm();
}
void printDateTime()
{
if (millis() - lastMillis > 1000) {
/**
/// Format output time*
Option:
DATETIME_FORMAT_HM
DATETIME_FORMAT_HMS
DATETIME_FORMAT_YYYY_MM_DD
DATETIME_FORMAT_MM_DD_YYYY
DATETIME_FORMAT_DD_MM_YYYY
DATETIME_FORMAT_YYYY_MM_DD_H_M_S
default: DATETIME_FORMAT_YYYY_MM_DD_H_M_S_WEEK
*/
Serial.println(rtc.strftime());
lastMillis = millis();
}
}
// Test seconds timing
void testAlarmSeconds()
{
while (1) {
if (digitalRead(SENSOR_IRQ) == LOW) {
Serial.println("testAlarmSeconds Interrupt .... ");
if (rtc.isAlarmActive()) {
Serial.println("Alarm active");
rtc.resetAlarm();
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
rtc.setAlarmByMinutes(0);
return;
}
}
printDateTime();
}
}
// Test minute timing
void testAlarmMinute()
{
while (1) {
if (digitalRead(SENSOR_IRQ) == LOW) {
Serial.println("testAlarmMinute Interrupt .... ");
if (rtc.isAlarmActive()) {
Serial.println("Alarm active");
rtc.resetAlarm();
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
nextHour++;
if (nextHour >= 24) {
nextHour = 23;
nextDay = 25;
rtc.setAlarmByHours(0);
Serial.println("setAlarmByHours");
return;
}
}
}
printDateTime();
}
}
// Test hour timing
void testAlarmHour()
{
while (1) {
if (digitalRead(SENSOR_IRQ) == LOW) {
Serial.println("testAlarmHour Interrupt .... ");
if (rtc.isAlarmActive()) {
Serial.println("Alarm active");
rtc.resetAlarm();
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
nextDay++;
if (nextDay >= 30) {
nextMonth = 1;
nextHour = 23;
nextMinute = 59;
nextSecond = 55;
nextDay = rtc.getDaysInMonth(nextMonth, 2022);
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
rtc.setAlarmByDays(1);
Serial.println("setAlarmByDays");
return;
}
}
}
printDateTime();
}
}
// Test day timing
void testAlarmDay()
{
while (1) {
if (digitalRead(SENSOR_IRQ) == LOW) {
Serial.println("testAlarmDay Interrupt .... ");
if (rtc.isAlarmActive()) {
Serial.println("Alarm active");
rtc.resetAlarm();
nextDay = rtc.getDaysInMonth(nextMonth, 2022);
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
nextMonth++;
if (nextMonth >= 12) {
return;
}
}
}
printDateTime();
}
}
void loop()
{
testAlarmSeconds();
testAlarmMinute();
testAlarmHour();
testAlarmDay();
Serial.println("Test done ...");
while (1) {
delay(100);
}
}

View File

@ -0,0 +1,92 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* 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.
*
* @file PCF85063_SimpleTime.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-07
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorPCF85063.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 7
#endif
SensorPCF85063 rtc;
uint32_t lastMillis;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT_PULLUP);
if (!rtc.begin(Wire, PCF85063_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find PCF8563 - check your wiring!");
while (1) {
delay(1000);
}
}
uint16_t year = 2023;
uint8_t month = 9;
uint8_t day = 7;
uint8_t hour = 11;
uint8_t minute = 24;
uint8_t second = 30;
rtc.setDateTime(year, month, day, hour, minute, second);
}
void loop()
{
if (millis() - lastMillis > 1000) {
lastMillis = millis();
RTC_DateTime datetime = rtc.getDateTime();
Serial.printf(" Year :"); Serial.print(datetime.year);
Serial.printf(" Month:"); Serial.print(datetime.month);
Serial.printf(" Day :"); Serial.print(datetime.day);
Serial.printf(" Hour:"); Serial.print(datetime.hour);
Serial.printf(" Minute:"); Serial.print(datetime.minute);
Serial.printf(" Sec :"); Serial.println(datetime.second);
}
}

View File

@ -0,0 +1,193 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file PCF8563_AlarmByUnits.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-12-11
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <time.h>
#include "SensorPCF8563.hpp"
#ifdef ESP32
#define SENSOR_SDA 42
#define SENSOR_SCL 41
#define SENSOR_IRQ 14
#else
#define _PINNUM(port, pin) ((port)*32 + (pin))
#define SENSOR_SDA _PINNUM(0,26)
#define SENSOR_SCL _PINNUM(0,27)
#define SENSOR_IRQ _PINNUM(0,16)
#endif
SensorPCF8563 rtc;
uint32_t lastMillis = 0;
uint8_t nextHour = 22;
uint8_t nextMonth = 1;
uint8_t nextDay = 1;
uint8_t nextMinute = 59;
uint8_t nextSecond = 55;
void setup()
{
Serial.begin(115200);
while (!Serial);
if (!rtc.begin(Wire, PCF8563_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find PCF8563 - check your wiring!");
while (1) {
delay(1000);
}
}
pinMode(SENSOR_IRQ, INPUT_PULLUP);
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
// From minute timer
rtc.setAlarmByMinutes(0);
rtc.enableAlarm();
}
void printDateTime()
{
if (millis() - lastMillis > 1000) {
/**
/// Format output time*
Option:
DATETIME_FORMAT_HM
DATETIME_FORMAT_HMS
DATETIME_FORMAT_YYYY_MM_DD
DATETIME_FORMAT_MM_DD_YYYY
DATETIME_FORMAT_DD_MM_YYYY
DATETIME_FORMAT_YYYY_MM_DD_H_M_S
default: DATETIME_FORMAT_YYYY_MM_DD_H_M_S_WEEK
*/
Serial.println(rtc.strftime());
lastMillis = millis();
}
}
// Test minute timing
void testAlarmMinute()
{
while (1) {
if (digitalRead(SENSOR_IRQ) == LOW) {
Serial.println("testAlarmMinute Interrupt .... ");
if (rtc.isAlarmActive()) {
Serial.println("Alarm active");
rtc.resetAlarm();
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
nextHour++;
if (nextHour >= 24) {
nextHour = 23;
nextDay = 25;
rtc.setAlarmByHours(0);
Serial.println("setAlarmByHours");
return;
}
}
}
printDateTime();
}
}
// Test hour timing
void testAlarmHour()
{
while (1) {
if (digitalRead(SENSOR_IRQ) == LOW) {
Serial.println("testAlarmHour Interrupt .... ");
if (rtc.isAlarmActive()) {
Serial.println("Alarm active");
rtc.resetAlarm();
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
nextDay++;
if (nextDay >= 30) {
nextMonth = 1;
nextHour = 23;
nextMinute = 59;
nextSecond = 55;
nextDay = rtc.getDaysInMonth(nextMonth, 2022);
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
rtc.setAlarmByDays(1);
Serial.println("setAlarmByDays");
return;
}
}
}
printDateTime();
}
}
// Test day timing
void testAlarmDay()
{
while (1) {
if (digitalRead(SENSOR_IRQ) == LOW) {
Serial.println("testAlarmDay Interrupt .... ");
if (rtc.isAlarmActive()) {
Serial.println("Alarm active");
rtc.resetAlarm();
nextDay = rtc.getDaysInMonth(nextMonth, 2022);
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
nextMonth++;
if (nextMonth >= 12) {
return;
}
}
}
printDateTime();
}
}
void loop()
{
testAlarmMinute();
testAlarmHour();
testAlarmDay();
Serial.println("Test done ...");
while (1) {
delay(100);
}
}

View File

@ -0,0 +1,87 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file PCF8563_SimpleTime.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-12-12
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorPCF8563.hpp"
// lilygo t-beam-s3-core pin
#define SENSOR_SDA 42
#define SENSOR_SCL 41
#define SENSOR_IRQ 14
SensorPCF8563 rtc;
uint32_t lastMillis;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT_PULLUP);
if (!rtc.begin(Wire, PCF8563_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find PCF8563 - check your wiring!");
while (1) {
delay(1000);
}
}
uint16_t year = 2022;
uint8_t month = 12;
uint8_t day = 12;
uint8_t hour = 21;
uint8_t minute = 00;
uint8_t second = 30;
rtc.setDateTime(year, month, day, hour, minute, second);
}
void loop()
{
if (millis() - lastMillis > 1000) {
lastMillis = millis();
RTC_DateTime datetime = rtc.getDateTime();
Serial.printf(" Year :"); Serial.print(datetime.year);
Serial.printf(" Month:"); Serial.print(datetime.month);
Serial.printf(" Day :"); Serial.print(datetime.day);
Serial.printf(" Hour:"); Serial.print(datetime.hour);
Serial.printf(" Minute:"); Serial.print(datetime.minute);
Serial.printf(" Sec :"); Serial.println(datetime.second);
}
}

View File

@ -0,0 +1,98 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file PCF8563_TimeLib.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-12-12
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorPCF8563.hpp"
#include <time.h>
// lilygo t-beam-s3-core pin
#define SENSOR_SDA 42
#define SENSOR_SCL 41
#define SENSOR_IRQ 14
SensorPCF8563 rtc;
uint32_t lastMillis;
char buf[64];
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT_PULLUP);
if (!rtc.begin(Wire, PCF8563_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find PCF8563 - check your wiring!");
while (1) {
delay(1000);
}
}
}
void loop()
{
if (millis() - lastMillis > 1000) {
lastMillis = millis();
struct tm timeinfo;
// Get the time C library structure
rtc.getDateTime(&timeinfo);
// Format the output using the strftime function
// For more formats, please refer to :
// https://man7.org/linux/man-pages/man3/strftime.3.html
size_t written = strftime(buf, 64, "%A, %B %d %Y %H:%M:%S", &timeinfo);
if (written != 0) {
Serial.println(buf);
}
written = strftime(buf, 64, "%b %d %Y %H:%M:%S", &timeinfo);
if (written != 0) {
Serial.println(buf);
}
written = strftime(buf, 64, "%A, %d. %B %Y %I:%M%p", &timeinfo);
if (written != 0) {
Serial.println(buf);
}
}
}

View File

@ -0,0 +1,150 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file PCF8563_TimeSynchronization.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-12-12
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <time.h>
#include <WiFi.h>
#include <sntp.h>
#include "SensorPCF8563.hpp"
// lilygo t-beam-s3-core pin
#define SENSOR_SDA 42
#define SENSOR_SCL 41
#define SENSOR_IRQ 14
const char *ssid = "YOUR_SSID";
const char *password = "YOUR_PASS";
const char *ntpServer1 = "pool.ntp.org";
const char *ntpServer2 = "time.nist.gov";
const long gmtOffset_sec = 3600;
const int daylightOffset_sec = 3600;
const char *time_zone = "CST-8"; // TimeZone rule for Europe/Rome including daylight adjustment rules (optional)
SensorPCF8563 rtc;
uint32_t lastMillis;
// Callback function (get's called when time adjusts via NTP)
void timeavailable(struct timeval *t)
{
Serial.println("Got time adjustment from NTP, Write the hardware clock");
// Write synchronization time to hardware
rtc.hwClockWrite();
}
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT_PULLUP);
if (!rtc.begin(Wire, PCF8563_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find PCF8563 - check your wiring!");
while (1) {
delay(1000);
}
}
// set notification call-back function
sntp_set_time_sync_notification_cb( timeavailable );
/**
* NTP server address could be aquired via DHCP,
*
* NOTE: This call should be made BEFORE esp32 aquires IP address via DHCP,
* otherwise SNTP option 42 would be rejected by default.
* NOTE: configTime() function call if made AFTER DHCP-client run
* will OVERRIDE aquired NTP server address
*/
sntp_servermode_dhcp(1); // (optional)
/**
* This will set configured ntp servers and constant TimeZone/daylightOffset
* should be OK if your time zone does not need to adjust daylightOffset twice a year,
* in such a case time adjustment won't be handled automagicaly.
*/
// configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1, ntpServer2);
/**
* A more convenient approach to handle TimeZones with daylightOffset
* would be to specify a environmnet variable with TimeZone definition including daylight adjustmnet rules.
* A list of rules for your zone could be obtained from https://github.com/esp8266/Arduino/blob/master/cores/esp8266/TZ.h
*/
configTzTime(time_zone, ntpServer1, ntpServer2);
//connect to WiFi
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
}
void loop()
{
if (millis() - lastMillis > 1000) {
lastMillis = millis();
// hardware clock
struct tm hwTimeinfo;
rtc.getDateTime(&hwTimeinfo);
Serial.print("Hardware clock :");
Serial.println(&hwTimeinfo, "%A, %B %d %Y %H:%M:%S");
// system clock
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("No time available (yet)");
return;
}
Serial.print("System clock :");
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
Serial.println();
}
}

View File

@ -0,0 +1,244 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMC6310_CalibrateExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorQMC6310.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
SensorQMC6310 qmc;
void calibrate()
{
qmc.setDataOutputRate(SensorQMC6310::DATARATE_200HZ);
int32_t x_min = 65535;
int32_t x_max = -65535;
int32_t y_min = 65535;
int32_t y_max = -65535;
int32_t z_min = 65535;
int32_t z_max = -65535;
Serial.println("Place the sensor on the plane and slowly rotate the sensor...");
int32_t range = 1000;
int32_t i = 0;
int32_t x = 0, y = 0, z = 0;;
float a = 0.5 ;
float x_offset = 0;
float y_offset = 0;
float z_offset = 0;
while (i < range) {
i += 1;
if (qmc.isDataReady()) {
qmc.readData();
x = a * qmc.getRawX() + (1 - a) * x;
y = a * qmc.getRawY() + (1 - a) * y;
z = a * qmc.getRawZ() + (1 - a) * z;
if (x < x_min) {
x_min = x;
i = 0;
}
if (x > x_max) {
x_max = x;
i = 0;
}
if (y < y_min) {
y_min = y;
i = 0;
}
if (y > y_max) {
y_max = y;
i = 0;
}
if (z < z_min) {
z_min = z;
i = 0;
}
if (z > z_max) {
z_max = z;
i = 0;
}
int j = round(10 * i / range);
Serial.print("[");
for (int k = 0; k < j; ++k) {
Serial.print("*");
}
Serial.println("]");
}
delay(5);
}
x_offset = (x_max + x_min) / 2;
y_offset = (y_max + y_min) / 2;
z_offset = (z_max + z_min) / 2;
Serial.printf("x_min:%d x_max:%d y_min:%d y_max:%d z_min:%d z_max:%d\n", x_min, x_max, y_min, y_max, z_min, z_max);
Serial.printf("x_offset:%.2f y_offset:%.2f z_offset:%.2f \n", x_offset, y_offset, z_offset);
// Set the calibration value and the user calculates the deviation
qmc.setOffset(x_offset, y_offset, z_offset);
}
void setup()
{
Serial.begin(115200);
while (!Serial);
if (!qmc.begin(Wire, QMC6310_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMC6310 - check your wiring!");
while (1) {
delay(1000);
}
}
/* Get Magnetometer chip id*/
Serial.print("Device ID:");
Serial.println(qmc.getChipID(), HEX);
/* Config Magnetometer */
qmc.configMagnetometer(
/*
* Run Mode
* MODE_SUSPEND
* MODE_NORMAL
* MODE_SINGLE
* MODE_CONTINUOUS
* * */
SensorQMC6310::MODE_CONTINUOUS,
/*
* Full Range
* RANGE_30G
* RANGE_12G
* RANGE_8G
* RANGE_2G
* * */
SensorQMC6310::RANGE_8G,
/*
* Output data rate
* DATARATE_10HZ
* DATARATE_50HZ
* DATARATE_100HZ
* DATARATE_200HZ
* * */
SensorQMC6310::DATARATE_200HZ,
/*
* Over sample Ratio1
* OSR_8
* OSR_4
* OSR_2
* OSR_1
* * * */
SensorQMC6310::OSR_1,
/*
* Down sample Ratio1
* DSR_8
* DSR_4
* DSR_2
* DSR_1
* * */
SensorQMC6310::DSR_1);
// Calibration algorithm reference from
// https://github.com/CoreElectronics/CE-PiicoDev-QMC6310-MicroPython-Module
calibrate();
Serial.println("Calibration done .");
delay(5000);
Serial.println("Read data now...");
}
void loop()
{
//Wiat data ready
if (qmc.isDataReady()) {
qmc.readData();
Serial.print("GYR: ");
Serial.print("X:");
Serial.print(qmc.getX());
Serial.print(" Y:");
Serial.print(qmc.getY());
Serial.print(" Z:");
Serial.print(qmc.getZ());
Serial.println(" uT");
Serial.print("RAW: ");
Serial.print("X:");
Serial.print(qmc.getRawX());
Serial.print(" Y:");
Serial.print(qmc.getRawY());
Serial.print(" Z:");
Serial.println(qmc.getRawZ());
/*
float x, y, z;
qmc.getMag(x, y, z);
Serial.print("X:");
Serial.print(x);
Serial.print(" Y:");
Serial.print(y);
Serial.print(" Z:");
Serial.println(x);
*/
}
delay(100);
}

View File

@ -0,0 +1,234 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMC6310_GetDataExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#ifndef ARDUINO_ARCH_RP2040
#include "SensorQMC6310.hpp"
#include "SH1106Wire.h" //Oled display from https://github.com/ThingPulse/esp8266-oled-ssd1306
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
#define I2C1_SDA 22 //Display Wire SDA Pin
#define I2C1_SCL 21 //Display Wire SCL Pin
SH1106Wire display(0x3c, I2C1_SDA, I2C1_SCL);
SensorQMC6310 qmc;
int last_dx, last_dy, dx, dy, angle;
const int centreX = 32;
const int centreY = 30;
const int radius = 22;
//Compass application from https://github.com/G6EJD/ESP8266_micro_compass_HMC5883_OLED
void arrow(int x2, int y2, int x1, int y1, int alength, int awidth, OLEDDISPLAY_COLOR color)
{
display.setColor(color);
float distance;
int dx, dy, x2o, y2o, x3, y3, x4, y4, k;
distance = sqrt(pow((x1 - x2), 2) + pow((y1 - y2), 2));
dx = x2 + (x1 - x2) * alength / distance;
dy = y2 + (y1 - y2) * alength / distance;
k = awidth / alength;
x2o = x2 - dx;
y2o = dy - y2;
x3 = y2o * k + dx;
y3 = x2o * k + dy;
x4 = dx - y2o * k;
y4 = dy - x2o * k;
display.drawLine(x1, y1, x2, y2);
display.drawLine(x1, y1, dx, dy);
display.drawLine(x3, y3, x4, y4);
display.drawLine(x3, y3, x2, y2);
display.drawLine(x2, y2, x4, y4);
}
void setup()
{
Serial.begin(115200);
while (!Serial);
if (!qmc.begin(Wire, QMC6310_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMC6310 - check your wiring!");
while (1) {
delay(1000);
}
}
display.init();
last_dx = centreX;
last_dy = centreY;
/* Get Magnetometer chip id*/
Serial.print("Device ID:");
Serial.println(qmc.getChipID(), HEX);
/* Config Magnetometer */
int r = qmc.configMagnetometer(
/*
* Run Mode
* MODE_SUSPEND
* MODE_NORMAL
* MODE_SINGLE
* MODE_CONTINUOUS
* * */
SensorQMC6310::MODE_NORMAL,
/*
* Full Range
* RANGE_30G
* RANGE_12G
* RANGE_8G
* RANGE_2G
* * */
SensorQMC6310::RANGE_2G,
/*
* Output data rate
* DATARATE_10HZ
* DATARATE_50HZ
* DATARATE_100HZ
* DATARATE_200HZ
* * */
SensorQMC6310::DATARATE_100HZ,
/*
* Over sample Ratio1
* OSR_8
* OSR_4
* OSR_2
* OSR_1
* * * */
SensorQMC6310::OSR_1,
/*
* Down sample Ratio1
* DSR_8
* DSR_4
* DSR_2
* DSR_1
* * */
SensorQMC6310::DSR_1);
if (r != DEV_WIRE_NONE) {
Serial.println("Device config failed!");
while (1)delay(1000);
}
// Print register configuration information
qmc.dumpCtrlRegister();
Serial.println("Read data now...");
}
void loop()
{
//Wiat data ready
if (qmc.isDataReady()) {
qmc.readData();
display.drawString(29, 0, "N");
display.drawString( 0, 28, "W");
display.drawString(60, 28, "E");
display.drawString(29, 53, "S");
display.drawLine(1, 1, 7, 7);
display.drawLine(62, 1, 56, 7);
display.drawLine(1, 62, 7, 56);
display.drawLine(56, 56, 62, 62);
//Compass application from https://github.com/G6EJD/ESP8266_micro_compass_HMC5883_OLED
float heading = atan2(qmc.getY(), qmc.getX()); // Result is in radians
// Now add the 'Declination Angle' for you location. Declination is the variation in magnetic field at your location.
// Find your declination here: http://www.magnetic-declination.com/
// At my location it is : -2° 20' W, or -2.33 Degrees, which needs to be in radians so = -2.33 / 180 * PI = -0.041 West is + E is -
// Make declination = 0 if you can't find your Declination value, the error is negible for nearly all locations
float declination = -0.041;
heading = heading + declination;
if (heading < 0) heading += 2 * PI; // Correct for when signs are reversed.
if (heading > 2 * PI) heading -= 2 * PI; // Correct for when heading exceeds 360-degree, especially when declination is included
angle = int(heading * 180 / M_PI); // Convert radians to degrees for more a more usual result
// For the screen -X = up and +X = down and -Y = left and +Y = right, so does not follow coordinate conventions
dx = (0.7 * radius * cos((angle - 90) * 3.14 / 180)) + centreX; // calculate X position for the screen coordinates - can be confusing!
dy = (0.7 * radius * sin((angle - 90) * 3.14 / 180)) + centreY; // calculate Y position for the screen coordinates - can be confusing!
arrow(last_dx, last_dy, centreX, centreY, 2, 2, BLACK); // Erase last arrow
arrow(dx, dy, centreX, centreY, 2, 2, WHITE); // Draw arrow in new position
display.setColor(BLACK);
display.fillRect(80, 50, 25, 48);
display.setColor(WHITE);
display.drawString(80, 50, String(angle) + "°");
display.display();
last_dx = dx;
last_dy = dy;
// for debug.
Serial.print("GYR: ");
Serial.print("X:");
Serial.print(qmc.getX());
Serial.print(" Y:");
Serial.print(qmc.getY());
Serial.print(" Z:");
Serial.print(qmc.getZ());
Serial.println(" uT");
}
delay(100);
}
#else
void setup()
{
Serial.begin(115200);
}
void loop()
{
Serial.println("display lib not support RP2040"); delay(1000);
}
#endif

View File

@ -0,0 +1,155 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMC6310_GetDataExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorQMC6310.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
SensorQMC6310 qmc;
void setup()
{
Serial.begin(115200);
while (!Serial);
if (!qmc.begin(Wire, QMC6310_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMC6310 - check your wiring!");
while (1) {
delay(1000);
}
}
/* Get Magnetometer chip id*/
Serial.print("Device ID:");
Serial.println(qmc.getChipID(), HEX);
/* Config Magnetometer */
qmc.configMagnetometer(
/*
* Run Mode
* MODE_SUSPEND
* MODE_NORMAL
* MODE_SINGLE
* MODE_CONTINUOUS
* * */
SensorQMC6310::MODE_CONTINUOUS,
/*
* Full Range
* RANGE_30G
* RANGE_12G
* RANGE_8G
* RANGE_2G
* * */
SensorQMC6310::RANGE_8G,
/*
* Output data rate
* DATARATE_10HZ
* DATARATE_50HZ
* DATARATE_100HZ
* DATARATE_200HZ
* * */
SensorQMC6310::DATARATE_200HZ,
/*
* Over sample Ratio1
* OSR_8
* OSR_4
* OSR_2
* OSR_1
* * * */
SensorQMC6310::OSR_1,
/*
* Down sample Ratio1
* DSR_8
* DSR_4
* DSR_2
* DSR_1
* * */
SensorQMC6310::DSR_1);
Serial.println("Read data now...");
}
void loop()
{
//Wiat data ready
if (qmc.isDataReady()) {
qmc.readData();
Serial.print("GYR: ");
Serial.print("X:");
Serial.print(qmc.getX());
Serial.print(" Y:");
Serial.print(qmc.getY());
Serial.print(" Z:");
Serial.print(qmc.getZ());
Serial.println(" uT");
Serial.print("RAW: ");
Serial.print("X:");
Serial.print(qmc.getRawX());
Serial.print(" Y:");
Serial.print(qmc.getRawY());
Serial.print(" Z:");
Serial.println(qmc.getRawZ());
/*
float x, y, z;
qmc.getMag(x, y, z);
Serial.print("X:");
Serial.print(x);
Serial.print(" Y:");
Serial.print(y);
Serial.print(" Z:");
Serial.println(x);
*/
}
delay(100);
}

View File

@ -0,0 +1,133 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMC6310_GetPolarExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorQMC6310.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
SensorQMC6310 qmc;
void setup()
{
Serial.begin(115200);
while (!Serial);
if (!qmc.begin(Wire, QMC6310_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMC6310 - check your wiring!");
while (1) {
delay(1000);
}
}
/* Get Magnetometer chip id*/
Serial.print("Device ID:");
Serial.println(qmc.getChipID(), HEX);
/* Config Magnetometer */
qmc.configMagnetometer(
/*
* Run Mode
* MODE_SUSPEND
* MODE_NORMAL
* MODE_SINGLE
* MODE_CONTINUOUS
* * */
SensorQMC6310::MODE_NORMAL,
/*
* Full Range
* RANGE_30G
* RANGE_12G
* RANGE_8G
* RANGE_2G
* * */
SensorQMC6310::RANGE_8G,
/*
* Output data rate
* DATARATE_10HZ
* DATARATE_50HZ
* DATARATE_100HZ
* DATARATE_200HZ
* * */
SensorQMC6310::DATARATE_200HZ,
/*
* Over sample Ratio1
* OSR_8
* OSR_4
* OSR_2
* OSR_1
* * * */
SensorQMC6310::OSR_8,
/*
* Down sample Ratio1
* DSR_8
* DSR_4
* DSR_2
* DSR_1
* * */
SensorQMC6310::DSR_1);
qmc.dumpCtrlRegister();
// Declination is the difference between magnetic-north and true-north ("heading") and depends on location
qmc.setDeclination(-2.77); // Found with: https://www.magnetic-declination.com/CHINA/SHENZHEN/475119.html
Serial.println("Read data now...");
}
void loop()
{
Polar data;
// Wait for data ready
if (qmc.readPolar(data)) {
Serial.print(" polar:"); Serial.print(data.polar); Serial.print("°");
Serial.print(" Gauss:"); Serial.print(data.Gauss);
Serial.print(" uT:"); Serial.println(data.uT);
}
delay(100);
}

View File

@ -0,0 +1,262 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMI8658_BlockExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#ifndef ARDUINO_ARCH_RP2040
#include "SensorQMI8658.hpp"
#include <MadgwickAHRS.h> //MadgwickAHRS from https://github.com/arduino-libraries/MadgwickAHRS
#include "SH1106Wire.h" //Oled display from https://github.com/ThingPulse/esp8266-oled-ssd1306
// #define USE_WIRE
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
#define I2C1_SDA 22 //Display Wire SDA Pin
#define I2C1_SCL 21 //Display Wire SCL Pin
SH1106Wire display(0x3c, I2C1_SDA, I2C1_SCL);
SensorQMI8658 qmi;
IMUdata acc;
IMUdata gyr;
Madgwick filter;
unsigned long microsPerReading, microsPrevious;
float posX = 64;
float posY = 32;
float lastPosX = posX;
float lastPosY = posY;
void setup()
{
Serial.begin(115200);
while (!Serial);
display.init();
#ifdef USE_WIRE
//Using WIRE !!
if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#else
#ifndef CONFIG_IDF_TARGET_ESP32
//Use tbeams3 defalut spi pin
#define SPI_MOSI (35)
#define SPI_SCK (36)
#define SPI_MISO (37)
#define SPI_CS (47)
#define IMU_CS (34)
#define IMU_INT1 (33) //INTERRUPT PIN1 & PIN2 ,Use or logic to form a pin
pinMode(SPI_CS, OUTPUT); //sdcard pin set high
digitalWrite(SPI_CS, HIGH);
if (!qmi.begin(IMU_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
#else
//Use esp32dev module defalut spi pin
#define IMU_CS (5)
#define IMU_INT1 (15)
#define IMU_INT2 (22)
if (!qmi.begin(IMU_CS)) {
#endif
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#endif
/* Get chip id*/
Serial.print("Device ID:");
Serial.println(qmi.getChipID(), HEX);
display.flipScreenVertically();
qmi.configAccelerometer(
/*
* ACC_RANGE_2G
* ACC_RANGE_4G
* ACC_RANGE_8G
* ACC_RANGE_16G
* */
SensorQMI8658::ACC_RANGE_2G,
/*
* ACC_ODR_1000H
* ACC_ODR_500Hz
* ACC_ODR_250Hz
* ACC_ODR_125Hz
* ACC_ODR_62_5Hz
* ACC_ODR_31_25Hz
* ACC_ODR_LOWPOWER_128Hz
* ACC_ODR_LOWPOWER_21Hz
* ACC_ODR_LOWPOWER_11Hz
* ACC_ODR_LOWPOWER_3H
* */
SensorQMI8658::ACC_ODR_1000Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_0,
// selfTest enable
true);
qmi.configGyroscope(
/*
* GYR_RANGE_16DPS
* GYR_RANGE_32DPS
* GYR_RANGE_64DPS
* GYR_RANGE_128DPS
* GYR_RANGE_256DPS
* GYR_RANGE_512DPS
* GYR_RANGE_1024DPS
* */
SensorQMI8658::GYR_RANGE_256DPS,
/*
* GYR_ODR_7174_4Hz
* GYR_ODR_3587_2Hz
* GYR_ODR_1793_6Hz
* GYR_ODR_896_8Hz
* GYR_ODR_448_4Hz
* GYR_ODR_224_2Hz
* GYR_ODR_112_1Hz
* GYR_ODR_56_05Hz
* GYR_ODR_28_025H
* */
SensorQMI8658::GYR_ODR_896_8Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_3,
// selfTest enable
true);
// In 6DOF mode (accelerometer and gyroscope are both enabled),
// the output data rate is derived from the nature frequency of gyroscope
qmi.enableGyroscope();
qmi.enableAccelerometer();
// Print register configuration information
qmi.dumpCtrlRegister();
// start filter
filter.begin(25);
// initialize variables to pace updates to correct rate
microsPerReading = 1000000 / 25;
microsPrevious = micros();
Serial.println("Read data now...");
}
const uint8_t rectWidth = 10;
void loop()
{
float roll, pitch, heading;
// check if it's time to read data and update the filter
if (micros() - microsPrevious >= microsPerReading) {
// read raw data from IMU
if (qmi.getDataReady()) {
qmi.getAccelerometer(acc.x, acc.y, acc.z);
qmi.getGyroscope(gyr.x, gyr.y, gyr.z);
// update the filter, which computes orientation
filter.updateIMU(gyr.x, gyr.y, gyr.z, acc.x, acc.y, acc.z);
// print the heading, pitch and roll
roll = filter.getRoll();
pitch = filter.getPitch();
heading = filter.getYaw();
posX -= roll * 2;
posY += pitch;
Serial.printf("x:%.2f y:%.2f \n", posX, posY);
posX = constrain(posX, 0, display.width() - rectWidth);
posY = constrain(posY, 0, display.height() - rectWidth);
display.setColor(BLACK);
display.fillRect(lastPosX, lastPosY, 10, 10);
display.setColor(WHITE);
display.fillRect(posX, posY, 10, 10);
display.display();
lastPosX = posX;
lastPosY = posY;
}
// increment previous time, so we keep proper pace
microsPrevious = microsPrevious + microsPerReading;
}
}
#else
void setup()
{
Serial.begin(115200);
}
void loop()
{
Serial.println("display lib not support RP2040"); delay(1000);
}
#endif

View File

@ -0,0 +1,195 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMI8658_GetDataExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include "SensorQMI8658.hpp"
#define USE_WIRE
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
#define IMU_CS 5
SensorQMI8658 qmi;
IMUdata acc;
IMUdata gyr;
void setup()
{
Serial.begin(115200);
while (!Serial);
#ifdef USE_WIRE
//Using WIRE !!
if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#else
if (!qmi.begin(IMU_CS)) {
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#endif
/* Get chip id*/
Serial.print("Device ID:");
Serial.println(qmi.getChipID(), HEX);
qmi.configAccelerometer(
/*
* ACC_RANGE_2G
* ACC_RANGE_4G
* ACC_RANGE_8G
* ACC_RANGE_16G
* */
SensorQMI8658::ACC_RANGE_4G,
/*
* ACC_ODR_1000H
* ACC_ODR_500Hz
* ACC_ODR_250Hz
* ACC_ODR_125Hz
* ACC_ODR_62_5Hz
* ACC_ODR_31_25Hz
* ACC_ODR_LOWPOWER_128Hz
* ACC_ODR_LOWPOWER_21Hz
* ACC_ODR_LOWPOWER_11Hz
* ACC_ODR_LOWPOWER_3H
* */
SensorQMI8658::ACC_ODR_1000Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_0,
// selfTest enable
true);
qmi.configGyroscope(
/*
* GYR_RANGE_16DPS
* GYR_RANGE_32DPS
* GYR_RANGE_64DPS
* GYR_RANGE_128DPS
* GYR_RANGE_256DPS
* GYR_RANGE_512DPS
* GYR_RANGE_1024DPS
* */
SensorQMI8658::GYR_RANGE_64DPS,
/*
* GYR_ODR_7174_4Hz
* GYR_ODR_3587_2Hz
* GYR_ODR_1793_6Hz
* GYR_ODR_896_8Hz
* GYR_ODR_448_4Hz
* GYR_ODR_224_2Hz
* GYR_ODR_112_1Hz
* GYR_ODR_56_05Hz
* GYR_ODR_28_025H
* */
SensorQMI8658::GYR_ODR_896_8Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_3,
// selfTest enable
true);
// In 6DOF mode (accelerometer and gyroscope are both enabled),
// the output data rate is derived from the nature frequency of gyroscope
qmi.enableGyroscope();
qmi.enableAccelerometer();
// Print register configuration information
qmi.dumpCtrlRegister();
Serial.println("Read data now...");
}
void loop()
{
if (qmi.getDataReady()) {
if (qmi.getAccelerometer(acc.x, acc.y, acc.z)) {
Serial.print("{ACCEL: ");
Serial.print(acc.x);
Serial.print(",");
Serial.print(acc.y);
Serial.print(",");
Serial.print(acc.z);
Serial.println("}");
}
if (qmi.getGyroscope(gyr.x, gyr.y, gyr.z)) {
Serial.print("{GYRO: ");
Serial.print(gyr.x);
Serial.print(",");
Serial.print(gyr.y );
Serial.print(",");
Serial.print(gyr.z);
Serial.println("}");
}
Serial.printf("\t\t\t\t > %lu %.2f *C\n", qmi.getTimestamp(), qmi.getTemperature_C());
}
delay(100);
}

View File

@ -0,0 +1,272 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMI8658_InterruptBlockExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#ifndef ARDUINO_ARCH_RP2040
#include "SensorQMI8658.hpp"
#include <MadgwickAHRS.h> //MadgwickAHRS from https://github.com/arduino-libraries/MadgwickAHRS
#include "SH1106Wire.h" //Oled display from https://github.com/ThingPulse/esp8266-oled-ssd1306
// #define USE_WIRE
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
#define I2C1_SDA 22 //Display Wire SDA Pin
#define I2C1_SCL 21 //Display Wire SCL Pin
SH1106Wire display(0x3c, I2C1_SDA, I2C1_SCL);
SensorQMI8658 qmi;
IMUdata acc;
IMUdata gyr;
Madgwick filter;
unsigned long microsPerReading, microsPrevious;
float posX = 64;
float posY = 32;
float lastPosX = posX;
float lastPosY = posY;
void setup()
{
Serial.begin(115200);
while (!Serial);
display.init();
display.flipScreenVertically();
#ifdef USE_WIRE
//Using WIRE !!
if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#else
#ifndef CONFIG_IDF_TARGET_ESP32
//Use tbeams3 defalut spi pin
#define SPI_MOSI (35)
#define SPI_SCK (36)
#define SPI_MISO (37)
#define SPI_CS (47)
#define IMU_CS (34)
#define IMU_INT1 (33) //INTERRUPT PIN1 & PIN2 ,Use or logic to form a pin
pinMode(SPI_CS, OUTPUT); //sdcard pin set high
digitalWrite(SPI_CS, HIGH);
if (!qmi.begin(IMU_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
#else
//Use esp32dev module defalut spi pin
#define IMU_CS (5)
#define IMU_INT1 (15)
#define IMU_INT2 (22)
if (!qmi.begin(IMU_CS)) {
#endif
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#endif
/* Get chip id*/
Serial.print("Device ID:");
Serial.println(qmi.getChipID(), HEX);
qmi.configAccelerometer(
/*
* ACC_RANGE_2G
* ACC_RANGE_4G
* ACC_RANGE_8G
* ACC_RANGE_16G
* */
SensorQMI8658::ACC_RANGE_2G,
/*
* ACC_ODR_1000H
* ACC_ODR_500Hz
* ACC_ODR_250Hz
* ACC_ODR_125Hz
* ACC_ODR_62_5Hz
* ACC_ODR_31_25Hz
* ACC_ODR_LOWPOWER_128Hz
* ACC_ODR_LOWPOWER_21Hz
* ACC_ODR_LOWPOWER_11Hz
* ACC_ODR_LOWPOWER_3H
* */
SensorQMI8658::ACC_ODR_1000Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_0,
// selfTest enable
true);
qmi.configGyroscope(
/*
* GYR_RANGE_16DPS
* GYR_RANGE_32DPS
* GYR_RANGE_64DPS
* GYR_RANGE_128DPS
* GYR_RANGE_256DPS
* GYR_RANGE_512DPS
* GYR_RANGE_1024DPS
* */
SensorQMI8658::GYR_RANGE_256DPS,
/*
* GYR_ODR_7174_4Hz
* GYR_ODR_3587_2Hz
* GYR_ODR_1793_6Hz
* GYR_ODR_896_8Hz
* GYR_ODR_448_4Hz
* GYR_ODR_224_2Hz
* GYR_ODR_112_1Hz
* GYR_ODR_56_05Hz
* GYR_ODR_28_025H
* */
SensorQMI8658::GYR_ODR_896_8Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_3,
// selfTest enable
true);
// In 6DOF mode (accelerometer and gyroscope are both enabled),
// the output data rate is derived from the nature frequency of gyroscope
qmi.enableGyroscope();
qmi.enableAccelerometer();
pinMode(IMU_INT1, INPUT);
#ifdef IMU_INT2
pinMode(IMU_INT2, INPUT);
#endif
// qmi.enableINT(SensorQMI8658::IntPin1); //no use
// Enable data ready to interrupt pin2
qmi.enableINT(SensorQMI8658::IntPin2);
qmi.enableDataReadyINT();
// Print register configuration information
qmi.dumpCtrlRegister();
// start filter
filter.begin(25);
// initialize variables to pace updates to correct rate
microsPerReading = 1000000 / 25;
microsPrevious = micros();
Serial.println("Read data now...");
}
const uint8_t rectWidth = 10;
void loop()
{
float roll, pitch, heading;
// check if it's time to read data and update the filter
if (micros() - microsPrevious >= microsPerReading) {
// read raw data from IMU
if (digitalRead(IMU_INT1) == HIGH) {
qmi.getAccelerometer(acc.x, acc.y, acc.z);
qmi.getGyroscope(gyr.x, gyr.y, gyr.z);
// update the filter, which computes orientation
filter.updateIMU(gyr.x, gyr.y, gyr.z, acc.x, acc.y, acc.z);
// print the heading, pitch and roll
roll = filter.getRoll();
pitch = filter.getPitch();
heading = filter.getYaw();
posX -= roll * 2;
posY += pitch;
Serial.printf("x:%.2f y:%.2f \n", posX, posY);
posX = constrain(posX, 0, display.width() - rectWidth);
posY = constrain(posY, 0, display.height() - rectWidth);
display.setColor(BLACK);
display.fillRect(lastPosX, lastPosY, 10, 10);
display.setColor(WHITE);
display.fillRect(posX, posY, 10, 10);
display.display();
lastPosX = posX;
lastPosY = posY;
}
// increment previous time, so we keep proper pace
microsPrevious = microsPrevious + microsPerReading;
}
}
#else
void setup()
{
Serial.begin(115200);
}
void loop()
{
Serial.println("display lib not support RP2040");
delay(1000);
}
#endif

View File

@ -0,0 +1,247 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMI8658_InterruptExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-11-03
*
*/
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include "SensorQMI8658.hpp"
// #define USE_WIRE
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
SensorQMI8658 qmi;
IMUdata acc;
IMUdata gyr;
void setup()
{
Serial.begin(115200);
while (!Serial);
#ifdef USE_WIRE
//Using WIRE !!
if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#else
#ifndef CONFIG_IDF_TARGET_ESP32
//Use tbeams3 defalut spi pin
#define SPI_MOSI (35)
#define SPI_SCK (36)
#define SPI_MISO (37)
#define SPI_CS (47)
#define IMU_CS (34)
#define IMU_INT1 (33)
pinMode(SPI_CS, OUTPUT); //sdcard pin set high
digitalWrite(SPI_CS, HIGH);
if (!qmi.begin(IMU_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
#else
//Use esp32dev module defalut spi pin
#define IMU_CS (5)
#define IMU_INT1 (15)
#define IMU_INT2 (22)
if (!qmi.begin(IMU_CS)) {
#endif
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#endif
/* Get chip id*/
Serial.print("Device ID:");
Serial.println(qmi.getChipID(), HEX);
qmi.configAccelerometer(
/*
* ACC_RANGE_2G
* ACC_RANGE_4G
* ACC_RANGE_8G
* ACC_RANGE_16G
* */
SensorQMI8658::ACC_RANGE_4G,
/*
* ACC_ODR_1000H
* ACC_ODR_500Hz
* ACC_ODR_250Hz
* ACC_ODR_125Hz
* ACC_ODR_62_5Hz
* ACC_ODR_31_25Hz
* ACC_ODR_LOWPOWER_128Hz
* ACC_ODR_LOWPOWER_21Hz
* ACC_ODR_LOWPOWER_11Hz
* ACC_ODR_LOWPOWER_3H
* */
SensorQMI8658::ACC_ODR_1000Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_0,
// selfTest enable
true);
qmi.configGyroscope(
/*
* GYR_RANGE_16DPS
* GYR_RANGE_32DPS
* GYR_RANGE_64DPS
* GYR_RANGE_128DPS
* GYR_RANGE_256DPS
* GYR_RANGE_512DPS
* GYR_RANGE_1024DPS
* */
SensorQMI8658::GYR_RANGE_64DPS,
/*
* GYR_ODR_7174_4Hz
* GYR_ODR_3587_2Hz
* GYR_ODR_1793_6Hz
* GYR_ODR_896_8Hz
* GYR_ODR_448_4Hz
* GYR_ODR_224_2Hz
* GYR_ODR_112_1Hz
* GYR_ODR_56_05Hz
* GYR_ODR_28_025H
* */
SensorQMI8658::GYR_ODR_896_8Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_3,
// selfTest enable
true);
// In 6DOF mode (accelerometer and gyroscope are both enabled),
// the output data rate is derived from the nature frequency of gyroscope
qmi.enableGyroscope();
qmi.enableAccelerometer();
pinMode(IMU_INT1, INPUT);
#ifdef IMU_INT2
pinMode(IMU_INT2, INPUT);
#endif
// qmi.enableINT(SensorQMI8658::IntPin1); //no use
// Enable data ready to interrupt pin2
qmi.enableINT(SensorQMI8658::IntPin2);
qmi.enableDataReadyINT();
// Print register configuration information
qmi.dumpCtrlRegister();
Serial.println("Read data now...");
}
void readSensorData(const char *name)
{
uint8_t status = qmi.getIrqStatus();
// status == 0x01
// If syncSmpl (CTRL7.bit7) = 1:
// 0: Sensor Data is not available
// 1: Sensor Data is available for reading
// If syncSmpl = 0, this bit shows the same value of INT2 level
Serial.print(name);
Serial.print(" -> [");
Serial.print(millis());
Serial.print("]: -<HEX> ");
Serial.print(status);
Serial.print(" -<BIN> ");
Serial.println(status, BIN);
if (status & 0x01) {
if (qmi.getAccelerometer(acc.x, acc.y, acc.z)) {
Serial.print("{ACCEL: ");
Serial.print(acc.x);
Serial.print(",");
Serial.print(acc.y);
Serial.print(",");
Serial.print(acc.z);
Serial.println("}");
}
if (qmi.getGyroscope(gyr.x, gyr.y, gyr.z)) {
Serial.print("{GYRO: ");
Serial.print(gyr.x);
Serial.print(",");
Serial.print(gyr.y );
Serial.print(",");
Serial.print(gyr.z);
Serial.println("}");
}
Serial.printf("\t\t\t\t > %lu %.2f *C\n", qmi.getTimestamp(), qmi.getTemperature_C());
}
}
void loop()
{
if (digitalRead(IMU_INT1) == HIGH) {
readSensorData("INT1");
}
#ifdef IMU_INT2
if (digitalRead(IMU_INT2) == HIGH) {
readSensorData("INT2");
}
#endif
}

View File

@ -0,0 +1,246 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMI8658_LockingMechanismExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-11-07
*
*/
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include "SensorQMI8658.hpp"
// #define USE_WIRE
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
SensorQMI8658 qmi;
IMUdata acc;
IMUdata gyr;
bool interruptFlag = false;
void setFlag(void)
{
interruptFlag = true;
}
// Callback when data is locked
void lockingMechanismHandler()
{
if (qmi.getAccelerometer(acc.x, acc.y, acc.z)) {
Serial.print("{ACCEL: ");
Serial.print(acc.x);
Serial.print(",");
Serial.print(acc.y);
Serial.print(",");
Serial.print(acc.z);
Serial.println("}");
}
if (qmi.getGyroscope(gyr.x, gyr.y, gyr.z)) {
Serial.print("{GYRO: ");
Serial.print(gyr.x);
Serial.print(",");
Serial.print(gyr.y );
Serial.print(",");
Serial.print(gyr.z);
Serial.println("}");
}
Serial.printf("\t\t\t\t > %lu %.2f *C\n", qmi.getTimestamp(), qmi.getTemperature_C());
}
void setup()
{
Serial.begin(115200);
while (!Serial);
#ifdef USE_WIRE
//Using WIRE !!
if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#else
#ifndef CONFIG_IDF_TARGET_ESP32
//Use tbeams3 defalut spi pin
#define SPI_MOSI (35)
#define SPI_SCK (36)
#define SPI_MISO (37)
#define SPI_CS (47)
#define IMU_CS (34)
#define IMU_INT1 (33)
pinMode(SPI_CS, OUTPUT); //sdcard pin set high
digitalWrite(SPI_CS, HIGH);
if (!qmi.begin(IMU_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
#else
//Use esp32dev module defalut spi pin
#define IMU_CS (5)
#define IMU_INT1 (15)
#define IMU_INT2 (22)
if (!qmi.begin(IMU_CS)) {
#endif
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#endif
/* Get chip id*/
Serial.print("Device ID:");
Serial.println(qmi.getChipID(), HEX);
qmi.configAccelerometer(
/*
* ACC_RANGE_2G
* ACC_RANGE_4G
* ACC_RANGE_8G
* ACC_RANGE_16G
* */
SensorQMI8658::ACC_RANGE_4G,
/*
* ACC_ODR_1000H
* ACC_ODR_500Hz
* ACC_ODR_250Hz
* ACC_ODR_125Hz
* ACC_ODR_62_5Hz
* ACC_ODR_31_25Hz
* ACC_ODR_LOWPOWER_128Hz
* ACC_ODR_LOWPOWER_21Hz
* ACC_ODR_LOWPOWER_11Hz
* ACC_ODR_LOWPOWER_3H
* */
SensorQMI8658::ACC_ODR_1000Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_0,
// selfTest enable
true);
qmi.configGyroscope(
/*
* GYR_RANGE_16DPS
* GYR_RANGE_32DPS
* GYR_RANGE_64DPS
* GYR_RANGE_128DPS
* GYR_RANGE_256DPS
* GYR_RANGE_512DPS
* GYR_RANGE_1024DPS
* */
SensorQMI8658::GYR_RANGE_64DPS,
/*
* GYR_ODR_7174_4Hz
* GYR_ODR_3587_2Hz
* GYR_ODR_1793_6Hz
* GYR_ODR_896_8Hz
* GYR_ODR_448_4Hz
* GYR_ODR_224_2Hz
* GYR_ODR_112_1Hz
* GYR_ODR_56_05Hz
* GYR_ODR_28_025H
* */
SensorQMI8658::GYR_ODR_896_8Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_3,
// selfTest enable
true);
// In 6DOF mode (accelerometer and gyroscope are both enabled),
// the output data rate is derived from the nature frequency of gyroscope
qmi.enableGyroscope();
qmi.enableAccelerometer();
//Enable Locking Mechanism
qmi.enableLockingMechanism();
// Set locking data event callback
qmi.setDataLockingEvevntCallBack(lockingMechanismHandler);
// Use interrupt .
// QMI8658 interrupt always outputs low level by default,
// and the interrupt is triggered when the rising edge
pinMode(IMU_INT1, INPUT_PULLUP);
#ifdef IMU_INT2
pinMode(IMU_INT2, INPUT_PULLUP);
attachInterrupt(IMU_INT2, setFlag, RISING);
#else
attachInterrupt(IMU_INT1, setFlag, RISING);
#endif
// qmi.enableINT(SensorQMI8658::IntPin1); //no use
// Enable data ready to interrupt pin2
qmi.enableINT(SensorQMI8658::IntPin2);
// Print register configuration information
qmi.dumpCtrlRegister();
Serial.println("Read data now...");
}
void loop()
{
if (interruptFlag) {
interruptFlag = false;
qmi.readSensorStatus();
}
delay(100);
}

View File

@ -0,0 +1,204 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMI8658_MadgwickAHRS.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include "SensorQMI8658.hpp"
#include <MadgwickAHRS.h> //MadgwickAHRS from https://github.com/arduino-libraries/MadgwickAHRS
#define USE_WIRE
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
#define IMU_CS 5
SensorQMI8658 qmi;
IMUdata acc;
IMUdata gyr;
Madgwick filter;
unsigned long microsPerReading, microsPrevious;
void setup()
{
Serial.begin(115200);
while (!Serial);
#ifdef USE_WIRE
//Using WIRE !!
if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#else
if (!qmi.begin(IMU_CS)) {
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#endif
/* Get chip id*/
Serial.print("Device ID:");
Serial.println(qmi.getChipID(), HEX);
qmi.configAccelerometer(
/*
* ACC_RANGE_2G
* ACC_RANGE_4G
* ACC_RANGE_8G
* ACC_RANGE_16G
* */
SensorQMI8658::ACC_RANGE_2G,
/*
* ACC_ODR_1000H
* ACC_ODR_500Hz
* ACC_ODR_250Hz
* ACC_ODR_125Hz
* ACC_ODR_62_5Hz
* ACC_ODR_31_25Hz
* ACC_ODR_LOWPOWER_128Hz
* ACC_ODR_LOWPOWER_21Hz
* ACC_ODR_LOWPOWER_11Hz
* ACC_ODR_LOWPOWER_3H
* */
SensorQMI8658::ACC_ODR_1000Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_0,
// selfTest enable
true);
qmi.configGyroscope(
/*
* GYR_RANGE_16DPS
* GYR_RANGE_32DPS
* GYR_RANGE_64DPS
* GYR_RANGE_128DPS
* GYR_RANGE_256DPS
* GYR_RANGE_512DPS
* GYR_RANGE_1024DPS
* */
SensorQMI8658::GYR_RANGE_256DPS,
/*
* GYR_ODR_7174_4Hz
* GYR_ODR_3587_2Hz
* GYR_ODR_1793_6Hz
* GYR_ODR_896_8Hz
* GYR_ODR_448_4Hz
* GYR_ODR_224_2Hz
* GYR_ODR_112_1Hz
* GYR_ODR_56_05Hz
* GYR_ODR_28_025H
* */
SensorQMI8658::GYR_ODR_896_8Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_3,
// selfTest enable
true);
// In 6DOF mode (accelerometer and gyroscope are both enabled),
// the output data rate is derived from the nature frequency of gyroscope
qmi.enableGyroscope();
qmi.enableAccelerometer();
// Print register configuration information
qmi.dumpCtrlRegister();
// start filter
filter.begin(25);
// initialize variables to pace updates to correct rate
microsPerReading = 1000000 / 25;
microsPrevious = micros();
Serial.println("Read data now...");
}
void loop()
{
float roll, pitch, heading;
// check if it's time to read data and update the filter
if (micros() - microsPrevious >= microsPerReading) {
// read raw data from IMU
if (qmi.getDataReady()) {
qmi.getAccelerometer(acc.x, acc.y, acc.z);
qmi.getGyroscope(gyr.x, gyr.y, gyr.z);
// update the filter, which computes orientation
filter.updateIMU(gyr.x, gyr.y, gyr.z, acc.x, acc.y, acc.z);
// print the heading, pitch and roll
roll = filter.getRoll();
pitch = filter.getPitch();
heading = filter.getYaw();
Serial.print("Orientation: ");
Serial.print(heading);
Serial.print(" ");
Serial.print(pitch);
Serial.print(" ");
Serial.println(roll);
}
// increment previous time, so we keep proper pace
microsPrevious = microsPrevious + microsPerReading;
}
}

View File

@ -0,0 +1,196 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMI8658_GetDataExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include "SensorQMI8658.hpp"
#define USE_WIRE
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
#define IMU_CS 5
SensorQMI8658 qmi;
void setup()
{
Serial.begin(115200);
while (!Serial);
#ifdef USE_WIRE
//Using WIRE !!
if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#else
if (!qmi.begin(IMU_CS)) {
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#endif
/* Get chip id*/
Serial.print("Device ID:");
Serial.println(qmi.getChipID(), HEX);
qmi.configAccelerometer(
/*
* ACC_RANGE_2G
* ACC_RANGE_4G
* ACC_RANGE_8G
* ACC_RANGE_16G
* */
SensorQMI8658::ACC_RANGE_4G,
/*
* ACC_ODR_1000H
* ACC_ODR_500Hz
* ACC_ODR_250Hz
* ACC_ODR_125Hz
* ACC_ODR_62_5Hz
* ACC_ODR_31_25Hz
* ACC_ODR_LOWPOWER_128Hz
* ACC_ODR_LOWPOWER_21Hz
* ACC_ODR_LOWPOWER_11Hz
* ACC_ODR_LOWPOWER_3H
* */
SensorQMI8658::ACC_ODR_125Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_0,
// selfTest enable
true);
qmi.configGyroscope(
/*
* GYR_RANGE_16DPS
* GYR_RANGE_32DPS
* GYR_RANGE_64DPS
* GYR_RANGE_128DPS
* GYR_RANGE_256DPS
* GYR_RANGE_512DPS
* GYR_RANGE_1024DPS
* */
SensorQMI8658::GYR_RANGE_64DPS,
/*
* GYR_ODR_7174_4Hz
* GYR_ODR_3587_2Hz
* GYR_ODR_1793_6Hz
* GYR_ODR_896_8Hz
* GYR_ODR_448_4Hz
* GYR_ODR_224_2Hz
* GYR_ODR_112_1Hz
* GYR_ODR_56_05Hz
* GYR_ODR_28_025H
* */
SensorQMI8658::GYR_ODR_112_1Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_3,
// selfTest enable
true);
// In 6DOF mode (accelerometer and gyroscope are both enabled),
// the output data rate is derived from the nature frequency of gyroscope
qmi.enableGyroscope();
qmi.enableAccelerometer();
qmi.configPedometer(0x007D, 0x00CC, 0x0066, 0x00C8, 0x14, 0x0A, 0, 0x04);
qmi.enablePedometer();
// Print register configuration information
qmi.dumpCtrlRegister();
Serial.println("Read data now...");
}
void loop()
{
// Get IMU status
uint8_t status = qmi.getStatusRegister();
Serial.printf("STATUS:0x%x BIN:", status);
Serial.println(status, BIN);
if (status & SensorQMI8658::EVENT_TAP_MOTION) {
Serial.println("Detected TAP event");
qmi.getTapStatus();
}
if (status & SensorQMI8658::EVENT_WOM_MOTION) {
Serial.println("Detected Wom event");
}
if (status & SensorQMI8658::EVENT_PEDOMETER_MOTION) {
Serial.println("Detected Pedometer event");
uint32_t val = qmi.getPedometerCounter();
Serial.println(val);
}
if (status & SensorQMI8658::EVENT_ANY_MOTION) {
Serial.println("Detected Any Motion event");
}
if (status & SensorQMI8658::EVENT_NO_MOTION) {
Serial.println("Detected No Motion event");
}
if (status & SensorQMI8658::EVENT_SIGNIFICANT_MOTION) {
Serial.println("Detected Significant Motion event");
}
delay(500);
}

View File

@ -0,0 +1,218 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMI8658_ReadFromFifoExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include "SensorQMI8658.hpp"
#define USE_WIRE
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
#define IMU_CS 5
SensorQMI8658 qmi;
IMUdata acc[128];
IMUdata gyr[128];
void setup()
{
Serial.begin(115200);
while (!Serial);
#ifdef USE_WIRE
//Using WIRE !!
if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#else
//Using SPI !!
if (!qmi.begin(IMU_CS)) {
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#endif
/* Get chip id*/
Serial.print("Device ID:");
Serial.println(qmi.getChipID(), HEX);
qmi.configAccelerometer(
/*
* ACC_RANGE_2G
* ACC_RANGE_4G
* ACC_RANGE_8G
* ACC_RANGE_16G
* */
SensorQMI8658::ACC_RANGE_4G,
/*
* ACC_ODR_1000H
* ACC_ODR_500Hz
* ACC_ODR_250Hz
* ACC_ODR_125Hz
* ACC_ODR_62_5Hz
* ACC_ODR_31_25Hz
* ACC_ODR_LOWPOWER_128Hz
* ACC_ODR_LOWPOWER_21Hz
* ACC_ODR_LOWPOWER_11Hz
* ACC_ODR_LOWPOWER_3H
* */
SensorQMI8658::ACC_ODR_1000Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_0,
// selfTest enable
true);
qmi.configGyroscope(
/*
* GYR_RANGE_16DPS
* GYR_RANGE_32DPS
* GYR_RANGE_64DPS
* GYR_RANGE_128DPS
* GYR_RANGE_256DPS
* GYR_RANGE_512DPS
* GYR_RANGE_1024DPS
* */
SensorQMI8658::GYR_RANGE_64DPS,
/*
* GYR_ODR_7174_4Hz
* GYR_ODR_3587_2Hz
* GYR_ODR_1793_6Hz
* GYR_ODR_896_8Hz
* GYR_ODR_448_4Hz
* GYR_ODR_224_2Hz
* GYR_ODR_112_1Hz
* GYR_ODR_56_05Hz
* GYR_ODR_28_025H
* */
SensorQMI8658::GYR_ODR_896_8Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_3,
// selfTest enable
true);
qmi.configFIFO(
/**
* FIFO_MODE_BYPASS -- Disable fifo
* FIFO_MODE_FIFO -- Will not overwrite
* FIFO_MODE_STREAM -- Cover
*/
SensorQMI8658::FIFO_MODE_FIFO,
/*
* FIFO_SAMPLES_16
* FIFO_SAMPLES_32
* FIFO_SAMPLES_64
* FIFO_SAMPLES_128
* */
SensorQMI8658::FIFO_SAMPLES_16,
//FiFo mapped interrupt IO port
SensorQMI8658::IntPin1,
// watermark level
8);
// In 6DOF mode (accelerometer and gyroscope are both enabled),
// the output data rate is derived from the nature frequency of gyroscope
qmi.enableGyroscope();
qmi.enableAccelerometer();
// Print register configuration information
qmi.dumpCtrlRegister();
Serial.println("Read data now...");
}
void loop()
{
// If the reading is successful, true will be returned
if (!qmi.readFromFifo(acc, 128, gyr, 128)) {
return;
}
for (int i = 0; i < 16; ++i) {
Serial.print("ACCEL: ");
Serial.print("X:");
Serial.print(acc[i].x);
Serial.print(" Y:");
Serial.print(acc[i].y);
Serial.print(" Z:");
Serial.println(acc[i].z);
Serial.print("GYRO: ");
Serial.print(" X:");
Serial.print(gyr[i].x);
Serial.print(" Y:");
Serial.print(gyr[i].y );
Serial.print(" Z:");
Serial.println(gyr[i].z);
}
delay(100);
}

View File

@ -0,0 +1,160 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMI8658_WakeOnMotion.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-11-05
*
*/
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include "SensorQMI8658.hpp"
// #define USE_WIRE
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
SensorQMI8658 qmi;
IMUdata acc;
IMUdata gyr;
bool interruptFlag = false;
void setFlag(void)
{
interruptFlag = true;
}
void setup()
{
Serial.begin(115200);
while (!Serial);
#ifdef USE_WIRE
//Using WIRE !!
if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#else
#ifndef CONFIG_IDF_TARGET_ESP32
//Use tbeams3 defalut spi pinz
#define SPI_MOSI (35)
#define SPI_SCK (36)
#define SPI_MISO (37)
#define SPI_CS (47)
#define IMU_CS (34)
#define IMU_INT1 (33) //INTERRUPT PIN1 & PIN2 ,Use or logic to form a pin
pinMode(SPI_CS, OUTPUT); //sdcard pin set high
digitalWrite(SPI_CS, HIGH);
if (!qmi.begin(IMU_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
#else
//Use esp32dev module defalut spi pin
#define IMU_CS (5)
#define IMU_INT1 (15)
#define IMU_INT2 (22)
if (!qmi.begin(IMU_CS)) {
#endif
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#endif
/* Get chip id*/
Serial.print("Device ID:");
Serial.println(qmi.getChipID(), HEX);
// enabling wake on motion low power mode with a threshold of 120 mg and
// an accelerometer data rate of 128 Hz.
qmi.configWakeOnMotion();
/*
* When the QMI8658 is configured as Wom, the interrupt level is arbitrary,
* not absolute high or low, and it is in the jump transition state
*/
pinMode(IMU_INT1, INPUT_PULLUP);
#ifdef IMU_INT2
pinMode(IMU_INT2, INPUT_PULLUP);
attachInterrupt(IMU_INT2, setFlag, CHANGE);
#else
attachInterrupt(IMU_INT1, setFlag, CHANGE);
#endif
// Print register configuration information
qmi.dumpCtrlRegister();
}
void loop()
{
if (interruptFlag) {
interruptFlag = false;
uint8_t status = qmi.getStatusRegister();
Serial.printf("status:0x%X BIN:", status);
Serial.println(status, BIN);
if (status & SensorQMI8658::EVENT_SIGNIFICANT_MOTION) {
Serial.println("EVENT_SIGNIFICANT_MOTION");
} else if (status & SensorQMI8658::EVENT_NO_MOTION) {
Serial.println("EVENT_NO_MOITON");
} else if (status & SensorQMI8658::EVENT_ANY_MOTION) {
Serial.println("EVENT_ANY_MOTION");
} else if (status & SensorQMI8658::EVENT_PEDOMETER_MOTION) {
Serial.println("EVENT_PEDOMETER_MOTION");
} else if (status & SensorQMI8658::EVENT_WOM_MOTION) {
Serial.println("EVENT_WOM_MOTION");
} else if (status & SensorQMI8658::EVENT_TAP_MOTION) {
Serial.println("EVENT_TAP_MOTION");
}
}
}

View File

@ -0,0 +1,152 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMI8658_WakeOnMotionCallBack.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-11-07
*
*/
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include "SensorQMI8658.hpp"
// #define USE_WIRE
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
SensorQMI8658 qmi;
IMUdata acc;
IMUdata gyr;
bool interruptFlag = false;
void setFlag(void)
{
interruptFlag = true;
}
void wakeUp()
{
Serial.println("Awake!");
}
void setup()
{
Serial.begin(115200);
while (!Serial);
#ifdef USE_WIRE
//Using WIRE !!
if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#else
#ifndef CONFIG_IDF_TARGET_ESP32
//Use tbeams3 defalut spi pinz
#define SPI_MOSI (35)
#define SPI_SCK (36)
#define SPI_MISO (37)
#define SPI_CS (47)
#define IMU_CS (34)
#define IMU_INT1 (33) //INTERRUPT PIN1 & PIN2 ,Use or logic to form a pin
pinMode(SPI_CS, OUTPUT); //sdcard pin set high
digitalWrite(SPI_CS, HIGH);
if (!qmi.begin(IMU_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
#else
//Use esp32dev module defalut spi pin
#define IMU_CS (5)
#define IMU_INT1 (15)
#define IMU_INT2 (22)
if (!qmi.begin(IMU_CS)) {
#endif
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
#endif
/* Get chip id*/
Serial.print("Device ID:");
Serial.println(qmi.getChipID(), HEX);
// enabling wake on motion low power mode with a threshold of 200 mg and
// an accelerometer data rate of 128 Hz.
qmi.configWakeOnMotion();
qmi.setWakeupMotionEventCallBack(wakeUp);
/*
* When the QMI8658 is configured as Wom, the interrupt level is arbitrary,
* not absolute high or low, and it is in the jump transition state
*/
pinMode(IMU_INT1, INPUT_PULLUP);
#ifdef IMU_INT2
pinMode(IMU_INT2, INPUT_PULLUP);
attachInterrupt(IMU_INT2, setFlag, CHANGE);
#else
attachInterrupt(IMU_INT1, setFlag, CHANGE);
#endif
// Print register configuration information
qmi.dumpCtrlRegister();
}
void loop()
{
if (interruptFlag) {
interruptFlag = false;
qmi.readSensorStatus();
}
}

View File

@ -0,0 +1,92 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file TouchDrv_CHSC5816_GetPoint.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-17
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "TouchDrvCHSC5816.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 39
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 40
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 13
#endif
#ifndef SENSOR_RST
#define SENSOR_RST 14
#endif
TouchDrvCHSC5816 touch;
void setup()
{
Serial.begin(115200);
while (!Serial);
touch.setPins(SENSOR_RST, SENSOR_IRQ);
if (!touch.begin(Wire, CHSC5816_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find CHSC5816 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init CHSC5816 Touch device success!");
}
void loop()
{
int16_t x[2], y[2];
if (digitalRead(SENSOR_IRQ) == LOW) {
uint8_t touched = touch.getPoint(x, y);
for (int i = 0; i < touched; ++i) {
Serial.print("X[");
Serial.print(i);
Serial.print("]:");
Serial.print(x[i]);
Serial.print(" ");
Serial.print(" Y[");
Serial.print(i);
Serial.print("]:");
Serial.print(y[i]);
Serial.print(" ");
}
Serial.println();
}
}

View File

@ -0,0 +1,175 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file TouchDrv_CSTxxx_GetPoint.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-24
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "TouchDrvCSTXXX.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 8
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 10
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 5
#endif
#ifndef SENSOR_RST
#define SENSOR_RST -1
#endif
TouchDrvCSTXXX touch;
int16_t x[5], y[5];
void scanDevices(void)
{
byte error, address;
int nDevices = 0;
Serial.println("Scanning for I2C devices ...");
for (address = 0x01; address < 0x7f; address++) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.printf("I2C device found at address 0x%02X\n", address);
nDevices++;
} else if (error != 2) {
Serial.printf("Error %d at address 0x%02X\n", error, address);
}
}
if (nDevices == 0) {
Serial.println("No I2C devices found");
}
}
void setup()
{
Serial.begin(115200);
while (!Serial);
#if SENSOR_RST != -1
pinMode(SENSOR_RST, OUTPUT);
digitalWrite(SENSOR_RST, LOW);
delay(30);
digitalWrite(SENSOR_RST, HIGH);
delay(50);
// delay(1000);
#endif
// Search for known CSTxxx device addresses
uint8_t address = 0xFF;
#ifdef ARDUINO_ARCH_RP2040
Wire.setSCL(SENSOR_SCL);
Wire.setSDA(SENSOR_SDA);
#else
Wire.begin(SENSOR_SDA, SENSOR_SCL);
#endif
// Scan I2C devices
scanDevices();
Wire.beginTransmission(CST816_SLAVE_ADDRESS);
if (Wire.endTransmission() == 0) {
address = CST816_SLAVE_ADDRESS;
}
Wire.beginTransmission(CST226SE_SLAVE_ADDRESS);
if (Wire.endTransmission() == 0) {
address = CST226SE_SLAVE_ADDRESS;
}
Wire.beginTransmission(CST328_SLAVE_ADDRESS);
if (Wire.endTransmission() == 0) {
address = CST328_SLAVE_ADDRESS;
}
while (address == 0xFF) {
Serial.println("Could't find touch chip!"); delay(1000);
}
touch.setPins(SENSOR_RST, SENSOR_IRQ);
touch.begin(Wire, address, SENSOR_SDA, SENSOR_SCL);
Serial.print("Model :"); Serial.println(touch.getModelName());
// T-Display-S3 CST816 touch panel, touch button coordinates are is 85 , 160
touch.setCenterButtonCoordinate(85, 360);
// T-Display-AMOLED 1.91 Inch CST816T touch panel, touch button coordinates is 600, 120.
// touch.setCenterButtonCoordinate(600, 120); // Only suitable for AMOLED 1.91 inch
// Depending on the touch panel, not all touch panels have touch buttons.
touch.setHomeButtonCallback([](void *user_data) {
Serial.println("Home key pressed!");
}, NULL);
// Unable to obtain coordinates after turning on sleep
// CST816T sleep current = 1.1 uA
// CST226SE sleep current = 60 uA
// touch.sleep();
// Set touch max xy
// touch.setMaxCoordinates(536, 240);
// Set swap xy
// touch.setSwapXY(true);
// Set mirror xy
// touch.setMirrorXY(true, true);
}
void loop()
{
uint8_t touched = touch.getPoint(x, y, touch.getSupportTouchPoint());
if (touched) {
for (int i = 0; i < touched; ++i) {
Serial.print("X[");
Serial.print(i);
Serial.print("]:");
Serial.print(x[i]);
Serial.print(" ");
Serial.print(" Y[");
Serial.print(i);
Serial.print("]:");
Serial.print(y[i]);
Serial.print(" ");
}
Serial.println();
}
delay(5);
}

View File

@ -0,0 +1,115 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file TouchDrv_FT3267_LilyGo_T_RGB.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-17
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "TouchDrvFT6X36.hpp"
#include "ExtensionIOXL9555.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 8
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 48
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 1
#endif
#ifndef SENSOR_RST
#define SENSOR_RST 1
#endif
TouchDrvFT6X36 touch;
ExtensionIOXL9555 extIO;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT);
// T-RGB Use 0x20 device address
if (!extIO.begin(Wire, XL9555_SLAVE_ADDRESS0, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find XL9555 - check your wiring!");
while (1) {
delay(1000);
}
}
// Set PORT0 as output
extIO.configPort(ExtensionIOXL9555::PORT0, OUTPUT);
extIO.writePort(ExtensionIOXL9555::PORT0, 0xFF);
extIO.digitalWrite(SENSOR_RST, LOW);
delay(300);
extIO.digitalWrite(SENSOR_RST, HIGH);
delay(300);
if (!touch.begin(Wire, FT3267_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find FT3267 - check your wiring!");
while (1) {
delay(1000);
}
}
touch.interruptTrigger();
Serial.println("Init FT3267 Sensor success!");
}
void loop()
{
int16_t x[2], y[2];
if (digitalRead(SENSOR_IRQ) == LOW) {
uint8_t touched = touch.getPoint(x, y, 2);
for (int i = 0; i < touched; ++i) {
Serial.print("X[");
Serial.print(i);
Serial.print("]:");
Serial.print(x[i]);
Serial.print(" ");
Serial.print(" Y[");
Serial.print(i);
Serial.print("]:");
Serial.print(y[i]);
Serial.print(" ");
}
Serial.println();
}
delay(50);
}

View File

@ -0,0 +1,92 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file TouchDrv_FT6232_GetPoint.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-02
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "TouchDrvFT6X36.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 21
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 22
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 39
#endif
TouchDrvFT6X36 touch;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT);
if (!touch.begin(Wire, FT6X36_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find FT6X36 - check your wiring!");
while (1) {
delay(1000);
}
}
touch.interruptTrigger();
Serial.println("Init FT6X36 Sensor success!");
}
void loop()
{
int16_t x[2], y[2];
if (digitalRead(SENSOR_IRQ) == LOW) {
uint8_t touched = touch.getPoint(x, y, 2);
for (int i = 0; i < touched; ++i) {
Serial.print("X[");
Serial.print(i);
Serial.print("]:");
Serial.print(x[i]);
Serial.print(" ");
Serial.print(" Y[");
Serial.print(i);
Serial.print("]:");
Serial.print(y[i]);
Serial.print(" ");
}
Serial.println();
}
delay(50);
}

View File

@ -0,0 +1,121 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file GT911_GetPoint.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-12
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "TouchDrvGT911.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 2
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 3
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 1
#endif
#ifndef SENSOR_RST
#define SENSOR_RST 10
#endif
TouchDrvGT911 touch;
int16_t x[5], y[5];
void setup()
{
Serial.begin(115200);
while (!Serial);
Wire.begin(SENSOR_SDA, SENSOR_SCL);
/*
* The touch reset pin uses hardware pull-up,
* and the function of setting the I2C device address cannot be used.
* Use scanning to obtain the touch device address.
* * */
uint8_t touchAddress = 0;
Wire.beginTransmission(0x14);
if (Wire.endTransmission() == 0) {
touchAddress = 0x14;
}
Wire.beginTransmission(0x5D);
if (Wire.endTransmission() == 0) {
touchAddress = 0x5D;
}
if (touchAddress == 0) {
while (1) {
Serial.println("Failed to find GT911 - check your wiring!");
delay(1000);
}
}
touch.setPins(SENSOR_RST, SENSOR_IRQ);
if (!touch.begin(Wire, touchAddress, SENSOR_SDA, SENSOR_SCL )) {
while (1) {
Serial.println("Failed to find GT911 - check your wiring!");
delay(1000);
}
}
//Set to trigger on falling edge
touch.setInterruptMode(FALLING);
Serial.println("Init GT911 Sensor success!");
}
void loop()
{
if (touch.isPressed()) {
uint8_t touched = touch.getPoint(x, y, touch.getSupportTouchPoint());
for (int i = 0; i < touched; ++i) {
Serial.print("X[");
Serial.print(i);
Serial.print("]:");
Serial.print(x[i]);
Serial.print(" ");
Serial.print(" Y[");
Serial.print(i);
Serial.print("]:");
Serial.print(y[i]);
Serial.print(" ");
}
Serial.println();
}
delay(5);
}

View File

@ -0,0 +1,161 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file TouchDrv_GT911_LilyGo_T_RGB.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-12
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "TouchDrvGT911.hpp"
#include "ExtensionIOXL9555.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 8
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 48
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 1
#endif
#ifndef SENSOR_RST
#define SENSOR_RST 1
#endif
TouchDrvGT911 touch;
ExtensionIOXL9555 extIO;
int16_t x[5], y[5];
void scanDevices(void)
{
byte error, address;
int nDevices = 0;
Serial.println("Scanning for I2C devices ...");
for (address = 0x01; address < 0x7f; address++) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.printf("I2C device found at address 0x%02X\n", address);
nDevices++;
} else if (error != 2) {
Serial.printf("Error %d at address 0x%02X\n", error, address);
}
}
if (nDevices == 0) {
Serial.println("No I2C devices found");
}
}
void digitalWrite_CB(uint32_t pin, uint8_t value)
{
extIO.digitalWrite(pin, value);
}
void pinMode_CB(uint32_t pin, uint8_t mode)
{
extIO.pinMode(pin, mode);
}
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println("Start!");
#ifdef ARDUINO_ARCH_RP2040
Wire.setSCL(SENSOR_SCL);
Wire.setSDA(SENSOR_SDA);
#else
Wire.begin(SENSOR_SDA, SENSOR_SCL);
#endif
scanDevices();
// T-RGB Use 0x20 device address
if (!extIO.begin(Wire, XL9555_SLAVE_ADDRESS0, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find XL9555 - check your wiring!");
while (1) {
delay(1000);
}
}
// Set PORT0 as output
extIO.configPort(ExtensionIOXL9555::PORT0, OUTPUT);
extIO.writePort(ExtensionIOXL9555::PORT0, 0xFF);
touch.setPins(SENSOR_RST, SENSOR_IRQ);
touch.setGpioWriteCallback(digitalWrite_CB);
touch.setGpioModeCallback(pinMode_CB);
if (!touch.begin(Wire, GT911_SLAVE_ADDRESS_L, SENSOR_SDA, SENSOR_SCL )) {
scanDevices();
while (1) {
Serial.println("Failed to find GT911 - check your wiring!");
delay(1000);
}
}
//Set to trigger on falling edge
touch.setInterruptMode(FALLING);
Serial.println("Init GT911 Sensor success!");
}
void loop()
{
if (touch.isPressed()) {
uint8_t touched = touch.getPoint(x, y, touch.getSupportTouchPoint());
if (touched) {
for (int i = 0; i < touched; ++i) {
Serial.print("X[");
Serial.print(i);
Serial.print("]:");
Serial.print(x[i]);
Serial.print(" ");
Serial.print(" Y[");
Serial.print(i);
Serial.print("]:");
Serial.print(y[i]);
Serial.print(" ");
}
Serial.println();
}
}
delay(5);
}

View File

@ -0,0 +1,204 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* 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.
*
* @file TouchDrv_LilyGo_T_RGB.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2024-01-21
* @note T-RGB has three types of screens, each of which uses different touch driver chips.
* The example demonstrates using the touch interface class and one sketch is suitable for three types of touch chips.
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "ExtensionIOXL9555.hpp"
#include "TouchDrvGT911.hpp"
#include "TouchDrvFT6X36.hpp"
#include "TouchDrvCSTXXX.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 8
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 48
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 1 //ESP32S3 GPIO1
#endif
#ifndef SENSOR_RST
#define SENSOR_RST 1 //XL9555 GPIO1
#endif
TouchDrvInterface *touchDrv = NULL;
ExtensionIOXL9555 extension;
ExtensionIOXL9555::ExtensionGPIO tp_reset = ExtensionIOXL9555::IO1;
ExtensionIOXL9555::ExtensionGPIO power_enable = ExtensionIOXL9555::IO2;
int16_t x[5], y[5];
//GPIO callback function
void TouchDrvDigitalWrite(uint32_t gpio, uint8_t level)
{
if (gpio & 0x80) {
extension.digitalWrite(gpio & 0x7F, level);
} else {
digitalWrite(gpio, level);
}
}
//GPIO callback function
int TouchDrvDigitalRead(uint32_t gpio)
{
if (gpio & 0x80) {
return extension.digitalRead(gpio & 0x7F);
} else {
return digitalRead(gpio);
}
}
//GPIO callback function
void TouchDrvPinMode(uint32_t gpio, uint8_t mode)
{
if (gpio & 0x80) {
extension.pinMode(gpio & 0x7F, mode);
} else {
pinMode(gpio, mode);
}
}
bool setupTouchDrv()
{
//Touch interrupt uses ESP32S3 GPIO1, touch reset uses XL9555 extended IO chip GPIO1, and needs to add a mask to distinguish
const uint8_t touch_reset_pin = 1 | 0x80;
const uint8_t touch_irq_pin = 1;
bool result = false;
touchDrv = new TouchDrvCSTXXX();
// T-RGB reset GPIO is connected through the expansion chip, and the GPIO callback function needs to be set.
touchDrv->setGpioCallback(TouchDrvPinMode, TouchDrvDigitalWrite, TouchDrvDigitalRead);
touchDrv->setPins(touch_reset_pin, touch_irq_pin);
result = touchDrv->begin(Wire, CST816_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL);
if (result) {
const char *model = touchDrv->getModelName();
Serial.printf("Successfully initialized %s, using %s Driver!", model, model);
return true;
}
delete touchDrv;
touchDrv = new TouchDrvGT911();
// T-RGB reset GPIO is connected through the expansion chip, and the GPIO callback function needs to be set.
touchDrv->setGpioCallback(TouchDrvPinMode, TouchDrvDigitalWrite, TouchDrvDigitalRead);
touchDrv->setPins(touch_reset_pin, touch_irq_pin);
result = touchDrv->begin(Wire, GT911_SLAVE_ADDRESS_H, SENSOR_SDA, SENSOR_SCL);
if (result) {
Serial.println("Successfully initialized GT911, using GT911 Driver!");
return true;
}
delete touchDrv;
touchDrv = new TouchDrvFT6X36();
// T-RGB reset GPIO is connected through the expansion chip, and the GPIO callback function needs to be set.
touchDrv->setGpioCallback(TouchDrvPinMode, TouchDrvDigitalWrite, TouchDrvDigitalRead);
touchDrv->setPins(touch_reset_pin, touch_irq_pin);
result = touchDrv->begin(Wire, FT3267_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL);
if (result) {
const char *model = touchDrv->getModelName();
Serial.printf("Successfully initialized %s, using %s Driver!", model, model);
return true;
}
delete touchDrv;
return false;
}
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println("Start!");
#ifdef ARDUINO_ARCH_RP2040
Wire.setSCL(SENSOR_SCL);
Wire.setSDA(SENSOR_SDA);
#else
Wire.begin(SENSOR_SDA, SENSOR_SCL);
#endif
// T-RGB XL9555 Use 0x20 device address
if (!extension.begin(Wire, XL9555_SLAVE_ADDRESS0, SENSOR_SDA, SENSOR_SCL)) {
while (1) {
Serial.println("Failed to find XL9555 - check your wiring!");
delay(1000);
}
}
// T-RGB power enable GPIO connected to XL9555 expansion chip GPIO
extension.pinMode(power_enable, OUTPUT);
extension.digitalWrite(power_enable, HIGH);
// Initialize touch using touch driver interface class
if (!setupTouchDrv()) {
while (1) {
Serial.println("Failed to find touch - check your wiring!");
delay(1000);
}
}
}
void loop()
{
if (touchDrv) {
if (touchDrv->isPressed()) {
uint8_t touched = touchDrv->getPoint(x, y, touchDrv->getSupportTouchPoint());
if (touched) {
for (int i = 0; i < touched; ++i) {
Serial.print("X[");
Serial.print(i);
Serial.print("]:");
Serial.print(x[i]);
Serial.print(" ");
Serial.print(" Y[");
Serial.print(i);
Serial.print("]:");
Serial.print(y[i]);
Serial.print(" ");
}
Serial.println();
}
}
}
delay(5);
}

View File

@ -0,0 +1,83 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file XL9555_ExtensionIOInterrupt.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-01-03
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <time.h>
#include "ExtensionIOXL9555.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
ExtensionIOXL9555 extIO;
void setup()
{
Serial.begin(115200);
while (!Serial);
// Device address 0x20~0x27
if (!extIO.begin(Wire, XL9555_SLAVE_ADDRESS4, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find XL9555 - check your wiring!");
while (1) {
delay(1000);
}
}
pinMode(SENSOR_IRQ, INPUT_PULLUP);
// Set PORT0 as input,mask = 0xFF = all pin input
extIO.configPort(ExtensionIOXL9555::PORT0, 0xFF);
// Set PORT1 as input,mask = 0xFF = all pin input
extIO.configPort(ExtensionIOXL9555::PORT1, 0xFF);
}
void loop()
{
// When the interrupt occurs, we read the mask value of PORT
if (digitalRead(SENSOR_IRQ) == LOW) {
Serial.print("PORT0:0b");
Serial.print(extIO.readPort(ExtensionIOXL9555::PORT0), BIN);
Serial.print("\tPORT1:0b");
Serial.println(extIO.readPort(ExtensionIOXL9555::PORT1), BIN);
}
}

View File

@ -0,0 +1,117 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file XL9555_ExtensionIORead.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-01-03
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <time.h>
#include "ExtensionIOXL9555.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
ExtensionIOXL9555 extIO;
void setup()
{
Serial.begin(115200);
while (!Serial);
// Device address 0x20~0x27
if (!extIO.begin(Wire, XL9555_SLAVE_ADDRESS4, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find XL9555 - check your wiring!");
while (1) {
delay(1000);
}
}
pinMode(SENSOR_IRQ, INPUT_PULLUP);
// Set PORT0 as input,mask = 0xFF = all pin input
extIO.configPort(ExtensionIOXL9555::PORT0, 0xFF);
// Set PORT1 as input,mask = 0xFF = all pin input
extIO.configPort(ExtensionIOXL9555::PORT1, 0xFF);
}
void loop()
{
Serial.print("PORT0:0b");
Serial.print(extIO.readPort(ExtensionIOXL9555::PORT0), BIN);
Serial.print("\tPORT1:0b");
Serial.println(extIO.readPort(ExtensionIOXL9555::PORT1), BIN);
//Allowable range of parameter input: IO0 ~ IO15
Serial.println("IO0:\tIO1:\tIO2:\tIO3:\tIO4:\tIO5:\tIO6:\tIO7:\tIO8:\tIO9:\tIO10:\tIO11:\tIO12:\tIO13:\tIO14:\tIO15:\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO0));
Serial.print("\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO1));
Serial.print("\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO2));
Serial.print("\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO3));
Serial.print("\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO4));
Serial.print("\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO5));
Serial.print("\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO6));
Serial.print("\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO7));
Serial.print("\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO8));
Serial.print("\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO9));
Serial.print("\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO10));
Serial.print("\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO11));
Serial.print("\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO12));
Serial.print("\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO13));
Serial.print("\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO14));
Serial.print("\t");
Serial.print(extIO.digitalRead(ExtensionIOXL9555::IO15));
Serial.println();
delay(1000);
}

View File

@ -0,0 +1,94 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file XL9555_ExtensionIOWirte.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-01-03
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <time.h>
#include "ExtensionIOXL9555.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
ExtensionIOXL9555 extIO;
void setup()
{
Serial.begin(115200);
while (!Serial);
// Device address 0x20~0x27
if (!extIO.begin(Wire, XL9555_SLAVE_ADDRESS4, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find XL9555 - check your wiring!");
while (1) {
delay(1000);
}
}
// Set PORT0 as output ,mask = 0x00 = all pin output
extIO.configPort(ExtensionIOXL9555::PORT0, 0x00);
// Set PORT1 as output ,mask = 0x00 = all pin output
extIO.configPort(ExtensionIOXL9555::PORT1, 0x00);
}
void loop()
{
// Set all PORTs to 1, and the parameters here are mask values, corresponding to the 0~7 bits
Serial.println("Set port HIGH");
extIO.writePort(ExtensionIOXL9555::PORT0, 0xFF);
delay(1000);
Serial.println("Set port LOW");
// Set all PORTs to 0, and the parameters here are mask values, corresponding to the 0~7 bits
extIO.writePort(ExtensionIOXL9555::PORT1, 0x00);
delay(1000);
Serial.println("digitalWrite");
extIO.digitalWrite(ExtensionIOXL9555::IO0, HIGH);
delay(1000);
Serial.println("digitalToggle");
extIO.digitalToggle(ExtensionIOXL9555::IO0);
delay(1000);
}

177
lib/SensorLib/keywords.txt Normal file
View File

@ -0,0 +1,177 @@
#######################################
# Syntax Coloring Map For SensorLib By lewis He
# github:https://github.com/lewisxhe
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
ExtensionIOXL9555 KEYWORD1
RTC_DateTime KEYWORD1
RTC_Alarm KEYWORD1
SensorPCF8563 KEYWORD1
SensorQMC6310 KEYWORD1
MagRange KEYWORD1
OutputRate KEYWORD1
CtrlReg KEYWORD1
OverSampleRatio KEYWORD1
DownSampleRatio KEYWORD1
SensorQMI8658 KEYWORD1
AccelRange KEYWORD1
GyroRange KEYWORD1
AccelODR KEYWORD1
GyroODR KEYWORD1
LpfMode KEYWORD1
MotionEvent KEYWORD1
IntPin KEYWORD1
Fifo_Samples KEYWORD1
FIFO_Mode KEYWORD1
SampleMode KEYWORD1
CommandTable KEYWORD1
StatusReg KEYWORD1
TagPriority KEYWORD1
SensorStatus KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
# XL9555 Coloring Map
init KEYWORD2
deinit KEYWORD2
pinMode KEYWORD2
digitalRead KEYWORD2
digitalWrite KEYWORD2
digitalToggle KEYWORD2
readPort KEYWORD2
writePort KEYWORD2
readConfig KEYWORD2
configPort KEYWORD2
# PCF8563 Coloring Map
setDateTime KEYWORD2
getDateTime KEYWORD2
getAlarm KEYWORD2
enableAlarm KEYWORD2
disableAlarm KEYWORD2
resetAlarm KEYWORD2
isAlarmActive KEYWORD2
setAlarm KEYWORD2
setAlarmByMinutes KEYWORD2
setAlarmByDays KEYWORD2
setAlarmByHours KEYWORD2
setAlarmByWeekDay KEYWORD2
isCountdownTimerEnable KEYWORD2
isCountdownTimerActive KEYWORD2
enableCountdownTimer KEYWORD2
disableCountdownTimer KEYWORD2
setCountdownTimer KEYWORD2
clearCountdownTimer KEYWORD2
enableCLK KEYWORD2
strftime KEYWORD2
conversionUnixTime KEYWORD2
hwClockRead KEYWORD2
hwClockWrite KEYWORD2
getDayOfWeek KEYWORD2
getNextMonth KEYWORD2
getNextYear KEYWORD2
getLeapYear KEYWORD2
getDaysInMonth KEYWORD2
# SensorQMC6310 Coloring Map
reset KEYWORD2
getChipID KEYWORD2
getStatus KEYWORD2
isDataReady KEYWORD2
isDataOverflow KEYWORD2
setSelfTest KEYWORD2
setMode KEYWORD2
setCtrlRegister KEYWORD2
setDataOutputRate KEYWORD2
setOverSampleRate KEYWORD2
setDownSampleRate KEYWORD2
setSign KEYWORD2
configMagnetometer KEYWORD2
setMagRange KEYWORD2
setOffset KEYWORD2
readData KEYWORD2
setDeclination KEYWORD2
readPolar KEYWORD2
getRawX KEYWORD2
getRawY KEYWORD2
getRawZ KEYWORD2
getX KEYWORD2
getY KEYWORD2
getZ KEYWORD2
getMag KEYWORD2
dumpCtrlRegister KEYWORD2
# SensorQMI8658 Coloring Map
whoAmI KEYWORD2
getTimestamp KEYWORD2
getTemperature_C KEYWORD2
enableINT KEYWORD2
getIrqStatus KEYWORD2
enableDataReadyINT KEYWORD2
configAccelerometer KEYWORD2
configGyroscope KEYWORD2
configFIFO KEYWORD2
getFifoNeedBytes KEYWORD2
readFromFifo KEYWORD2
enableAccelerometer KEYWORD2
disableAccelerometer KEYWORD2
isEnableAccelerometer KEYWORD2
isEnableGyroscope KEYWORD2
enableGyroscope KEYWORD2
disableGyroscope KEYWORD2
getAccelRaw KEYWORD2
getAccelerometer KEYWORD2
getAccelerometerScales KEYWORD2
getGyroscopeScales KEYWORD2
getGyroRaw KEYWORD2
getGyroscope KEYWORD2
getDataReady KEYWORD2
enableSyncSampleMode KEYWORD2
disableSyncSampleMode KEYWORD2
enableLockingMechanism KEYWORD2
disableLockingMechanism KEYWORD2
powerDown KEYWORD2
powerOn KEYWORD2
getStatusRegister KEYWORD2
configActivityInterruptMap KEYWORD2
configPedometer KEYWORD2
getPedometerCounter KEYWORD2
clearPedometerCounter KEYWORD2
enablePedometer KEYWORD2
disablePedometer KEYWORD2
configTap KEYWORD2
enableTap KEYWORD2
disableTap KEYWORD2
getTapStatus KEYWORD2
configMotion KEYWORD2
enableMotionDetect KEYWORD2
disableMotionDetect KEYWORD2
configWakeOnMotion KEYWORD2
getChipUsid KEYWORD2
getChipFirmwareVersion KEYWORD2
readSensorStatus KEYWORD2
setWakeupMotionEventCallBack KEYWORD2
setTapEventCallBack KEYWORD2
setPedometerEventCallBack KEYWORD2
setNoMotionEventCallBack KEYWORD2
setAnyMotionEventCallBack KEYWORD2
setSignificantMotionEventCallBack KEYWORD2
setGyroDataReadyCallBack KEYWORD2
setAccelDataReadyEventCallBack KEYWORD2
setDataLockingEvevntCallBack KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View File

@ -0,0 +1,32 @@
{
"name": "SensorLib",
"version": "0.2.0",
"description": "Commonly used I2C , SPI device multi-platform libraries",
"keywords": "QMC6310, QMI8658, PCF8563, PCF85063, XL9555, BMA423, BHI260AP, DRV2605, CM32181, LTR553, FT5206, FT3267, FT6236, FT6336, CST816S,CST816T,CST816D, CST820, CST226, CHSC5816, GT911",
"authors": [
{
"name": "LewisHe",
"url": "https://github.com/lewisxhe",
"maintainer": true
}
],
"repository": {
"type": "git",
"url": "https://github.com/lewisxhe/SensorsLib.git"
},
"homepage": "https://github.com/lewisxhe/SensorsLib",
"export": {
"include": [
"LICENSE",
"library.json",
"library.properties",
"README.md",
"keywords.txt",
"src/*",
"examples/*"
]
},
"frameworks": ["arduino", "espidf"],
"platforms": "esp32,raspberrypi,ststm32,espressif32",
"license": "MIT"
}

View File

@ -0,0 +1,9 @@
name=SensorLib
version=0.2.0
author=Lewis He
maintainer=Lewis He <lewishe@outlook.com>
sentence=Commonly used I2C , SPI device multi-platform libraries
paragraph=Support QMC6310,QMI8658,PCF8563,PCF85063,XL9555,BMA423,BHI260AP,DRV2605,CM32181,LTR553,FT5206,FT3267,FT6236,FT6336,CST816S/T/D,CST820,CST226,CHSC5816,GT911
category=Communication
url=https://github.com/lewisxhe/SensorsLib
architectures=esp32

View File

@ -0,0 +1,204 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file ExtensionIOXL9555.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2022-12-27
*
*/
#pragma once
#include "REG/XL9555Constants.h"
#include "SensorCommon.tpp"
#include "ExtensionSPI.tpp"
class ExtensionIOXL9555 :
public SensorCommon<ExtensionIOXL9555>,
public ExtensionSPI<ExtensionIOXL9555>
{
friend class SensorCommon<ExtensionIOXL9555>;
friend class ExtensionSPI<ExtensionIOXL9555>;
public:
enum {
PORT0,
PORT1,
};
enum ExtensionGPIO {
IO0,
IO1,
IO2,
IO3,
IO4,
IO5,
IO6,
IO7,
IO8,
IO9,
IO10,
IO11,
IO12,
IO13,
IO14,
IO15,
};
#if defined(ARDUINO)
ExtensionIOXL9555(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = XL9555_SLAVE_ADDRESS0)
{
__wire = &w;
__sda = sda;
__scl = scl;
__addr = addr;
}
#endif
ExtensionIOXL9555()
{
#if defined(ARDUINO)
__wire = &Wire;
__sda = DEFAULT_SDA;
__scl = DEFAULT_SCL;
#endif
__addr = XL9555_SLAVE_ADDRESS0;
}
~ExtensionIOXL9555()
{
deinit();
}
#if defined(ARDUINO)
bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = XL9555_SLAVE_ADDRESS0)
{
return SensorCommon::begin(w, addr, sda, scl);
}
#endif
void deinit()
{
// end();
}
void pinMode(uint8_t pin, uint8_t mode)
{
uint8_t registers = 0;
if (pin >= IO8) {
pin -= IO8;
registers = XL9555_CTRL_CFG1;
} else {
registers = XL9555_CTRL_CFG0;
}
switch (mode) {
case INPUT:
setRegisterBit(registers, pin);
break;
case OUTPUT:
clrRegisterBit(registers, pin);
break;
default:
break;
}
}
int digitalRead(uint8_t pin)
{
uint8_t registers = 0;
if (pin >= IO8) {
pin -= IO8;
registers = XL9555_CTRL_INP1;
} else {
registers = XL9555_CTRL_INP0;
}
return getRegisterBit(registers, pin);
}
void digitalWrite(uint8_t pin, uint8_t val)
{
uint8_t registers = 0;
if (pin >= IO8) {
pin -= IO8;
registers = XL9555_CTRL_OUTP1;
} else {
registers = XL9555_CTRL_OUTP0;
}
val ? setRegisterBit(registers, pin) : clrRegisterBit(registers, pin);
}
void digitalToggle(uint8_t pin)
{
int state = 1 - digitalRead(pin);
digitalWrite(pin, state);
}
int readPort(uint8_t port)
{
return readRegister(port == PORT0 ? XL9555_CTRL_INP0 : XL9555_CTRL_INP1);
}
int writePort(uint8_t port, uint8_t mask)
{
return writeRegister(port == PORT0 ? XL9555_CTRL_OUTP0 : XL9555_CTRL_OUTP1, mask);
}
int readConfig(uint8_t port)
{
return readRegister(port == PORT0 ? XL9555_CTRL_CFG0 : XL9555_CTRL_CFG1);
}
int configPort(uint8_t port, uint8_t mask)
{
return writeRegister(port == PORT0 ? XL9555_CTRL_CFG0 : XL9555_CTRL_CFG1, mask);
}
private:
bool initImpl()
{
int cfg1 = readConfig(PORT0);
if (cfg1 == DEV_WIRE_ERR)return false;
configPort(PORT0, 0x03);
uint8_t val = readConfig(PORT0);
if (val != 0x03) {
return false;
}
writePort(PORT0, cfg1);
return true;
}
int getReadMaskImpl()
{
return -1;
}
protected:
};

View File

@ -0,0 +1,124 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* 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.
*
* @file ExtensionSPI.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2024-01-19
*
*/
#pragma once
#include "SensorLib.h"
template <class chipType>
class ExtensionSPI
{
public:
void beginSPI(int mosi,
int miso,
int sck,
int cs
)
{
_mosi = mosi;
_miso = miso;
_sck = sck;
_cs = cs;
thisChip().pinMode(_mosi, OUTPUT);
thisChip().pinMode(_sck, OUTPUT);
if (_cs != SENSOR_PIN_NONE) {
thisChip().pinMode(_cs, OUTPUT);
thisChip().digitalWrite(_cs, HIGH);
}
if (_miso != SENSOR_PIN_NONE) {
thisChip().pinMode(_miso, INPUT);
}
thisChip().digitalWrite(_mosi, HIGH);
thisChip().digitalWrite(_sck, HIGH);
}
void setBitOrder(uint8_t order)
{
_order = order & 1;
}
uint8_t transfer8(uint8_t val)
{
return transferDataBits(val, 8);
}
uint16_t transfer9(uint16_t val)
{
return transferDataBits(val, 9);
}
uint32_t transferDataBits(uint32_t val, uint32_t bits)
{
uint32_t mask = _BV(bits - 1);
uint8_t out = 0;
if (_cs != SENSOR_PIN_NONE) {
thisChip().digitalWrite(_cs, LOW);
}
for (int i = 0; i < bits ; i++) {
thisChip().digitalWrite(_sck, LOW);
out <<= 1;
if (_miso != SENSOR_PIN_NONE) {
if (thisChip().digitalRead(_miso)) {
out |= 0x01;
}
}
thisChip().digitalWrite(_mosi, val & mask ? HIGH : LOW);
val <<= 1;
thisChip().digitalWrite(_sck, HIGH);
}
if (_cs != SENSOR_PIN_NONE) {
thisChip().digitalWrite(_cs, HIGH);
}
return out;
}
protected:
inline const chipType &thisChip() const
{
return static_cast<const chipType &>(*this);
}
inline chipType &thisChip()
{
return static_cast<chipType &>(*this);
}
private:
int _mosi;
int _sck;
int _miso;
int _order;
int _cs;
};

View File

@ -0,0 +1,726 @@
#pragma once
#define BMA423_SLAVE_ADDRESS (0x19)
#define BAM423_SENSOR_RESOLUTION (12)
#define BMA423_RESET_REG (0x7E)
/**\name CHIP ID ADDRESS*/
#define BMA4_CHIP_ID_ADDR (0x00)
/**\name Chip ID of BMA423 sensor */
#define BMA423_CHIP_ID (0x13)
/**\name POWER_CTRL REGISTER*/
#define BMA4_POWER_CONF_ADDR (0x7C)
#define BMA4_POWER_CTRL_ADDR (0x7D)
/**\name ADVANCE POWER SAVE POSITION AND MASK*/
#define BMA4_ADVANCE_POWER_SAVE_MSK (0x01)
/**\name MAP INTERRUPT 1 and 2 REGISTERS*/
#define BMA4_INT_MAP_1_ADDR (0X56)
#define BMA4_INT_MAP_2_ADDR (0X57)
#define BMA4_INT_MAP_DATA_ADDR (0x58)
#define BMA4_INIT_CTRL_ADDR (0x59)
/**\name FEATURE CONFIG RELATED */
#define BMA4_RESERVED_REG_5B_ADDR (0x5B)
#define BMA4_RESERVED_REG_5C_ADDR (0x5C)
#define BMA4_FEATURE_CONFIG_ADDR (0x5E)
#define BMA4_INTERNAL_ERROR (0x5F)
/**\name GPIO REGISTERS*/
#define BMA4_STEP_CNT_OUT_0_ADDR (0x1E)
#define BMA4_HIGH_G_OUT_ADDR (0x1F)
#define BMA4_ACTIVITY_OUT_ADDR (0x27)
#define BMA4_ORIENTATION_OUT_ADDR (0x28)
#define BMA4_INTERNAL_STAT (0x2A)
/**\name SENSOR TIME REGISTERS*/
#define BMA4_SENSORTIME_0_ADDR (0X18)
/**\name INTERRUPT/FEATURE STATUS REGISTERS*/
#define BMA4_INT_STAT_0_ADDR (0X1C)
/**\name INTERRUPT/FEATURE STATUS REGISTERS*/
#define BMA4_INT_STAT_1_ADDR (0X1D)
/**\name BUS READ AND WRITE LENGTH FOR MAG & ACCEL*/
#define BMA4_MAG_TRIM_DATA_SIZE (16)
#define BMA4_MAG_XYZ_DATA_LENGTH (6)
#define BMA4_MAG_XYZR_DATA_LENGTH (8)
#define BMA4_ACCEL_DATA_LENGTH (6)
#define BMA4_FIFO_DATA_LENGTH (2)
#define BMA4_TEMP_DATA_SIZE (1)
/**\name AUX/ACCEL DATA BASE ADDRESS REGISTERS*/
#define BMA4_DATA_0_ADDR (0X0A)
#define BMA4_DATA_8_ADDR (0X12)
/**\name Feature offset address */
#define BMA423_ANY_NO_MOTION_OFFSET (0x00)
#define BMA423_STEP_CNTR_OFFSET (0x36)
#define BMA423_STEP_CNTR_PARAM_OFFSET (0x04)
#define BMA423_WAKEUP_OFFSET (0x38)
#define BMA423_TILT_OFFSET (0x3A)
#define BMA423_CONFIG_ID_OFFSET (0x3C)
#define BMA423_AXES_REMAP_OFFSET (0x3E)
/**\name Sensor feature size */
#define BMA423_FEATURE_SIZE (64)
#define BMA423_ANYMOTION_EN_LEN (2)
#define BMA423_RD_WR_MIN_LEN (2)
/**************************************************************/
/**\name Remap Axes */
/**************************************************************/
#define BMA423_X_AXIS_MASK (0x03)
#define BMA423_X_AXIS_SIGN_MASK (0x04)
#define BMA423_Y_AXIS_MASK (0x18)
#define BMA423_Y_AXIS_SIGN_MASK (0x20)
#define BMA423_Z_AXIS_MASK (0xC0)
#define BMA423_Z_AXIS_SIGN_MASK (0x01)
/**\name ACCELEROMETER ENABLE POSITION AND MASK*/
#define BMA4_ACCEL_ENABLE_MSK (0x04)
#define BMA4_ASIC_INITIALIZED (0x01)
#define BMA4_CONFIG_STREAM_SIZE (6144)
/**\name Feature configuration file */
static const unsigned char bma423_config_file[] = {
0x80, 0x2e, 0xfc, 0x00, 0x80, 0x2e, 0xfe, 0x00, 0xc8, 0x2e, 0x00, 0x2e,
0x80, 0x2e, 0xfa, 0x00, 0x80, 0x2e, 0x23, 0xb1, 0x80, 0x2e, 0xfd, 0x00,
0x80, 0x2e, 0xfb, 0x00, 0x80, 0x2e, 0x5a, 0xb1, 0x50, 0x39, 0x21, 0x2e,
0xb0, 0xf0, 0x10, 0x30, 0x21, 0x2e, 0x16, 0xf0, 0x80, 0x2e, 0xfc, 0x01,
0x5d, 0x50, 0x45, 0x52, 0x01, 0x42, 0x3b, 0x80, 0x41, 0x30, 0x01, 0x42,
0x3c, 0x80, 0x00, 0x2e, 0x01, 0x40, 0x01, 0x42, 0x21, 0x2e, 0xff, 0xaf,
0xb8, 0x2e, 0xb6, 0xd6, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0xfd, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x24, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x2e,
0x99, 0x01, 0x20, 0x26, 0x98, 0x2e, 0xf6, 0x00, 0x98, 0x2e, 0xe9, 0x01,
0x10, 0x30, 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0x00, 0x2e,
0x00, 0x2e, 0xd0, 0x2e, 0x98, 0x2e, 0xdd, 0x00, 0x01, 0x2e, 0x56, 0x00,
0x00, 0xb2, 0x11, 0x2f, 0x00, 0x30, 0x21, 0x2e, 0x56, 0x00, 0x41, 0x50,
0x98, 0x2e, 0xcc, 0xb0, 0x41, 0x50, 0x98, 0x2e, 0x8f, 0xb4, 0x01, 0x2e,
0x03, 0xf0, 0x0d, 0xbc, 0x0f, 0xb8, 0x00, 0x90, 0x02, 0x2f, 0x45, 0x50,
0x21, 0x2e, 0xbc, 0xf0, 0x01, 0x2e, 0x55, 0x00, 0x00, 0xb2, 0x1a, 0x2f,
0x00, 0x30, 0x21, 0x2e, 0x55, 0x00, 0x43, 0x50, 0x98, 0x2e, 0xcc, 0xb0,
0x43, 0x50, 0x98, 0x2e, 0xdc, 0xb1, 0x43, 0x50, 0x98, 0x2e, 0x92, 0xb5,
0x43, 0x50, 0x98, 0x2e, 0x00, 0xb0, 0x01, 0x2e, 0x1c, 0x01, 0x0f, 0xbc,
0x0f, 0xb8, 0x00, 0x90, 0x45, 0x50, 0x02, 0x2f, 0x21, 0x2e, 0xbc, 0xf0,
0x02, 0x2d, 0x21, 0x2e, 0xba, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0xc3, 0x2d,
0x01, 0x2e, 0x55, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, 0x55, 0xf0, 0x03, 0x2e,
0x00, 0xf0, 0x45, 0x54, 0x01, 0x2e, 0x59, 0xf0, 0x4a, 0x0e, 0x02, 0x2f,
0xf1, 0x33, 0x0d, 0x2c, 0x01, 0x08, 0xf2, 0x30, 0x4a, 0x08, 0x79, 0x84,
0x82, 0xa2, 0x04, 0x2f, 0x02, 0x34, 0x82, 0x0a, 0x47, 0xa2, 0x03, 0x2c,
0x10, 0x22, 0x45, 0x52, 0x01, 0x0a, 0xc0, 0x2e, 0x21, 0x2e, 0x59, 0xf0,
0x00, 0x31, 0xc0, 0x2e, 0x21, 0x2e, 0xba, 0xf0, 0xc8, 0x2e, 0xc8, 0x2e,
0xc8, 0x2e, 0xc8, 0x2e, 0xc8, 0x2e, 0x44, 0x47, 0xaa, 0x00, 0x05, 0x00,
0x2d, 0x01, 0xd4, 0x7b, 0x3b, 0x01, 0xdb, 0x7a, 0x04, 0x00, 0x3f, 0x7b,
0xcd, 0x6c, 0xc3, 0x04, 0x85, 0x09, 0xc3, 0x04, 0xec, 0xe6, 0x0c, 0x46,
0x01, 0x00, 0x27, 0x00, 0x19, 0x00, 0x96, 0x00, 0xa0, 0x00, 0x01, 0x00,
0x0c, 0x00, 0xf0, 0x3c, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00,
0x0e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x43, 0x28, 0x88, 0x00,
0x52, 0x00, 0x4f, 0x00, 0x80, 0x00, 0x5b, 0x00, 0x00, 0x40, 0xaf, 0x00,
0xff, 0x00, 0xff, 0xb7, 0x00, 0x02, 0x00, 0xb0, 0x05, 0x80, 0xb1, 0xf0,
0xc0, 0x00, 0x00, 0x01, 0x5e, 0xf0, 0x39, 0xf0, 0x89, 0xf0, 0x00, 0x20,
0xff, 0x7f, 0x7d, 0x00, 0x5e, 0x00, 0x62, 0x00, 0x7c, 0x00, 0xff, 0xfb,
0x52, 0xf0, 0x56, 0xf0, 0x33, 0x09, 0x33, 0x07, 0x00, 0x08, 0x90, 0x01,
0x00, 0xf8, 0x67, 0x00, 0x4c, 0x04, 0xa0, 0x00, 0xe8, 0x03, 0x81, 0x00,
0x82, 0x00, 0x6a, 0x00, 0x6d, 0x00, 0x6c, 0x00, 0xeb, 0x07, 0xae, 0x07,
0x72, 0x00, 0x6f, 0x00, 0xa1, 0x01, 0x1e, 0x05, 0x47, 0xfd, 0x73, 0x00,
0x77, 0x00, 0x79, 0x00, 0x76, 0x00, 0xcc, 0x00, 0x30, 0x50, 0x50, 0x40,
0x00, 0x18, 0x50, 0x40, 0x56, 0x25, 0x47, 0x25, 0x00, 0x18, 0x2e, 0x00,
0x41, 0x40, 0xa7, 0x02, 0x09, 0x18, 0xc6, 0x00, 0xfb, 0x7f, 0x00, 0x30,
0x49, 0x52, 0x05, 0x30, 0x05, 0x2c, 0x17, 0x03, 0x1e, 0xbd, 0xd2, 0xba,
0x92, 0xb8, 0x6a, 0x0b, 0x61, 0x0e, 0xf9, 0x2f, 0x61, 0x1a, 0x01, 0x2f,
0x5d, 0x0e, 0xf5, 0x2f, 0xd4, 0x7f, 0x02, 0x30, 0x1f, 0x2c, 0xe3, 0x7f,
0x85, 0x01, 0xd1, 0x03, 0x7c, 0x0e, 0x03, 0x2f, 0x7c, 0x1a, 0x0f, 0x2f,
0x73, 0x0f, 0x0d, 0x2f, 0xe3, 0x6f, 0xde, 0x04, 0x5f, 0xba, 0x11, 0xbf,
0xb4, 0x0b, 0xd4, 0x6f, 0x27, 0x07, 0xb3, 0x25, 0xd1, 0xbf, 0xeb, 0x7f,
0x07, 0x00, 0xb4, 0x25, 0x96, 0x02, 0xdb, 0x7f, 0x2f, 0xbf, 0x9e, 0xbf,
0x01, 0xb8, 0xd2, 0xba, 0x21, 0xb9, 0x92, 0xb8, 0x06, 0x0a, 0x6f, 0x0b,
0x40, 0x90, 0xdf, 0x2f, 0x40, 0x91, 0xdd, 0x2f, 0xfb, 0x6f, 0xd0, 0x5f,
0xb8, 0x2e, 0x57, 0x50, 0x41, 0x30, 0x02, 0x40, 0x51, 0x0a, 0x01, 0x42,
0x18, 0x82, 0x4b, 0x50, 0x60, 0x42, 0x70, 0x3c, 0x4d, 0x54, 0x42, 0x42,
0x69, 0x82, 0x82, 0x32, 0x43, 0x40, 0x18, 0x08, 0x02, 0x0a, 0x40, 0x42,
0x42, 0x80, 0x02, 0x3f, 0x01, 0x40, 0x10, 0x50, 0x4a, 0x08, 0xfb, 0x7f,
0x11, 0x42, 0x0b, 0x31, 0x0b, 0x42, 0x3e, 0x80, 0x01, 0x32, 0x01, 0x42,
0x00, 0x2e, 0x01, 0x2e, 0x40, 0xf0, 0x13, 0x90, 0x20, 0x2f, 0x03, 0x30,
0x51, 0x50, 0x4f, 0x54, 0xf4, 0x34, 0x06, 0x30, 0x55, 0x52, 0x55, 0x32,
0x1d, 0x1a, 0xe3, 0x22, 0x18, 0x1a, 0x53, 0x58, 0xe3, 0x22, 0x04, 0x30,
0xd5, 0x40, 0xb5, 0x0d, 0xe1, 0xbe, 0x6f, 0xbb, 0x80, 0x91, 0xa9, 0x0d,
0x01, 0x89, 0xb5, 0x23, 0x10, 0xa1, 0xf7, 0x2f, 0xda, 0x0e, 0xf4, 0x34,
0xeb, 0x2f, 0x01, 0x2e, 0x25, 0x00, 0x70, 0x1a, 0x00, 0x30, 0x21, 0x30,
0x02, 0x2c, 0x08, 0x22, 0x30, 0x30, 0x00, 0xb2, 0x06, 0x2f, 0x21, 0x2e,
0x59, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e,
0xfb, 0x6f, 0xf0, 0x5f, 0xb8, 0x2e, 0x01, 0x2e, 0xb1, 0xf0, 0x59, 0x52,
0x01, 0x0a, 0x21, 0x2e, 0xb1, 0xf0, 0x01, 0x2e, 0x1c, 0x01, 0x0f, 0xbc,
0x0f, 0xb8, 0x00, 0x90, 0x45, 0x50, 0x02, 0x2f, 0xc0, 0x2e, 0x21, 0x2e,
0xbc, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, 0xba, 0xf0, 0x1a, 0x24, 0x26, 0x00,
0x80, 0x2e, 0x8f, 0x00, 0x03, 0x2e, 0x01, 0x01, 0x05, 0x2e, 0x01, 0x01,
0x92, 0xbd, 0x20, 0x50, 0x03, 0x2e, 0x01, 0x01, 0xbf, 0xba, 0x21, 0xbd,
0x2f, 0xbb, 0x1f, 0xba, 0x40, 0x91, 0xf0, 0x7f, 0x04, 0x2f, 0x80, 0x91,
0x02, 0x2f, 0x00, 0xb3, 0x90, 0x2e, 0xc7, 0xb0, 0x03, 0x2e, 0x7b, 0x00,
0x01, 0x80, 0x40, 0x90, 0x14, 0x2f, 0x41, 0x84, 0xf1, 0x6f, 0x25, 0x2e,
0x7b, 0x00, 0x41, 0x40, 0x23, 0x2e, 0x5a, 0x00, 0x47, 0x52, 0x12, 0x40,
0x52, 0x42, 0x02, 0x30, 0x00, 0x40, 0x40, 0x42, 0xe0, 0x5f, 0x25, 0x2e,
0x57, 0x00, 0x25, 0x2e, 0x58, 0x00, 0x25, 0x2e, 0x5d, 0x00, 0xb8, 0x2e,
0x07, 0x2e, 0x00, 0x01, 0x03, 0x2e, 0x01, 0x01, 0x05, 0x2e, 0x00, 0x01,
0x24, 0xbd, 0x0f, 0x2e, 0x59, 0x00, 0xb5, 0xbd, 0x93, 0xbc, 0x2f, 0xb9,
0xb5, 0xb9, 0x93, 0xb8, 0x3a, 0x1a, 0x06, 0x2f, 0x07, 0x30, 0x25, 0x2e,
0x59, 0x00, 0x2f, 0x2e, 0x57, 0x00, 0x2f, 0x2e, 0x58, 0x00, 0x40, 0xb3,
0x05, 0x30, 0x07, 0x30, 0x0a, 0x2f, 0xf7, 0x6f, 0xe6, 0x7f, 0x00, 0x2e,
0xc6, 0x41, 0x0f, 0x2e, 0x5a, 0x00, 0xb7, 0x05, 0x80, 0xa9, 0xee, 0x05,
0xf7, 0x23, 0xe6, 0x6f, 0x80, 0xb3, 0x06, 0x30, 0x09, 0x2f, 0xe7, 0x7f,
0x00, 0x2e, 0x06, 0x40, 0x0f, 0x2e, 0x5b, 0x00, 0xb7, 0x05, 0x80, 0xa9,
0xee, 0x05, 0xb7, 0x23, 0xe7, 0x6f, 0x00, 0xb3, 0x04, 0x30, 0x0b, 0x2f,
0xf4, 0x6f, 0x02, 0x89, 0xe7, 0x7f, 0x00, 0x2e, 0x04, 0x41, 0x0f, 0x2e,
0x5c, 0x00, 0x27, 0x05, 0x00, 0xa9, 0xec, 0x05, 0x27, 0x23, 0xe7, 0x6f,
0x7b, 0x0f, 0x17, 0x30, 0x0b, 0x2f, 0x73, 0x0f, 0x05, 0x30, 0x17, 0x30,
0x07, 0x2f, 0x63, 0x0f, 0x15, 0x30, 0x17, 0x30, 0x00, 0x2f, 0x07, 0x30,
0xe3, 0x0e, 0x00, 0x2f, 0x05, 0x30, 0x80, 0x90, 0x05, 0x2e, 0x57, 0x00,
0x13, 0x30, 0x13, 0x29, 0xf2, 0x6f, 0x47, 0x5c, 0x17, 0x2f, 0xc0, 0x91,
0x05, 0x30, 0x0b, 0x2f, 0x07, 0x2e, 0x58, 0x00, 0xc1, 0x86, 0x2b, 0x2e,
0x57, 0x00, 0x59, 0x0e, 0x27, 0x2e, 0x58, 0x00, 0x24, 0x2f, 0x2b, 0x2e,
0x5d, 0x00, 0x22, 0x2d, 0x61, 0x0e, 0x29, 0x2e, 0x57, 0x00, 0x2b, 0x2e,
0x58, 0x00, 0x1b, 0x2f, 0x27, 0x2e, 0x5d, 0x00, 0x19, 0x2d, 0x40, 0x91,
0x05, 0x2f, 0x01, 0x30, 0x23, 0x2e, 0x57, 0x00, 0x23, 0x2e, 0x5d, 0x00,
0x06, 0x2d, 0x29, 0x2e, 0x57, 0x00, 0x61, 0x0e, 0x01, 0x2f, 0x27, 0x2e,
0x5d, 0x00, 0x81, 0x40, 0x23, 0x2e, 0x5a, 0x00, 0x30, 0x25, 0x47, 0x52,
0xd4, 0x40, 0x54, 0x42, 0x00, 0x2e, 0xc3, 0x40, 0x43, 0x42, 0x00, 0x2e,
0x03, 0x2e, 0x5d, 0x00, 0x40, 0xb2, 0x0d, 0x2f, 0x81, 0x40, 0x23, 0x2e,
0x5a, 0x00, 0x11, 0x40, 0x91, 0x43, 0x01, 0x34, 0x00, 0x40, 0x80, 0x43,
0x23, 0x2e, 0x5e, 0xf0, 0x03, 0x2d, 0x00, 0x30, 0x21, 0x2e, 0x7b, 0x00,
0xe0, 0x5f, 0xb8, 0x2e, 0x50, 0x50, 0xf0, 0x7f, 0x1a, 0x25, 0x13, 0x40,
0x7b, 0x84, 0xe0, 0x7f, 0x83, 0x42, 0x35, 0x30, 0x11, 0x40, 0x04, 0x40,
0xc1, 0x7f, 0xd4, 0x7f, 0x86, 0x31, 0x07, 0x2e, 0x59, 0xf0, 0x03, 0x2e,
0x1f, 0x01, 0x0d, 0x09, 0x02, 0xab, 0x05, 0x30, 0x8e, 0x09, 0x2c, 0x23,
0xe3, 0xba, 0x42, 0xab, 0x16, 0x30, 0x75, 0x23, 0x59, 0x5c, 0x8e, 0x09,
0x66, 0xbb, 0x82, 0xab, 0x27, 0x30, 0xbe, 0x23, 0x3e, 0x80, 0x25, 0x1a,
0x06, 0x2f, 0x2e, 0x1a, 0x04, 0x2f, 0x26, 0x1a, 0x02, 0x2f, 0xf7, 0x3d,
0x03, 0x2c, 0xdf, 0x08, 0x07, 0x32, 0xdf, 0x0a, 0x14, 0x01, 0x55, 0x01,
0x04, 0x41, 0x14, 0x42, 0x16, 0x01, 0x42, 0x41, 0x45, 0x30, 0x4d, 0x09,
0x04, 0x41, 0x12, 0x42, 0x04, 0x42, 0x40, 0xb3, 0x04, 0x2f, 0xf0, 0x6f,
0x02, 0x30, 0x04, 0x40, 0x94, 0x04, 0x02, 0x42, 0x00, 0x32, 0x08, 0x08,
0x00, 0xb2, 0x00, 0x30, 0x05, 0x2f, 0xe2, 0x6f, 0x00, 0x2e, 0x84, 0x40,
0x04, 0x05, 0x84, 0x42, 0x00, 0x2e, 0x5b, 0x54, 0x4a, 0x08, 0x40, 0xb2,
0xf1, 0x6f, 0x04, 0x2f, 0x42, 0x82, 0x00, 0x2e, 0x42, 0x40, 0x02, 0x04,
0x40, 0x42, 0xb0, 0x5f, 0x27, 0x2e, 0x59, 0xf0, 0xb8, 0x2e, 0x50, 0x50,
0xf7, 0x7f, 0x00, 0x2e, 0x0f, 0x2e, 0xb8, 0xf0, 0xf8, 0xbf, 0xff, 0xbb,
0xc0, 0xb3, 0x2a, 0x2f, 0x0f, 0x2e, 0x01, 0xf0, 0xfe, 0xbf, 0xe6, 0x7f,
0x7e, 0xbb, 0xd5, 0x7f, 0x37, 0x30, 0x5f, 0x5a, 0xbe, 0x05, 0x67, 0x41,
0xc4, 0x7f, 0x78, 0xbe, 0x47, 0x41, 0x27, 0x0b, 0xb3, 0x7f, 0xe6, 0x11,
0x41, 0x56, 0x43, 0x89, 0xd7, 0x42, 0x00, 0x2e, 0x27, 0x41, 0x05, 0x41,
0xf8, 0xbf, 0x7d, 0x0b, 0x6e, 0x11, 0x03, 0x8f, 0xd5, 0x42, 0x14, 0x30,
0xe5, 0x41, 0xc7, 0x41, 0xd8, 0xbe, 0x6f, 0x0b, 0x6e, 0x11, 0xc5, 0x42,
0x29, 0x2e, 0x56, 0x00, 0x45, 0x56, 0x27, 0x2e, 0xb8, 0xf0, 0xe6, 0x6f,
0xd5, 0x6f, 0xc4, 0x6f, 0xb3, 0x6f, 0xf7, 0x6f, 0xb0, 0x5f, 0xc8, 0x2e,
0x50, 0x50, 0xe5, 0x7f, 0xd7, 0x7f, 0xf6, 0x7f, 0x36, 0x30, 0x0b, 0x2e,
0x01, 0xf0, 0xde, 0xbe, 0xde, 0xbb, 0x61, 0x5a, 0xb7, 0x05, 0x67, 0x41,
0xc4, 0x7f, 0x78, 0xbe, 0x47, 0x41, 0x27, 0x0b, 0xb3, 0x7f, 0xe6, 0x11,
0x43, 0x56, 0x43, 0x89, 0xd7, 0x42, 0x00, 0x2e, 0x27, 0x41, 0x05, 0x41,
0xf8, 0xbf, 0x7d, 0x0b, 0x6e, 0x11, 0x03, 0x8f, 0xd5, 0x42, 0x14, 0x30,
0xe5, 0x41, 0xc7, 0x41, 0xd8, 0xbe, 0x6f, 0x0b, 0x6e, 0x11, 0xc5, 0x42,
0x29, 0x2e, 0x55, 0x00, 0x03, 0x31, 0x27, 0x2e, 0xb8, 0xf0, 0xf6, 0x6f,
0xe5, 0x6f, 0xd7, 0x6f, 0xc4, 0x6f, 0xb3, 0x6f, 0xb0, 0x5f, 0xc8, 0x2e,
0x40, 0x50, 0xf6, 0x7f, 0x1a, 0x18, 0x63, 0x56, 0x33, 0x00, 0x06, 0x30,
0xfe, 0x03, 0x0e, 0xb8, 0xf2, 0xbf, 0x07, 0x0a, 0x2a, 0x18, 0x63, 0x5a,
0xb5, 0x01, 0x03, 0x30, 0xfb, 0x03, 0x6e, 0xbb, 0xf2, 0xbf, 0xe1, 0x7f,
0xf7, 0x0b, 0x56, 0x40, 0x36, 0x25, 0x46, 0x40, 0x06, 0x28, 0xc7, 0x7f,
0x22, 0x18, 0xd1, 0x7f, 0xb5, 0x00, 0x01, 0x30, 0x39, 0x03, 0x2e, 0xb9,
0x42, 0xbe, 0x14, 0x0b, 0xf2, 0x6f, 0x10, 0x18, 0xb5, 0x00, 0xb9, 0x03,
0x2e, 0xb9, 0x62, 0xbf, 0x96, 0x0a, 0xb6, 0x6f, 0x30, 0x18, 0x75, 0x01,
0xb9, 0x03, 0x5c, 0x28, 0xe2, 0xbf, 0xde, 0xb9, 0xd6, 0x6f, 0xdf, 0x0a,
0x8a, 0x28, 0xc4, 0x6f, 0x82, 0x43, 0x23, 0x29, 0xe5, 0x6f, 0xc0, 0x2e,
0x44, 0x43, 0xc0, 0x5f, 0x40, 0x50, 0xd0, 0x7f, 0x4a, 0x17, 0x00, 0x40,
0x01, 0x18, 0x46, 0x25, 0x07, 0x25, 0x65, 0x56, 0xd9, 0x04, 0x53, 0x18,
0xeb, 0x18, 0x05, 0x30, 0x49, 0x16, 0x69, 0x06, 0xca, 0x18, 0xa6, 0x00,
0xc7, 0x02, 0x65, 0x58, 0xcb, 0x7f, 0x98, 0x2e, 0x7f, 0xb6, 0xcb, 0x6f,
0xd2, 0x6f, 0xc0, 0x2e, 0x80, 0x42, 0xc0, 0x5f, 0x09, 0x2e, 0x1b, 0x01,
0x05, 0x2e, 0x1b, 0x01, 0xa3, 0xbc, 0x44, 0xbe, 0x90, 0x50, 0x4f, 0xb9,
0x07, 0x2e, 0x1b, 0x01, 0x4a, 0x25, 0x9f, 0xb8, 0x39, 0x8f, 0xb2, 0xbd,
0xf2, 0x7f, 0xbf, 0xb9, 0xeb, 0x7f, 0x8a, 0x0a, 0x37, 0x89, 0x0b, 0x30,
0x93, 0x0a, 0x8b, 0x7f, 0xcb, 0x43, 0x0b, 0x43, 0x80, 0xb2, 0xd3, 0x7f,
0xc1, 0x7f, 0x90, 0x2e, 0x87, 0xb2, 0x20, 0x25, 0x01, 0x2e, 0x64, 0x00,
0x01, 0x90, 0x0e, 0x2f, 0x67, 0x52, 0x01, 0x2e, 0x61, 0x00, 0xb4, 0x7f,
0xa2, 0x7f, 0x98, 0x2e, 0x8d, 0xb2, 0x00, 0x30, 0x21, 0x2e, 0x64, 0x00,
0xc1, 0x6f, 0xd3, 0x6f, 0xa2, 0x6f, 0xb4, 0x6f, 0x0b, 0x30, 0x01, 0x2e,
0x1b, 0x01, 0x06, 0xbc, 0x06, 0xbb, 0x57, 0x25, 0x01, 0x2e, 0x1b, 0x01,
0x94, 0xb1, 0x05, 0xbc, 0xb6, 0x7f, 0x0f, 0xbb, 0x6b, 0x50, 0x80, 0xb3,
0x0f, 0x2f, 0x0d, 0x2e, 0x1b, 0x01, 0x6f, 0x5e, 0xb7, 0x09, 0x2d, 0x2e,
0x1b, 0x01, 0x71, 0x5c, 0x69, 0x5e, 0x9b, 0x43, 0x9b, 0x43, 0xdb, 0x43,
0x9b, 0x43, 0x1b, 0x42, 0xcb, 0x43, 0x0b, 0x42, 0x8b, 0x43, 0x40, 0xb2,
0x05, 0x2f, 0x69, 0x50, 0x00, 0x2e, 0x16, 0x40, 0x0b, 0x40, 0x76, 0x7f,
0x8b, 0x7f, 0xcb, 0x0a, 0x01, 0x2e, 0x61, 0x00, 0x67, 0x52, 0x6d, 0x5c,
0x98, 0x2e, 0xd3, 0xb2, 0x90, 0x6f, 0x00, 0xb2, 0x0b, 0x2f, 0xf0, 0x6f,
0x00, 0xb2, 0x08, 0x2f, 0x69, 0x58, 0x6b, 0x50, 0x12, 0x41, 0x12, 0x42,
0x21, 0x30, 0x04, 0x41, 0x04, 0x42, 0x23, 0x2e, 0x5e, 0xf0, 0xc0, 0x6f,
0x00, 0xb2, 0x26, 0x2f, 0x74, 0x6f, 0x80, 0x6f, 0x71, 0x54, 0x88, 0xbd,
0xc8, 0xb8, 0x4b, 0x0a, 0x94, 0x42, 0x91, 0x42, 0x90, 0x42, 0x88, 0xba,
0x69, 0x52, 0xf3, 0x6f, 0x54, 0x42, 0x85, 0x42, 0xc0, 0x90, 0x40, 0x42,
0x15, 0x2f, 0x6b, 0x52, 0x00, 0x2e, 0x52, 0x40, 0x41, 0x40, 0xa2, 0x04,
0x41, 0x06, 0x40, 0xaa, 0x04, 0x2f, 0x40, 0x90, 0x0b, 0x2f, 0xb1, 0x6f,
0x4a, 0x0f, 0x08, 0x2f, 0xb2, 0x6f, 0x80, 0xb2, 0x05, 0x2f, 0x6b, 0x54,
0x21, 0x30, 0x94, 0x42, 0x80, 0x42, 0x23, 0x2e, 0x5e, 0xf0, 0xd0, 0x6f,
0x00, 0xb2, 0x13, 0x2f, 0x01, 0x2e, 0x60, 0x00, 0x09, 0x2e, 0x7c, 0x00,
0x04, 0x1a, 0x0d, 0x2f, 0x73, 0x50, 0x29, 0x2e, 0x60, 0x00, 0x24, 0x42,
0x44, 0x30, 0x02, 0x40, 0x02, 0x42, 0x09, 0x80, 0x00, 0x2e, 0x04, 0x42,
0x03, 0x2d, 0x10, 0x30, 0x21, 0x2e, 0x64, 0x00, 0xeb, 0x6f, 0x70, 0x5f,
0xb8, 0x2e, 0x09, 0x86, 0x49, 0x54, 0xe4, 0x40, 0xc3, 0x80, 0x94, 0x04,
0xc3, 0x40, 0x13, 0x05, 0x05, 0x40, 0x25, 0x05, 0x8a, 0x17, 0x73, 0x30,
0x73, 0x09, 0x8c, 0x17, 0xf3, 0x08, 0xe3, 0x00, 0x4c, 0x82, 0x95, 0x00,
0xb3, 0xb5, 0x23, 0xb5, 0x53, 0x42, 0x52, 0x42, 0x53, 0x42, 0x42, 0x42,
0x71, 0x82, 0x75, 0x54, 0x52, 0x42, 0x10, 0x50, 0x77, 0x54, 0x52, 0x42,
0xfb, 0x7f, 0x22, 0x30, 0x79, 0x56, 0x43, 0x42, 0x44, 0x82, 0x0b, 0x30,
0x52, 0x42, 0x5b, 0x42, 0x7c, 0x84, 0x4b, 0x42, 0x35, 0x82, 0x8c, 0x80,
0x8b, 0x42, 0x0b, 0x42, 0x39, 0x80, 0x04, 0x30, 0x0b, 0x42, 0x37, 0x80,
0x15, 0x30, 0x60, 0x25, 0x98, 0x2e, 0xc6, 0xb2, 0x8b, 0x83, 0xfb, 0x6f,
0x65, 0x42, 0xc0, 0x2e, 0x44, 0x42, 0xf0, 0x5f, 0x05, 0x80, 0x02, 0x30,
0x51, 0x82, 0x02, 0x42, 0x13, 0x30, 0x41, 0x40, 0x4b, 0x08, 0x7b, 0x54,
0x3e, 0x80, 0x51, 0x14, 0xc0, 0x2e, 0x01, 0x42, 0x00, 0x2e, 0x40, 0x51,
0xd1, 0x7f, 0x12, 0x25, 0x02, 0x30, 0x42, 0x43, 0x32, 0x30, 0x82, 0x43,
0xc6, 0x7f, 0xe5, 0x7f, 0xb4, 0x7f, 0xa3, 0x7f, 0x90, 0x7f, 0x8b, 0x7f,
0x98, 0x2e, 0x54, 0x01, 0xc0, 0x7e, 0x00, 0xac, 0x01, 0x2f, 0x65, 0x50,
0xc0, 0x7e, 0x00, 0x2e, 0x90, 0x6f, 0x09, 0x8a, 0xd1, 0x6f, 0x75, 0x7f,
0x4c, 0x82, 0x63, 0x41, 0x65, 0x7f, 0x11, 0x7f, 0x00, 0x2e, 0x64, 0x41,
0x44, 0x85, 0x52, 0x7f, 0x45, 0x7f, 0x00, 0x2e, 0xa6, 0x40, 0x80, 0x40,
0x32, 0x7f, 0x82, 0x8e, 0xc2, 0x6e, 0x45, 0x41, 0xf0, 0x7f, 0x27, 0x7f,
0x02, 0x7f, 0x98, 0x2e, 0x8a, 0xb1, 0x23, 0x6f, 0xd1, 0x6f, 0xc2, 0x40,
0xf9, 0x86, 0x23, 0x7f, 0x80, 0xb2, 0xe0, 0x7e, 0x0f, 0x2f, 0x32, 0x6f,
0x64, 0x6f, 0x82, 0x40, 0xf2, 0x7f, 0x4e, 0x82, 0x42, 0x6f, 0x50, 0x6f,
0x73, 0x6f, 0x85, 0x40, 0xc3, 0x40, 0x04, 0x41, 0x06, 0x40, 0xe2, 0x6e,
0x98, 0x2e, 0x8a, 0xb1, 0xe0, 0x7e, 0xf3, 0x31, 0x10, 0x6f, 0x36, 0x80,
0xe1, 0x6e, 0x02, 0x40, 0x71, 0x7f, 0x51, 0x04, 0x02, 0x30, 0x40, 0xa8,
0x91, 0x04, 0x4a, 0x22, 0x89, 0x16, 0x93, 0x08, 0x4a, 0x00, 0x95, 0xb4,
0x09, 0x18, 0x8e, 0x16, 0x13, 0x30, 0x93, 0x08, 0x21, 0x6f, 0x60, 0x7f,
0x4d, 0x86, 0x02, 0x80, 0xb2, 0x00, 0x41, 0x40, 0x21, 0xb5, 0x50, 0x7f,
0x43, 0x7f, 0x98, 0x2e, 0xc2, 0xb1, 0x40, 0x6f, 0x62, 0x6f, 0x55, 0x6f,
0x13, 0x40, 0x84, 0x40, 0x01, 0x40, 0x45, 0x41, 0x42, 0xbe, 0x1d, 0x18,
0x4c, 0x04, 0x31, 0x0f, 0x04, 0x8a, 0xc0, 0x6f, 0x11, 0x30, 0x02, 0x2f,
0x00, 0x2e, 0x03, 0x2c, 0x01, 0x42, 0x23, 0x30, 0x03, 0x42, 0x00, 0x2e,
0xd6, 0x6f, 0x44, 0x41, 0x8a, 0x87, 0x76, 0x8b, 0x00, 0xb3, 0x53, 0x7f,
0x15, 0x2f, 0x04, 0x6f, 0x7d, 0x5e, 0x8b, 0x8d, 0xe7, 0x01, 0xc0, 0xa5,
0x84, 0x41, 0x01, 0x2f, 0x00, 0xa1, 0x03, 0x2f, 0xc0, 0xad, 0x08, 0x2f,
0x00, 0xa5, 0x06, 0x2f, 0xc6, 0x40, 0x81, 0x8d, 0x07, 0x30, 0x3c, 0x05,
0xd6, 0x42, 0x04, 0x2c, 0xc4, 0x42, 0x02, 0x2c, 0x07, 0x30, 0x07, 0x30,
0x86, 0x86, 0x94, 0x6f, 0xd7, 0x7e, 0x0e, 0x8d, 0x00, 0x40, 0x74, 0x89,
0xc7, 0x40, 0x02, 0xb2, 0xf9, 0x29, 0x45, 0x41, 0x86, 0x41, 0xbe, 0x80,
0x21, 0x41, 0x75, 0x23, 0x82, 0x40, 0xc7, 0x42, 0x45, 0x7f, 0x34, 0x7f,
0x20, 0x7f, 0x98, 0x2e, 0xc2, 0xb1, 0x31, 0x6f, 0x60, 0x6f, 0x24, 0x6f,
0x22, 0x40, 0x05, 0x41, 0x43, 0x40, 0x13, 0x01, 0x43, 0x86, 0xac, 0x0f,
0xd1, 0x6f, 0x30, 0x7f, 0x00, 0x2f, 0x44, 0x42, 0x48, 0x8a, 0x41, 0x88,
0xe1, 0x40, 0x13, 0x7f, 0x04, 0x7f, 0xf5, 0x7e, 0x98, 0x2e, 0xc2, 0xb1,
0x11, 0x6f, 0x60, 0x6f, 0x34, 0x6f, 0x42, 0x40, 0x03, 0x40, 0x9a, 0x04,
0x04, 0x41, 0x43, 0x82, 0xa2, 0x0e, 0x03, 0x6f, 0x00, 0x2f, 0xc2, 0x42,
0x00, 0x2e, 0x41, 0x40, 0x72, 0x6f, 0x98, 0x2e, 0xc2, 0xb1, 0x25, 0x6f,
0x72, 0x6f, 0x53, 0x41, 0x93, 0x0e, 0xd1, 0x6f, 0x46, 0x80, 0x1b, 0x30,
0x03, 0x30, 0x0c, 0x2f, 0x04, 0x40, 0x00, 0x91, 0x42, 0x42, 0x08, 0x2f,
0xf6, 0x6e, 0x44, 0x6f, 0x86, 0x41, 0xb4, 0x0e, 0x03, 0x2f, 0x02, 0x88,
0xdb, 0x7e, 0x03, 0x43, 0x0b, 0x42, 0x46, 0x8d, 0x44, 0x41, 0x47, 0x80,
0x05, 0x6f, 0x94, 0x0f, 0x76, 0x7f, 0x60, 0x7f, 0x02, 0x2f, 0x45, 0x89,
0x42, 0x43, 0x03, 0x43, 0x49, 0x88, 0xa5, 0x6f, 0x40, 0x91, 0xa4, 0x7f,
0x15, 0x30, 0xe2, 0x6f, 0xd3, 0x6e, 0x03, 0x2f, 0x04, 0x30, 0x83, 0x42,
0x80, 0x2e, 0x77, 0xb4, 0x04, 0x40, 0x25, 0x29, 0x04, 0x42, 0x83, 0x42,
0x45, 0x82, 0x94, 0x6f, 0x04, 0x85, 0xc0, 0xb2, 0x90, 0x2e, 0x63, 0xb4,
0x15, 0x87, 0x3c, 0x8c, 0xc4, 0x40, 0x46, 0x7f, 0xc2, 0x86, 0x07, 0x40,
0x86, 0x41, 0xf4, 0xbf, 0x00, 0xb3, 0x0c, 0x2f, 0x90, 0x6f, 0x16, 0x80,
0x46, 0x25, 0x00, 0x40, 0x57, 0x25, 0x04, 0x18, 0xae, 0x0e, 0x10, 0x30,
0x06, 0x30, 0x75, 0x25, 0x46, 0x23, 0x60, 0x6f, 0x64, 0x25, 0xc4, 0x40,
0xfa, 0x86, 0x00, 0xb3, 0x33, 0x7f, 0x09, 0x2f, 0x93, 0x6f, 0xd8, 0x88,
0x53, 0x6f, 0x04, 0x41, 0xc3, 0x40, 0xdc, 0x0e, 0x13, 0x30, 0x04, 0x30,
0xdc, 0x22, 0xb3, 0x25, 0x40, 0xb3, 0x02, 0x2f, 0x3b, 0x25, 0xc0, 0x90,
0x05, 0x2f, 0x91, 0x6f, 0xd0, 0x6f, 0x98, 0x2e, 0xc6, 0xb2, 0x4d, 0x2c,
0x04, 0x30, 0x8d, 0x88, 0x43, 0x40, 0x82, 0x40, 0x54, 0x7f, 0xda, 0x0f,
0x04, 0x30, 0x08, 0x2f, 0xc1, 0x80, 0x40, 0x42, 0xc2, 0x0f, 0x02, 0x2f,
0x00, 0x30, 0xc0, 0x7e, 0x1b, 0x2d, 0xc0, 0x7e, 0x19, 0x2d, 0xe1, 0xbc,
0x92, 0x6f, 0x4f, 0x04, 0x90, 0x84, 0x40, 0xa8, 0x21, 0x05, 0x83, 0x40,
0x4c, 0x22, 0x4b, 0x0e, 0xb6, 0x84, 0x21, 0x30, 0x02, 0x2f, 0x11, 0x30,
0x04, 0x2c, 0xc1, 0x7e, 0xe3, 0x6f, 0xc1, 0x7e, 0xc1, 0x42, 0x00, 0x2e,
0x00, 0x40, 0x81, 0x40, 0x04, 0xbd, 0x40, 0x6f, 0x98, 0x2e, 0xc2, 0xb1,
0x50, 0x6f, 0x11, 0x30, 0x02, 0x40, 0x51, 0x08, 0xc3, 0x6e, 0x03, 0x80,
0x99, 0x15, 0x0b, 0x40, 0xb1, 0x6f, 0xd0, 0x6f, 0xb6, 0x7f, 0x5b, 0x7f,
0x04, 0x30, 0x4d, 0x54, 0x03, 0x30, 0x11, 0x2c, 0x10, 0x80, 0x55, 0x6f,
0x06, 0x40, 0x75, 0x01, 0x58, 0xbb, 0x6a, 0x09, 0x05, 0x42, 0xc1, 0x86,
0x47, 0x40, 0x51, 0x25, 0xbe, 0x01, 0x56, 0x43, 0x00, 0x2e, 0x46, 0x41,
0xf4, 0x03, 0xb6, 0x6f, 0x47, 0x43, 0x5e, 0x0e, 0xed, 0x2f, 0x31, 0x6f,
0x60, 0x6f, 0x42, 0x40, 0x15, 0x30, 0x02, 0x82, 0x95, 0x08, 0x04, 0x42,
0x52, 0x42, 0x02, 0x2c, 0x44, 0x42, 0x04, 0x30, 0x3e, 0x8e, 0x91, 0x6f,
0x4f, 0x8c, 0x02, 0x40, 0x83, 0x41, 0xb5, 0x8d, 0x93, 0x0e, 0xd0, 0x6f,
0x01, 0x2f, 0x98, 0x2e, 0xc6, 0xb2, 0x00, 0x2e, 0xc0, 0x41, 0x81, 0x41,
0xc1, 0x0f, 0xc0, 0x6f, 0x01, 0x2f, 0x04, 0x42, 0x00, 0x2e, 0x70, 0x6f,
0x3c, 0x82, 0x00, 0x40, 0x41, 0x40, 0x89, 0x16, 0x95, 0x08, 0x4a, 0x00,
0x04, 0xbc, 0x91, 0xb4, 0x01, 0x0e, 0xe0, 0x6f, 0x07, 0x2f, 0xa1, 0x6f,
0x00, 0x2e, 0x41, 0x40, 0x40, 0xb2, 0x02, 0x2f, 0xa1, 0x6f, 0x05, 0x42,
0x44, 0x42, 0x00, 0x2e, 0x8b, 0x6f, 0xc0, 0x5e, 0xb8, 0x2e, 0x03, 0x2e,
0x1c, 0x01, 0x9c, 0xbc, 0x1d, 0xb9, 0x02, 0x82, 0x25, 0x2e, 0x8e, 0x00,
0x83, 0x56, 0x13, 0x18, 0x01, 0x2e, 0x66, 0x00, 0x43, 0x40, 0xd8, 0x04,
0x05, 0x2e, 0x65, 0x00, 0x40, 0x50, 0x27, 0x2e, 0x65, 0x00, 0xfb, 0x7f,
0xda, 0x05, 0x8b, 0x50, 0x4b, 0x40, 0x02, 0x40, 0x81, 0x82, 0x01, 0x42,
0x03, 0x80, 0x81, 0x52, 0xb1, 0x00, 0x03, 0x40, 0x3b, 0x82, 0x85, 0x58,
0x14, 0x01, 0xc0, 0xb2, 0x37, 0x2e, 0x66, 0x00, 0xd1, 0x7f, 0xe2, 0x7f,
0x04, 0x2f, 0x05, 0x2e, 0x6b, 0x00, 0x81, 0x84, 0x25, 0x2e, 0x6b, 0x00,
0x62, 0x40, 0x3a, 0x0f, 0x45, 0x40, 0xc1, 0x7f, 0x21, 0x30, 0x12, 0x30,
0x42, 0x2f, 0x0d, 0x2e, 0x69, 0x00, 0x3e, 0x0e, 0x33, 0x2f, 0x05, 0x2e,
0x6a, 0x00, 0x01, 0x35, 0x91, 0x0e, 0x01, 0x30, 0x03, 0x2f, 0x09, 0x2e,
0x6e, 0x00, 0x00, 0xb3, 0x24, 0x2f, 0xc0, 0x35, 0x90, 0x0e, 0x39, 0x2f,
0x8f, 0x50, 0x02, 0x30, 0x01, 0x40, 0x7f, 0x82, 0x43, 0xa2, 0x02, 0x2f,
0x00, 0x2e, 0x0c, 0x2c, 0x01, 0x30, 0xc0, 0xb2, 0x11, 0x30, 0x02, 0x2f,
0x25, 0x2e, 0x6d, 0x00, 0x03, 0x2d, 0x23, 0x2e, 0x6d, 0x00, 0x21, 0x30,
0x25, 0x2e, 0x6b, 0x00, 0x42, 0xb2, 0x04, 0x2f, 0x41, 0xb2, 0x02, 0x2f,
0x25, 0x2e, 0x6d, 0x00, 0x31, 0x30, 0x3e, 0x80, 0x04, 0x86, 0x25, 0x2e,
0x6c, 0x00, 0x02, 0x42, 0xc2, 0x42, 0x18, 0x2d, 0x02, 0x35, 0x01, 0x42,
0x25, 0x2e, 0x6a, 0x00, 0x13, 0x2d, 0x2c, 0x04, 0x38, 0x1e, 0x21, 0x2e,
0x69, 0x00, 0x7f, 0x50, 0x11, 0x30, 0x22, 0x30, 0x98, 0x2e, 0x66, 0xb5,
0x09, 0x2c, 0x01, 0x30, 0x2c, 0x00, 0x38, 0x1c, 0x21, 0x2e, 0x68, 0x00,
0x7f, 0x50, 0x98, 0x2e, 0x66, 0xb5, 0x01, 0x30, 0xc0, 0x6f, 0xd4, 0xb1,
0xf5, 0xbd, 0x6b, 0xba, 0x91, 0x5a, 0x02, 0x40, 0x15, 0x18, 0xf5, 0xbe,
0xeb, 0xbb, 0xe3, 0x0a, 0x3d, 0x0b, 0xd2, 0x6f, 0xe3, 0x00, 0x84, 0x40,
0x63, 0x05, 0x93, 0x58, 0x2c, 0x18, 0xf5, 0xbe, 0x03, 0x42, 0xeb, 0xbb,
0xfd, 0x0b, 0xe0, 0x6f, 0x58, 0x01, 0xdf, 0x01, 0x7d, 0x1f, 0x95, 0x42,
0x18, 0x04, 0x85, 0x40, 0x5d, 0x05, 0x2c, 0x18, 0x75, 0xbe, 0xeb, 0xba,
0x2c, 0x0b, 0xdc, 0x04, 0x18, 0x1c, 0x80, 0x42, 0x84, 0x80, 0x02, 0x30,
0x00, 0x40, 0x00, 0xb2, 0x0c, 0x2f, 0x01, 0x2e, 0x6b, 0x00, 0x03, 0x35,
0x83, 0x0e, 0x07, 0x2f, 0x8d, 0x50, 0x3e, 0x80, 0x25, 0x2e, 0x6d, 0x00,
0x02, 0x42, 0x03, 0x80, 0x00, 0x2e, 0x02, 0x42, 0x40, 0xb2, 0x04, 0x2f,
0x8b, 0x50, 0x04, 0x80, 0x25, 0x2e, 0x6a, 0x00, 0x02, 0x42, 0x42, 0xb2,
0x89, 0x56, 0x9a, 0x22, 0x41, 0xb2, 0x01, 0x2e, 0x1c, 0x01, 0x87, 0x52,
0x0b, 0xbc, 0x8a, 0x22, 0x0f, 0xb8, 0x00, 0x90, 0x01, 0x32, 0x06, 0x2f,
0x10, 0x30, 0x90, 0x08, 0x80, 0xb2, 0x08, 0x2f, 0x23, 0x2e, 0x5e, 0xf0,
0x06, 0x2d, 0x20, 0x30, 0x90, 0x08, 0x80, 0xb2, 0x01, 0x2f, 0x23, 0x2e,
0x5e, 0xf0, 0xfb, 0x6f, 0xc0, 0x5f, 0xb8, 0x2e, 0x07, 0x86, 0xfc, 0x88,
0xc6, 0x40, 0x05, 0x41, 0x31, 0x1a, 0x12, 0x2f, 0x80, 0x91, 0x22, 0x2f,
0x01, 0x35, 0x29, 0x0f, 0x0a, 0x2f, 0x06, 0x80, 0x00, 0x2e, 0x00, 0x40,
0x00, 0xb2, 0x01, 0x2f, 0x44, 0xa9, 0x03, 0x2f, 0x00, 0x30, 0xc0, 0x42,
0x00, 0x43, 0xb8, 0x2e, 0xc2, 0x42, 0x01, 0x43, 0xb8, 0x2e, 0x01, 0x35,
0xa9, 0x0e, 0x0e, 0x2f, 0x03, 0x3b, 0xeb, 0x00, 0xcc, 0xa8, 0x0a, 0x2f,
0x05, 0x86, 0xc2, 0x80, 0xc3, 0x40, 0x02, 0x42, 0x3c, 0x84, 0xc1, 0x80,
0x81, 0x42, 0x82, 0x84, 0xc0, 0x2e, 0x80, 0x42, 0x00, 0x2e, 0xb8, 0x2e,
0x03, 0x2e, 0x1d, 0x01, 0x9f, 0xbc, 0x9f, 0xb8, 0x90, 0x50, 0x40, 0xb2,
0x90, 0x2e, 0x71, 0xb6, 0x12, 0x40, 0x03, 0x30, 0x11, 0x40, 0x80, 0xa8,
0x5a, 0x05, 0x9f, 0x58, 0x55, 0x23, 0x00, 0x40, 0x75, 0x7f, 0x40, 0xa8,
0x16, 0x41, 0xd9, 0x05, 0xcf, 0x23, 0x56, 0x05, 0x40, 0xa9, 0x9d, 0x05,
0x87, 0x7f, 0x6e, 0x23, 0x17, 0x41, 0xa5, 0x7f, 0x3e, 0x8b, 0x04, 0x41,
0x52, 0x43, 0x00, 0xa8, 0x98, 0x05, 0xf2, 0x7f, 0x86, 0x22, 0xcf, 0x05,
0xc0, 0xa9, 0x9f, 0x05, 0xbe, 0x23, 0x04, 0x05, 0x92, 0x7f, 0x00, 0xa9,
0xdc, 0x05, 0x51, 0x43, 0xb6, 0x7f, 0x27, 0x23, 0xa7, 0x54, 0xe1, 0x7f,
0x02, 0x18, 0x7d, 0x83, 0x40, 0x43, 0xeb, 0xba, 0x75, 0xbd, 0xaa, 0x0a,
0x0b, 0x2e, 0x71, 0x00, 0x77, 0x5c, 0x2e, 0x18, 0xf5, 0xbe, 0x6b, 0xbb,
0x75, 0x0b, 0xaa, 0x00, 0xc4, 0x7f, 0x25, 0x2e, 0x71, 0x00, 0xb2, 0x6f,
0xa5, 0x6f, 0xaa, 0x00, 0x54, 0x01, 0x84, 0x6f, 0x72, 0x6f, 0x94, 0x05,
0x80, 0xa9, 0xde, 0x05, 0xb7, 0x23, 0x99, 0x5e, 0x77, 0x0e, 0x41, 0x40,
0x97, 0x5c, 0xb1, 0x01, 0xd5, 0x7f, 0x00, 0x2e, 0x85, 0x41, 0x0e, 0x2f,
0x00, 0xa0, 0x0c, 0x2f, 0x14, 0x0f, 0x04, 0x2f, 0xe0, 0x6f, 0x00, 0xac,
0x10, 0x30, 0x08, 0x2c, 0x18, 0x22, 0xf0, 0x6f, 0x00, 0xac, 0x30, 0x30,
0x24, 0x30, 0x02, 0x2c, 0x20, 0x22, 0x40, 0x30, 0x0d, 0x2e, 0x71, 0x00,
0x80, 0xa1, 0x1e, 0x23, 0x79, 0x5e, 0x37, 0x0f, 0xbc, 0x23, 0x00, 0x90,
0x14, 0x30, 0x10, 0x30, 0x18, 0x2f, 0x9d, 0x50, 0x30, 0x00, 0x9b, 0x56,
0x43, 0x0e, 0x02, 0x2f, 0x10, 0x30, 0x0a, 0x2c, 0x03, 0x30, 0x99, 0x50,
0x10, 0x0e, 0x13, 0x30, 0x00, 0x2f, 0x03, 0x30, 0x90, 0x0f, 0x10, 0x30,
0x00, 0x2f, 0x00, 0x30, 0x00, 0x90, 0x10, 0x30, 0x00, 0x2f, 0x00, 0x30,
0xc0, 0x90, 0x13, 0x30, 0x00, 0x2f, 0x03, 0x30, 0x40, 0xb2, 0x87, 0x5c,
0x22, 0x2f, 0x41, 0x90, 0x4a, 0x2f, 0xa5, 0x50, 0x00, 0x2e, 0x01, 0x40,
0x41, 0x82, 0x01, 0x42, 0x02, 0x80, 0x4a, 0xa8, 0x01, 0x40, 0x06, 0x2f,
0xd0, 0x6f, 0x85, 0x0e, 0x3e, 0x2f, 0x41, 0x80, 0x21, 0x2e, 0x78, 0x00,
0x3b, 0x2d, 0x95, 0x50, 0xfb, 0x7f, 0x4a, 0xa8, 0x06, 0x2f, 0x98, 0x2e,
0x73, 0xb6, 0xc0, 0x90, 0xfb, 0x6f, 0x32, 0x2f, 0x00, 0x2e, 0x30, 0x2d,
0x98, 0x2e, 0x73, 0xb6, 0x29, 0x2e, 0x7a, 0x00, 0x2b, 0x2c, 0xfb, 0x6f,
0xa1, 0x52, 0xd2, 0x6f, 0x95, 0x0e, 0x41, 0x40, 0x05, 0x2f, 0x00, 0x90,
0x17, 0x2f, 0x05, 0x2e, 0x7a, 0x00, 0x80, 0x90, 0x13, 0x2f, 0x7f, 0x82,
0x40, 0xac, 0x23, 0x2e, 0x77, 0x00, 0x01, 0x30, 0x18, 0x2f, 0xa1, 0x54,
0x82, 0x84, 0x23, 0x2e, 0x77, 0x00, 0x82, 0x40, 0x80, 0xb2, 0x11, 0x2f,
0x00, 0x90, 0x23, 0x2e, 0x79, 0x00, 0x0d, 0x2f, 0x29, 0x2e, 0x72, 0x00,
0x0b, 0x2d, 0x41, 0x80, 0x21, 0x2e, 0x77, 0x00, 0x0f, 0xa4, 0x05, 0x2f,
0xa3, 0x50, 0x3e, 0x80, 0xf1, 0x30, 0x29, 0x2e, 0x79, 0x00, 0x01, 0x42,
0x06, 0x30, 0x34, 0x08, 0x00, 0xb2, 0x02, 0x2f, 0x80, 0x30, 0x21, 0x2e,
0x5e, 0xf0, 0x70, 0x5f, 0xb8, 0x2e, 0x04, 0x84, 0x01, 0x30, 0x81, 0x42,
0x82, 0x84, 0x01, 0x42, 0xa1, 0x42, 0x81, 0x42, 0x82, 0x84, 0x00, 0x2e,
0x91, 0x42, 0x81, 0x42, 0xb8, 0x2e, 0x30, 0x50, 0xf3, 0x7f, 0xc0, 0xac,
0xe4, 0x7f, 0xd5, 0x7f, 0x03, 0x2f, 0x00, 0x30, 0x82, 0x04, 0xf3, 0x6f,
0xc3, 0x06, 0x40, 0xad, 0x05, 0x2f, 0xe0, 0x6f, 0x05, 0x30, 0x28, 0x04,
0xd1, 0x6f, 0x69, 0x07, 0xe0, 0x7f, 0x40, 0xa1, 0x01, 0x30, 0x20, 0x2f,
0x13, 0x25, 0x02, 0x25, 0x04, 0x32, 0x06, 0x30, 0x02, 0x30, 0x03, 0x30,
0xaf, 0xbb, 0xb1, 0xbd, 0xdf, 0x0a, 0x9f, 0xbb, 0x21, 0xbd, 0x97, 0x0a,
0x8f, 0xbb, 0x91, 0xbc, 0x01, 0xbc, 0x4f, 0x0a, 0x6b, 0x0e, 0x04, 0x2f,
0x6b, 0x1a, 0x07, 0x2f, 0xe7, 0x6f, 0x7a, 0x0f, 0x04, 0x2f, 0xe7, 0x6f,
0x97, 0x04, 0x17, 0x30, 0x07, 0x0a, 0xdd, 0x06, 0x81, 0x8d, 0x34, 0x0e,
0xe6, 0x2f, 0x00, 0x2e, 0x0d, 0x2d, 0x6b, 0x0e, 0x00, 0x30, 0x05, 0x2f,
0x6b, 0x1a, 0x07, 0x2f, 0xe0, 0x6f, 0x42, 0x0f, 0x00, 0x30, 0x03, 0x2f,
0xe0, 0x6f, 0x90, 0x04, 0xdd, 0x06, 0x10, 0x30, 0xf5, 0x6f, 0xc3, 0x7f,
0xb2, 0x7f, 0x40, 0xad, 0x06, 0x2f, 0x03, 0x30, 0xb2, 0x6f, 0x9a, 0x04,
0xc4, 0x6f, 0xdc, 0x06, 0xb2, 0x7f, 0xc3, 0x7f, 0x00, 0x2e, 0xd2, 0x6f,
0xaa, 0x0c, 0x80, 0xac, 0x02, 0x30, 0x01, 0x2f, 0x10, 0x04, 0x51, 0x06,
0xd0, 0x5f, 0xb8, 0x2e, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00
};
#define BMA4_ACCEL_CONFIG_ADDR (0X40)
#define BMA4_TEMPERATURE_ADDR (0X22)
/**************************************************************/
/**\name Step Counter & Detector */
/**************************************************************/
/**\name Step counter enable macros */
#define BMA423_STEP_CNTR_EN_POS (4)
#define BMA423_STEP_CNTR_EN_MSK (0x10)
#define BMA423_ACTIVITY_EN_MSK (0x20)
/**\name Step counter watermark macros */
#define BMA423_STEP_CNTR_WM_MSK (0x03FF)
/**\name Step counter reset macros */
#define BMA423_STEP_CNTR_RST_POS (2)
#define BMA423_STEP_CNTR_RST_MSK (0x04)
/**\name Step detector enable macros */
#define BMA423_STEP_DETECTOR_EN_POS (3)
#define BMA423_STEP_DETECTOR_EN_MSK (0x08)
/**\name Tilt enable macros */
#define BMA423_TILT_EN_MSK (0x01)
/**\name Step count output length*/
#define BMA423_STEP_CNTR_DATA_SIZE (4)
/**\name Wakeup enable macros */
#define BMA423_WAKEUP_EN_MSK (0x01)
/**\name Wake up sensitivity macros */
#define BMA423_WAKEUP_SENS_POS (1)
#define BMA423_WAKEUP_SENS_MSK (0x0E)
/**\name Tap selection macro */
#define BMA423_TAP_SEL_POS (4)
#define BMA423_TAP_SEL_MSK (0x10)
/**************************************************************/
/**\name Any Motion */
/**************************************************************/
/**\name Any motion threshold macros */
#define BMA423_ANY_NO_MOTION_THRES_POS (0)
#define BMA423_ANY_NO_MOTION_THRES_MSK (0x07FF)
/**\name Any motion selection macros */
#define BMA423_ANY_NO_MOTION_SEL_POS (3)
#define BMA423_ANY_NO_MOTION_SEL_MSK (0x08)
/**\name Any motion enable macros */
#define BMA423_ANY_NO_MOTION_AXIS_EN_POS (5)
#define BMA423_ANY_NO_MOTION_AXIS_EN_MSK (0xE0)
/**\name Any motion duration macros */
#define BMA423_ANY_NO_MOTION_DUR_MSK (0x1FFF)
/**\name INTERRUPT MAPS */
#define BMA4_INTR1_MAP (0)
#define BMA4_INTR2_MAP (1)
/**\name INTERRUPT ENABLE REGISTERS*/
#define BMA4_INT1_IO_CTRL_ADDR (0X53)
#define BMA4_INT2_IO_CTRL_ADDR (0X54)
/**\name LATCH DURATION REGISTERS*/
#define BMA4_INTR_LATCH_ADDR (0X55)
/**\name CONSTANTS */
#define BMA4_FIFO_CONFIG_LENGTH (2)
#define BMA4_ACCEL_CONFIG_LENGTH (2)
#define BMA4_FIFO_WM_LENGTH (2)
#define BMA4_CONFIG_STREAM_SIZE (6144)
#define BMA4_NON_LATCH_MODE (0)
#define BMA4_LATCH_MODE (1)
#define BMA4_OPEN_DRAIN (1)
#define BMA4_PUSH_PULL (0)
#define BMA4_ACTIVE_HIGH (1)
#define BMA4_ACTIVE_LOW (0)
#define BMA4_EDGE_TRIGGER (1)
#define BMA4_LEVEL_TRIGGER (0)
#define BMA4_OUTPUT_ENABLE (1)
#define BMA4_OUTPUT_DISABLE (0)
#define BMA4_INPUT_ENABLE (1)
#define BMA4_INPUT_DISABLE (0)
/**\name OUTPUT TYPE ENABLE POSITION AND MASK*/
#define BMA4_INT_EDGE_CTRL_MASK (0x01)
#define BMA4_INT_EDGE_CTRL_POS (0x00)
#define BMA4_INT_LEVEL_MASK (0x02)
#define BMA4_INT_LEVEL_POS (0x01)
#define BMA4_INT_OPEN_DRAIN_MASK (0x04)
#define BMA4_INT_OPEN_DRAIN_POS (0x02)
#define BMA4_INT_OUTPUT_EN_MASK (0x08)
#define BMA4_INT_OUTPUT_EN_POS (0x03)
#define BMA4_INT_INPUT_EN_MASK (0x10)
#define BMA4_INT_INPUT_EN_POS (0x04)
/**\name Interrupt status macros */
#define BMA423_STEP_CNTR_INT (0x02)
#define BMA423_ACTIVITY_INT (0x04)
#define BMA423_TILT_INT (0x08)
#define BMA423_WAKEUP_INT (0x20)
#define BMA423_ANY_NO_MOTION_INT (0x40)
#define BMA423_ERROR_INT (0x80)

View File

@ -0,0 +1,66 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file CHSC5816Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-17
*
*/
#pragma once
#define CHSC5816_SLAVE_ADDRESS (0x2E)
#define CHSC5816_REG_CMD_BUFF (0x20000000U)
#define CHSC5816_REG_RSP_BUFF (0x20000000U)
#define CHSC5816_REG_IMG_HEAD (0x20000014U)
#define CHSC5816_REG_POINT (0x2000002CU)
#define CHSC5816_REG_WR_BUFF (0x20002000U)
#define CHSC5816_REG_RD_BUFF (0x20002400U)
#define CHSC5816_REG_HOLD_MCU (0x40007000U)
#define CHSC5816_REG_AUTO_FEED (0x40007010U)
#define CHSC5816_REG_REMAP_MCU (0x40007000U)
#define CHSC5816_REG_RELEASE_MCU (0x40007000U)
#define CHSC5816_REG_BOOT_STATE (0x20000018U)
#define CHSC5816_HOLD_MCU_VAL (0x12044000U)
#define CHSC5816_AUTO_FEED_VAL (0x0000925aU)
#define CHSC5816_REMAP_MCU_VAL (0x12044002U)
#define CHSC5816_RELEASE_MCU_VAL (0x12044003U)
#define CHSC5816_REG_VID_PID_BACKUP (40 * 1024 + 0x10U)
#define CHSC5816_SIG_VALUE (0x43534843U)
/*ctp work staus*/
#define CHSC5816_POINTING_WORK (0x00000000U)
#define CHSC5816_READY_UPGRADE (1 << 1)
#define CHSC5816_UPGRAD_RUNING (1 << 2)
#define CHSC5816_SLFTEST_RUNING (1 << 3)
#define CHSC5816_SUSPEND_GATE (1 << 16)
#define CHSC5816_GUESTURE_GATE (1 << 17)
#define CHSC5816_PROXIMITY_GATE (1 << 18)
#define CHSC5816_GLOVE_GATE (1 << 19)
#define CHSC5816_ORIENTATION_GATE (1 << 20)

View File

@ -0,0 +1,62 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file CM32181Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-14
*
*/
#pragma once
#define CM32181_SLAVE_ADDRESS (0x10)
// CM32181 slave address can be 0x10 or 0x48, determined by pin ADDR configuration
#define CM32181_ADDR_ALS (0x10) // 7-bit
#define CM32181_ADDR_ALS1 (0x48) // 7-bit
// CM32181 registers
#define CM32181_REG_ALS_CONF (uint8_t)(0x00)
#define CM32181_REG_ALS_THDH (uint8_t)(0x01)
#define CM32181_REG_ALS_THDL (uint8_t)(0x02)
#define CM32181_REG_ALS_PSM (uint8_t)(0x03)
#define CM32181_REG_ALS_DATA (uint8_t)(0x04)
#define CM32181_REG_ALS_STATUS (uint8_t)(0x06)
#define CM32181_REG_ID (uint8_t)(0x07)
#define CM32181_CHIP_ID (0x81)

View File

@ -0,0 +1,46 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file CSTxxxConstants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-24
*
*/
#pragma once
#define CSTXXX_SLAVE_ADDRESS (0x15)
#define CST816_SLAVE_ADDRESS (0x15)
#define CST328_SLAVE_ADDRESS (0x1A)
#define CST226SE_SLAVE_ADDRESS (0x5A)
#define CST816S_CHIP_ID (0xB4)
#define CST816T_CHIP_ID (0xB5)
#define CST716_CHIP_ID (0x20)
#define CST226SE_CHIP_ID (0xA8)

View File

@ -0,0 +1,80 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file DRV2605Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-03
*
*/
#pragma once
#define DRV2605_SLAVE_ADDRESS (0x5A)
#define DRV2604_CHIP_ID (0x04) //* DRV2604 (contains RAM, does not contain licensed ROM library)
#define DRV2605_CHIP_ID (0x03) //* DRV2605 (contains licensed ROM library, does not contain RAM)
#define DRV2604L_CHIP_ID (0x06) //* DRV2604L (low-voltage version of the DRV2604 device)
#define DRV2605L_CHIP_ID (0x07) //* DRV2605L (low-voltage version of the DRV2605 device)
#define DRV2605_REG_STATUS (0x00) //* Status register
#define DRV2605_REG_MODE (0x01) //* Mode register
#define DRV2605_MODE_INTTRIG (0x00) //* Internal trigger mode
#define DRV2605_MODE_EXTTRIGEDGE (0x01) //* External edge trigger mode
#define DRV2605_MODE_EXTTRIGLVL (0x02) //* External level trigger mode
#define DRV2605_MODE_PWMANALOG (0x03) //* PWM/Analog input mode
#define DRV2605_MODE_AUDIOVIBE (0x04) //* Audio-to-vibe mode
#define DRV2605_MODE_REALTIME (0x05) //* Real-time playback (RTP) mode
#define DRV2605_MODE_DIAGNOS (0x06) //* Diagnostics mode
#define DRV2605_MODE_AUTOCAL (0x07) //* Auto calibration mode
#define DRV2605_REG_RTPIN (0x02) //* Real-time playback input register
#define DRV2605_REG_LIBRARY (0x03) //* Waveform library selection register
#define DRV2605_REG_WAVESEQ1 (0x04) //* Waveform sequence register 1
#define DRV2605_REG_WAVESEQ2 (0x05) //* Waveform sequence register 2
#define DRV2605_REG_WAVESEQ3 (0x06) //* Waveform sequence register 3
#define DRV2605_REG_WAVESEQ4 (0x07) //* Waveform sequence register 4
#define DRV2605_REG_WAVESEQ5 (0x08) //* Waveform sequence register 5
#define DRV2605_REG_WAVESEQ6 (0x09) //* Waveform sequence register 6
#define DRV2605_REG_WAVESEQ7 (0x0A) //* Waveform sequence register 7
#define DRV2605_REG_WAVESEQ8 (0x0B) //* Waveform sequence register 8
#define DRV2605_REG_GO (0x0C) //* Go register
#define DRV2605_REG_OVERDRIVE (0x0D) //* Overdrive time offset register
#define DRV2605_REG_SUSTAINPOS (0x0E) //* Sustain time offset, positive register
#define DRV2605_REG_SUSTAINNEG (0x0F) //* Sustain time offset, negative register
#define DRV2605_REG_BREAK (0x10) //* Brake time offset register
#define DRV2605_REG_AUDIOCTRL (0x11) //* Audio-to-vibe control register
#define DRV2605_REG_AUDIOLVL (0x12) //* Audio-to-vibe minimum input level register
#define DRV2605_REG_AUDIOMAX (0x13) //* Audio-to-vibe maximum input level register
#define DRV2605_REG_AUDIOOUTMIN (0x14) //* Audio-to-vibe minimum output drive register
#define DRV2605_REG_AUDIOOUTMAX (0x15) //* Audio-to-vibe maximum output drive register
#define DRV2605_REG_RATEDV (0x16) //* Rated voltage register
#define DRV2605_REG_CLAMPV (0x17) //* Overdrive clamp voltage register
#define DRV2605_REG_AUTOCALCOMP (0x18) //* Auto-calibration compensation result register
#define DRV2605_REG_AUTOCALEMP (0x19) //* Auto-calibration back-EMF result register
#define DRV2605_REG_FEEDBACK (0x1A) //* Feedback control register
#define DRV2605_REG_CONTROL1 (0x1B) //* Control1 Register
#define DRV2605_REG_CONTROL2 (0x1C) //* Control2 Register
#define DRV2605_REG_CONTROL3 (0x1D) //* Control3 Register
#define DRV2605_REG_CONTROL4 (0x1E) //* Control4 Register
#define DRV2605_REG_VBAT (0x21) //* Vbat voltage-monitor register
#define DRV2605_REG_LRARESON (0x22) //* LRA resonance-period register

View File

@ -0,0 +1,65 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file FT6X36Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-01
*
*/
#pragma once
#define FT3267_SLAVE_ADDRESS (0x38)
#define FT5206_SLAVE_ADDRESS (0x38)
#define FT6X36_SLAVE_ADDRESS (0x38)
#define FT6X36_VEND_ID (0x11)
#define FT3267_CHIP_ID (0x33)
#define FT6206_CHIP_ID (0x06)
#define FT6236_CHIP_ID (0x36)
#define FT6236U_CHIP_ID (0x64)
#define FT5206U_CHIP_ID (0x64)
#define FT6X36_REG_MODE (0x00)
#define FT6X36_REG_GEST (0x01)
#define FT6X36_REG_STATUS (0x02)
#define FT6X36_REG_TOUCH1_XH (0x03)
#define FT6X36_REG_TOUCH1_XL (0x04)
#define FT6X36_REG_TOUCH1_YH (0x05)
#define FT6X36_REG_TOUCH1_YL (0x06)
#define FT6X36_REG_THRESHOLD (0x80)
#define FT6X36_REG_MONITOR_TIME (0x87)
#define FT6X36_REG_PERIOD_ACTIVE (0x88)
#define FT6X36_REG_PERIOD_MONITOR (0x89)
#define FT6X36_REG_AUTO_CLB_MODE (0xA0)
#define FT6X36_REG_LIB_VERSION_H (0xA1)
#define FT6X36_REG_LIB_VERSION_L (0xA2)
#define FT6X36_REG_INT_STATUS (0xA4)
#define FT6X36_REG_POWER_MODE (0xA5)
#define FT6X36_REG_FIRM_VERS (0xA6)
#define FT6X36_REG_CHIP_ID (0xA3)
#define FT6X36_REG_VENDOR1_ID (0xA8)
#define FT6X36_REG_ERROR_STATUS (0xA9)

View File

@ -0,0 +1,156 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file GT911Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-12
*
*/
#pragma once
#define GT911_SLAVE_ADDRESS_H (0x14)
#define GT911_SLAVE_ADDRESS_L (0x5D)
// Real-time command (Write only)
#define GT911_COMMAND (0x8040)
#define GT911_ESD_CHECK (0x8041)
#define GT911_COMMAND_CHECK (0x8046)
// Configuration information (R/W)
#define GT911_CONFIG_START (0x8047)
#define GT911_CONFIG_VERSION (0x8047)
#define GT911_X_OUTPUT_MAX_LOW (0x8048)
#define GT911_X_OUTPUT_MAX_HIGH (0x8049)
#define GT911_Y_OUTPUT_MAX_LOW (0x804A)
#define GT911_Y_OUTPUT_MAX_HIGH (0x804B)
#define GT911_TOUCH_NUMBER (0x804C)
#define GT911_MODULE_SWITCH_1 (0x804D)
#define GT911_MODULE_SWITCH_2 (0x804E)
#define GT911_SHAKE_COUNT (0x804F)
#define GT911_FILTER (0x8050)
#define GT911_LARGE_TOUCH (0x8051)
#define GT911_NOISE_REDUCTION (0x8052)
#define GT911_SCREEN_TOUCH_LEVEL (0x8053)
#define GT911_SCREEN_RELEASE_LEVEL (0x8054)
#define GT911_LOW_POWER_CONTROL (0x8055)
#define GT911_REFRESH_RATE (0x8056)
#define GT911_X_THRESHOLD (0x8057)
#define GT911_Y_THRESHOLD (0x8058)
#define GT911_X_SPEED_LIMIT (0x8059) // Reserve
#define GT911_Y_SPEED_LIMIT (0x805A) // Reserve
#define GT911_SPACE_TOP_BOTTOM (0x805B)
#define GT911_SPACE_LEFT_RIGHT (0x805C)
#define GT911_MINI_FILTER (0x805D)
#define GT911_STRETCH_R0 (0x805E)
#define GT911_STRETCH_R1 (0x805F)
#define GT911_STRETCH_R2 (0x8060)
#define GT911_STRETCH_RM (0x8061)
#define GT911_DRV_GROUPA_NUM (0x8062)
#define GT911_DRV_GROUPB_NUM (0x8063)
#define GT911_SENSOR_NUM (0x8064)
#define GT911_FREQ_A_FACTOR (0x8065)
#define GT911_FREQ_B_FACTOR (0x8066)
#define GT911_PANEL_BIT_FREQ_L (0x8067)
#define GT911_PANEL_BIT_FREQ_H (0x8068)
#define GT911_PANEL_SENSOR_TIME_L (0x8069) // Reserve
#define GT911_PANEL_SENSOR_TIME_H (0x806A)
#define GT911_PANEL_TX_GAIN (0x806B)
#define GT911_PANEL_RX_GAIN (0x806C)
#define GT911_PANEL_DUMP_SHIFT (0x806D)
#define GT911_DRV_FRAME_CONTROL (0x806E)
#define GT911_CHARGING_LEVEL_UP (0x806F)
#define GT911_MODULE_SWITCH3 (0x8070)
#define GT911_GESTURE_DIS (0X8071)
#define GT911_GESTURE_LONG_PRESS_TIME (0x8072)
#define GT911_X_Y_SLOPE_ADJUST (0X8073)
#define GT911_GESTURE_CONTROL (0X8074)
#define GT911_GESTURE_SWITCH1 (0X8075)
#define GT911_GESTURE_SWITCH2 (0X8076)
#define GT911_GESTURE_REFRESH_RATE (0x8077)
#define GT911_GESTURE_TOUCH_LEVEL (0x8078)
#define GT911_NEWGREENWAKEUPLEVEL (0x8079)
#define GT911_FREQ_HOPPING_START (0x807A)
#define GT911_FREQ_HOPPING_END (0X807B)
#define GT911_NOISE_DETECT_TIMES (0x807C)
#define GT911_HOPPING_FLAG (0X807D)
#define GT911_HOPPING_THRESHOLD (0X807E)
#define GT911_NOISE_THRESHOLD (0X807F) // Reserve
#define GT911_NOISE_MIN_THRESHOLD (0X8080)
#define GT911_HOPPING_SENSOR_GROUP (0X8082)
#define GT911_HOPPING_SEG1_NORMALIZE (0X8083)
#define GT911_HOPPING_SEG1_FACTOR (0X8084)
#define GT911_MAIN_CLOCK_AJDUST (0X8085)
#define GT911_HOPPING_SEG2_NORMALIZE (0X8086)
#define GT911_HOPPING_SEG2_FACTOR (0X8087)
#define GT911_HOPPING_SEG3_NORMALIZE (0X8089)
#define GT911_HOPPING_SEG3_FACTOR (0X808A)
#define GT911_HOPPING_SEG4_NORMALIZE (0X808C)
#define GT911_HOPPING_SEG4_FACTOR (0X808D)
#define GT911_HOPPING_SEG5_NORMALIZE (0X808F)
#define GT911_HOPPING_SEG5_FACTOR (0X8090)
#define GT911_HOPPING_SEG6_NORMALIZE (0X8092)
#define GT911_KEY_1 (0X8093)
#define GT911_KEY_2 (0X8094)
#define GT911_KEY_3 (0X8095)
#define GT911_KEY_4 (0X8096)
#define GT911_KEY_AREA (0X8097)
#define GT911_KEY_TOUCH_LEVEL (0X8098)
#define GT911_KEY_LEAVE_LEVEL (0X8099)
#define GT911_KEY_SENS_1_2 (0X809A)
#define GT911_KEY_SENS_3_4 (0X809B)
#define GT911_KEY_RESTRAIN (0X809C)
#define GT911_KEY_RESTRAIN_TIME (0X809D)
#define GT911_GESTURE_LARGE_TOUCH (0X809E)
#define GT911_HOTKNOT_NOISE_MAP (0X80A1)
#define GT911_LINK_THRESHOLD (0X80A2)
#define GT911_PXY_THRESHOLD (0X80A3)
#define GT911_GHOT_DUMP_SHIFT (0X80A4)
#define GT911_GHOT_RX_GAIN (0X80A5)
#define GT911_FREQ_GAIN0 (0X80A6)
#define GT911_FREQ_GAIN1 (0X80A7)
#define GT911_FREQ_GAIN2 (0X80A8)
#define GT911_FREQ_GAIN3 (0X80A9)
#define GT911_COMBINE_DIS (0X80B3)
#define GT911_SPLIT_SET (0X80B4)
#define GT911_SENSOR_CH0 (0X80B7)
#define GT911_DRIVER_CH0 (0X80D5)
#define GT911_CONFIG_CHKSUM (0X80FF)
#define GT911_CONFIG_FRESH (0X8100)
#define GT911_CONFIG_SIZE (0xFF - 0x46)
// Coordinate information
#define GT911_PRODUCT_ID (0x8140)
#define GT911_FIRMWARE_VERSION (0x8144)
#define GT911_X_RESOLUTION (0x8146)
#define GT911_Y_RESOLUTION (0x8148)
#define GT911_VENDOR_ID (0X8140)
#define GT911_IMFORMATION (0X8140)
#define GT911_POINT_INFO (0X814E)
#define GT911_POINT_1 (0X814F)
#define GT911_POINT_2 (0X8157)
#define GT911_POINT_3 (0X815F)
#define GT911_POINT_4 (0X8167)
#define GT911_POINT_5 (0X816F)

View File

@ -0,0 +1,63 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* 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.
*
* @file LTR533Constants.tpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-09
*/
#pragma once
#define LTR553_SLAVE_ADDRESS (0x23)
#define LTR553_REG_ALS_CONTR (0x80)
#define LTR553_REG_PS_CONTR (0x81)
#define LTR553_REG_PS_LED (0x82)
#define LTR553_REG_PS_N_PULSES (0x83)
#define LTR553_REG_PS_MEAS_RATE (0x84)
#define LTR553_REG_ALS_MEAS_RATE (0x85)
#define LTR553_REG_PART_ID (0x86)
#define LTR553_REG_MANUFAC_ID (0x87)
#define LTR553_REG_ALS_DATA_CH1_0 (0x88)
#define LTR553_REG_ALS_DATA_CH1_1 (0x89)
#define LTR553_REG_ALS_DATA_CH0_0 (0x8A)
#define LTR553_REG_ALS_DATA_CH0_1 (0x8B)
#define LTR553_REG_ALS_PS_STATUS (0x8C)
#define LTR553_REG_PS_DATA_0 (0x8D)
#define LTR553_REG_PS_DATA_1 (0x8E)
#define LTR553_REG_INTERRUPT (0x8F)
#define LTR553_REG_PS_THRES_UP_0 (0x90)
#define LTR553_REG_PS_THRES_UP_1 (0x91)
#define LTR553_REG_PS_THRES_LOW_0 (0x92)
#define LTR553_REG_PS_THRES_LOW_1 (0x93)
#define LTR553_REG_PS_OFFSET_1 (0x94)
#define LTR553_REG_PS_OFFSET_0 (0x95)
#define LTR553_REG_ALS_THRES_UP_0 (0x97)
#define LTR553_REG_ALS_THRES_UP_1 (0x98)
#define LTR553_REG_ALS_THRES_LOW_0 (0x99)
#define LTR553_REG_ALS_THRES_LOW_1 (0x9A)
#define LTR553_REG_INTERRUPT_PERSIST (0x9E)
#define LTR553_DEFAULT_MAN_ID (0x05)

View File

@ -0,0 +1,115 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file MPU6886Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#pragma once
#define MPU6886_SLAVE_ADDRESS (0x68)
#define MPU6886_REG_XG_OFFS_TC_H (0x04)
#define MPU6886_REG_XG_OFFS_TC_L (0x05)
#define MPU6886_REG_YG_OFFS_TC_H (0x07)
#define MPU6886_REG_YG_OFFS_TC_L (0x08)
#define MPU6886_REG_ZG_OFFS_TC_H (0x0A)
#define MPU6886_REG_ZG_OFFS_TC_L (0x0B)
#define MPU6886_REG_SELF_TEST_X_ACCEL (0x0D)
#define MPU6886_REG_SELF_TEST_Y_ACCEL (0x0E)
#define MPU6886_REG_SELF_TEST_Z_ACCEL (0x0F)
#define MPU6886_REG_XG_OFFS_USRH (0x13)
#define MPU6886_REG_XG_OFFS_USRL (0x14)
#define MPU6886_REG_YG_OFFS_USRH (0x15)
#define MPU6886_REG_YG_OFFS_USRL (0x16)
#define MPU6886_REG_ZG_OFFS_USRH (0x17)
#define MPU6886_REG_ZG_OFFS_USRL (0x18)
#define MPU6886_REG_SMPLRT_DIV (0x19)
#define MPU6886_REG_CONFIG (0x1A)
#define MPU6886_REG_GYRO_CONFIG (0x1B)
#define MPU6886_REG_ACCEL_CONFIG (0x1C)
#define MPU6886_REG_ACCEL_CONFIG_2 (0x1D)
#define MPU6886_REG_LP_MODE_CFG (0x1E)
#define MPU6886_REG_ACCEL_WOM_X_THR (0x20)
#define MPU6886_REG_ACCEL_WOM_Y_THR (0x21)
#define MPU6886_REG_ACCEL_WOM_Z_THR (0x22)
#define MPU6886_REG_FIFO_EN (0x23)
#define MPU6886_REG_FSYNC_INT (0x36)
#define MPU6886_REG_INT_PIN_CFG (0x37)
#define MPU6886_REG_INT_ENABLE (0x38)
#define MPU6886_REG_FIFO_WM_INT_STATUS (0x39)
#define MPU6886_REG_INT_STATUS (0x3A)
#define MPU6886_REG_ACCEL_XOUT_H (0x3B)
#define MPU6886_REG_ACCEL_XOUT_L (0x3C)
#define MPU6886_REG_ACCEL_YOUT_H (0x3D)
#define MPU6886_REG_ACCEL_YOUT_L (0x3E)
#define MPU6886_REG_ACCEL_ZOUT_H (0x3F)
#define MPU6886_REG_ACCEL_ZOUT_L (0x40)
#define MPU6886_REG_TEMP_OUT_H (0x41)
#define MPU6886_REG_TEMP_OUT_L (0x42)
#define MPU6886_REG_GYRO_XOUT_H (0x43)
#define MPU6886_REG_GYRO_XOUT_L (0x44)
#define MPU6886_REG_GYRO_YOUT_H (0x45)
#define MPU6886_REG_GYRO_YOUT_L (0x46)
#define MPU6886_REG_GYRO_ZOUT_H (0x47)
#define MPU6886_REG_GYRO_ZOUT_L (0x48)
#define MPU6886_REG_SELF_TEST_X_GYRO (0x50)
#define MPU6886_REG_SELF_TEST_Y_GYRO (0x51)
#define MPU6886_REG_SELF_TEST_Z_GYRO (0x52)
#define MPU6886_REG_E_ID0 (0x53)
#define MPU6886_REG_E_ID1 (0x54)
#define MPU6886_REG_E_ID2 (0x55)
#define MPU6886_REG_E_ID3 (0x56)
#define MPU6886_REG_E_ID4 (0x57)
#define MPU6886_REG_E_ID5 (0x58)
#define MPU6886_REG_E_ID6 (0x59)
#define MPU6886_REG_FIFO_WM_TH1 (0x60)
#define MPU6886_REG_FIFO_WM_TH2 (0x61)
#define MPU6886_REG_SIGNAL_PATH_RESET (0x68)
#define MPU6886_REG_ACCEL_INTEL_CTRL (0x69)
#define MPU6886_REG_USER_CTRL (0x6A)
#define MPU6886_REG_PWR_MGMT_1 (0x6B)
#define MPU6886_REG_PWR_MGMT_2 (0x6C)
#define MPU6886_REG_I2C_IF (0x70)
#define MPU6886_REG_FIFO_COUNTH (0x72)
#define MPU6886_REG_FIFO_COUNTL (0x73)
#define MPU6886_REG_FIFO_R_W (0x74)
#define MPU6886_REG_WHO_AM_I (0x75)
#define MPU6886_REG_XA_OFFSET_H (0x77)
#define MPU6886_REG_XA_OFFSET_L (0x78)
#define MPU6886_REG_YA_OFFSET_H (0x7A)
#define MPU6886_REG_YA_OFFSET_L (0x7B)
#define MPU6886_REG_ZA_OFFSET_H (0x7D)
#define MPU6886_REG_ZA_OFFSET_L (0x7E)
#define MPU6886_WHO_AM_I_RES (0x19)

View File

@ -0,0 +1,63 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file PCF85063Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-07
*
*/
#pragma once
#define PCF85063_SLAVE_ADDRESS (0x51)
#define PCF85063_CTRL1_REG (0x00)
#define PCF85063_CTRL2_REG (0x01)
#define PCF85063_OFFSET_REG (0x02)
#define PCF85063_RAM_REG (0x03)
#define PCF85063_SEC_REG (0x04)
#define PCF85063_MIN_REG (0x05)
#define PCF85063_HR_REG (0x06)
#define PCF85063_DAY_REG (0x07)
#define PCF85063_WEEKDAY_REG (0x08)
#define PCF85063_MONTH_REG (0x09)
#define PCF85063_YEAR_REG (0x0A)
#define PCF85063_ALRM_SEC_REG (0x0B)
#define PCF85063_ALRM_MIN_REG (0x0C)
#define PCF85063_ALRM_HR_REG (0x0D)
#define PCF85063_ALRM_DAY_REG (0x0E)
#define PCF85063_ALRM_WEEK_REG (0x0F)
#define PCF85063_TIMER_VAL_REG (0x10)
#define PCF85063_TIMER_MD_REG (0x11)
#define PCF85063_CTRL1_TEST_EN_MASK (1<<7u)
#define PCF85063_CTRL1_CLOCK_EN_MASK (1<<5u)
#define PCF85063_CTRL1_SOFTRST_EN_MASK (1<<4u)
#define PCF85063_CTRL1_CIE_EN_MASK (1<<2u)
#define PCF85063_CTRL1_HOUR_FORMAT_12H_MASK (1<<1u)
#define PCF85063_NO_ALARM (0xFF)
#define PCF85063_ALARM_ENABLE (0x80)

View File

@ -0,0 +1,70 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file PCF8563Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2022-12-09
*
*/
#pragma once
#define PCF8563_SLAVE_ADDRESS (0x51)
#define PCF8563_STAT1_REG (0x00)
#define PCF8563_STAT2_REG (0x01)
#define PCF8563_SEC_REG (0x02)
#define PCF8563_MIN_REG (0x03)
#define PCF8563_HR_REG (0x04)
#define PCF8563_DAY_REG (0x05)
#define PCF8563_WEEKDAY_REG (0x06)
#define PCF8563_MONTH_REG (0x07)
#define PCF8563_YEAR_REG (0x08)
#define PCF8563_ALRM_MIN_REG (0x09)
#define PCF8563_SQW_REG (0x0D)
#define PCF8563_TIMER1_REG (0x0E)
#define PCF8563_TIMER2_REG (0x0F)
#define PCF8563_VOL_LOW_MASK (0x80)
#define PCF8563_MINUTES_MASK (0x7F)
#define PCF8563_HOUR_MASK (0x3F)
#define PCF8563_WEEKDAY_MASK (0x07)
#define PCF8563_CENTURY_MASK (0x80)
#define PCF8563_DAY_MASK (0x3F)
#define PCF8563_MONTH_MASK (0x1F)
#define PCF8563_TIMER_CTL_MASK (0x03)
#define PCF8563_ALARM_AF (0x08)
#define PCF8563_TIMER_TF (0x04)
#define PCF8563_ALARM_AIE (0x02)
#define PCF8563_TIMER_TIE (0x01)
#define PCF8563_TIMER_TE (0x80)
#define PCF8563_TIMER_TD10 (0x03)
#define PCF8563_NO_ALARM (0xFF)
#define PCF8563_ALARM_ENABLE (0x80)
#define PCF8563_CLK_ENABLE (0x80)

View File

@ -0,0 +1,53 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMC6310Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#pragma once
// @brief device address
#define QMC6310_SLAVE_ADDRESS (0x1C)
#define QMC6310_DEFAULT_ID (0x80)
#define QMC6310_REG_CHIP_ID (0x00)
#define QMC6310_REG_LSB_DX (0X01)
#define QMC6310_REG_MSB_DX (0X02)
#define QMC6310_REG_LSB_DY (0X03)
#define QMC6310_REG_MSB_DY (0X04)
#define QMC6310_REG_LSB_DZ (0X05)
#define QMC6310_REG_MSB_DZ (0X06)
#define QMC6310_REG_STAT (0X09)
#define QMC6310_REG_CMD1 (0x0A)
#define QMC6310_REG_CMD2 (0x0B)
#define QMC6310_REG_SIGN (0x29)

View File

@ -0,0 +1,133 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file QMI8658Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#pragma once
// @brief device address
#define QMI8658_L_SLAVE_ADDRESS (0x6B)
#define QMI8658_H_SLAVE_ADDRESS (0x6A)
// @brief registers default value
#define QMI8658_REG_WHOAMI_DEFAULT (0x05)
#define QMI8658_REG_STATUS_DEFAULT (0x03)
#define QMI8658_REG_RESET_DEFAULT (0xB0)
// @brief registers list
#define QMI8658_REG_WHOAMI (0x00)
#define QMI8658_REG_REVISION (0x01)
#define QMI8658_REG_CTRL1 (0x02)
#define QMI8658_REG_CTRL2 (0x03)
#define QMI8658_REG_CTRL3 (0x04)
// #define QMI8658_REG_CTRL4 (0x05)
#define QMI8658_REG_CTRL5 (0x06)
// #define QMI8658_REG_CTRL6 (0x07)
#define QMI8658_REG_CTRL7 (0x08)
#define QMI8658_REG_CTRL8 (0x09)
#define QMI8658_REG_CTRL9 (0x0A)
#define QMI8658_REG_CAL1_L (0x0B)
#define QMI8658_REG_CAL1_H (0x0C)
#define QMI8658_REG_CAL2_L (0x0D)
#define QMI8658_REG_CAL2_H (0x0E)
#define QMI8658_REG_CAL3_L (0x0F)
#define QMI8658_REG_CAL3_H (0x10)
#define QMI8658_REG_CAL4_L (0x11)
#define QMI8658_REG_CAL4_H (0x12)
#define QMI8658_REG_FIFOWMKTH (0x13)
#define QMI8658_REG_FIFOCTRL (0x14)
#define QMI8658_REG_FIFOCOUNT (0x15)
#define QMI8658_REG_FIFOSTATUS (0x16)
#define QMI8658_REG_FIFODATA (0x17)
// #define QMI8658_REG_STATUSI2CM (0x2C)
#define QMI8658_REG_STATUSINT (0x2D)
#define QMI8658_REG_STATUS0 (0x2E)
#define QMI8658_REG_STATUS1 (0x2F)
#define QMI8658_REG_TIMESTAMP_L (0x30)
#define QMI8658_REG_TIMESTAMP_M (0x31)
#define QMI8658_REG_TIMESTAMP_H (0x32)
#define QMI8658_REG_TEMPEARTURE_L (0x33)
#define QMI8658_REG_TEMPEARTURE_H (0x34)
#define QMI8658_REG_AX_L (0x35)
#define QMI8658_REG_AX_H (0x36)
#define QMI8658_REG_AY_L (0x37)
#define QMI8658_REG_AY_H (0x38)
#define QMI8658_REG_AZ_L (0x39)
#define QMI8658_REG_AZ_H (0x3A)
#define QMI8658_REG_GX_L (0x3B)
#define QMI8658_REG_GX_H (0x3C)
#define QMI8658_REG_GY_L (0x3D)
#define QMI8658_REG_GY_H (0x3E)
#define QMI8658_REG_GZ_L (0x3F)
#define QMI8658_REG_GZ_H (0x40)
#define QMI8658_REG_COD_STATUS (0x46)
#define QMI8658_REG_DQW_L (0x49)
#define QMI8658_REG_DQW_H (0x4A)
#define QMI8658_REG_DQX_L (0x4B)
#define QMI8658_REG_DQX_H (0x4C)
#define QMI8658_REG_DQY_L (0x4D)
#define QMI8658_REG_DQY_H (0x4E)
#define QMI8658_REG_DQZ_L (0x4F)
#define QMI8658_REG_DQZ_H (0x50)
#define QMI8658_REG_DVX_L (0x51)
#define QMI8658_REG_DVX_H (0x52)
#define QMI8658_REG_DVY_L (0x53)
#define QMI8658_REG_DVY_H (0x54)
#define QMI8658_REG_DVZ_L (0x55)
#define QMI8658_REG_DVZ_H (0x56)
#define QMI8658_REG_TAP_STATUS (0x59)
#define QMI8658_REG_PEDO_L (0x5A)
#define QMI8658_REG_PEDO_M (0x5B)
#define QMI8658_REG_PEDO_H (0x5C)
#define QMI8658_REG_RESET (0x60)
#define QMI8658_REG_RST_RESULT (0x4D)
#define QMI8658_REG_RST_RESULT_VAL (0x80)
#define STATUS0_ACCE_AVAIL (0x01)
#define STATUS0_GYRO_AVAIL (0x02)
#define QMI8658_ACCEL_LPF_MASK (0xF9)
#define QMI8658_GYRO_LPF_MASK (0x9F)
#define QMI8658_ACCEL_EN_MASK (0x01)
#define QMI8658_GYRO_EN_MASK (0x02)
#define QMI8658_ACCEL_GYRO_EN_MASK (0x03)
#define QMI8658_FIFO_MAP_INT1 0x04 // ctrl1

View File

@ -0,0 +1,32 @@
#pragma once
// A0, A1, A2 connect to GND
#define XL9555_SLAVE_ADDRESS0 (0x20)
#define XL9555_SLAVE_ADDRESS1 (0x21)
#define XL9555_SLAVE_ADDRESS2 (0x22)
#define XL9555_SLAVE_ADDRESS3 (0x23)
#define XL9555_SLAVE_ADDRESS4 (0x24)
#define XL9555_SLAVE_ADDRESS5 (0x25)
#define XL9555_SLAVE_ADDRESS6 (0x26)
#define XL9555_SLAVE_ADDRESS7 (0x27)
// Input Port 0 /R
#define XL9555_CTRL_INP0 (0x00)
// Input Port 1 /R
#define XL9555_CTRL_INP1 (0x01)
// Output Port 0 /RW
#define XL9555_CTRL_OUTP0 (0x02)
// Output Port 1 /RW
#define XL9555_CTRL_OUTP1 (0x03)
// Polarity Inversion Port 0 /RW
#define XL9555_CTRL_PIP0 (0x04)
// Polarity Inversion Port 1 /RW
#define XL9555_CTRL_PIP1 (0x05)
// Configuration Port 0 /RW
#define XL9555_CTRL_CFG0 (0x06)
// Configuration Port 1 /RW
#define XL9555_CTRL_CFG1 (0x07)

View File

@ -0,0 +1,690 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file SensorBHI260AP.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-06
* @note Most source code references come from the https://github.com/boschsensortec/BHY2-Sensor-API
* Simplification for Arduino
*/
#pragma once
#include "bosch/BoschParse.h"
#include "bosch/SensorBhy2Define.h"
#include "bosch/firmware/BHI260AP.fw.h"
#if defined(ARDUINO)
class SensorBHI260AP
{
friend class BoschParse;
public:
SensorBHI260AP(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = BHI260AP_SLAVE_ADDRESS_L)
{
__handler.u.i2c_dev.scl = scl;
__handler.u.i2c_dev.sda = sda;
__handler.u.i2c_dev.addr = addr;
__handler.u.i2c_dev.wire = &w;
__handler.intf = SENSORLIB_I2C_INTERFACE;
}
SensorBHI260AP(int cs, int mosi = -1, int miso = -1, int sck = -1,
PLATFORM_SPI_TYPE &spi = SPI
)
{
__handler.u.spi_dev.cs = cs;
__handler.u.spi_dev.miso = miso;
__handler.u.spi_dev.mosi = mosi;
__handler.u.spi_dev.sck = sck;
__handler.u.spi_dev.spi = &spi;
__handler.intf = SENSORLIB_SPI_INTERFACE;
}
~SensorBHI260AP()
{
deinit();
}
SensorBHI260AP()
{
memset(&__handler, 0, sizeof(__handler));
}
void setPins(int rst, int irq)
{
__handler.irq = irq;
__handler.rst = rst;
}
bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = BHI260AP_SLAVE_ADDRESS_L)
{
__handler.u.i2c_dev.scl = scl;
__handler.u.i2c_dev.sda = sda;
__handler.u.i2c_dev.addr = addr;
__handler.u.i2c_dev.wire = &w;
__handler.intf = SENSORLIB_I2C_INTERFACE;
return initImpl();
}
bool init(
PLATFORM_SPI_TYPE &spi,
int cs, int mosi = MOSI, int miso = MISO, int sck = SCK)
{
__handler.u.spi_dev.cs = cs;
__handler.u.spi_dev.miso = miso;
__handler.u.spi_dev.mosi = mosi;
__handler.u.spi_dev.sck = sck;
__handler.u.spi_dev.spi = &spi;
__handler.intf = SENSORLIB_SPI_INTERFACE;
return initImpl();
}
bool init()
{
return initImpl();
}
void deinit()
{
if (processBuffer) {
free(processBuffer);
}
processBuffer = NULL;
if (bhy2) {
free(bhy2);
bhy2 = NULL;
}
if (__handler.irq != SENSOR_PIN_NONE) {
detachInterrupt(__handler.irq);
}
// end();
}
void reset()
{
if (__handler.rst != SENSOR_PIN_NONE) {
digitalWrite(__handler.rst, HIGH);
delay(5);
digitalWrite(__handler.rst, LOW);
delay(10);
digitalWrite(__handler.rst, HIGH);
delay(5);
}
}
void update()
{
if (!processBuffer) {
return;
}
if (__handler.irq != SENSOR_PIN_NONE) {
if (__data_available) {
bhy2_get_and_process_fifo(processBuffer, processBufferSize, bhy2);
}
} else {
bhy2_get_and_process_fifo(processBuffer, processBufferSize, bhy2);
}
}
bool enablePowerSave()
{
return true;
}
bool disablePowerSave()
{
return true;
}
void disableInterruptCtrl()
{
}
void enableInterruptCtrl()
{
}
bhy2_dev *getHandler()
{
return bhy2;
}
void printSensors(Stream &port)
{
uint8_t cnt = 0;
bool presentBuff[256];
for (uint16_t i = 0; i < sizeof(bhy2->present_buff); i++) {
for (uint8_t j = 0; j < 8; j++) {
presentBuff[i * 8 + j] = ((bhy2->present_buff[i] >> j) & 0x01);
}
}
port.println("Present sensors: ");
for (int i = 0; i < (int)sizeof(presentBuff); i++) {
if (presentBuff[i]) {
cnt++;
port.print(i);
port.print(" - ");
port.print(get_sensor_name(i));
port.println();
}
}
port.printf("Total %u Sensor online .\n", cnt);
}
bool printInfo(Stream &stream)
{
uint16_t kernel_version = 0, user_version = 0;
uint16_t rom_version = 0;
uint8_t product_id = 0;
uint8_t host_status = 0, feat_status = 0;
uint8_t boot_status = 0;
uint8_t sensor_error;
struct bhy2_sensor_info info;
/* Get product_id */
__error_code = (bhy2_get_product_id(&product_id, bhy2));
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_product_id failed!", false);
/* Get Kernel version */
__error_code = (bhy2_get_kernel_version(&kernel_version, bhy2));
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_kernel_version failed!", false);
/* Get User version */
__error_code = (bhy2_get_user_version(&user_version, bhy2));
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_user_version failed!", false);
/* Get ROM version */
__error_code = (bhy2_get_rom_version(&rom_version, bhy2));
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_rom_version failed!", false);
__error_code = (bhy2_get_host_status(&host_status, bhy2));
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_host_status failed!", false);
__error_code = (bhy2_get_feature_status(&feat_status, bhy2));
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_feature_status failed!", false);
stream.printf("Product ID : %02x\r\n", product_id);
stream.printf("Kernel version : %04u\r\n", kernel_version);
stream.printf("User version : %04u\r\n", user_version);
stream.printf("ROM version : %04u\r\n", rom_version);
stream.printf("Power state : %s\r\n", (host_status & BHY2_HST_POWER_STATE) ? "sleeping" : "active");
stream.printf("Host interface : %s\r\n", (host_status & BHY2_HST_HOST_PROTOCOL) ? "SPI" : "I2C");
stream.printf("Feature status : 0x%02x\r\n", feat_status);
/* Read boot status */
__error_code = (bhy2_get_boot_status(&boot_status, bhy2));
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_boot_status failed!", false);
stream.printf("Boot Status : 0x%02x: \r\n", boot_status);
if (boot_status & BHY2_BST_FLASH_DETECTED) {
stream.println("\tFlash detected. ");
}
if (boot_status & BHY2_BST_FLASH_VERIFY_DONE) {
stream.println("\tFlash verify done. ");
}
if (boot_status & BHY2_BST_FLASH_VERIFY_ERROR) {
stream.println("Flash verification failed. ");
}
if (boot_status & BHY2_BST_NO_FLASH) {
stream.println("\tNo flash installed. ");
}
if (boot_status & BHY2_BST_HOST_INTERFACE_READY) {
stream.println("\tHost interface ready. ");
}
if (boot_status & BHY2_BST_HOST_FW_VERIFY_DONE) {
stream.println("\tFirmware verification done. ");
}
if (boot_status & BHY2_BST_HOST_FW_VERIFY_ERROR) {
stream.println("\tFirmware verification error. ");
}
if (boot_status & BHY2_BST_HOST_FW_IDLE) {
stream.println("\tFirmware halted. ");
}
/* Read error value */
__error_code = (bhy2_get_error_value(&sensor_error, bhy2));
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_error_value failed!", false);
if (sensor_error) {
log_e("%s\r\n", get_sensor_error_text(sensor_error));
}
if (feat_status & BHY2_FEAT_STATUS_OPEN_RTOS_MSK) {
bhy2_update_virtual_sensor_list(bhy2);
/* Get present virtual sensor */
bhy2_get_virt_sensor_list(bhy2);
stream.printf("Virtual sensor list.\r\n");
stream.printf("Sensor ID | Sensor Name | ID | Ver | Min rate | Max rate |\r\n");
stream.printf("----------+--------------------------------------+-----+-----+-----------+-----------|\r\n");
for (uint8_t i = 0; i < BHY2_SENSOR_ID_MAX; i++) {
if (bhy2_is_sensor_available(i, bhy2)) {
if (i < BHY2_SENSOR_ID_CUSTOM_START) {
stream.printf(" %8u | %36s ", i, get_sensor_name(i));
}
__error_code = (bhy2_get_sensor_info(i, &info, bhy2));
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_sensor_info failed!", false);
stream.printf("| %3u | %3u | %9.4f | %9.4f |\r\n",
info.driver_id,
info.driver_version,
info.min_rate.f_val,
info.max_rate.f_val);
}
}
}
return true;
}
bool setInterruptCtrl(uint8_t data)
{
__error_code = bhy2_set_host_interrupt_ctrl(data, bhy2);
if (__error_code != BHY2_OK) {
return false;
}
}
uint8_t getInterruptCtrl()
{
uint8_t data;
__error_code = bhy2_get_host_interrupt_ctrl(&data, bhy2);
if (__error_code != BHY2_OK) {
return 0;
}
return data;
}
void printInterruptCtrl(Stream &stream)
{
uint8_t data;
__error_code = bhy2_get_host_interrupt_ctrl(&data, bhy2);
if (__error_code != BHY2_OK) {
return ;
}
stream.printf("Host interrupt control\r\n");
stream.printf("-- Wake up FIFO %s.\r\n", (data & BHY2_ICTL_DISABLE_FIFO_W) ? "disabled" : "enabled");
stream.printf("-- Non wake up FIFO %s.\r\n", (data & BHY2_ICTL_DISABLE_FIFO_NW) ? "disabled" : "enabled");
stream.printf("-- Status FIFO %s.\r\n", (data & BHY2_ICTL_DISABLE_STATUS_FIFO) ? "disabled" : "enabled");
stream.printf("-- Debugging %s.\r\n", (data & BHY2_ICTL_DISABLE_DEBUG) ? "disabled" : "enabled");
stream.printf("-- Fault %s.\r\n", (data & BHY2_ICTL_DISABLE_FAULT) ? "disabled" : "enabled");
stream.printf("-- Interrupt is %s.\r\n", (data & BHY2_ICTL_ACTIVE_LOW) ? "active low" : "active high");
stream.printf("-- Interrupt is %s triggered.\r\n", (data & BHY2_ICTL_EDGE) ? "pulse" : "level");
stream.printf("-- Interrupt pin drive is %s.\r\n", (data & BHY2_ICTL_OPEN_DRAIN) ? "open drain" : "push-pull");
}
bool isReady()
{
uint8_t boot_status = 0;
__error_code = bhy2_get_boot_status(&boot_status, bhy2);
log_i("boot_status:0x%x", boot_status);
if (__error_code != BHY2_OK) {
return false;
}
return (boot_status & BHY2_BST_HOST_INTERFACE_READY) == false;
}
uint16_t getKernelVersion()
{
uint16_t version = 0;
__error_code = bhy2_get_kernel_version(&version, bhy2);
if ((__error_code != BHY2_OK) && (version == 0)) {
return 0;
}
log_i("Boot successful. Kernel version %u.\r\n", version);
return version;
}
void onEvent(BhySensorEvent event_id, BhyEventCb callback)
{
SensorEventCbList_t newEventHandler;
newEventHandler.cb = callback;
newEventHandler.event = event_id;
BoschParse::bhyEventVector.push_back(newEventHandler);
}
void removeEvent(BhySensorEvent event_id, BhyEventCb callback)
{
if (!callback) {
return;
}
for (uint32_t i = 0; i < BoschParse::bhyEventVector.size(); i++) {
SensorEventCbList_t entry = BoschParse::bhyEventVector[i];
if (entry.cb == callback && entry.event == event_id) {
BoschParse::bhyEventVector.erase(BoschParse::bhyEventVector.begin() + i);
}
}
}
void onResultEvent(BhySensorID sensor_id, BhyParseDataCallback callback)
{
ParseCallBackList_t newEventHandler;
newEventHandler.cb = callback;
newEventHandler.id = sensor_id;
BoschParse::bhyParseEventVector.push_back(newEventHandler);
}
void removeResultEvent(BhySensorID sensor_id, BhyParseDataCallback callback)
{
if (!callback) {
return;
}
for (uint32_t i = 0; i < BoschParse::bhyParseEventVector.size(); i++) {
ParseCallBackList_t entry = BoschParse::bhyParseEventVector[i];
if (entry.cb == callback && entry.id == sensor_id) {
BoschParse::bhyParseEventVector.erase(BoschParse::bhyParseEventVector.begin() + i);
}
}
}
void setProcessBufferSize(uint32_t size)
{
processBufferSize = size;
}
bool uploadFirmware(const uint8_t *firmware, uint32_t length, bool write2Flash = false)
{
uint8_t sensor_error;
uint8_t boot_status;
log_i("Upload Firmware ...");
__error_code = bhy2_get_boot_status(&boot_status, bhy2);
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_boot_status failed!", false);
if (write2Flash) {
if (boot_status & BHY2_BST_FLASH_DETECTED) {
uint32_t start_addr = BHY2_FLASH_SECTOR_START_ADDR;
uint32_t end_addr = start_addr + length;
log_i("Flash detected. Erasing flash to upload firmware\r\n");
__error_code = bhy2_erase_flash(start_addr, end_addr, bhy2);
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_erase_flash failed!", false);
} else {
log_e("Flash not detected\r\n");
return false;
}
printf("Loading firmware into FLASH.\r\n");
__error_code = bhy2_upload_firmware_to_flash(firmware, length, bhy2);
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_upload_firmware_to_flash failed!", false);
} else {
log_i("Loading firmware into RAM.\r\n");
log_i("upload size = %lu", length);
__error_code = bhy2_upload_firmware_to_ram(firmware, length, bhy2);
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_upload_firmware_to_ram failed!", false);
}
log_i("Loading firmware into RAM Done\r\n");
__error_code = bhy2_get_error_value(&sensor_error, bhy2);
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_error_value failed!", false);
if (sensor_error != BHY2_OK) {
__error_code = bhy2_get_error_value(&sensor_error, bhy2);
log_e("%s\r\n", get_sensor_error_text(sensor_error));
return false;
}
if (write2Flash) {
log_i("Booting from FLASH.\r\n");
__error_code = bhy2_boot_from_flash(bhy2);
} else {
log_i("Booting from RAM.\r\n");
__error_code = bhy2_boot_from_ram(bhy2);
}
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2 boot failed!", false);
__error_code = bhy2_get_error_value(&sensor_error, bhy2);
if (sensor_error) {
log_e("%s\r\n", get_sensor_error_text(sensor_error));
return false;
}
return sensor_error == BHY2_OK;
}
String getError()
{
String err = get_api_error(__error_code);
err += " Code:" + String(__error_code);
return err;
}
bool configure(uint8_t sensor_id, float sample_rate, uint32_t report_latency_ms)
{
__error_code = bhy2_set_virt_sensor_cfg(sensor_id, sample_rate, report_latency_ms, bhy2);
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_set_virt_sensor_cfg failed!", false);
log_i("Enable %s at %.2fHz.\r\n", get_sensor_name(sensor_id), sample_rate);
return true;
}
struct bhy2_virt_sensor_conf getConfigure(uint8_t sensor_id)
{
bhy2_virt_sensor_conf conf;
bhy2_get_virt_sensor_cfg(sensor_id, &conf, bhy2);
log_i("range:%u sample_rate:%f latency:%lu sensitivity:%u\n", conf.range, conf.sample_rate, conf.latency, conf.sensitivity);
return conf;
}
float getScaling(uint8_t sensor_id)
{
return get_sensor_default_scaling(sensor_id);
}
void setFirmware(const uint8_t *image, size_t image_len, bool write_flash)
{
__firmware = image;
__firmware_size = image_len;
__write_flash = write_flash;
}
static const char *getSensorName(uint8_t sensor_id)
{
return get_sensor_name(sensor_id);
}
private:
static void handleISR()
{
__data_available = true;
}
bool initImpl()
{
uint8_t product_id = 0;
if (__handler.rst != SENSOR_PIN_NONE) {
pinMode(__handler.rst, OUTPUT);
}
reset();
bhy2 = (struct bhy2_dev *)malloc(sizeof(struct bhy2_dev ));
BHY2_RLST_CHECK(!bhy2, " Device handler malloc failed!", false);
switch (__handler.intf) {
case BHY2_I2C_INTERFACE:
// esp32s3 test I2C maximum read and write is 64 bytes
__max_rw_length = 64;
BHY2_RLST_CHECK(!__handler.u.i2c_dev.wire, "Wire ptr NULL", false);
if (!SensorInterfaces::setup_interfaces(__handler)) {
log_e("setup_interfaces failed");
return false;
}
__error_code = bhy2_init(BHY2_I2C_INTERFACE,
SensorInterfaces::bhy2_i2c_read,
SensorInterfaces::bhy2_i2c_write,
SensorInterfaces::bhy2_delay_us,
__max_rw_length, &__handler, bhy2);
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_init failed!", false);
// __error_code = bhy2_set_host_intf_ctrl(BHY2_I2C_INTERFACE, bhy2);
// BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_set_host_intf_ctrl failed!", false);
break;
case BHY2_SPI_INTERFACE:
// esp32s3 test SPI maximum read and write is 256 bytes
__max_rw_length = 256;
BHY2_RLST_CHECK(!__handler.u.spi_dev.spi, "SPI ptr NULL", false);
if (!SensorInterfaces::setup_interfaces(__handler)) {
log_e("setup_interfaces failed");
return false;
}
__error_code = bhy2_init(BHY2_SPI_INTERFACE,
SensorInterfaces::bhy2_spi_read,
SensorInterfaces::bhy2_spi_write,
SensorInterfaces::bhy2_delay_us,
__max_rw_length,
&__handler,
bhy2);
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_init failed!", false);
// __error_code = bhy2_set_host_intf_ctrl(BHY2_SPI_INTERFACE, bhy2);
// BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_set_host_intf_ctrl failed!", false);
break;
default:
return false;
}
__error_code = bhy2_soft_reset(bhy2);
BHY2_RLST_CHECK(__error_code != BHY2_OK, "reset bhy2 failed!", false);
__error_code = bhy2_get_product_id(&product_id, bhy2);
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_get_product_id failed!", false);
/* Check for a valid product ID */
if (product_id != BHY2_PRODUCT_ID) {
log_e("Product ID read %X. Expected %X\r\n", product_id, BHY2_PRODUCT_ID);
return false;
} else {
log_i("BHI260/BHA260 found. Product ID read %X\r\n", product_id);
}
if (!__firmware) {
// Default write to ram
setFirmware(bhy2_firmware_image, sizeof(bhy2_firmware_image), false);
}
if (!isReady()) {
if (!uploadFirmware(__firmware, __firmware_size, __write_flash)) {
log_e("uploadFirmware failed!");
return false;
}
}
uint16_t version = getKernelVersion();
BHY2_RLST_CHECK(!version, "getKernelVersion failed!", false);
log_i("Boot successful. Kernel version %u.\r\n", version);
//Set event callback
__error_code = bhy2_register_fifo_parse_callback(BHY2_SYS_ID_META_EVENT, BoschParse::parseMetaEvent, NULL, bhy2);
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_register_fifo_parse_callback failed!", false);
__error_code = bhy2_register_fifo_parse_callback(BHY2_SYS_ID_META_EVENT_WU, BoschParse::parseMetaEvent, NULL, bhy2);
BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_register_fifo_parse_callback failed!", false);
// __error_code = bhy2_register_fifo_parse_callback(BHY2_SYS_ID_DEBUG_MSG, BoschParse::parseDebugMessage, NULL, bhy2);
// BHY2_RLST_CHECK(__error_code != BHY2_OK, "bhy2_register_fifo_parse_callback parseDebugMessage failed!", false);
//Set process buffer
#if defined(ESP32) && defined(BOARD_HAS_PSRAM)
processBuffer = (uint8_t *)ps_malloc(processBufferSize);
#else
processBuffer = (uint8_t *)malloc(processBufferSize);
#endif
BHY2_RLST_CHECK(!processBuffer, "process buffer malloc failed!", false);
__error_code = bhy2_get_and_process_fifo(processBuffer, processBufferSize, bhy2);
if (__error_code != BHY2_OK) {
log_e("bhy2_get_and_process_fifo failed");
free(processBuffer);
return false;
}
/* Update the callback table to enable parsing of sensor hintr_ctrl */
bhy2_update_virtual_sensor_list(bhy2);
/* Get present virtual sensor */
bhy2_get_virt_sensor_list(bhy2);
// Only register valid sensor IDs
for (uint8_t i = 0; i < BHY2_SENSOR_ID_MAX; i++) {
if (bhy2_is_sensor_available(i, bhy2)) {
bhy2_register_fifo_parse_callback(i, BoschParse::parseData, NULL, bhy2);
}
}
if (__handler.irq != SENSOR_PIN_NONE) {
#if defined(ARDUINO_ARCH_RP2040)
attachInterrupt((pin_size_t)(__handler.irq), handleISR, (PinStatus )RISING);
#elif defined(NRF52840_XXAA) || defined(NRF52832_XXAA) || defined(ESP32)
attachInterrupt(__handler.irq, handleISR, RISING);
#else
#error "No support ."
#endif
}
return __error_code == BHY2_OK;
}
protected:
struct bhy2_dev *bhy2 = NULL;
SensorLibConfigure __handler;
int8_t __error_code;
static volatile bool __data_available;
uint8_t *processBuffer = NULL;
size_t processBufferSize = BHY_PROCESS_BUFFER_SZIE;
const uint8_t *__firmware;
size_t __firmware_size;
bool __write_flash;
uint16_t __max_rw_length;
};
volatile bool SensorBHI260AP::__data_available;
#endif /*defined(ARDUINO)*/

View File

@ -0,0 +1,846 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file SensorBMA423.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2022-03-31
* @note Most source code references come from the https://github.com/boschsensortec/BMA423-Sensor-API
* Simplification for Arduino
*/
#pragma once
#include "REG/BMA423Constants.h"
#include "SensorCommon.tpp"
class SensorBMA423 :
public SensorCommon<SensorBMA423>
{
friend class SensorCommon<SensorBMA423>;
public:
enum AccelRange {
RANGE_2G,
RANGE_4G,
RANGE_8G,
RANGE_16G
};
/*! Output data rate in Hz */
enum AccelODR {
ODR_0_78HZ = 1,
ODR_1_56HZ,
ODR_3_12HZ,
ODR_6_25HZ,
ODR_12_5HZ,
ODR_25HZ,
ODR_50HZ,
ODR_100HZ,
ODR_200HZ,
ODR_400HZ,
ODR_800HZ,
ODR_1600HZ,
};
/*! Bandwidth parameter, determines filter configuration */
enum BandWidth {
BW_OSR4_AVG1,
BW_OSR2_AVG2,
BW_NORMAL_AVG4,
BW_CIC_AVG8,
BW_RES_AVG16,
BW_RES_AVG32,
BW_RES_AVG64,
BW_RES_AVG128,
};
enum PerformanceMode {
PERF_CIC_AVG_MODE,
PERF_CONTINUOUS_MODE,
};
enum TemperatureUnit {
TEMP_DEG,
TEMP_FAHREN,
TEMP_KELVIN,
};
// Calculate direction facing the front of the chip
enum SensorDir {
DIRECTION_BOTTOM_LEFT,
DIRECTION_TOP_RIGHT,
DIRECTION_TOP_LEFT,
DIRECTION_BOTTOM_RIGHT,
DIRECTION_BOTTOM,
DIRECTION_TOP
};
// Chip orientation and orientation
enum SensorRemap {
// Top right corner
REMAP_TOP_LAYER_RIGHT_CORNER,
// Front bottom left corner
REMAP_TOP_LAYER_BOTTOM_LEFT_CORNER,
// Top left corner
REMAP_TOP_LAYER_LEFT_CORNER,
// Top bottom right corner
REMAP_TOP_LAYER_BOTTOM_RIGHT_CORNER,
// Bottom top right corner
REMAP_BOTTOM_LAYER_TOP_RIGHT_CORNER,
// Bottom bottom left corner
REMAP_BOTTOM_LAYER_BOTTOM_LEFT_CORNER,
// Bottom bottom right corner
REMAP_BOTTOM_LAYER_BOTTOM_RIGHT_CORNER,
// Bottom top left corner
REMAP_BOTTOM_LAYER_TOP_LEFT_CORNER,
};
enum Feature {
/**\name Feature enable macros for the sensor */
FEATURE_STEP_CNTR = 0x01,
/**\name Below macros are mutually exclusive */
FEATURE_ANY_MOTION = 0x02,
FEATURE_NO_MOTION = 0x04,
FEATURE_ACTIVITY = 0x08,
FEATURE_TILT = 0x10,
FEATURE_WAKEUP = 0x20,
};
/**\name Interrupt status macros */
enum FeatureInterrupt {
INT_STEP_CNTR = 0x02,
INT_ACTIVITY = 0x04,
INT_TILT = 0x05,
INT_WAKEUP = 0x20,
INT_ANY_NO_MOTION = 0x40,
};
#if defined(ARDUINO)
SensorBMA423(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = BMA423_SLAVE_ADDRESS)
{
__wire = &w;
__sda = sda;
__scl = scl;
__addr = addr;
}
#endif
SensorBMA423()
{
#if defined(ARDUINO)
__wire = &Wire;
__sda = DEFAULT_SDA;
__scl = DEFAULT_SCL;
#endif
__addr = BMA423_SLAVE_ADDRESS;
}
~SensorBMA423()
{
deinit();
}
#if defined(ARDUINO)
bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = BMA423_SLAVE_ADDRESS)
{
return SensorCommon::begin(w, addr, sda, scl);
}
#endif
void deinit()
{
// end();
}
void reset()
{
writeRegister(BMA423_RESET_REG, 0xB6);
delay(20);
}
bool enablePowerSave()
{
uint8_t val;
val = readRegister(BMA4_POWER_CONF_ADDR);
val |= BMA4_ADVANCE_POWER_SAVE_MSK;
writeRegister(BMA4_POWER_CONF_ADDR, val);
return true;
}
bool disablePowerSave()
{
uint8_t val;
val = readRegister(BMA4_POWER_CONF_ADDR);
val &= ~(BMA4_ADVANCE_POWER_SAVE_MSK);
writeRegister(BMA4_POWER_CONF_ADDR, val);
return true;
}
void disableInterruptCtrl()
{
writeRegister(BMA4_INIT_CTRL_ADDR, 0x00);
}
void enableInterruptCtrl()
{
writeRegister(BMA4_INIT_CTRL_ADDR, 0x01);
}
bool enableAccelerometer()
{
uint8_t val;
val = readRegister(BMA4_POWER_CTRL_ADDR);
val |= BMA4_ACCEL_ENABLE_MSK;
writeRegister(BMA4_POWER_CTRL_ADDR, val);
return true;
}
bool disableAccelerometer()
{
uint8_t val;
val = readRegister( BMA4_POWER_CTRL_ADDR);
val &= (~BMA4_ACCEL_ENABLE_MSK);
writeRegister(BMA4_POWER_CTRL_ADDR, val);
return true;
}
bool configAccelerometer(AccelRange range = RANGE_4G, AccelODR odr = ODR_200HZ,
BandWidth bw = BW_NORMAL_AVG4,
PerformanceMode perfMode = PERF_CONTINUOUS_MODE)
{
uint8_t buffer[2] = {0, 0};
if (perfMode == PERF_CONTINUOUS_MODE) {
if (bw > BW_NORMAL_AVG4) {
return false;
}
} else if (perfMode == PERF_CIC_AVG_MODE) {
if (bw > BW_RES_AVG128) {
return false;
}
} else {
return false;
}
if ((odr < ODR_0_78HZ) || (odr > ODR_1600HZ)) {
return false;
}
buffer[0] = odr & 0x0F;
buffer[0] |= (uint8_t)(bw << 4);
buffer[0] |= (uint8_t)(perfMode << 7);
buffer[1] = range & 0x03;
/* Burst write is not possible in
suspend mode hence individual write is
used with delay of 1 ms */
writeRegister(BMA4_ACCEL_CONFIG_ADDR, buffer[0]);
delay(2);
writeRegister(BMA4_ACCEL_CONFIG_ADDR + 1, buffer[1]);
return true;
}
bool getAccelRaw(int16_t *rawBuffer)
{
uint8_t buffer[6] = {0};
if (readRegister(BMA4_DATA_8_ADDR, buffer, 6) != DEV_WIRE_ERR) {
/* Accel data x axis */
rawBuffer[0] = (int16_t)(buffer[1] << 8) | (buffer[0]);
/* Accel data y axis */
rawBuffer[1] = (int16_t)(buffer[3] << 8) | (buffer[2]);
/* Accel data z axis */
rawBuffer[2] = (int16_t)(buffer[5] << 8) | (buffer[4]);
} else {
return false;
}
return true;
}
bool getAccelerometer(int16_t &x, int16_t &y, int16_t &z)
{
int16_t raw[3];
if (getAccelRaw(raw)) {
x = raw[0] / 16;
y = raw[1] / 16;
z = raw[2] / 16;
return true;
}
return false;
}
float getTemperature(TemperatureUnit unit)
{
int32_t raw = readRegister(BMA4_TEMPERATURE_ADDR);
/* '0' value read from the register corresponds to 23 degree C */
raw = (raw * 1000) + (23 * 1000);
switch (unit) {
case TEMP_FAHREN:
/* Temperature in degree Fahrenheit */
/* 1800 = 1.8 * 1000 */
raw = ((raw / 1000) * 1800) + (32 * 1000);
break;
case TEMP_KELVIN:
/* Temperature in degree Kelvin */
/* 273150 = 273.15 * 1000 */
raw = raw + 273150;
break;
default:
break;
}
float res = (float)raw / (float)1000.0;
/* 0x80 - raw read from the register and 23 is the ambient raw added.
* If the raw read from register is 0x80, it means no valid
* information is available */
if (((raw - 23) / 1000) == 0x80) {
return 0;
}
return res;
}
uint8_t direction()
{
int16_t x = 0, y = 0, z = 0;
getAccelerometer(x, y, z);
uint16_t absX = abs(x);
uint16_t absY = abs(y);
uint16_t absZ = abs(z);
if ((absZ > absX) && (absZ > absY)) {
if (z > 0) {
return DIRECTION_TOP;
} else {
return DIRECTION_BOTTOM;
}
} else if ((absY > absX) && (absY > absZ)) {
if (y > 0) {
return DIRECTION_TOP_RIGHT;
} else {
return DIRECTION_BOTTOM_LEFT;
}
} else {
if (x < 0) {
return DIRECTION_BOTTOM_RIGHT;
} else {
return DIRECTION_TOP_LEFT;
}
}
return 0;
}
bool setReampAxes(SensorRemap remap)
{
//Top
// No.1 REG: 0x3e -> 0x88 REG: 0x3f -> 0x0
// No.2 REG: 0x3e -> 0xac REG: 0x3f -> 0x0
// No.3 REG: 0x3e -> 0x85 REG: 0x3f -> 0x0
// No.4 REG: 0x3e -> 0xa1 REG: 0x3f -> 0x0
// Bottom
// No.5 REG: 0x3e -> 0x81 REG: 0x3f -> 0x1
// No.6 REG: 0x3e -> 0xa5 REG: 0x3f -> 0x1
// No.7 REG: 0x3e -> 0x8c REG: 0x3f -> 0x1
// No.8 REG: 0x3e -> 0xa8 REG: 0x3f -> 0x1
uint8_t configReg0[] = {0x88, 0xAC, 0x85, 0xA1, 0x81, 0xA5, 0x8C, 0xA8};
if (remap > sizeof(configReg0) / sizeof(configReg0[0])) {
return false;
}
uint8_t buffer[BMA423_FEATURE_SIZE] = {0};
uint8_t index = BMA423_AXES_REMAP_OFFSET;
if (readRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE) == DEV_WIRE_ERR) {
return false;
}
buffer[index] = configReg0[remap];
buffer[index + 1] = remap >= 4 ? 0x00 : 0x01;
return writeRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE) != DEV_WIRE_ERR;
}
bool setStepCounterWatermark(uint16_t watermark)
{
uint8_t buffer[BMA423_FEATURE_SIZE] = {0};
uint8_t index = BMA423_STEP_CNTR_OFFSET;
uint16_t wm_lsb = 0;
uint16_t wm_msb = 0;
int rslt;
uint16_t data = 0;
rslt = readRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE);
if (rslt != DEV_WIRE_ERR) {
wm_lsb = buffer[index];
wm_msb = buffer[index + 1] << 8;
data = wm_lsb | wm_msb;
/* Sets only watermark bits in the complete 16 bits of data */
data = ((data & ~(0x03FFU)) | (watermark & 0x03FFU));
/* Splits 16 bits of data to individual 8 bits data */
buffer[index] = (uint8_t)(data & 0x00FFU);
buffer[index + 1] = (uint8_t)((data & 0xFF00U) >> 8);
/* Writes stepcounter watermark settings in the sensor */
rslt = writeRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE);
}
return rslt != DEV_WIRE_ERR;
}
bool disablePedometer()
{
return enablePedometer(false);
}
bool enablePedometer(bool enable = true)
{
int rslt;
uint8_t buffer[BMA423_FEATURE_SIZE] = {0};
/* Step detector enable bit pos. is 1 byte ahead of the base address */
uint8_t index = BMA423_STEP_CNTR_OFFSET + 1;
rslt = readRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE);
if (rslt != DEV_WIRE_ERR) {
buffer[index] = ((buffer[index] & ~0x08) | ((enable << 3) & 0x08));
rslt = writeRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE);
}
return rslt != DEV_WIRE_ERR;
}
uint32_t getPedometerCounter()
{
uint8_t buffer[4] = {0};
/* Reads the step counter output data from the gpio register */
int rslt = readRegister(BMA4_STEP_CNT_OUT_0_ADDR, buffer, 4);
if (rslt != DEV_WIRE_ERR) {
return ((uint32_t)buffer[0]) | ((uint32_t)buffer[1] << 8) | ((uint32_t)buffer[2] << 16) | ((uint32_t)buffer[3] << 24);
}
return DEV_WIRE_NONE;
}
void resetPedometer()
{
uint8_t buffer[BMA423_FEATURE_SIZE] = {0};
/* Reset bit is 1 byte ahead of base address */
uint8_t index = BMA423_STEP_CNTR_OFFSET + 1;
int rslt = readRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE);
if (rslt != DEV_WIRE_ERR) {
buffer[index] = ((buffer[index] & ~0x04U) | ((1 << 2U) & 0x04U));
writeRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, BMA423_FEATURE_SIZE);
}
}
bool enableFeature(uint8_t feature, uint8_t enable)
{
uint8_t buffer[BMA423_FEATURE_SIZE] = {0};
int rslt;
uint8_t len;
/* Update the length for read and write */
update_len(&len, feature, enable);
rslt = readRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, len);
if (rslt != DEV_WIRE_ERR) {
if (enable) {
/* Enables the feature */
rslt = feature_enable(feature, len, buffer);
} else {
/* Disables the feature */
rslt = feature_disable(feature, len, buffer);
}
}
return rslt != DEV_WIRE_ERR;
}
uint16_t readIrqStatus()
{
uint8_t data[2] = {0};
if (readRegister(BMA4_INT_STAT_0_ADDR, data, 2) != DEV_WIRE_ERR) {
int_status = data[0] | (data[1] << 8);
return int_status;
}
return DEV_WIRE_NONE;
}
uint16_t getIrqStatus()
{
return int_status;
}
bool configInterrupt(
/*! Trigger condition of interrupt pin */
uint8_t edge_ctrl = BMA4_LEVEL_TRIGGER,
/*! Level of interrupt pin */
uint8_t level = BMA4_ACTIVE_HIGH,
/*! Behaviour of interrupt pin to open drain */
uint8_t od = BMA4_PUSH_PULL,
/*! Output enable for interrupt pin */
uint8_t output_en = BMA4_OUTPUT_ENABLE,
/*! Input enable for interrupt pin */
uint8_t input_en = BMA4_INPUT_DISABLE,
/*! Variable used to select the interrupt pin1 or pin2 for interrupt configuration. */
uint8_t int_line = BMA4_INTR1_MAP
)
{
uint8_t interrupt_address_array[2] = {BMA4_INT1_IO_CTRL_ADDR, BMA4_INT2_IO_CTRL_ADDR};
uint8_t data = 0;
if (int_line > 1) {
return false;
}
data = ((uint8_t)((edge_ctrl & BMA4_INT_EDGE_CTRL_MASK) |
((level << 1) & BMA4_INT_LEVEL_MASK) |
((od << 2) & BMA4_INT_OPEN_DRAIN_MASK) |
((output_en << 3) & BMA4_INT_OUTPUT_EN_MASK) |
((input_en << 4) & BMA4_INT_INPUT_EN_MASK)));
this->int_line = int_line;
return writeRegister(interrupt_address_array[int_line], &data, 1) != DEV_WIRE_ERR;
}
bool configreFeatureInterrupt(uint16_t feature_interrupt_mask, bool enable)
{
return interruptMap(int_line, feature_interrupt_mask, enable);
}
bool enablePedometerIRQ()
{
return (interruptMap(int_line, INT_STEP_CNTR, true));
}
bool enableTiltIRQ()
{
return (interruptMap(int_line, INT_TILT, true));
}
bool enableWakeupIRQ()
{
return (interruptMap(int_line, INT_WAKEUP, true));
}
bool enableAnyNoMotionIRQ()
{
return (interruptMap(int_line, INT_ANY_NO_MOTION, true));
}
bool enableActivityIRQ()
{
return (interruptMap(int_line, INT_ACTIVITY, true));
}
bool disablePedometerIRQ()
{
return (interruptMap(int_line, INT_STEP_CNTR, false));
}
bool disableTiltIRQ()
{
return (interruptMap(int_line, INT_TILT, false));
}
bool disableWakeupIRQ()
{
return (interruptMap(int_line, INT_WAKEUP, false));
}
bool disableAnyNoMotionIRQ()
{
return (interruptMap(int_line, INT_ANY_NO_MOTION, false));
}
bool disableActivityIRQ()
{
return (interruptMap(int_line, INT_ACTIVITY, false));
}
inline bool isActivity()
{
return (int_status & BMA423_ACTIVITY_INT);
}
inline bool isTilt()
{
return (int_status & BMA423_TILT_INT);
}
inline bool isDoubleTap()
{
return (int_status & BMA423_WAKEUP_INT);
}
inline bool isAnyNoMotion()
{
return (int_status & BMA423_ACTIVITY_INT);
}
inline bool isPedometer()
{
return (int_status & BMA423_STEP_CNTR_INT);
}
private:
bool interruptMap(uint8_t int_line, uint16_t int_map, uint8_t enable)
{
int rslt;
uint8_t data[3] = {0, 0, 0};
uint8_t index[2] = {BMA4_INT_MAP_1_ADDR, BMA4_INT_MAP_2_ADDR};
rslt = readRegister(BMA4_INT_MAP_1_ADDR, data, 3);
if (enable) {
/* Feature interrupt mapping */
data[int_line] |= (uint8_t)(int_map & (0x00FF));
/* Hardware interrupt mapping */
if (int_line == BMA4_INTR2_MAP)
data[2] |= (uint8_t)((int_map & (0xFF00)) >> 4);
else
data[2] |= (uint8_t)((int_map & (0xFF00)) >> 8);
rslt = writeRegister(index[int_line], &data[int_line], 1);
rslt = writeRegister(BMA4_INT_MAP_DATA_ADDR, &data[2], 1);
} else {
/* Feature interrupt un-mapping */
data[int_line] &= (~(uint8_t)(int_map & (0x00FF)));
/* Hardware interrupt un-mapping */
if (int_line == BMA4_INTR2_MAP)
data[2] &= (~(uint8_t)((int_map & (0xFF00)) >> 4));
else
data[2] &= (~(uint8_t)((int_map & (0xFF00)) >> 8));
rslt = writeRegister(index[int_line], &data[int_line], 1);
rslt = writeRegister(BMA4_INT_MAP_DATA_ADDR, &data[2], 1);
}
return rslt != DEV_WIRE_ERR;
}
/*!
* @brief This API sets the interrupt mode in the sensor.
*/
bool setInterruptMode(uint8_t mode)
{
if (mode == BMA4_NON_LATCH_MODE || mode == BMA4_LATCH_MODE)
return writeRegister(BMA4_INTR_LATCH_ADDR, &mode, 1) != DEV_WIRE_ERR;
return false;
}
bool feature_disable(uint8_t feature, uint8_t len, uint8_t *buffer)
{
uint8_t index = 0;
/* Disable step counter */
if ((feature & FEATURE_STEP_CNTR) > 0) {
/* Step counter enable bit pos. is 1 byte ahead of the
base address */
index = BMA423_STEP_CNTR_OFFSET + 1;
buffer[index] = buffer[index] & (~BMA423_STEP_CNTR_EN_MSK);
}
/* Disable activity */
if ((feature & FEATURE_ACTIVITY) > 0) {
/* Activity enable bit pos. is 1 byte ahead of the
base address */
index = BMA423_STEP_CNTR_OFFSET + 1;
buffer[index] = buffer[index] & (~BMA423_ACTIVITY_EN_MSK);
}
/* Disable tilt */
if ((feature & FEATURE_TILT) > 0) {
/* Tilt enable bit pos. is the base address(0x3A) of tilt */
index = BMA423_TILT_OFFSET;
buffer[index] = buffer[index] & (~BMA423_TILT_EN_MSK);
}
/* Disable wakeup */
if ((feature & FEATURE_WAKEUP) > 0) {
/* Tilt enable bit pos. is the base address(0x38) of wakeup */
index = BMA423_WAKEUP_OFFSET;
buffer[index] = buffer[index] & (~BMA423_WAKEUP_EN_MSK);
}
/* Disable anymotion/nomotion */
if ((feature & FEATURE_ANY_MOTION) > 0 || (feature & FEATURE_NO_MOTION) > 0) {
/* Any/Nomotion enable bit pos. is 1 bytes ahead of the
any/nomotion base address(0x00) */
index = 1;
if ((feature & FEATURE_ANY_MOTION) > 0) {
/* Disable anymotion */
buffer[index] = buffer[index] | BMA423_ANY_NO_MOTION_SEL_MSK;
} else {
/* Disable nomotion */
buffer[index] = buffer[index] & (~BMA423_ANY_NO_MOTION_SEL_MSK);
}
/* Any/Nomotion axis enable bit pos. is 3 byte ahead of the
any/nomotion base address(0x00) */
index = 3;
buffer[index] = buffer[index] & (~BMA423_ANY_NO_MOTION_AXIS_EN_MSK);
}
/* Write the configured settings in the sensor */
return writeRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, len) != DEV_WIRE_ERR;
}
int feature_enable(uint8_t feature, uint8_t len, uint8_t *buffer)
{
uint8_t index = 0;
/* Enable step counter */
if ((feature & FEATURE_STEP_CNTR) > 0) {
/* Step counter enable bit pos. is 1 byte ahead of the
base address */
index = BMA423_STEP_CNTR_OFFSET + 1;
buffer[index] = buffer[index] | BMA423_STEP_CNTR_EN_MSK;
}
/* Enable activity */
if ((feature & FEATURE_ACTIVITY) > 0) {
/* Activity enable bit pos. is 1 byte ahead of the
base address */
index = BMA423_STEP_CNTR_OFFSET + 1;
buffer[index] = buffer[index] | BMA423_ACTIVITY_EN_MSK;
}
/* Enable tilt */
if ((feature & FEATURE_TILT) > 0) {
/* Tilt enable bit pos. is the base address(0x3A) of tilt */
index = BMA423_TILT_OFFSET;
buffer[index] = buffer[index] | BMA423_TILT_EN_MSK;
}
/* Enable wakeup */
if ((feature & FEATURE_WAKEUP) > 0) {
/* Wakeup enable bit pos. is the base address(0x38) of wakeup */
index = BMA423_WAKEUP_OFFSET;
buffer[index] = buffer[index] | BMA423_WAKEUP_EN_MSK;
}
/* Enable anymotion/nomotion */
if ((feature & FEATURE_ANY_MOTION) > 0 || (feature & FEATURE_NO_MOTION) > 0) {
/* Any/Nomotion enable bit pos. is 1 bytes ahead of the
any/nomotion base address(0x00) */
index = 1;
if ((feature & FEATURE_ANY_MOTION) > 0) {
/* Enable anymotion */
buffer[index] = buffer[index] & (~BMA423_ANY_NO_MOTION_SEL_MSK);
} else {
/* Enable nomotion */
buffer[index] = buffer[index] | BMA423_ANY_NO_MOTION_SEL_MSK;
}
}
/* Write the feature enable settings in the sensor */
return writeRegister(BMA4_FEATURE_CONFIG_ADDR, buffer, len) != DEV_WIRE_ERR;
}
void update_len(uint8_t *len, uint8_t feature, uint8_t enable)
{
uint8_t length = BMA423_FEATURE_SIZE;
if ((feature == FEATURE_ANY_MOTION) || (feature == FEATURE_NO_MOTION)) {
/* Change the feature length to 2 for reading and writing of 2 bytes for
any/no-motion enable */
length = BMA423_ANYMOTION_EN_LEN;
/* Read and write 4 byte to disable the any/no motion completely along with
all axis */
if (!enable) {
/*Change the feature length to 4 for reading and writing
of 4 bytes for any/no-motion enable */
length = length + 2;
}
}
*len = length;
}
bool configure()
{
uint8_t val;
val = readRegister(BMA4_INTERNAL_STAT);
if (val == BMA4_ASIC_INITIALIZED) {
LOG("%s No need configure!\n", __func__);
readIrqStatus(); //clear irq status
return true;
}
disablePowerSave();
delay(1);
disableInterruptCtrl();
const uint8_t *stream_data = bma423_config_file;
const uint8_t maxReadWriteLenght = 32;
for (size_t index = 0; index < BMA4_CONFIG_STREAM_SIZE; index += maxReadWriteLenght) {
uint8_t asic_msb = (uint8_t)((index / 2) >> 4);
uint8_t asic_lsb = ((index / 2) & 0x0F);
writeRegister(BMA4_RESERVED_REG_5B_ADDR, asic_lsb);
writeRegister(BMA4_RESERVED_REG_5C_ADDR, asic_msb);
writeRegister(BMA4_FEATURE_CONFIG_ADDR, (uint8_t *)(stream_data + index), maxReadWriteLenght);
}
enableInterruptCtrl();
delay(150);
val = readRegister(BMA4_INTERNAL_STAT);
if (val == BMA4_ASIC_INITIALIZED) {
LOG("%s SUCCESS!\n", __func__);
} else {
LOG("%s FAILED!\n", __func__);
}
return val == BMA4_ASIC_INITIALIZED;
}
bool initImpl()
{
uint8_t id;
int retry = 2;
while (retry--) {
id = readRegister(BMA4_CHIP_ID_ADDR);
if (id != BMA423_CHIP_ID) {
reset();
}
}
if (id == BMA423_CHIP_ID) {
return configure();
}
LOG("ChipID:0x%x should be 0x%x\n", id, BMA423_CHIP_ID);
return false;
}
int getReadMaskImpl()
{
return DEV_WIRE_ERR;
}
uint16_t int_status;
uint8_t int_line;
protected:
};

View File

@ -0,0 +1,332 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* 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.
*
* @file SensorBMM150.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-10-09
* @note Most source code references come from the https://github.com/boschsensortec/BMM150-Sensor-API
* Simplification for Arduino
*/
#pragma once
#include "bosch/common/bosch_interfaces.h"
#include "bosch/BMM150/bmm150.h"
#include "bosch/SensorBhy2Define.h"
#if defined(ARDUINO)
/*! @name I2C ADDRESS */
#define BMM150_DEFAULT_I2C_ADDRESS UINT8_C(0x10)
#define BMM150_I2C_ADDRESS_CSB_LOW_SDO_HIGH UINT8_C(0x11)
#define BMM150_I2C_ADDRESS_CSB_HIGH_SDO_LOW UINT8_C(0x12)
#define BMM150_I2C_ADDRESS_CSB_HIGH_SDO_HIGH UINT8_C(0x13)
class SensorBMM150
{
public:
enum PowerMode {
POWERMODE_NORMAL,
POWERMODE_FORCED,
POWERMODE_SLEEP,
POWERMODE_SUSPEND,
};
enum InterruptLevel {
INTERRUPT_HIGH_ACTIVE,
INTERRUPT_LOW_ACTIVE,
};
SensorBMM150(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = BMM150_DEFAULT_I2C_ADDRESS)
{
__handler.u.i2c_dev.scl = scl;
__handler.u.i2c_dev.sda = sda;
__handler.u.i2c_dev.addr = addr;
__handler.u.i2c_dev.wire = &w;
__handler.intf = SENSORLIB_I2C_INTERFACE;
}
SensorBMM150(int cs, int mosi = -1, int miso = -1, int sck = -1, PLATFORM_SPI_TYPE &spi = SPI )
{
__handler.u.spi_dev.cs = cs;
__handler.u.spi_dev.miso = miso;
__handler.u.spi_dev.mosi = mosi;
__handler.u.spi_dev.sck = sck;
__handler.u.spi_dev.spi = &spi;
__handler.intf = SENSORLIB_SPI_INTERFACE;
}
~SensorBMM150()
{
deinit();
}
SensorBMM150()
{
memset(&__handler, 0, sizeof(__handler));
}
void setPins(int rst, int irq)
{
__handler.irq = irq;
__handler.rst = rst;
}
bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = BMM150_DEFAULT_I2C_ADDRESS)
{
__handler.u.i2c_dev.scl = scl;
__handler.u.i2c_dev.sda = sda;
__handler.u.i2c_dev.addr = addr;
__handler.u.i2c_dev.wire = &w;
__handler.intf = SENSORLIB_I2C_INTERFACE;
return initImpl();
}
bool init( PLATFORM_SPI_TYPE &spi, int cs, int mosi = MOSI, int miso = MISO, int sck = SCK)
{
__handler.u.spi_dev.cs = cs;
__handler.u.spi_dev.miso = miso;
__handler.u.spi_dev.mosi = mosi;
__handler.u.spi_dev.sck = sck;
__handler.u.spi_dev.spi = &spi;
__handler.intf = SENSORLIB_SPI_INTERFACE;
return initImpl();
}
bool init()
{
return initImpl();
}
void deinit()
{
if (dev) {
free(dev);
dev = NULL;
}
if (__handler.irq != SENSOR_PIN_NONE) {
detachInterrupt(__handler.irq);
}
}
void reset()
{
if (__handler.rst != SENSOR_PIN_NONE) {
digitalWrite(__handler.rst, HIGH);
delay(5);
digitalWrite(__handler.rst, LOW);
delay(10);
digitalWrite(__handler.rst, HIGH);
delay(5);
}
}
void sleep()
{
setMode(POWERMODE_SLEEP);
}
bool setMode(PowerMode mode)
{
settings.pwr_mode = mode;
return bmm150_set_op_mode(&settings, dev) == BMM150_OK;
}
bool setThreshold(uint8_t high_th, uint8_t low_th)
{
settings.int_settings.high_threshold = high_th;
settings.int_settings.low_threshold = low_th;
return bmm150_set_sensor_settings(BMM150_SEL_HIGH_THRESHOLD_SETTING, &settings, dev) == BMM150_OK;
}
bool setInterruptLevel(InterruptLevel level)
{
settings.int_settings.high_int_en = level;
return bmm150_set_sensor_settings(BMM150_SEL_HIGH_THRESHOLD_INT, &settings, dev) == BMM150_OK;
}
bool enableINT()
{
settings.int_settings.int_pin_en = BMM150_INT_ENABLE;
return bmm150_set_sensor_settings(BMM150_SEL_INT_PIN_EN, &settings, dev) == BMM150_OK;
}
bool disableINT()
{
settings.int_settings.int_pin_en = BMM150_INT_DISABLE;
return bmm150_set_sensor_settings(BMM150_SEL_INT_PIN_EN, &settings, dev) == BMM150_OK;
}
bool enabledDtatReady()
{
settings.int_settings.drdy_pin_en = BMM150_INT_ENABLE;
return bmm150_set_sensor_settings(BMM150_SEL_DRDY_PIN_EN, &settings, dev) == BMM150_OK;
}
bool disabledDtatReady()
{
settings.int_settings.drdy_pin_en = BMM150_INT_DISABLE;
return bmm150_set_sensor_settings(BMM150_SEL_DRDY_PIN_EN, &settings, dev) == BMM150_OK;
}
uint8_t getChipID()
{
return dev->chip_id;
}
uint8_t getInterruptStatus()
{
bmm150_get_interrupt_status(dev);
return dev->int_status;
}
bool isDataReady()
{
return dev->int_status & BMM150_INT_ASSERTED_DRDY;
}
bool isLowThreshold()
{
return dev->int_status & BMM150_INT_ASSERTED_LOW_THRES;
}
bool isHighThreshold()
{
return dev->int_status & BMM150_INT_ASSERTED_HIGH_THRES;
}
struct bmm150_mag_data getMag()
{
struct bmm150_mag_data data = {0};
bmm150_read_mag_data(&data, dev);
return data;
}
bool getMag(int16_t &x, int16_t &y, int16_t &z)
{
struct bmm150_mag_data data;
if (bmm150_read_mag_data(&data, dev) != BMM150_OK) {
return false;
}
x = data.x;
y = data.y;
z = data.z;
return true;
}
private:
static void IRAM_ATTR handleISR(void *available)
{
*(bool *)(available) = true;
}
bool initImpl()
{
memset(&settings, 0, sizeof(settings));
if (__handler.rst != SENSOR_PIN_NONE) {
pinMode(__handler.rst, OUTPUT);
}
reset();
dev = (struct bmm150_dev *)malloc(sizeof(struct bmm150_dev));
BHY2_RLST_CHECK(!dev, " Device handler malloc failed!", false);
switch (__handler.intf) {
case SENSORLIB_I2C_INTERFACE:
BHY2_RLST_CHECK(!__handler.u.i2c_dev.wire, "Wire ptr NULL", false);
if (!SensorInterfaces::setup_interfaces(__handler)) {
log_e("setup_interfaces failed");
free(dev);
return false;
}
dev->intf = BMM150_I2C_INTF;
dev->read = SensorInterfaces::bhy2_i2c_read;
dev->write = SensorInterfaces::bhy2_i2c_write;
dev->intf_ptr = &__handler;
break;
case SENSORLIB_SPI_INTERFACE:
BHY2_RLST_CHECK(!__handler.u.spi_dev.spi, "SPI ptr NULL", false);
if (!SensorInterfaces::setup_interfaces(__handler)) {
log_e("setup_interfaces failed");
free(dev);
return false;
}
dev->intf = BMM150_I2C_INTF;
dev->read = SensorInterfaces::bhy2_spi_read;
dev->write = SensorInterfaces::bhy2_spi_write;
dev->intf_ptr = &__handler;
break;
default:
free(dev);
return false;
}
dev->delay_us = SensorInterfaces::bhy2_delay_us;
__error_code = bmm150_init(dev);
if (__error_code != BMM150_OK) {
log_e("bmm150 init failed!");
free(dev);
return false;
}
__error_code = bmm150_soft_reset(dev);
if (__error_code != BMM150_OK) {
log_e("reset failed!");
free(dev);
return false;
}
bmm150_get_sensor_settings(&settings, dev);
if (__handler.irq != SENSOR_PIN_NONE) {
#if defined(ARDUINO_ARCH_RP2040)
attachInterruptParam((pin_size_t)(__handler.irq), handleISR, (PinStatus )RISING, (void *)&__data_available);
#else
attachInterruptArg(__handler.irq, handleISR, (void *)&__data_available, RISING);
#endif
}
return __error_code == BMM150_OK;
}
protected:
struct bmm150_settings settings;
struct bmm150_dev *dev = NULL;
SensorLibConfigure __handler;
int8_t __error_code;
volatile bool __data_available;
};
#endif /*defined(ARDUINO)*/

View File

@ -0,0 +1,234 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file SensorCM32181.tpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-14
*
*/
#pragma once
#include "REG/CM32181Constants.h"
#include "SensorCommon.tpp"
class SensorCM32181 :
public SensorCommon<SensorCM32181>
{
friend class SensorCommon<SensorCM32181>;
public:
enum Sampling {
SAMPLING_X1, //ALS Sensitivity x 1
SAMPLING_X2, //ALS Sensitivity x 2
SAMPLING_X1_8, //ALS Sensitivity x (1/8)
SAMPLING_X1_4, //ALS Sensitivity x (1/4)
};
enum IntegrationTime {
INTEGRATION_TIME_25MS = 0x0C,
INTEGRATION_TIME_50MS = 0x08,
INTEGRATION_TIME_100MS = 0x00, //0000 = 100ms
INTEGRATION_TIME_200MS, //0001 = 200ms
INTEGRATION_TIME_400MS, //0010 = 400ms
INTEGRATION_TIME_800MS, //0011 = 800ms
};
enum PowerSaveMode {
PowerSaveMode1 = 0x00,
PowerSaveMode2,
PowerSaveMode3,
PowerSaveMode4
};
enum InterruptEvent {
ALS_EVENT_LOW_TRIGGER = 0x00,
ALS_EVENT_HIGH_TRIGGER,
ALS_EVENT_NULL,
};
#if defined(ARDUINO)
SensorCM32181(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = CM32181_SLAVE_ADDRESS)
{
__wire = &w;
__sda = sda;
__scl = scl;
__addr = addr;
}
#endif
SensorCM32181()
{
#if defined(ARDUINO)
__wire = &Wire;
__sda = DEFAULT_SDA;
__scl = DEFAULT_SCL;
#endif
__addr = CM32181_SLAVE_ADDRESS;
}
~SensorCM32181()
{
deinit();
}
#if defined(ARDUINO)
bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = CM32181_SLAVE_ADDRESS)
{
return SensorCommon::begin(w, addr, sda, scl);
}
#endif
void deinit()
{
// end();
}
void setSampling(Sampling tempSampling = SAMPLING_X1,
IntegrationTime int_time = INTEGRATION_TIME_200MS
)
{
uint16_t data;
readRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2);
data &= ~(0x03 << 11);
data |= tempSampling << 11;
data &= ~(0xF << 6);
data |= int_time << 6;
readRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2);
}
void setIntThreshold(uint16_t low_threshold, uint16_t high_threshold)
{
uint8_t buffer[2] = {0};
buffer[1] = highByte(high_threshold);
buffer[0] = lowByte(high_threshold);;
writeRegister(CM32181_REG_ALS_THDH, buffer, 2);
buffer[1] = highByte(low_threshold);
buffer[0] = lowByte(low_threshold);
writeRegister(CM32181_REG_ALS_THDL, buffer, 2);
}
void powerSave(PowerSaveMode mode, bool enable)
{
uint16_t data = 0x00;
readRegister(CM32181_REG_ALS_PSM, (uint8_t *)&data, 2);
data |= mode << 1;
enable ? data |= 0x01 : data |= 0x00;
writeRegister(CM32181_REG_ALS_PSM, (uint8_t *)&data, 2);
}
// Read CM32181_REG_ALS_STATUS register to clear interrupt
InterruptEvent getIrqStatus()
{
uint16_t data;
readRegister(CM32181_REG_ALS_STATUS, (uint8_t *)&data, 2);
return bitRead(data, 15) ? ALS_EVENT_LOW_TRIGGER : bitRead(data, 14) ? ALS_EVENT_HIGH_TRIGGER : ALS_EVENT_NULL;
}
void enableINT()
{
uint16_t data;
readRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2);
bitWrite(data, 1, 1);
writeRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2);
}
void disableINT()
{
uint16_t data;
readRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2);
bitWrite(data, 1, 0);
writeRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2);
}
void powerOn()
{
uint16_t data;
readRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2);
bitClear(data, 0);
writeRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2);
}
void powerDown()
{
uint16_t data;
readRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2);
bitSet(data, 0);
writeRegister(CM32181_REG_ALS_CONF, (uint8_t *)&data, 2);
}
uint16_t getRaw()
{
uint8_t buffer[2] = {0};
readRegister(CM32181_REG_ALS_DATA, buffer, 2);
return (uint16_t) buffer[0] | (uint16_t)(buffer[1] << 8);
}
float getLux()
{
return getRaw() * calibration_factor;
}
int getChipID()
{
uint8_t buffer[2] = {0};
readRegister(CM32181_REG_ID, buffer, 2);
return lowByte(buffer[0]);
}
private:
bool initImpl()
{
setReadRegisterSendStop(false);
int chipID = getChipID();
log_i("chipID:%d\n", chipID);
if (chipID == DEV_WIRE_ERR ) {
return false;
}
if (chipID != CM32181_CHIP_ID) {
return false;
}
return true;
}
int getReadMaskImpl()
{
return -1;
}
protected:
// The default calibration value, learned from the manual,
// is now unable to obtain the calibration value from the specified register
const float calibration_factor = 0.286;
};

View File

@ -0,0 +1,699 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file SensorCommon.tpp
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#pragma once
#include "SensorLib.h"
typedef union {
struct {
uint8_t low;
uint8_t high;
} bits;
uint16_t full;
} RegData_t;
typedef int (*iic_fptr_t)(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len);
typedef void (*gpio_write_fptr_t)(uint32_t gpio, uint8_t value);
typedef int (*gpio_read_fptr_t)(uint32_t gpio);
typedef void (*gpio_mode_fptr_t)(uint32_t gpio, uint8_t mode);
typedef void (*delay_ms_fptr_t)(uint32_t ms);
template <class chipType>
class SensorCommon
{
public:
~SensorCommon()
{
#if defined(ARDUINO)
if (__spiSetting) {
delete __spiSetting;
}
#endif
}
#if defined(ARDUINO)
void setSpiSetting(uint32_t freq, uint8_t dataOrder = SPI_DATA_ORDER, uint8_t dataMode = SPI_MODE0)
{
__freq = freq;
__dataOrder = dataOrder;
__dataMode = dataMode;
}
bool begin(PLATFORM_WIRE_TYPE &w, uint8_t addr, int sda, int scl)
{
log_i("Using Arduino Wire interface.\n");
if (__has_init)return thisChip().initImpl();
__wire = &w;
__sda = sda;
__scl = scl;
#if defined(NRF52840_XXAA) || defined(NRF52832_XXAA)
__wire->begin();
#elif defined(ARDUINO_ARCH_RP2040)
__wire->end();
__wire->setSDA(__sda);
__wire->setSCL(__scl);
__wire->begin();
#else
__wire->begin(__sda, __scl);
#endif
__addr = addr;
__spi = NULL;
__i2c_master_read = NULL;
__i2c_master_write = NULL;
__has_init = thisChip().initImpl();
return __has_init;
}
bool begin(int cs, int mosi = -1, int miso = -1, int sck = -1,
PLATFORM_SPI_TYPE &spi = SPI
)
{
log_i("Using Arduino SPI interface.\n");
if (__has_init)return thisChip().initImpl();
__cs = cs;
__spi = &spi;
pinMode(__cs, OUTPUT);
digitalWrite(__cs, HIGH);
__spiSetting = new DEFAULT_SPISETTING;
if (!__spiSetting) {
return false;
}
if (mosi != -1 && miso != -1 && sck != -1) {
#if defined(NRF52840_XXAA) || defined(NRF52832_XXAA)
__spi->begin();
#elif defined(ARDUINO_ARCH_RP2040)
__spi->setSCK(sck);
__spi->setRX(miso);
__spi->setTX(mosi);
__spi->begin();
#else
__spi->begin(sck, miso, mosi);
#endif
} else {
__spi->begin();
}
__wire = NULL;
__readMask = thisChip().getReadMaskImpl();
__has_init = thisChip().initImpl();
return __has_init;
}
#elif defined(ESP_PLATFORM) && !defined(ARDUINO)
#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API))
// * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle,
// * which is useful when the bus shares multiple devices.
bool begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr)
{
log_i("Using ESP-IDF Driver interface.\n");
if (i2c_dev_bus_handle == NULL) return false;
if (__has_init)return thisChip().initImpl();
__i2c_master_read = NULL;
__i2c_master_write = NULL;
__addr = addr;
/*
i2c_master_bus_config_t i2c_bus_config;
memset(&i2c_bus_config, 0, sizeof(i2c_bus_config));
i2c_bus_config.clk_source = I2C_CLK_SRC_DEFAULT;
i2c_bus_config.i2c_port = port_num;
i2c_bus_config.scl_io_num = (gpio_num_t)__scl;
i2c_bus_config.sda_io_num = (gpio_num_t)__sda;
i2c_bus_config.glitch_ignore_cnt = 7;
i2c_new_master_bus(&i2c_bus_config, &bus_handle);
*/
bus_handle = i2c_dev_bus_handle;
__i2c_dev_conf.dev_addr_length = I2C_ADDR_BIT_LEN_7;
__i2c_dev_conf.device_address = __addr;
__i2c_dev_conf.scl_speed_hz = SENSORLIB_I2C_MASTER_SEEED;
if (ESP_OK != i2c_master_bus_add_device(bus_handle,
&__i2c_dev_conf,
&__i2c_device)) {
log_i("i2c_master_bus_add_device failed !\n");
return false;
}
log_i("Added Device Address : 0x%X New Dev Address: %p Speed :%lu \n", __addr, __i2c_device, __i2c_dev_conf.scl_speed_hz);
__has_init = thisChip().initImpl();
if (!__has_init) {
// Initialization failed, delete device
log_i("i2c_master_bus_rm_device !\n");
i2c_master_bus_rm_device(__i2c_device);
}
return __has_init;
}
#else //ESP 4.X
bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl)
{
__i2c_num = port_num;
log_i("Using ESP-IDF Driver interface.\n");
if (__has_init)return thisChip().initImpl();
__sda = sda;
__scl = scl;
__addr = addr;
__i2c_master_read = NULL;
__i2c_master_write = NULL;
i2c_config_t i2c_conf;
memset(&i2c_conf, 0, sizeof(i2c_conf));
i2c_conf.mode = I2C_MODE_MASTER;
i2c_conf.sda_io_num = sda;
i2c_conf.scl_io_num = scl;
i2c_conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
i2c_conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
i2c_conf.master.clk_speed = SENSORLIB_I2C_MASTER_SEEED;
/**
* @brief Without checking whether the initialization is successful,
* I2C may be initialized externally,
* so just make sure there is an initialization here.
*/
i2c_param_config(__i2c_num, &i2c_conf);
i2c_driver_install(__i2c_num,
i2c_conf.mode,
SENSORLIB_I2C_MASTER_RX_BUF_DISABLE,
SENSORLIB_I2C_MASTER_TX_BUF_DISABLE, 0);
__has_init = thisChip().initImpl();
return __has_init;
}
#endif //ESP 5.X
#endif
bool begin(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback)
{
log_i("Using Custom interface.\n");
if (__has_init)return thisChip().initImpl();
__i2c_master_read = readRegCallback;
__i2c_master_write = writeRegCallback;
__addr = addr;
#if defined(ARDUINO)
__spi = NULL;
#endif
__has_init = thisChip().initImpl();
return __has_init;
}
void setGpioWriteCallback(gpio_write_fptr_t cb)
{
__set_gpio_level = cb;
}
void setGpioReadCallback(gpio_read_fptr_t cb)
{
__get_gpio_level = cb;
}
void setGpioModeCallback(gpio_mode_fptr_t cb)
{
__set_gpio_mode = cb;
}
void setDelayCallback(delay_ms_fptr_t cb)
{
__delay_ms = cb;
}
protected:
inline void setGpioMode(uint32_t gpio, uint8_t mode)
{
if (__set_gpio_mode) {
return __set_gpio_mode(gpio, mode);
}
#if defined(ARDUINO) || defined(ESP_PLATFORM)
return pinMode(gpio, mode);
#endif
}
inline void setGpioLevel(uint32_t gpio, uint8_t level)
{
if (__set_gpio_level) {
return __set_gpio_level(gpio, level);
}
#if defined(ARDUINO) || defined(ESP_PLATFORM)
return digitalWrite(gpio, level);
#endif
}
inline int getGpioLevel(uint32_t gpio)
{
if (__get_gpio_level) {
return __get_gpio_level(gpio);
}
#if defined(ARDUINO) || defined(ESP_PLATFORM)
return digitalRead(gpio);
#endif
}
bool probe()
{
#if defined(ARDUINO)
if (__wire) {
__wire->beginTransmission(__addr);
return __wire->endTransmission() == 0;
}
return false;
#elif defined(ESP_PLATFORM)
#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API))
return i2c_master_probe(bus_handle, __addr, 1000);
#else
return true;
#endif
#else
return true;
#endif
}
//! Write method
int writeRegister(uint8_t reg, uint8_t norVal, uint8_t orVal)
{
int val = readRegister(reg);
if (val == DEV_WIRE_ERR) {
return DEV_WIRE_ERR;
}
val &= norVal;
val |= orVal;
return writeRegister(reg, val);
}
int writeRegister(int reg, uint8_t val)
{
return writeRegister(reg, &val, 1);
}
int writeRegister(int reg, RegData_t data)
{
return writeRegister(reg, (uint8_t *)&data.full, 2);
}
int writeThenRead(uint8_t *write_buffer, uint8_t write_len, uint8_t *read_buffer, uint8_t read_len)
{
#if defined(ARDUINO)
if (__wire) {
__wire->beginTransmission(__addr);
__wire->write(write_buffer, write_len);
if (__wire->endTransmission(__sendStop) != 0) {
return DEV_WIRE_ERR;
}
__wire->requestFrom(__addr, read_len);
return __wire->readBytes(read_buffer, read_len) == read_len ? DEV_WIRE_NONE : DEV_WIRE_ERR;
}
#elif defined(ESP_PLATFORM)
#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API))
if (ESP_OK == i2c_master_transmit_receive(
__i2c_device,
write_buffer,
write_len,
read_buffer,
read_len,
-1)) {
return DEV_WIRE_NONE;
}
#else //ESP_IDF_VERSION
if (ESP_OK == i2c_master_write_read_device(
__i2c_num,
__addr,
write_buffer,
write_len,
read_buffer,
read_len,
SENSORLIB_I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS)) {
return DEV_WIRE_NONE;
}
#endif //ESP_IDF_VERSION
#endif //ESP_PLATFORM
return DEV_WIRE_ERR;
}
int writeBuffer(uint8_t *buf, size_t length)
{
#if defined(ARDUINO)
if (__wire) {
__wire->beginTransmission(__addr);
__wire->write(buf, length);
uint8_t ret = (__wire->endTransmission());
return ret == 0 ? DEV_WIRE_NONE : DEV_WIRE_ERR;
}
#elif defined(ESP_PLATFORM)
#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API))
if (ESP_OK == i2c_master_transmit(
__i2c_device,
buf,
length,
-1)) {
return DEV_WIRE_NONE;
}
#else //ESP_IDF_VERSION
if (ESP_OK == i2c_master_write_to_device(__i2c_num,
__addr,
buf,
length,
SENSORLIB_I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS)) {
return DEV_WIRE_NONE;
}
#endif //ESP_IDF_VERSION
#endif //ESP_PLATFORM
return DEV_WIRE_ERR;
}
int writeRegister(int reg, uint8_t *buf, uint8_t length)
{
if (__i2c_master_write) {
return __i2c_master_write(__addr, reg, buf, length);
}
#if defined(ARDUINO)
if (__wire) {
__wire->beginTransmission(__addr);
if (__reg_addr_len == 1) {
__wire->write(reg);
} else {
for (int i = 0; i < __reg_addr_len; ++i) {
__wire->write(reg >> (8 * ((__reg_addr_len - 1) - i)));
}
}
__wire->write(buf, length);
return (__wire->endTransmission() == 0) ? DEV_WIRE_NONE : DEV_WIRE_ERR;
}
if (__spi) {
__spi->beginTransaction(*__spiSetting);
digitalWrite(__cs, LOW);
if (__reg_addr_len == 1) {
__spi->transfer(reg);
} else {
for (int i = 0; i < __reg_addr_len; ++i) {
__spi->transfer(reg >> (8 * ((__reg_addr_len - 1) - i)));
}
}
__spi->transfer(buf, length);
digitalWrite(__cs, HIGH);
__spi->endTransaction();
return DEV_WIRE_NONE;
}
return DEV_WIRE_ERR;
#elif defined(ESP_PLATFORM)
uint8_t *write_buffer = (uint8_t *)malloc(sizeof(uint8_t) * (length + __reg_addr_len));
if (!write_buffer) {
return DEV_WIRE_ERR;
}
write_buffer[0] = reg;
memcpy(write_buffer, &reg, __reg_addr_len);
memcpy(write_buffer + __reg_addr_len, buf, length);
int ret = writeBuffer(write_buffer, __reg_addr_len + length);
free(write_buffer);
return ret;
#endif //ESP_PLATFORM
}
//! Read method
int readRegister(int reg)
{
uint8_t val = 0;
return readRegister(reg, &val, 1) == -1 ? -1 : val;
}
int readRegister(int reg, RegData_t *data)
{
return readRegister(reg, (uint8_t *)data, 2);
}
int readRegister(int reg, uint8_t *buf, uint8_t length)
{
if (__i2c_master_read) {
return __i2c_master_read(__addr, reg, buf, length);
}
#if defined(ARDUINO)
if (__wire) {
__wire->beginTransmission(__addr);
if (__reg_addr_len == 1) {
__wire->write(reg);
} else {
for (int i = 0; i < __reg_addr_len; ++i) {
__wire->write(reg >> (8 * ((__reg_addr_len - 1) - i)));
}
}
if (__wire->endTransmission(__sendStop) != 0) {
return DEV_WIRE_ERR;
}
__wire->requestFrom(__addr, length);
return __wire->readBytes(buf, length) == length ? DEV_WIRE_NONE : DEV_WIRE_ERR;
}
if (__spi) {
__spi->beginTransaction(*__spiSetting);
digitalWrite(__cs, LOW);
if (__reg_addr_len == 1) {
__spi->transfer(__readMask != -1 ? (reg | __readMask) : reg);
} else {
uint8_t firstBytes = reg >> (8 * ((__reg_addr_len - 1)));
__spi->transfer(__readMask != -1 ? (firstBytes | __readMask) : firstBytes);
for (int i = 1; i < __reg_addr_len; ++i) {
__spi->transfer(reg >> (8 * ((__reg_addr_len - 1) - i)));
}
}
for (size_t i = 0; i < length; i++) {
buf[i] = __spi->transfer(0x00);
}
digitalWrite(__cs, HIGH);
__spi->endTransaction();
return DEV_WIRE_NONE;
}
#elif defined(ESP_PLATFORM)
#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API))
if (ESP_OK == i2c_master_transmit_receive(
__i2c_device,
(const uint8_t *)&reg,
__reg_addr_len,
buf,
length,
-1)) {
return DEV_WIRE_NONE;
}
#else //ESP_IDF_VERSION
if (ESP_OK == i2c_master_write_read_device(__i2c_num,
__addr,
(uint8_t *)&reg,
__reg_addr_len,
buf,
length,
SENSORLIB_I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS)) {
return DEV_WIRE_NONE;
}
#endif //ESP_IDF_VERSION
#endif //ESP_PLATFORM
return DEV_WIRE_ERR;
}
bool inline clrRegisterBit(int registers, uint8_t bit)
{
int val = readRegister(registers);
if (val == DEV_WIRE_ERR) {
return false;
}
return writeRegister(registers, (val & (~_BV(bit)))) == 0;
}
bool inline setRegisterBit(int registers, uint8_t bit)
{
int val = readRegister(registers);
if (val == DEV_WIRE_ERR) {
return false;
}
return writeRegister(registers, (val | (_BV(bit)))) == 0;
}
bool inline getRegisterBit(int registers, uint8_t bit)
{
int val = readRegister(registers);
if (val == DEV_WIRE_ERR) {
return false;
}
return val & _BV(bit);
}
uint16_t inline readRegisterH8L4(uint8_t highReg, uint8_t lowReg)
{
int h8 = readRegister(highReg);
int l4 = readRegister(lowReg);
if (h8 == DEV_WIRE_ERR || l4 == DEV_WIRE_ERR)return 0;
return (h8 << 4) | (l4 & 0x0F);
}
uint16_t inline readRegisterH8L5(uint8_t highReg, uint8_t lowReg)
{
int h8 = readRegister(highReg);
int l5 = readRegister(lowReg);
if (h8 == DEV_WIRE_ERR || l5 == DEV_WIRE_ERR)return 0;
return (h8 << 5) | (l5 & 0x1F);
}
uint16_t inline readRegisterH6L8(uint8_t highReg, uint8_t lowReg)
{
int h6 = readRegister(highReg);
int l8 = readRegister(lowReg);
if (h6 == DEV_WIRE_ERR || l8 == DEV_WIRE_ERR)return 0;
return ((h6 & 0x3F) << 8) | l8;
}
uint16_t inline readRegisterH5L8(uint8_t highReg, uint8_t lowReg)
{
int h5 = readRegister(highReg);
int l8 = readRegister(lowReg);
if (h5 == DEV_WIRE_ERR || l8 == DEV_WIRE_ERR)return 0;
return ((h5 & 0x1F) << 8) | l8;
}
void setRegAddressLength(uint8_t len)
{
__reg_addr_len = len;
}
void setReadRegisterSendStop(bool sendStop)
{
__sendStop = sendStop;
}
/*
* CRTP Helper
*/
protected:
// bool begin()
// {
// #if defined(ARDUINO)
// if (__has_init) return thisChip().initImpl();
// __has_init = true;
// if (__wire) {
// log_i("SDA:%d SCL:%d", __sda, __scl);
// #if defined(NRF52840_XXAA) || defined(NRF52832_XXAA)
// __wire->begin();
// #elif defined(ARDUINO_ARCH_RP2040)
// __wire->end();
// __wire->setSDA(__sda);
// __wire->setSCL(__scl);
// __wire->begin();
// #else
// __wire->begin(__sda, __scl);
// #endif
// }
// if (__spi) {
// // int cs, int mosi = -1, int miso = -1, int sck = -1, SPIClass &spi = SPI
// begin(__cs, __mosi, __miso, __sck, *__spi);
// }
// #endif /*ARDUINO*/
// return thisChip().initImpl();
// }
void end()
{
#if defined(ARDUINO)
if (__wire) {
#if defined(ESP_IDF_VERSION)
#if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(4,4,0)
__wire->end();
#endif /*ESP_IDF_VERSION*/
#endif /*ESP_IDF_VERSION*/
}
#endif /*ARDUINO*/
}
inline const chipType &thisChip() const
{
return static_cast<const chipType &>(*this);
}
inline chipType &thisChip()
{
return static_cast<chipType &>(*this);
}
protected:
bool __has_init = false;
#if defined(ARDUINO)
PLATFORM_WIRE_TYPE *__wire = NULL;
PLATFORM_SPI_TYPE *__spi = NULL;
SPISettings *__spiSetting = NULL;
uint8_t __dataOrder = SPI_DATA_ORDER;
uint8_t __dataMode = SPI_MODE0;
uint32_t __freq = 400000;
#elif defined(ESP_PLATFORM)
i2c_port_t __i2c_num;
#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API))
i2c_master_bus_handle_t bus_handle;
i2c_master_dev_handle_t __i2c_device;
i2c_device_config_t __i2c_dev_conf;
#endif //ESP_IDF_VERSION
#endif //ESP_PLATFORM
int __readMask = -1;
int __sda = -1;
int __scl = -1;
int __cs = -1;
int __miso = -1;
int __mosi = -1;
int __sck = -1;
bool __sendStop = true;
uint8_t __addr = 0xFF;
uint8_t __reg_addr_len = 1;
iic_fptr_t __i2c_master_read = NULL;
iic_fptr_t __i2c_master_write = NULL;
gpio_write_fptr_t __set_gpio_level = NULL;
gpio_read_fptr_t __get_gpio_level = NULL;
gpio_mode_fptr_t __set_gpio_mode = NULL;
delay_ms_fptr_t __delay_ms = NULL;
};

View File

@ -0,0 +1,235 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file SensorDRV2605.tpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-03
* @note Source code from https://github.com/adafruit/Adafruit_DRV2605_Library
*/
#pragma once
#include "REG/DRV2605Constants.h"
#include "SensorCommon.tpp"
class SensorDRV2605 :
public SensorCommon<SensorDRV2605>
{
friend class SensorCommon<SensorDRV2605>;
public:
#if defined(ARDUINO)
SensorDRV2605(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = DRV2605_SLAVE_ADDRESS)
{
__wire = &w;
__sda = sda;
__scl = scl;
__addr = addr;
}
#endif
SensorDRV2605()
{
#if defined(ARDUINO)
__wire = &Wire;
__sda = DEFAULT_SDA;
__scl = DEFAULT_SCL;
#endif
__addr = DRV2605_SLAVE_ADDRESS;
}
~SensorDRV2605()
{
deinit();
}
#if defined(ARDUINO)
bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = DRV2605_SLAVE_ADDRESS)
{
return SensorCommon::begin(w, addr, sda, scl);
}
#endif
void deinit()
{
// end();
}
/**************************************************************************/
/*!
@brief Select the haptic waveform to use.
@param slot The waveform slot to set, from 0 to 7
@param w The waveform sequence value, refers to an index in the ROM library.
Playback starts at slot 0 and continues through to slot 7, stopping if it
encounters a value of 0. A list of available waveforms can be found in
section 11.2 of the datasheet: http://www.adafruit.com/datasheets/DRV2605.pdf
*/
/**************************************************************************/
void setWaveform(uint8_t slot, uint8_t w)
{
writeRegister(DRV2605_REG_WAVESEQ1 + slot, w);
}
/**************************************************************************/
/*!
@brief Select the waveform library to use.
@param lib Library to use, 0 = Empty, 1-5 are ERM, 6 is LRA.
See section 7.6.4 in the datasheet for more details:
http://www.adafruit.com/datasheets/DRV2605.pdf
*/
/**************************************************************************/
void selectLibrary(uint8_t lib)
{
writeRegister(DRV2605_REG_LIBRARY, lib);
}
/**************************************************************************/
/*!
@brief Start playback of the waveforms (start moving!).
*/
/**************************************************************************/
void run()
{
writeRegister(DRV2605_REG_GO, 1);
}
/**************************************************************************/
/*!
@brief Stop playback.
*/
/**************************************************************************/
void stop()
{
writeRegister(DRV2605_REG_GO, 0);
}
/**************************************************************************/
/*!
@brief Set the device mode.
@param mode Mode value, see datasheet section 7.6.2:
http://www.adafruit.com/datasheets/DRV2605.pdf
0: Internal trigger, call run() to start playback\n
1: External trigger, rising edge on IN pin starts playback\n
2: External trigger, playback follows the state of IN pin\n
3: PWM/analog input\n
4: Audio\n
5: Real-time playback\n
6: Diagnostics\n
7: Auto calibration
*/
/**************************************************************************/
void setMode(uint8_t mode)
{
writeRegister(DRV2605_REG_MODE, mode);
}
/**************************************************************************/
/*!
@brief Set the realtime value when in RTP mode, used to directly drive the
haptic motor.
@param rtp 8-bit drive value.
*/
/**************************************************************************/
void setRealtimeValue(uint8_t rtp)
{
writeRegister(DRV2605_REG_RTPIN, rtp);
}
/**************************************************************************/
/*!
@brief Use ERM (Eccentric Rotating Mass) mode.
*/
/**************************************************************************/
void useERM()
{
writeRegister(DRV2605_REG_FEEDBACK, readRegister(DRV2605_REG_FEEDBACK) & 0x7F);
}
/**************************************************************************/
/*!
@brief Use LRA (Linear Resonance Actuator) mode.
*/
/**************************************************************************/
void useLRA()
{
writeRegister(DRV2605_REG_FEEDBACK, readRegister(DRV2605_REG_FEEDBACK) | 0x80);
}
private:
bool initImpl()
{
int chipID = readRegister(DRV2605_REG_STATUS);
if (chipID == -1) {
return false;
}
chipID >>= 5;
if (chipID != DRV2604_CHIP_ID &&
chipID != DRV2605_CHIP_ID &&
chipID != DRV2604L_CHIP_ID &&
chipID != DRV2605L_CHIP_ID ) {
LOG("ChipID:0x%x should be 0x03 or 0x04 or 0x06 or 0x07\n", chipID);
return false;
}
writeRegister(DRV2605_REG_MODE, 0x00); // out of standby
writeRegister(DRV2605_REG_RTPIN, 0x00); // no real-time-playback
writeRegister(DRV2605_REG_WAVESEQ1, 1); // strong click
writeRegister(DRV2605_REG_WAVESEQ2, 0); // end sequence
writeRegister(DRV2605_REG_OVERDRIVE, 0); // no overdrive
writeRegister(DRV2605_REG_SUSTAINPOS, 0);
writeRegister(DRV2605_REG_SUSTAINNEG, 0);
writeRegister(DRV2605_REG_BREAK, 0);
writeRegister(DRV2605_REG_AUDIOMAX, 0x64);
// ERM open loop
// turn off N_ERM_LRA
writeRegister(DRV2605_REG_FEEDBACK,
readRegister(DRV2605_REG_FEEDBACK) & 0x7F);
// turn on ERM_OPEN_LOOP
writeRegister(DRV2605_REG_CONTROL3,
readRegister(DRV2605_REG_CONTROL3) | 0x20);
return true;
}
int getReadMaskImpl()
{
return -1;
}
protected:
};

View File

@ -0,0 +1,349 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* 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.
*
* @file SensorLTR553ALS.tpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-09
*
*/
#pragma once
#include "REG/LTR533Constants.h"
#include "SensorCommon.tpp"
class SensorLTR553 :
public SensorCommon<SensorLTR553>
{
friend class SensorCommon<SensorLTR553>;
public:
enum IrqLevel {
ALS_IRQ_ACTIVE_LOW, // INT pin is considered active when it is a logic 0 (default)
ALS_IRQ_ACTIVE_HIGH // INT pin is considered active when it is a logic 1
};
enum IrqMode {
ALS_IRQ_ONLY_PS = 1, // Only PS measurement can trigger interrupt
ALS_IRQ_ONLY_ALS, // Only ALS measurement can trigger interrupt
ALS_IRQ_BOTH, // Both ALS and PS measurement can trigger interrupt
};
enum LightSensorGain {
ALS_GAIN_1X = 0x00, // 1 lux to 64k lux (default)
ALS_GAIN_2X = 0x01, // 0.5 lux to 32k lux
ALS_GAIN_4X = 0x02, // 0.25 lux to 16k lux
ALS_GAIN_8X = 0x03, // 0.125 lux to 8k lux
ALS_GAIN_48X = 0x06, // 0.02 lux to 1.3k lux
ALS_GAIN_96X = 0x07, // 0.01 lux to 600 lux
};
enum PsLedPeriod {
PS_LED_PLUSE_30KHZ = 0x00,
PS_LED_PLUSE_40KHZ,
PS_LED_PLUSE_50KHZ,
PS_LED_PLUSE_60KHZ,
PS_LED_PLUSE_70KHZ,
PS_LED_PLUSE_80KHZ,
PS_LED_PLUSE_90KHZ,
PS_LED_PLUSE_100KHZ,
};
enum PsLedDuty {
PS_LED_DUTY_25 = 0x00,
PS_LED_DUTY_50,
PS_LED_DUTY_75,
PS_LED_DUTY_100,
};
enum PsLedCurrent {
PS_LED_CUR_5MA = 0x00,
PS_LED_CUR_10MA,
PS_LED_CUR_20MA,
PS_LED_CUR_50MA,
PS_LED_CUR_100MA,
};
enum PsRate {
PS_MEAS_RATE_50MS,
PS_MEAS_RATE_70MS,
PS_MEAS_RATE_100MS,
PS_MEAS_RATE_200MS,
PS_MEAS_RATE_500MS,
PS_MEAS_RATE_1000MS,
PS_MEAS_RATE_2000MS,
PS_MEAS_RATE_10MS = 8,
};
enum IntegrationTime {
ALS_INTEGRATION_TIME_100MS = 0x00,
ALS_INTEGRATION_TIME_50MS,
ALS_INTEGRATION_TIME_200MS,
ALS_INTEGRATION_TIME_400MS,
ALS_INTEGRATION_TIME_150MS,
ALS_INTEGRATION_TIME_250MS,
ALS_INTEGRATION_TIME_300MS,
ALS_INTEGRATION_TIME_350MS,
};
enum MeasurementRate {
ALS_MEASUREMENT_TIME_50MS,
ALS_MEASUREMENT_TIME_100MS,
ALS_MEASUREMENT_TIME_200MS,
ALS_MEASUREMENT_TIME_500MS,
ALS_MEASUREMENT_TIME_1000MS,
ALS_MEASUREMENT_TIME_2000MS,
};
#if defined(ARDUINO)
SensorLTR553(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = LTR553_SLAVE_ADDRESS)
{
__wire = &w;
__sda = sda;
__scl = scl;
__addr = addr;
}
#endif
SensorLTR553()
{
#if defined(ARDUINO)
__wire = &Wire;
__sda = DEFAULT_SDA;
__scl = DEFAULT_SCL;
#endif
__addr = LTR553_SLAVE_ADDRESS;
}
~SensorLTR553()
{
deinit();
}
#if defined(ARDUINO)
bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = LTR553_SLAVE_ADDRESS)
{
return SensorCommon::begin(w, addr, sda, scl);
}
#endif
void deinit()
{
// end();
}
void setIRQLevel(IrqLevel level)
{
level ? setRegisterBit(LTR553_REG_INTERRUPT, 2) : clrRegisterBit(LTR553_REG_INTERRUPT, 2);
}
void enableIRQ(IrqMode mode)
{
writeRegister(LTR553_REG_INTERRUPT, 0xFC, mode);
}
void disableIRQ()
{
writeRegister(LTR553_REG_INTERRUPT, 0xFC, 0x00);
}
//! Light Sensor !
bool psAvailable()
{
return getRegisterBit(LTR553_REG_ALS_PS_STATUS, 0);
}
void setLightSensorThreshold(uint16_t low, uint16_t high)
{
uint8_t buffer[4] = {
(uint8_t)(high & 0xFF),
(uint8_t)((high >> 8) & 0xFF),
(uint8_t)(low & 0xFF),
(uint8_t)((low >> 8) & 0xFF),
};
writeRegister(LTR553_REG_ALS_THRES_UP_0, buffer, 4);
}
// Controls the N number of times the measurement data is outside the range
// defined by the upper and lower threshold limits before asserting the interrupt.
void setLightSensorPersists(uint8_t count)
{
writeRegister(LTR553_REG_INTERRUPT_PERSIST, 0xF0, count - 1);
}
void setLightSensorRate(IntegrationTime integrationTime, MeasurementRate measurementRate)
{
writeRegister(LTR553_REG_ALS_MEAS_RATE, 0x00, (integrationTime & 0xF) << 8 | (measurementRate & 0xF));
}
void enableLightSensor()
{
setRegisterBit(LTR553_REG_ALS_CONTR, 0);
}
void disableLightSensor()
{
clrRegisterBit(LTR553_REG_ALS_CONTR, 0);
}
void setLightSensorGain(LightSensorGain gain)
{
writeRegister(LTR553_REG_ALS_CONTR, 0xE3, gain);
}
int getLightSensor(uint8_t ch)
{
uint8_t buffer[2] = {0};
// Check ALS Data is Valid
if (getRegisterBit(LTR553_REG_ALS_PS_STATUS, 7) != false) {
return 0;
}
int val = readRegister(ch == 1 ? LTR553_REG_ALS_DATA_CH1_0 : LTR553_REG_ALS_DATA_CH0_0, buffer, 2);
if (val == DEV_WIRE_ERR) {
return DEV_WIRE_ERR;
}
return buffer[0] | (buffer[1] << 8);
}
//! Proximity sensor !
// Controls the N number of times the measurement data is outside the range
// defined by the upper and lower threshold limits before asserting the interrupt.
void setProximityPersists(uint8_t count)
{
writeRegister(LTR553_REG_INTERRUPT_PERSIST, 0x0F, count == 0 ? 0 : count - 1);
}
void setProximityThreshold(uint16_t low, uint16_t high)
{
writeRegister(LTR553_REG_PS_THRES_UP_0, lowByte(high));
writeRegister(LTR553_REG_PS_THRES_UP_1, lowByte(high >> 8) & 0x0F);
writeRegister(LTR553_REG_PS_THRES_LOW_0, lowByte(low));
writeRegister(LTR553_REG_PS_THRES_LOW_1, lowByte(low >> 8) & 0x0F);
}
void setProximityRate(PsRate rate)
{
writeRegister(LTR553_REG_PS_MEAS_RATE, 0xF0, rate & 0x0F);
}
void enableProximity()
{
writeRegister(LTR553_REG_PS_CONTR, 0xF3u, 0x03u);
}
void disableProximity()
{
writeRegister(LTR553_REG_PS_CONTR, 0xF3u, 0x00u);
}
void enablePsIndicator()
{
setRegisterBit(LTR553_REG_PS_CONTR, 5);
}
void disablePsIndicator()
{
clrRegisterBit(LTR553_REG_PS_CONTR, 5);
}
int getProximity(bool *saturated = NULL )
{
uint8_t buffer[2] = {0};
int val = readRegister(LTR553_REG_PS_DATA_0, buffer, 2);
if (val == DEV_WIRE_ERR) {
return DEV_WIRE_ERR;
}
if (saturated) {
*saturated = buffer[1] & 0x80;
}
return buffer[0] | (buffer[1] & 0x03);
}
void setPsLedPulsePeriod(PsLedPeriod period)
{
writeRegister(LTR553_REG_PS_LED, 0x1F, period);
}
void setPsLedDutyCycle(PsLedDuty duty)
{
writeRegister(LTR553_REG_PS_LED, 0xE7, duty);
}
void setPsLedCurrnet(PsLedCurrent cur)
{
writeRegister(LTR553_REG_PS_LED, 0xF8, cur);
}
void setPsLedPulses(uint8_t pulesNum)
{
writeRegister(LTR553_REG_PS_N_PULSES, 0xF0, pulesNum & 0x0F);
}
int getPartID()
{
int val = readRegister(LTR553_REG_PART_ID);
if (val == DEV_WIRE_ERR) {
return DEV_WIRE_ERR;
}
return (val >> 4) & 0x0F;
}
int getRevisionID()
{
int val = readRegister(LTR553_REG_PART_ID);
if (val == DEV_WIRE_ERR) {
return DEV_WIRE_ERR;
}
return (val) & 0x0F;
}
int getManufacturerID()
{
// Manufacturer ID (0x05H)
return readRegister(LTR553_REG_MANUFAC_ID);
}
void reset()
{
setRegisterBit(LTR553_REG_ALS_CONTR, 1);
}
private:
bool initImpl()
{
setReadRegisterSendStop(false);
reset();
return getManufacturerID() == LTR553_DEFAULT_MAN_ID;
}
int getReadMaskImpl()
{
return -1;
}
protected:
};

View File

@ -0,0 +1,233 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file SensorLib.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-10-05
*/
#pragma once
#if defined(ARDUINO)
#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
#elif defined(ESP_PLATFORM)
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "esp_log.h"
#include "esp_err.h"
#include <cstring>
#include "esp_idf_version.h"
#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API))
#include "driver/i2c_master.h"
#else
#include "driver/i2c.h"
#endif //ESP_IDF_VERSION
#else
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#endif
#ifdef ARDUINO_ARCH_MBED
// Not supported at the moment
#error The Arduino RP2040 MBED board package is not supported when PIO is used. Use the community package by Earle Philhower.
#endif
#if defined(ARDUINO)
#if defined(ARDUINO_ARCH_RP2040)
#define PLATFORM_SPI_TYPE SPIClassRP2040
#define PLATFORM_WIRE_TYPE TwoWire
#define SPI_DATA_ORDER SPI_MSB_FIRST
#define DEFAULT_SDA (0xFF)
#define DEFAULT_SCL (0xFF)
#define DEFAULT_SPISETTING SPISettings()
#elif defined(NRF52840_XXAA) || defined(NRF52832_XXAA)
#define PLATFORM_SPI_TYPE SPIClass
#define PLATFORM_WIRE_TYPE TwoWire
#define SPI_DATA_ORDER MSBFIRST
#define DEFAULT_SDA (0xFF)
#define DEFAULT_SCL (0xFF)
#define DEFAULT_SPISETTING SPISettings()
#else
#define PLATFORM_SPI_TYPE SPIClass
#define PLATFORM_WIRE_TYPE TwoWire
#define SPI_DATA_ORDER SPI_MSBFIRST
#define DEFAULT_SDA (SDA)
#define DEFAULT_SCL (SCL)
#define DEFAULT_SPISETTING SPISettings(__freq, __dataOrder, __dataMode);
#endif
#elif defined(ESP_PLATFORM)
#define SENSORLIB_I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define SENSORLIB_I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define SENSORLIB_I2C_MASTER_TIMEOUT_MS 1000
#define SENSORLIB_I2C_MASTER_SEEED 400000
#endif
enum SensorLibInterface {
SENSORLIB_SPI_INTERFACE = 1,
SENSORLIB_I2C_INTERFACE
};
typedef struct __SensorLibPins {
int irq;
int rst;
union __ {
struct {
int sda;
int scl;
int addr;
#ifdef ARDUINO
PLATFORM_WIRE_TYPE *wire;
#endif
} i2c_dev;
struct {
int cs;
int miso;
int mosi;
int sck;
#ifdef ARDUINO
PLATFORM_SPI_TYPE *spi;
#endif
} spi_dev;
} u ;
SensorLibInterface intf;
} SensorLibConfigure;
#define SENSOR_PIN_NONE (-1)
#define DEV_WIRE_NONE (0)
#define DEV_WIRE_ERR (-1)
#define DEV_WIRE_TIMEOUT (-2)
#ifndef IRAM_ATTR
#define IRAM_ATTR
#endif
#ifdef _BV
#undef _BV
#endif
#define _BV(b) (1UL << (uint32_t)(b))
// #define LOG_PORT Serial
#ifdef LOG_PORT
#define LOG(fmt, ...) LOG_PORT.printf("[%s] " fmt "\n", __func__, ##__VA_ARGS__)
#define LOG_BIN(x) LOG_PORT.println(x,BIN);
#else
#define LOG(fmt, ...) printf("[%s] " fmt "\n", __func__, ##__VA_ARGS__)
#define LOG_BIN(x) printf("[%s] 0x%X\n", __func__, x)
#endif
#ifndef lowByte
#define lowByte(w) ((uint8_t) ((w) & 0xff))
#endif
#ifndef highByte
#define highByte(w) ((uint8_t) ((w) >> 8))
#endif
#ifndef bitRead
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#endif
#ifndef bitSet
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#endif
#ifndef bitClear
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#endif
#ifndef bitToggle
#define bitToggle(value, bit) ((value) ^= (1UL << (bit)))
#endif
#ifndef bitWrite
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))
#endif
#define SENSORLIB_ATTR_NOT_IMPLEMENTED __attribute__((error("Not implemented")))
#define SENSORLIB_COUNT(x) (sizeof(x)/sizeof(*x))
#ifdef ARDUINO
#ifndef ESP32
#ifndef log_e
#define log_e(...) Serial.printf(__VA_ARGS__)
#endif
#ifndef log_i
#define log_i(...) Serial.printf(__VA_ARGS__)
#endif
#ifndef log_d
#define log_d(...) Serial.printf(__VA_ARGS__)
#endif
#endif
#elif defined(ESP_PLATFORM)
#define log_e(...) printf(__VA_ARGS__)
#define log_i(...) printf(__VA_ARGS__)
#define log_d(...) printf(__VA_ARGS__)
#else
#define log_e(...)
#define log_i(...)
#define log_d(...)
#endif
#if !defined(ARDUINO) && defined(ESP_PLATFORM)
#ifndef INPUT
#define INPUT (0x0)
#endif
#ifndef OUTPUT
#define OUTPUT (0x1)
#endif
#ifndef RISING
#define RISING (0x01)
#endif
#ifndef FALLING
#define FALLING (0x02)
#endif
#ifndef LOW
#define LOW 0
#endif
#ifndef HIGH
#define HIGH 1
#endif
#include "platform/esp_arduino.h"
#endif

View File

@ -0,0 +1,379 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file SensorPCF85063.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-07
*
*/
#pragma once
#include "REG/PCF85063Constants.h"
#include "SensorCommon.tpp"
#include "SensorRTC.h"
class SensorPCF85063 :
public SensorCommon<SensorPCF85063>,
public RTCCommon<SensorPCF85063>
{
friend class SensorCommon<SensorPCF85063>;
friend class RTCCommon<SensorPCF85063>;
public:
enum {
CLK_32_768KHZ,
CLK_1024KHZ,
CLK_32HZ,
CLK_1HZ,
};
#if defined(ARDUINO)
SensorPCF85063(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = PCF85063_SLAVE_ADDRESS)
{
__wire = &w;
__sda = sda;
__scl = scl;
__addr = addr;
}
#endif
SensorPCF85063()
{
#if defined(ARDUINO)
__wire = &Wire;
__sda = DEFAULT_SDA;
__scl = DEFAULT_SCL;
#endif
__addr = PCF85063_SLAVE_ADDRESS;
}
~SensorPCF85063()
{
deinit();
}
#if defined(ARDUINO)
bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = PCF85063_SLAVE_ADDRESS)
{
return SensorCommon::begin(w, addr, sda, scl);
}
#endif
void deinit()
{
// end();
}
void setDateTime(RTC_DateTime datetime)
{
setDateTime(datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second);
}
void setDateTime(uint16_t year,
uint8_t month,
uint8_t day,
uint8_t hour,
uint8_t minute,
uint8_t second)
{
uint8_t buffer[7];
buffer[0] = DEC2BCD(second) & 0x7F;
buffer[1] = DEC2BCD(minute);
buffer[2] = DEC2BCD(hour);
buffer[3] = DEC2BCD(day);
buffer[4] = getDayOfWeek(day, month, year);
buffer[5] = DEC2BCD(month);
buffer[6] = DEC2BCD(year % 100);
writeRegister(PCF85063_SEC_REG, buffer, 7);
}
RTC_DateTime getDateTime()
{
RTC_DateTime datetime;
uint8_t buffer[7];
readRegister(PCF85063_SEC_REG, buffer, 7);
datetime.available = ((buffer[0] & 0x80) == 0x80) ? false : true;
datetime.second = BCD2DEC(buffer[0] & 0x7F);
datetime.minute = BCD2DEC(buffer[1] & 0x7F);
if (is24Hour) {
datetime.hour = BCD2DEC(buffer[2] & 0x3F); // 24-hour mode
} else {
datetime.AMPM = (buffer[2] & 0x20) == 0x20 ? 'A' : 'P';
datetime.hour = BCD2DEC(buffer[2] & 0x1F); // 12-hour mode
}
datetime.day = BCD2DEC(buffer[3] & 0x3F);
datetime.week = BCD2DEC(buffer[4] & 0x07);
datetime.month = BCD2DEC(buffer[5] & 0x1F);
datetime.year = BCD2DEC(buffer[6]) + 2000;
return datetime;
}
void getDateTime(struct tm *timeinfo)
{
if (!timeinfo)return;
*timeinfo = conversionUnixTime(getDateTime());
}
/*
Defalut use 24H mode
bool is24HourMode()
{
return is24Hour;
}
bool is12HourMode()
{
return !is24Hour;
}
void set24Hour()
{
is24Hour = true;
clrRegisterBit(PCF85063_CTRL1_REG, 1);
}
void set12Hour()
{
is24Hour = false;
setRegisterBit(PCF85063_CTRL1_REG, 1);
}
*/
void stop()
{
setRegisterBit(PCF85063_CTRL1_REG, 5);
}
void start()
{
clrRegisterBit(PCF85063_CTRL1_REG, 5);
}
bool isRunning()
{
return !getRegisterBit(PCF85063_CTRL1_REG, 5);
}
void enableAlarm()
{
setRegisterBit(PCF85063_CTRL2_REG, 7);
}
void disableAlarm()
{
clrRegisterBit(PCF85063_CTRL2_REG, 7);
}
void resetAlarm()
{
clrRegisterBit(PCF85063_CTRL2_REG, 6);
}
bool isAlarmActive()
{
return getRegisterBit(PCF85063_CTRL2_REG, 6);
}
RTC_Alarm getAlarm()
{
uint8_t buffer[5];
readRegister(PCF85063_ALRM_MIN_REG, buffer, 5);
buffer[0] = BCD2DEC(buffer[0] & 0x80); //second
buffer[1] = BCD2DEC(buffer[1] & 0x40); //minute
buffer[2] = BCD2DEC(buffer[2] & 0x40); //hour
buffer[3] = BCD2DEC(buffer[3] & 0x08); //day
buffer[4] = BCD2DEC(buffer[4] & 0x08); //weekday
// RTC_Alarm(uint8_t hour, uint8_t minute, uint8_t second, uint8_t day, uint8_t week)
return RTC_Alarm(buffer[2], buffer[1], buffer[0], buffer[3], buffer[4]);
}
void setAlarm(RTC_Alarm alarm)
{
setAlarm(alarm.hour,
alarm.minute,
alarm.second,
alarm.day,
alarm.week);
}
void setAlarm(uint8_t hour,
uint8_t minute,
uint8_t second,
uint8_t day,
uint8_t week)
{
uint8_t buffer[5] = {0};
RTC_DateTime datetime = getDateTime();
uint8_t daysInMonth = getDaysInMonth(datetime.month, datetime.year);
if (second != PCF85063_NO_ALARM) {
if (second > 59) {
second = 59;
}
buffer[0] = DEC2BCD(second);
buffer[0] &= ~PCF85063_ALARM_ENABLE;
} else {
buffer[0] = PCF85063_ALARM_ENABLE;
}
if (minute != PCF85063_NO_ALARM) {
if (minute > 59) {
minute = 59;
}
buffer[1] = DEC2BCD(minute);
buffer[1] &= ~PCF85063_ALARM_ENABLE;
} else {
buffer[1] = PCF85063_ALARM_ENABLE;
}
if (hour != PCF85063_NO_ALARM) {
if (is24Hour) {
if (hour > 23) {
hour = 23;
}
buffer[2] = DEC2BCD(hour);
buffer[2] &= ~PCF85063_ALARM_ENABLE;
} else {
/*
if (hour > 12) {
hour = 12;
}
buffer[2] = DEC2BCD(hour);
buffer[2] |= isAM ? 0 : _BV(5);
buffer[2] &= ~PCF85063_ALARM_ENABLE;
*/
}
} else {
buffer[2] = PCF85063_ALARM_ENABLE;
}
if (day != PCF85063_NO_ALARM) {
//TODO:Check day in Month
buffer[3] = DEC2BCD(((day) < (1) ? (1) : ((day) > (daysInMonth) ? (daysInMonth) : (day))));
buffer[3] &= ~PCF85063_ALARM_ENABLE;
} else {
buffer[3] = PCF85063_ALARM_ENABLE;
}
if (week != PCF85063_NO_ALARM) {
if (week > 6) {
week = 6;
}
buffer[4] = DEC2BCD(week);
buffer[4] &= ~PCF85063_ALARM_ENABLE;
} else {
buffer[4] = PCF85063_ALARM_ENABLE;
}
writeRegister(PCF85063_ALRM_SEC_REG, buffer, 4);
}
void setAlarmByHours(uint8_t hour)
{
setAlarm(hour,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM);
}
void setAlarmBySecond(uint8_t second)
{
setAlarm(PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
second,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM);
}
void setAlarmByMinutes(uint8_t minute)
{
setAlarm(PCF85063_NO_ALARM,
minute,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM);
}
void setAlarmByDays(uint8_t day)
{
setAlarm(PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
day,
PCF85063_NO_ALARM);
}
void setAlarmByWeekDay(uint8_t week)
{
setAlarm(PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
week);
}
private:
bool initImpl()
{
// 230704:Does not use power-off judgment, if the RTC backup battery is not installed,
// it will return failure. Here only to judge whether the device communication is normal
//Check device is online
int ret = readRegister(PCF85063_SEC_REG);
if (ret == DEV_WIRE_ERR) {
return false;
}
if (BCD2DEC(ret & 0x7F) > 59) {
return false;
}
//Default use 24-hour mode
is24Hour = !getRegisterBit(PCF85063_CTRL1_REG, 1);
if (!is24Hour) {
// Set 24H Mode
clrRegisterBit(PCF85063_CTRL1_REG, 1);
}
//Trun on RTC
start();
return isRunning();
}
int getReadMaskImpl()
{
return -1;
}
protected:
bool is24Hour = true;
};

View File

@ -0,0 +1,359 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file SensorPCF8563.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2022-12-09
*
*/
#pragma once
#include "REG/PCF8563Constants.h"
#include "SensorCommon.tpp"
#include "SensorRTC.h"
class SensorPCF8563 :
public SensorCommon<SensorPCF8563>,
public RTCCommon<SensorPCF8563>
{
friend class SensorCommon<SensorPCF8563>;
friend class RTCCommon<SensorPCF8563>;
public:
enum {
CLK_32_768KHZ,
CLK_1024KHZ,
CLK_32HZ,
CLK_1HZ,
};
#if defined(ARDUINO)
SensorPCF8563(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = PCF8563_SLAVE_ADDRESS)
{
__wire = &w;
__sda = sda;
__scl = scl;
__addr = addr;
}
#endif
SensorPCF8563()
{
#if defined(ARDUINO)
__wire = &Wire;
__sda = DEFAULT_SDA;
__scl = DEFAULT_SCL;
#endif
__addr = PCF8563_SLAVE_ADDRESS;
}
~SensorPCF8563()
{
deinit();
}
#if defined(ARDUINO)
bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = PCF8563_SLAVE_ADDRESS)
{
return SensorCommon::begin(w, addr, sda, scl);
}
#endif
void deinit()
{
// end();
}
void setDateTime(RTC_DateTime datetime)
{
setDateTime(datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second);
}
void setDateTime(uint16_t year,
uint8_t month,
uint8_t day,
uint8_t hour,
uint8_t minute,
uint8_t second)
{
uint8_t buffer[7];
buffer[0] = DEC2BCD(second) & 0x7F;
buffer[1] = DEC2BCD(minute);
buffer[2] = DEC2BCD(hour);
buffer[3] = DEC2BCD(day);
buffer[4] = getDayOfWeek(day, month, year);
buffer[5] = DEC2BCD(month);
buffer[6] = DEC2BCD(year % 100);
if ((2000 % year) == 2000) {
buffer[5] &= 0x7F;
} else {
buffer[5] |= 0x80;
}
writeRegister(PCF8563_SEC_REG, buffer, 7);
}
RTC_DateTime getDateTime()
{
RTC_DateTime datetime;
uint8_t buffer[7];
readRegister(PCF8563_SEC_REG, buffer, 7);
datetime.available = ((buffer[0] & 0x80) == 0x80) ? false : true;
datetime.second = BCD2DEC(buffer[0] & 0x7F);
datetime.minute = BCD2DEC(buffer[1] & 0x7F);
datetime.hour = BCD2DEC(buffer[2] & 0x3F);
datetime.day = BCD2DEC(buffer[3] & 0x3F);
datetime.week = BCD2DEC(buffer[4] & 0x07);
datetime.month = BCD2DEC(buffer[5] & 0x1F);
datetime.year = BCD2DEC(buffer[6]);
//cetury : 0 = 1900 , 1 = 2000
datetime.year += (buffer[5] & PCF8563_CENTURY_MASK) ? 1900 : 2000;
return datetime;
}
void getDateTime(struct tm *timeinfo)
{
if (!timeinfo)return;
*timeinfo = conversionUnixTime(getDateTime());
}
RTC_Alarm getAlarm()
{
uint8_t buffer[4];
readRegister(PCF8563_ALRM_MIN_REG, buffer, 4);
buffer[0] = BCD2DEC(buffer[0] & 0x80); //minute
buffer[1] = BCD2DEC(buffer[1] & 0x40); //hour
buffer[2] = BCD2DEC(buffer[2] & 0x40); //day
buffer[3] = BCD2DEC(buffer[3] & 0x08); //weekday
// RTC_Alarm(uint8_t hour, uint8_t minute, uint8_t second, uint8_t day, uint8_t week)
return RTC_Alarm(buffer[1], buffer[0], 0, buffer[2], buffer[3]);
}
void enableAlarm()
{
setRegisterBit(PCF8563_STAT2_REG, 1);
}
void disableAlarm()
{
clrRegisterBit(PCF8563_STAT2_REG, 1);
}
void resetAlarm()
{
clrRegisterBit(PCF8563_STAT2_REG, 3);
}
bool isAlarmActive()
{
return getRegisterBit(PCF8563_STAT2_REG, 3);
}
void setAlarm(RTC_Alarm alarm)
{
setAlarm( alarm.hour, alarm.minute, alarm.day, alarm.week);
}
void setAlarm(uint8_t hour, uint8_t minute, uint8_t day, uint8_t week)
{
uint8_t buffer[4] = {0};
RTC_DateTime datetime = getDateTime();
uint8_t daysInMonth = getDaysInMonth(datetime.month, datetime.year);
if (minute != PCF8563_NO_ALARM) {
if (minute > 59) {
minute = 59;
}
buffer[0] = DEC2BCD(minute);
buffer[0] &= ~PCF8563_ALARM_ENABLE;
} else {
buffer[0] = PCF8563_ALARM_ENABLE;
}
if (hour != PCF8563_NO_ALARM) {
if (hour > 23) {
hour = 23;
}
buffer[1] = DEC2BCD(hour);
buffer[1] &= ~PCF8563_ALARM_ENABLE;
} else {
buffer[1] = PCF8563_ALARM_ENABLE;
}
if (day != PCF8563_NO_ALARM) {
//TODO:Check day in Month
buffer[2] = DEC2BCD(((day) < (1) ? (1) : ((day) > (daysInMonth) ? (daysInMonth) : (day))));
buffer[2] &= ~PCF8563_ALARM_ENABLE;
} else {
buffer[2] = PCF8563_ALARM_ENABLE;
}
if (week != PCF8563_NO_ALARM) {
if (week > 6) {
week = 6;
}
buffer[3] = DEC2BCD(week);
buffer[3] &= ~PCF8563_ALARM_ENABLE;
} else {
buffer[3] = PCF8563_ALARM_ENABLE;
}
writeRegister(PCF8563_ALRM_MIN_REG, buffer, 4);
}
void setAlarmByMinutes(uint8_t minute)
{
setAlarm(PCF8563_NO_ALARM, minute, PCF8563_NO_ALARM, PCF8563_NO_ALARM);
}
void setAlarmByDays(uint8_t day)
{
setAlarm(PCF8563_NO_ALARM, PCF8563_NO_ALARM, day, PCF8563_NO_ALARM);
}
void setAlarmByHours(uint8_t hour)
{
setAlarm(hour, PCF8563_NO_ALARM, PCF8563_NO_ALARM, PCF8563_NO_ALARM);
}
void setAlarmByWeekDay(uint8_t week)
{
setAlarm(PCF8563_NO_ALARM, PCF8563_NO_ALARM, PCF8563_NO_ALARM, week);
}
bool isCountdownTimerEnable()
{
uint8_t buffer[2];
buffer[0] = readRegister(PCF8563_STAT2_REG);
buffer[1] = readRegister(PCF8563_TIMER1_REG);
if (buffer[0] & PCF8563_TIMER_TIE) {
return buffer[1] & PCF8563_TIMER_TE ? true : false;
}
return false;
}
bool isCountdownTimerActive()
{
return getRegisterBit(PCF8563_STAT2_REG, 2);
}
void enableCountdownTimer()
{
setRegisterBit(PCF8563_STAT2_REG, 0);
}
void disableCountdownTimer()
{
clrRegisterBit(PCF8563_STAT2_REG, 0);
}
void setCountdownTimer(uint8_t val, uint8_t freq)
{
uint8_t buffer[3];
buffer[1] = readRegister(PCF8563_TIMER1_REG);
buffer[1] |= (freq & PCF8563_TIMER_TD10);
buffer[2] = val;
writeRegister(PCF8563_TIMER1_REG, buffer[1]);
writeRegister(PCF8563_TIMER2_REG, buffer[2]);
}
void clearCountdownTimer()
{
uint8_t val;
val = readRegister(PCF8563_STAT2_REG);
val &= ~(PCF8563_TIMER_TF | PCF8563_TIMER_TIE);
val |= PCF8563_ALARM_AF;
writeRegister(PCF8563_STAT2_REG, val);
writeRegister(PCF8563_TIMER1_REG, 0x00);
}
void enableCLK(uint8_t freq)
{
if (freq > CLK_1HZ) return;
writeRegister(PCF8563_SQW_REG, freq | PCF8563_CLK_ENABLE);
}
void disableCLK()
{
clrRegisterBit(PCF8563_SQW_REG, 7);
}
private:
bool initImpl()
{
// Check whether RTC time is valid? If it is invalid, it can be judged
// that there is a problem with the hardware, or the RTC power supply voltage is too low
/*
int count = 0;
for (int i = 0; i < 3; ++i) {
if (!getRegisterBit(PCF8563_SEC_REG, 7)) {
count++;
}
}
if (count != 3 ) {
return false;
}
*/
// 230704:Does not use power-off judgment, if the RTC backup battery is not installed,
// it will return failure. Here only to judge whether the device communication is normal
//Check device is online
int ret = readRegister(PCF8563_SEC_REG);
if (ret == DEV_WIRE_ERR) {
return false;
}
if (BCD2DEC(ret & 0x7F) > 59) {
return false;
}
// Determine whether the hardware clock year, month, and day match the internal time of the RTC.
// If they do not match, it will be updated to the compilation date
// RTC_DateTime compileDatetime = RTC_DateTime(__DATE__, __TIME__);
// RTC_DateTime hwDatetime = getDateTime();
// if (compileDatetime.year != hwDatetime.year ||
// compileDatetime.month != hwDatetime.month ||
// compileDatetime.day != hwDatetime.month
// ) {
// LOG("No match yy:mm:dd . set datetime to compilation date time");
// setDateTime(compileDatetime);
// }
return true;
}
int getReadMaskImpl()
{
return -1;
}
protected:
};

View File

@ -0,0 +1,402 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file SensorQMC6310.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#pragma once
#include "REG/QMC6310Constants.h"
#include "SensorCommon.tpp"
class Polar
{
public:
Polar(): polar(0), Gauss(0), uT(0) {}
Polar(float polar, float Gauss, float uT): polar(polar), Gauss(Gauss), uT(uT) {}
float polar;
float Gauss;
float uT;
};
class SensorQMC6310 :
public SensorCommon<SensorQMC6310>
{
friend class SensorCommon<SensorQMC6310>;
public:
enum SensorMode {
MODE_SUSPEND,
MODE_NORMAL,
MODE_SINGLE,
MODE_CONTINUOUS,
};
// Unit:Guass
enum MagRange {
RANGE_30G,
RANGE_12G,
RANGE_8G,
RANGE_2G,
};
enum OutputRate {
DATARATE_10HZ,
DATARATE_50HZ,
DATARATE_100HZ,
DATARATE_200HZ,
};
enum CtrlReg {
SET_RESET_ON,
SET_ONLY_ON,
SET_RESET_OFF,
};
enum OverSampleRatio {
OSR_8,
OSR_4,
OSR_2,
OSR_1,
};
enum DownSampleRatio {
DSR_1,
DSR_2,
DSR_4,
DSR_8,
};
#if defined(ARDUINO)
SensorQMC6310(PLATFORM_WIRE_TYPE &w, int sda = SDA, int scl = SCL, uint8_t addr = QMC6310_SLAVE_ADDRESS)
{
__wire = &w;
__sda = sda;
__scl = scl;
__addr = addr;
}
#endif
SensorQMC6310()
{
#if defined(ARDUINO)
__wire = &Wire;
__sda = SDA;
__scl = SCL;
#endif
__addr = QMC6310_SLAVE_ADDRESS;
}
~SensorQMC6310()
{
deinit();
}
#if defined(ARDUINO)
bool init(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = QMC6310_SLAVE_ADDRESS)
{
return SensorCommon::begin(w, addr, sda, scl);
}
#endif
void deinit()
{
// end();
}
void reset()
{
writeRegister(QMC6310_REG_CMD2, 0x80);
delay(10);
writeRegister(QMC6310_REG_CMD2, 0x00);
}
uint8_t getChipID()
{
return readRegister(QMC6310_REG_CHIP_ID);
}
int getStatus()
{
return readRegister(QMC6310_REG_STAT);
}
bool isDataReady()
{
if (readRegister(QMC6310_REG_STAT) & 0x01) {
return true;
}
LOG("No ready!\n");
return false;
}
bool isDataOverflow()
{
if (readRegister(QMC6310_REG_STAT) & 0x02) {
return true;
}
return false;
}
int setSelfTest(bool en)
{
return en ? setRegisterBit(QMC6310_REG_CMD2, 1)
: clrRegisterBit(QMC6310_REG_CMD2, 1);
}
int setMode(SensorMode m)
{
return writeRegister(QMC6310_REG_CMD1, 0xFC, m);
}
int setCtrlRegister(CtrlReg c)
{
return writeRegister(QMC6310_REG_CMD2, 0xFC, c);
}
int setDataOutputRate(OutputRate odr)
{
return writeRegister(QMC6310_REG_CMD1, 0xF3, (odr << 2));
}
int setOverSampleRate(OverSampleRatio osr)
{
return writeRegister(QMC6310_REG_CMD1, 0xCF, (osr << 4));
}
int setDownSampleRate(DownSampleRatio dsr)
{
return writeRegister(QMC6310_REG_CMD1, 0x3F, (dsr << 6));
}
// Define the sign for X Y and Z axis
int setSign(uint8_t x, uint8_t y, uint8_t z)
{
int sign = x + y * 2 + z * 4;
return writeRegister(QMC6310_REG_SIGN, sign);
}
int configMagnetometer(SensorMode mode, MagRange range, OutputRate odr,
OverSampleRatio osr, DownSampleRatio dsr)
{
if (setMagRange(range) != DEV_WIRE_NONE) {
return DEV_WIRE_ERR;
}
if (writeRegister(QMC6310_REG_CMD1, 0xFC, mode) != DEV_WIRE_NONE) {
return DEV_WIRE_ERR;
}
if (writeRegister(QMC6310_REG_CMD1, 0xF3, (odr << 2)) != DEV_WIRE_NONE) {
return DEV_WIRE_ERR;
}
if (writeRegister(QMC6310_REG_CMD1, 0xCF, (osr << 4)) != DEV_WIRE_NONE) {
return DEV_WIRE_ERR;
}
if (writeRegister(QMC6310_REG_CMD1, 0x3F, (dsr << 6)) != DEV_WIRE_NONE) {
return DEV_WIRE_ERR;
}
return DEV_WIRE_NONE;
}
int setMagRange(MagRange range)
{
switch (range) {
case RANGE_30G:
sensitivity = 0.1;
break;
case RANGE_12G:
sensitivity = 0.04;
break;
case RANGE_8G:
sensitivity = 0.026;
break;
case RANGE_2G:
sensitivity = 0.0066;
break;
default:
break;
}
return writeRegister(QMC6310_REG_CMD2, 0xF3, (range << 2));
}
void setOffset(int x, int y, int z)
{
x_offset = x; y_offset = y; z_offset = z;
}
int readData()
{
uint8_t buffer[6];
int16_t x, y, z;
if (readRegister(QMC6310_REG_LSB_DX, buffer,
6) != DEV_WIRE_ERR) {
x = (int16_t)(buffer[1] << 8) | (buffer[0]);
y = (int16_t)(buffer[3] << 8) | (buffer[2]);
z = (int16_t)(buffer[5] << 8) | (buffer[4]);
if (x == 32767) {
x = -((65535 - x) + 1);
}
x = (x - x_offset);
if (y == 32767) {
y = -((65535 - y) + 1);
}
y = (y - y_offset);
if (z == 32767) {
z = -((65535 - z) + 1);
}
z = (z - z_offset);
raw[0] = x;
raw[1] = y;
raw[2] = z;
mag[0] = (float)x * sensitivity;
mag[1] = (float)y * sensitivity;
mag[2] = (float)z * sensitivity;
return DEV_WIRE_NONE;
}
return DEV_WIRE_ERR;
}
void setDeclination(float dec)
{
_declination = dec;
}
bool readPolar(Polar &p)
{
if (isDataReady()) {
readData();
float x = getX();
float y = getY();
float z = getZ();
float angle = (atan2(x, -y) / PI) * 180.0 + _declination;
angle = _convertAngleToPositive(angle);
float magnitude = sqrt(x * x + y * y + z * z);
p = Polar(angle, magnitude * 100, magnitude);
return true;
}
return false;
}
int16_t getRawX()
{
return raw[0];
}
int16_t getRawY()
{
return raw[1];
}
int16_t getRawZ()
{
return raw[2];
}
float getX()
{
return mag[0];
}
float getY()
{
return mag[1];
}
float getZ()
{
return mag[2];
}
void getMag(float &x, float &y, float &z)
{
x = mag[0];
y = mag[1];
z = mag[2];
}
void dumpCtrlRegister()
{
uint8_t buffer[2];
readRegister(QMC6310_REG_CMD1, buffer, 2);
for (int i = 0; i < 2; ++i) {
#if defined(ARDUINO)
Serial.printf("CMD%d: 0x%02x", i + 1, buffer[i]);
#else
printf("CTRL%d: 0x%02x", i + 1, buffer[i]);
#endif
#if defined(ARDUINO)
Serial.print("\t\t BIN:");
Serial.println(buffer[i], BIN);
#else
LOG("\n");
#endif
}
#if defined(ARDUINO)
Serial.println();
#else
printf("\n");
#endif
}
private:
float _convertAngleToPositive(float angle)
{
if (angle >= 360.0) {
angle = angle - 360.0;
}
if (angle < 0) {
angle = angle + 360.0;
}
return angle;
}
bool initImpl()
{
reset();
return getChipID() == QMC6310_DEFAULT_ID;
}
int getReadMaskImpl()
{
return -1;
}
protected:
int16_t raw[3];
float mag[3];
float _declination;
float sensitivity;
int16_t x_offset = 0, y_offset = 0, z_offset = 0;
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,344 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* 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.
*
* @file SensorRTC.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-07
*
*/
#pragma once
#ifdef ARDUINO
#include <Arduino.h>
#else
#include <stdint.h>
#endif /*defined(ARDUINO)*/
#include <sys/time.h>
#define RTC_DAYS_IN_JANUARY (31u)
#define RTC_DAYS_IN_FEBRUARY (28u)
#define RTC_DAYS_IN_MARCH (31u)
#define RTC_DAYS_IN_APRIL (30u)
#define RTC_DAYS_IN_MAY (31u)
#define RTC_DAYS_IN_JUNE (30u)
#define RTC_DAYS_IN_JULY (31u)
#define RTC_DAYS_IN_AUGUST (31u)
#define RTC_DAYS_IN_SEPTEMBER (30u)
#define RTC_DAYS_IN_OCTOBER (31u)
#define RTC_DAYS_IN_NOVEMBER (30u)
#define RTC_DAYS_IN_DECEMBER (31u)
enum {
DATETIME_FORMAT_HM,
DATETIME_FORMAT_HMS,
DATETIME_FORMAT_YYYY_MM_DD,
DATETIME_FORMAT_MM_DD_YYYY,
DATETIME_FORMAT_DD_MM_YYYY,
DATETIME_FORMAT_YYYY_MM_DD_H_M_S,
DATETIME_FORMAT_YYYY_MM_DD_H_M_S_WEEK,
};
class RTC_DateTime
{
public:
RTC_DateTime() : year(0), month(0), day(0), hour(0), minute(0), second(0), week(0), available(false) {}
RTC_DateTime(const char *date, const char *time)
{
// sample input: date = "Dec 26 2009", time = "12:34:56"
year = 2000 + StringToUint8(date + 9);
// Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
switch (date[0]) {
case 'J':
if ( date[1] == 'a' )
month = 1;
else if ( date[2] == 'n' )
month = 6;
else
month = 7;
break;
case 'F':
month = 2;
break;
case 'A':
month = date[1] == 'p' ? 4 : 8;
break;
case 'M':
month = date[2] == 'r' ? 3 : 5;
break;
case 'S':
month = 9;
break;
case 'O':
month = 10;
break;
case 'N':
month = 11;
break;
case 'D':
month = 12;
break;
}
day = StringToUint8(date + 4);
hour = StringToUint8(time);
minute = StringToUint8(time + 3);
second = StringToUint8(time + 6);
}
RTC_DateTime(uint16_t year,
uint8_t month,
uint8_t day,
uint8_t hour,
uint8_t minute,
uint8_t second
)
{
this->year = year;
this->month = month;
this->day = day;
this->hour = hour;
this->minute = minute;
this->second = second;
this->week = week;
};
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t week;
char AMPM;
bool available;
bool operator==(RTC_DateTime d)
{
return ((d.year == year) &&
(d.month == month) &&
(d.day == day) &&
(d.hour == hour) &&
(d.minute == minute));
}
private:
uint8_t StringToUint8(const char *pString)
{
uint8_t value = 0;
// skip leading 0 and spaces
while ('0' == *pString || *pString == ' ') {
pString++;
}
// calculate number until we hit non-numeral char
while ('0' <= *pString && *pString <= '9') {
value *= 10;
value += *pString - '0';
pString++;
}
return value;
}
};
class RTC_Alarm
{
public:
RTC_Alarm(void): second(0), minute(0), hour(0), day(0), week(0) {}
RTC_Alarm(
uint8_t hour,
uint8_t minute,
uint8_t second,
uint8_t day,
uint8_t week
): second(second), minute(minute), hour(hour), day(day), week(week)
{
}
uint8_t second;
uint8_t minute;
uint8_t hour;
uint8_t day;
uint8_t week;
};
template <class chipType>
class RTCCommon
{
public:
const char *strftime(uint8_t sytle = DATETIME_FORMAT_YYYY_MM_DD_H_M_S_WEEK)
{
const char *weekString[] = {"Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat"};
static char format[64];
RTC_DateTime t = thisChip().getDateTime();
switch (sytle) {
case DATETIME_FORMAT_HM:
snprintf(format, sizeof(format), "%02d:%02d", t.hour, t.minute);
break;
case DATETIME_FORMAT_HMS:
snprintf(format, sizeof(format), "%02d:%02d:%02d", t.hour, t.minute, t.second);
break;
case DATETIME_FORMAT_YYYY_MM_DD:
snprintf(format, sizeof(format), "%d-%02d-%02d", t.year, t.month, t.day);
break;
case DATETIME_FORMAT_MM_DD_YYYY:
snprintf(format, sizeof(format), "%02d-%02d-%d", t.month, t.day, t.year);
break;
case DATETIME_FORMAT_DD_MM_YYYY:
snprintf(format, sizeof(format), "%02d-%02d-%d", t.day, t.month, t.year);
break;
case DATETIME_FORMAT_YYYY_MM_DD_H_M_S:
snprintf(format, sizeof(format), "%d-%02d-%02d/%02d:%02d:%02d", t.year, t.month, t.day, t.hour, t.minute, t.second);
break;
case DATETIME_FORMAT_YYYY_MM_DD_H_M_S_WEEK:
snprintf(format, sizeof(format), "%d-%02d-%02d/%02d:%02d:%02d - %s", t.year, t.month, t.day, t.hour, t.minute, t.second, weekString[t.week > 6 ? 0 : t.week]);
break;
default:
snprintf(format, sizeof(format), "%02d:%02d", t.hour, t.minute);
break;
}
return format;
}
struct tm conversionUnixTime(RTC_DateTime datetime)
{
struct tm t_tm;
t_tm.tm_hour = datetime.hour;
t_tm.tm_min = datetime.minute;
t_tm.tm_sec = datetime.second;
t_tm.tm_year = datetime.year - 1900; //Year, whose value starts from 1900
t_tm.tm_mon = datetime.month - 1; //Month (starting from January, 0 for January) - Value range is [0,11]
t_tm.tm_mday = datetime.day;
t_tm.tm_wday = datetime.week;
return t_tm;
}
time_t hwClockRead()
{
struct tm t_tm = conversionUnixTime(thisChip().getDateTime());
struct timeval val;
val.tv_sec = mktime(&t_tm);
val.tv_usec = 0;
#if __BSD_VISIBLE
settimeofday(&val, NULL);
#endif /*__BSD_VISIBLE*/
return val.tv_sec;
}
void hwClockWrite()
{
time_t now;
struct tm info;
time(&now);
localtime_r(&now, &info);
thisChip().setDateTime(info.tm_year + 1900,
info.tm_mon + 1,
info.tm_mday,
info.tm_hour,
info.tm_min,
info.tm_sec);
}
uint32_t getDayOfWeek(uint32_t day, uint32_t month, uint32_t year)
{
uint32_t val;
if (month < 3) {
month = 12u + month;
year--;
}
val = (day + (((month + 1u) * 26u) / 10u) + year + (year / 4u) + (6u * (year / 100u)) + (year / 400u)) % 7u;
if (0u == val) {
val = 7;
}
return (val - 1);
}
uint8_t getNextMonth(uint8_t curMonth)
{
return ((curMonth < 12u) ? (curMonth + 1u) : 1u);
}
uint16_t getNextYear(uint16_t curYear)
{
return (curYear + 1u);
}
uint32_t getLeapYear(uint32_t year)
{
uint32_t val;
if (((0u == (year % 4Lu)) && (0u != (year % 100Lu))) || (0u == (year % 400Lu))) {
val = 1uL;
} else {
val = 0uL;
}
return val;
}
uint8_t getDaysInMonth(uint8_t month, uint16_t year)
{
const uint8_t daysInMonthTable[12] = {RTC_DAYS_IN_JANUARY,
RTC_DAYS_IN_FEBRUARY,
RTC_DAYS_IN_MARCH,
RTC_DAYS_IN_APRIL,
RTC_DAYS_IN_MAY,
RTC_DAYS_IN_JUNE,
RTC_DAYS_IN_JULY,
RTC_DAYS_IN_AUGUST,
RTC_DAYS_IN_SEPTEMBER,
RTC_DAYS_IN_OCTOBER,
RTC_DAYS_IN_NOVEMBER,
RTC_DAYS_IN_DECEMBER
};
uint8_t val;
val = daysInMonthTable[month - 1u];
if (2 == month) {
if (0u != getLeapYear(year)) {
val++;
}
}
return val;
}
uint8_t BCD2DEC(uint8_t val)
{
return ((val / 16 * 10) + (val % 16));
}
uint8_t DEC2BCD(uint8_t val)
{
return ((val / 10 * 16) + (val % 10));
}
/*
* CRTP Helper
*/
protected:
inline const chipType &thisChip() const
{
return static_cast<const chipType &>(*this);
}
inline chipType &thisChip()
{
return static_cast<chipType &>(*this);
}
};

View File

@ -0,0 +1,123 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* 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.
*
* @file SensorWireHelper.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-10-05
*
*/
#include "SensorWireHelper.h"
#if defined(ARDUINO)
int SensorWireHelper::regdump(TwoWire &w, Stream &serial, uint8_t devAddr, uint8_t start, uint8_t length)
{
uint8_t *buffer = (uint8_t *)malloc(length);
if (!buffer) return -1;
w.begin();
w.beginTransmission(devAddr);
w.write(start);
if (w.endTransmission() != 0) {
free(buffer);
return -1;
}
size_t len = w.requestFrom(devAddr, length);
if (length != len) {
free(buffer);
return -1;
}
w.readBytes(buffer, length);
hexdump(buffer, length, serial);
free(buffer);
return 0;
}
void SensorWireHelper::dumpDevices(TwoWire &w, Stream &serial, int first, int last)
{
int i, j;
int ret;
serial.printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n");
for (i = 0; i < 128; i += 16) {
serial.printf("%02x: ", i);
for (j = 0; j < 16; j++) {
/* Skip unwanted addresses */
if (i + j < first || i + j > last) {
serial.printf(" ");
continue;
}
w.beginTransmission(i + j);
ret = w.endTransmission();
if (ret != 0)
serial.printf("-- ");
else
serial.printf("%02x ", i + j);
}
serial.printf("\n");
}
}
void SensorWireHelper::hexdump(uint8_t *data, size_t len, Stream &serial)
{
size_t rem_len = len;
for (size_t i = 0; i < len; i += 16) {
char str[80];
snprintf(str, 80, "%07x ", i);
size_t line_len = 16;
if (rem_len < line_len) {
line_len = rem_len;
}
for (size_t j = 0; j < line_len; j++) {
snprintf(&str[8 + j * 3], 80, "%02x ", data[i + j]);
}
for (size_t j = line_len; j < 16; j++) {
snprintf(&str[8 + j * 3], 80, " ");
}
str[56] = '|';
str[57] = ' ';
for (size_t j = 0; j < line_len; j++) {
char c = data[i + j];
if ((c < ' ') || (c > '~')) {
c = '.';
}
snprintf(&str[58 + j], 80, "%c", c);
}
for (size_t j = line_len; j < 16; j++) {
snprintf(&str[58 + j], 80, " ");
}
serial.println(str);
rem_len -= 16;
}
}
#endif //ARDUINO

View File

@ -0,0 +1,46 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* 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.
*
* @file SensorWireHelper.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-10
*
*/
#pragma once
#if defined(ARDUINO)
#include <Arduino.h>
#include <Wire.h>
class SensorWireHelper
{
public:
static int regdump(TwoWire &w, Stream &serial, uint8_t devAddr, uint8_t start, uint8_t len);
static void dumpDevices(TwoWire &w, Stream &serial = Serial, int first = 0, int last = 127);
static void hexdump(uint8_t *data, size_t len, Stream &serial = Serial);
};
#endif /*ARDUINO*/

View File

@ -0,0 +1,312 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file TouchDrvCHSC5816.tpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-12
*
*/
#pragma once
#include "REG/CHSC5816Constants.h"
#include "TouchDrvInterface.hpp"
#include "SensorCommon.tpp"
typedef struct __CHSC5816_Header {
uint16_t fw_ver;
uint16_t checksum;
uint32_t sig;
uint32_t vid_pid;
uint16_t raw_offet;
uint16_t dif_offet;
} CHSC5816_Header_t;
union __CHSC5816_PointReg {
struct {
uint8_t status;
uint8_t fingerNumber;
uint8_t x_l8;
uint8_t y_l8;
uint8_t z;
uint8_t x_h4: 4;
uint8_t y_h4: 4;
uint8_t id: 4;
uint8_t event: 4;
uint8_t p2;
} rp;
unsigned char data[8];
};
class TouchDrvCHSC5816 :
public TouchDrvInterface,
public SensorCommon<TouchDrvCHSC5816>
{
friend class SensorCommon<TouchDrvCHSC5816>;
public:
#if defined(ARDUINO)
TouchDrvCHSC5816(PLATFORM_WIRE_TYPE &w,
int sda = DEFAULT_SDA,
int scl = DEFAULT_SCL,
uint8_t addr = CHSC5816_SLAVE_ADDRESS)
{
__wire = &w;
__sda = sda;
__scl = scl;
__rst = SENSOR_PIN_NONE;
__irq = SENSOR_PIN_NONE;
__addr = addr;
}
#endif
TouchDrvCHSC5816()
{
#if defined(ARDUINO)
__wire = &Wire;
__sda = DEFAULT_SDA;
__scl = DEFAULT_SCL;
#endif
__rst = SENSOR_PIN_NONE;
__irq = SENSOR_PIN_NONE;
__addr = CHSC5816_SLAVE_ADDRESS;
}
~TouchDrvCHSC5816()
{
// deinit();
}
#if defined(ARDUINO)
bool begin(PLATFORM_WIRE_TYPE &w,
uint8_t addr = CHSC5816_SLAVE_ADDRESS,
int sda = DEFAULT_SDA,
int scl = DEFAULT_SCL)
{
return SensorCommon::begin(w, addr, sda, scl);
}
#endif
#if defined(ESP_PLATFORM) && !defined(ARDUINO)
#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API))
bool begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr)
{
return SensorCommon::begin(i2c_dev_bus_handle, addr);
}
#else
bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl)
{
return SensorCommon::begin(port_num, addr, sda, scl);
}
#endif //ESP_IDF_VERSION
#endif
bool begin(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback)
{
return SensorCommon::begin(addr, readRegCallback, writeRegCallback);
}
void reset()
{
if (__rst != SENSOR_PIN_NONE) {
this->setGpioLevel(__rst, LOW);
delay(3);
this->setGpioLevel(__rst, HIGH);
delay(5);
}
}
uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t get_point = 1)
{
__CHSC5816_PointReg touch;
// CHSC5816_REG_POINT
uint8_t write_buffer[] = {0x20, 0x00, 0x00, 0x2c};
writeThenRead(write_buffer, SENSORLIB_COUNT(write_buffer), touch.data, 8);
if (touch.rp.status == 0xFF && touch.rp.fingerNumber == 0) {
return 0;
}
if (x_array) {
*x_array = (unsigned int)(touch.rp.x_h4 << 8) | touch.rp.x_l8;
}
if (y_array) {
*y_array = (unsigned int)(touch.rp.y_h4 << 8) | touch.rp.y_l8;
}
updateXY(1, x_array, y_array);
return 1;
}
bool isPressed()
{
if (__irq != SENSOR_PIN_NONE) {
return this->getGpioLevel(__irq) == LOW;
}
return getPoint(NULL, NULL);
}
const char *getModelName()
{
return "CHSC5816";
}
//2uA
void sleep()
{
uint8_t write_buffer[] = {
0x20, 0x00, 0x00, 0x00, // CHSC5816_REG_CMD_BUFF
0xF8, 0x16, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE9
};
writeBuffer(write_buffer, SENSORLIB_COUNT(write_buffer));
}
void wakeup()
{
reset();
}
void idle()
{
uint8_t write_buffer[] = {
0x20, 0x00, 0x00, 0x00, // CHSC5816_REG_CMD_BUFF
0x20, 0x16, 0x02, 0x00, 0xDB, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE9
};
writeBuffer(write_buffer, SENSORLIB_COUNT(write_buffer));
}
uint8_t getSupportTouchPoint()
{
return 1;
}
bool getResolution(int16_t *x, int16_t *y)
{
/*
uint8_t buffer[16] = {
0xFC, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xe9
};
writeRegister(CHSC5816_REG_CMD_BUFF, buffer, 16);
memset(buffer, 0, 16);
readRegister(CHSC5816_REG_CMD_BUFF, buffer, 16);
for (int i = 0; i < 16; ++i) {
Serial.print(buffer[i], HEX);
Serial.print(",");
}
Serial.println();
return true;
*/
return false;
}
void setGpioCallback(gpio_mode_fptr_t mode_cb,
gpio_write_fptr_t write_cb,
gpio_read_fptr_t read_cb)
{
SensorCommon::setGpioModeCallback(mode_cb);
SensorCommon::setGpioWriteCallback(write_cb);
SensorCommon::setGpioReadCallback(read_cb);
}
private:
bool checkOnline()
{
CHSC5816_Header_t tmp;
memset(&tmp, 0, sizeof(CHSC5816_Header_t));
memset(&__header, 0, sizeof(CHSC5816_Header_t));
// CHSC5816_REG_BOOT_STATE 0x20000018
uint8_t write_buffer[] = {0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00};
if (writeBuffer(write_buffer, SENSORLIB_COUNT(write_buffer)) == DEV_WIRE_ERR) {
log_e("writeBuffer clean boot state failed!\n");
return false;
}
reset();
for (int i = 0; i < 10; ++i) {
delay(10);
// CHSC5816_REG_IMG_HEAD 0x20000014
uint8_t write_buffer[] = {0x20, 0x00, 0x00, 0x14};
if (writeThenRead(write_buffer, SENSORLIB_COUNT(write_buffer),
(uint8_t *)&__header,
sizeof(CHSC5816_Header_t)) == DEV_WIRE_ERR) {
printf("readRegister 1 failed!\n");
return false;
}
if (writeThenRead(write_buffer, SENSORLIB_COUNT(write_buffer),
(uint8_t *)&tmp,
sizeof(CHSC5816_Header_t)) == DEV_WIRE_ERR) {
printf("readRegister 2 failed!\n");
return false;
}
if (memcmp(&tmp, &__header, sizeof(CHSC5816_Header_t)) != 0 ) {
continue;
}
if (__header.sig == CHSC5816_SIG_VALUE) {
return true;
}
}
return false;
}
bool initImpl()
{
if (__irq != SENSOR_PIN_NONE) {
this->setGpioMode(__irq, INPUT);
}
if (__rst != SENSOR_PIN_NONE) {
this->setGpioMode(__rst, OUTPUT);
}
reset();
if (checkOnline()) {
reset();
return true;
}
return false;
}
int getReadMaskImpl()
{
return -1;
}
protected:
CHSC5816_Header_t __header;
};

View File

@ -0,0 +1,295 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file TouchDrvCSTXXX.tpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-24
* @date last 2023-10-05
*
*/
#pragma once
#include "REG/CSTxxxConstants.h"
#include "touch/TouchClassCST226.h"
#include "touch/TouchClassCST816.h"
#include "SensorCommon.tpp"
class TouchDrvCSTXXX : public TouchDrvInterface
{
public:
TouchDrvCSTXXX(): drv(NULL)
{
}
~TouchDrvCSTXXX()
{
if (drv) {
delete drv;
drv = NULL;
}
}
#if defined(ARDUINO)
bool begin(PLATFORM_WIRE_TYPE &wire,
uint8_t address,
int sda,
int scl
)
{
if (!drv) {
drv = new TouchClassCST816();
drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level);
drv->setPins(__rst, __irq);
if (!drv->begin(wire, address, sda, scl)) {
delete drv;
drv = NULL;
}
}
if (!drv) {
drv = new TouchClassCST226();
drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level);
drv->setPins(__rst, __irq);
if (!drv->begin(wire, address, sda, scl)) {
delete drv;
drv = NULL;
}
}
return drv != NULL;
}
#elif defined(ESP_PLATFORM)
#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API))
bool begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr)
{
if (!drv) {
drv = new TouchClassCST816();
drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level);
drv->setPins(__rst, __irq);
if (!drv->begin(i2c_dev_bus_handle, addr)) {
delete drv;
drv = NULL;
}
}
if (!drv) {
drv = new TouchClassCST226();
drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level);
drv->setPins(__rst, __irq);
if (!drv->begin(i2c_dev_bus_handle, addr)) {
delete drv;
drv = NULL;
}
}
return drv != NULL;
}
#else
bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl)
{
if (!drv) {
drv = new TouchClassCST816();
drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level);
drv->setPins(__rst, __irq);
if (!drv->begin(port_num, addr, sda, scl)) {
delete drv;
drv = NULL;
}
}
if (!drv) {
drv = new TouchClassCST226();
drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level);
drv->setPins(__rst, __irq);
if (!drv->begin(port_num, addr, sda, scl)) {
delete drv;
drv = NULL;
}
}
return drv != NULL;
}
#endif //ESP_IDF_VERSION
#endif//ARDUINO
void setGpioCallback(gpio_mode_fptr_t mode_cb,
gpio_write_fptr_t write_cb,
gpio_read_fptr_t read_cb)
{
__set_gpio_level = write_cb;
__get_gpio_level = read_cb;
__set_gpio_mode = mode_cb;
}
bool begin(uint8_t address, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback)
{
if (!drv) {
drv = new TouchClassCST816();
drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level);
drv->setPins(__rst, __irq);
if (!drv->begin(address, readRegCallback, writeRegCallback)) {
delete drv;
drv = NULL;
}
}
if (!drv) {
drv = new TouchClassCST226();
drv->setGpioCallback(__set_gpio_mode, __set_gpio_level, __get_gpio_level);
drv->setPins(__rst, __irq);
if (!drv->begin(address, readRegCallback, writeRegCallback)) {
delete drv;
drv = NULL;
}
}
return drv != NULL;
}
void reset()
{
if (!drv)return;
drv->reset();
}
uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t get_point = 1)
{
if (!drv)return 0;
return drv->getPoint(x_array, y_array, get_point);
}
bool isPressed()
{
if (!drv)return false;
return drv->isPressed();
}
const char *getModelName()
{
if (!drv)return "NULL";
return drv->getModelName();
}
void sleep()
{
if (!drv)return;
drv->sleep();
}
void wakeup()
{
if (!drv)return;
drv->reset();
}
void idle()
{
if (!drv)return;
drv->idle();
}
uint8_t getSupportTouchPoint()
{
if (!drv)return 0;
return drv->getSupportTouchPoint();
}
bool getResolution(int16_t *x, int16_t *y)
{
if (!drv)return false;
return drv->getResolution(x, y);
}
void setCenterButtonCoordinate(uint16_t x, uint16_t y)
{
if (!drv)return ;
const char *model = drv->getModelName();
if (strncmp(model, "CST8", 3) == 0) {
TouchClassCST816 *pT = static_cast<TouchClassCST816 *>(drv);
pT->setCenterButtonCoordinate(x, y);
}
}
void setHomeButtonCallback(home_button_callback_t callback, void *user_data = NULL)
{
if (!drv)return ;
const char *model = drv->getModelName();
if (strncmp(model, "CST8", 3) == 0) {
TouchClassCST816 *pT = static_cast<TouchClassCST816 *>(drv);
pT->setHomeButtonCallback(callback, user_data);
// pT->setCenterButtonCoordinate(600, 120); // Only suitable for AMOLED 1.91 inch
} if (strncmp(model, "CST2", 3) == 0) {
TouchClassCST226 *pT = static_cast<TouchClassCST226 *>(drv);
pT->setHomeButtonCallback(callback, user_data);
}
}
void disableAutoSleep()
{
if (!drv)return ;
const char *model = drv->getModelName();
if (strncmp(model, "CST8", 3) == 0) {
TouchClassCST816 *pT = static_cast<TouchClassCST816 *>(drv);
pT->disableAutoSleep();
}
}
void enableAutoSleep()
{
if (!drv)return ;
const char *model = drv->getModelName();
if (strncmp(model, "CST8", 3) == 0) {
TouchClassCST816 *pT = static_cast<TouchClassCST816 *>(drv);
pT->enableAutoSleep();
}
}
void setSwapXY(bool swap)
{
if (!drv)return ;
drv->setSwapXY(swap);
}
void setMirrorXY(bool mirrorX, bool mirrorY)
{
if (!drv)return ;
drv->setMirrorXY(mirrorX, mirrorY);
}
void setMaxCoordinates(uint16_t x, uint16_t y)
{
if (!drv)return ;
drv->setMaxCoordinates(x, y);
}
private:
gpio_write_fptr_t __set_gpio_level = NULL;
gpio_read_fptr_t __get_gpio_level = NULL;
gpio_mode_fptr_t __set_gpio_mode = NULL;
TouchDrvInterface *drv = NULL;
};

View File

@ -0,0 +1,426 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file TouchDrvFT6X36.tpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-01
*
*/
#pragma once
#include "REG/FT6X36Constants.h"
#include "TouchDrvInterface.hpp"
#include "SensorCommon.tpp"
class TouchDrvFT6X36 :
public TouchDrvInterface,
public SensorCommon<TouchDrvFT6X36>
{
friend class SensorCommon<TouchDrvFT6X36>;
public:
enum GesTrue {
NO_GESTURE,
MOVE_UP,
MOVE_LEFT,
MOVE_DOWN,
MOVE_RIGHT,
ZOOM_IN,
ZOOM_OUT,
} ;
enum EventFlag {
EVENT_PUT_DOWN,
EVENT_PUT_UP,
EVENT_CONTACT,
EVENT_NONE,
} ;
enum PowerMode {
PMODE_ACTIVE = 0, // ~4mA
PMODE_MONITOR = 1, // ~3mA
PMODE_DEEPSLEEP = 3, // ~100uA The reset pin must be pulled down to wake up
} ;
EventFlag event;
#if defined(ARDUINO)
TouchDrvFT6X36(PLATFORM_WIRE_TYPE &w, int sda = DEFAULT_SDA, int scl = DEFAULT_SCL, uint8_t addr = FT6X36_SLAVE_ADDRESS)
{
__wire = &w;
__sda = sda;
__scl = scl;
__addr = addr;
}
#endif
TouchDrvFT6X36()
{
#if defined(ARDUINO)
__wire = &Wire;
__sda = DEFAULT_SDA;
__scl = DEFAULT_SCL;
#endif
__addr = FT6X36_SLAVE_ADDRESS;
}
~TouchDrvFT6X36()
{
deinit();
}
#if defined(ARDUINO)
bool begin(PLATFORM_WIRE_TYPE &w,
uint8_t addr = FT6X36_SLAVE_ADDRESS,
int sda = DEFAULT_SDA,
int scl = DEFAULT_SCL)
{
return SensorCommon::begin(w, addr, sda, scl);
}
#elif defined(ESP_PLATFORM) && !defined(ARDUINO)
#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API))
bool begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr)
{
return SensorCommon::begin(i2c_dev_bus_handle, addr);
}
#else
bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl)
{
return SensorCommon::begin(port_num, addr, sda, scl);
}
#endif //ESP_IDF_VERSION
#endif
bool begin(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback)
{
return SensorCommon::begin(addr, readRegCallback, writeRegCallback);
}
void deinit()
{
// end();
}
uint8_t getDeviceMode(void)
{
return readRegister(FT6X36_REG_MODE) & 0x03;
}
// Obtaining gestures depends on whether the built-in firmware of the chip has this function
uint8_t getGesture()
{
int val = readRegister(FT6X36_REG_GEST);
switch (val) {
case 0x10:
return MOVE_UP;
case 0x14:
return MOVE_RIGHT;
case 0x18:
return MOVE_DOWN;
case 0x1C:
return MOVE_LEFT;
case 0x48:
return ZOOM_IN;
case 0x49:
return ZOOM_OUT;
default:
break;
}
return NO_GESTURE;
}
void setThreshold(uint8_t value)
{
writeRegister(FT6X36_REG_THRESHOLD, value);
}
uint8_t getThreshold(void)
{
return readRegister(FT6X36_REG_THRESHOLD);
}
uint8_t getMonitorTime(void)
{
return readRegister(FT6X36_REG_MONITOR_TIME);
}
void setMonitorTime(uint8_t sec)
{
writeRegister(FT6X36_REG_MONITOR_TIME, sec);
}
// Calibration useless actually,
// any value set will not be valid,
// depending on the internal firmware of the chip.
/*
void enableAutoCalibration(void)
{
writeRegister(FT6X36_REG_AUTO_CLB_MODE, 0x00);
}
void disableAutoCalibration(void)
{
writeRegister(FT6X36_REG_AUTO_CLB_MODE, 0xFF);
}
*/
uint16_t getLibraryVersion()
{
uint8_t buffer[2];
readRegister(FT6X36_REG_LIB_VERSION_H, buffer, 2);
return (buffer[0] << 8) | buffer[1];
}
// The interrupt is triggered only if a touch is detected during the scan cycle
void interruptPolling(void)
{
//datasheet this bit is 0,Actually, it's wrong
writeRegister(FT6X36_REG_INT_STATUS, 1);
}
// Triggers an interrupt whenever a touch is detected
void interruptTrigger(void)
{
//datasheet this bit is 1,Actually, it's wrong
writeRegister(FT6X36_REG_INT_STATUS, 0);
}
uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t size = 1)
{
uint8_t buffer[16];
if (!x_array || !y_array || !size)
return 0;
if (readRegister(FT6X36_REG_MODE, buffer, 16) == DEV_WIRE_ERR) {
return 0;
}
// uint8_t mode = buffer[0];
//REG 0x01
// uint8_t gesture = buffer[1];
//REG 0x02
uint8_t point = buffer[2] & 0x0F;
if (point == 0 || point == 0x0F) {
return 0;
}
//REG 0x03 ~ 0x04
// uint8_t eventFlag = (buffer[3] & 0xC0) >> 6;
uint16_t posX = ((buffer[3] & 0x0F) << 8) | buffer[4];
//REG 0x05 ~ 0x06
uint16_t posY = ((buffer[5] & 0x0F) << 8) | buffer[6] ;
x_array[0] = posX;
y_array[0] = posY;
#ifdef LOG_PORT
LOG_PORT.println("----------------------------------------------------------------------------");
LOG_PORT.println("Touched Gesture EvenFlag [0]PosX [0]PosY [1]PosX [1]PosY");
LOG_PORT.print(point); LOG_PORT.print("\t");
// LOG_PORT.print(gesture); LOG_PORT.print("\t");
// LOG_PORT.print(eventFlag); LOG_PORT.print("\t");
LOG_PORT.print(posX); LOG_PORT.print("\t");
LOG_PORT.print(posY); LOG_PORT.print("\t");
#endif
if (point == 2) {
//REG 0x09 ~ 0x0A
posX = ((buffer[9] & 0x0F) << 8) | buffer[10];
//REG 0x0B ~ 0x0C
posY = ((buffer[11] & 0x0F) << 8) | buffer[12] ;
#ifdef LOG_PORT
LOG_PORT.print(posX); LOG_PORT.print("\t");
LOG_PORT.print(posY); LOG_PORT.print("\t");
#endif
if (size == 2) {
x_array[1] = posX;
y_array[1] = posY;
}
}
#ifdef LOG_PORT
LOG_PORT.println();
#endif
updateXY(point, x_array, y_array);
return point;
}
bool isPressed()
{
if (__irq != SENSOR_PIN_NONE) {
return this->getGpioLevel(__irq) == LOW;
}
return readRegister(FT6X36_REG_STATUS) & 0x0F;
}
void setPowerMode(PowerMode mode)
{
writeRegister(FT6X36_REG_POWER_MODE, mode);
}
void sleep()
{
writeRegister(FT6X36_REG_POWER_MODE, PMODE_DEEPSLEEP);
}
void wakeup()
{
reset();
}
void idle()
{
}
uint8_t getSupportTouchPoint()
{
return 1;
}
uint32_t getChipID(void)
{
return readRegister(FT6X36_REG_CHIP_ID);
}
uint8_t getVendorID(void)
{
return readRegister(FT6X36_REG_VENDOR1_ID);
}
uint8_t getErrorCode(void)
{
return readRegister(FT6X36_REG_ERROR_STATUS);
}
const char *getModelName()
{
switch (__chipID) {
case FT6206_CHIP_ID: return "FT6206";
case FT6236_CHIP_ID: return "FT6236";
case FT6236U_CHIP_ID: return "FT6236U";
case FT3267_CHIP_ID: return "FT3267";
default: return "UNKNOWN";
}
}
bool getResolution(int16_t *x, int16_t *y)
{
return false;
}
void reset()
{
if (__rst != SENSOR_PIN_NONE) {
this->setGpioMode(__rst, OUTPUT);
this->setGpioLevel(__rst, HIGH);
delay(10);
this->setGpioLevel(__rst, LOW);
delay(30);
this->setGpioLevel(__rst, HIGH);
// For the variant of GPIO extended RST,
// communication and delay are carried out simultaneously, and 160ms is measured in T-RGB esp-idf new api
delay(160);
}
}
void setGpioCallback(gpio_mode_fptr_t mode_cb,
gpio_write_fptr_t write_cb,
gpio_read_fptr_t read_cb)
{
SensorCommon::setGpioModeCallback(mode_cb);
SensorCommon::setGpioWriteCallback(write_cb);
SensorCommon::setGpioReadCallback(read_cb);
}
private:
bool initImpl()
{
if (__irq != SENSOR_PIN_NONE) {
this->setGpioMode(__irq, INPUT);
}
reset();
uint8_t vendId = readRegister(FT6X36_REG_VENDOR1_ID);
if (vendId != FT6X36_VEND_ID) {
log_e("Vendor id is 0x%X not match!\n", vendId);
return false;
}
__chipID = readRegister(FT6X36_REG_CHIP_ID);
if ((__chipID != FT6206_CHIP_ID) &&
(__chipID != FT6236_CHIP_ID) &&
(__chipID != FT6236U_CHIP_ID) &&
(__chipID != FT3267_CHIP_ID)
) {
log_e("Vendor id is not match!\n");
log_e("ChipID:0x%lx should be 0x06 or 0x36 or 0x64\n", __chipID);
return false;
}
log_i("Vend ID: 0x%X\n", vendId);
log_i("Chip ID: 0x%lx\n", __chipID);
log_i("Firm Version: 0x%X\n", readRegister(FT6X36_REG_FIRM_VERS));
log_i("Point Rate Hz: %u\n", readRegister(FT6X36_REG_PERIOD_ACTIVE));
log_i("Thresh : %u\n", readRegister(FT6X36_REG_THRESHOLD));
// change threshold to be higher/lower
writeRegister(FT6X36_REG_THRESHOLD, 60);
log_i("Chip library version : 0x%x\n", getLibraryVersion());
// This register describes period of monitor status, it should not less than 30.
log_i("Chip period of monitor status : 0x%x\n", readRegister(FT6X36_REG_PERIOD_MONITOR));
// This register describes the period of active status, it should not less than 12
return true;
}
int getReadMaskImpl()
{
return -1;
}
};

View File

@ -0,0 +1,424 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file TouchDrvGT911.tpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-12
*
*/
#pragma once
#include "REG/GT911Constants.h"
#include "TouchDrvInterface.hpp"
#include "SensorCommon.tpp"
typedef struct GT911_Struct {
uint8_t trackID;
int16_t x;
int16_t y;
int16_t size;
} GT911Point_t;
class TouchDrvGT911 :
public TouchDrvInterface,
public SensorCommon<TouchDrvGT911>
{
friend class SensorCommon<TouchDrvGT911>;
public:
#if defined(ARDUINO)
TouchDrvGT911(PLATFORM_WIRE_TYPE &w,
int sda = DEFAULT_SDA,
int scl = DEFAULT_SCL,
uint8_t addr = GT911_SLAVE_ADDRESS_H)
{
__wire = &w;
__sda = sda;
__scl = scl;
__rst = SENSOR_PIN_NONE;
__irq = SENSOR_PIN_NONE;
__addr = addr;
}
#endif
TouchDrvGT911()
{
#if defined(ARDUINO)
__wire = &Wire;
__sda = DEFAULT_SDA;
__scl = DEFAULT_SCL;
#endif
__rst = SENSOR_PIN_NONE;
__irq = SENSOR_PIN_NONE;
__addr = GT911_SLAVE_ADDRESS_H;
}
~TouchDrvGT911()
{
deinit();
}
#if defined(ARDUINO)
bool begin(PLATFORM_WIRE_TYPE &w,
uint8_t addr = GT911_SLAVE_ADDRESS_H,
int sda = DEFAULT_SDA,
int scl = DEFAULT_SCL
)
{
return SensorCommon::begin(w, addr, sda, scl);
}
#elif defined(ESP_PLATFORM) && !defined(ARDUINO)
#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API))
bool begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr)
{
return SensorCommon::begin(i2c_dev_bus_handle, addr);
}
#else
bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl)
{
return SensorCommon::begin(port_num, addr, sda, scl);
}
#endif //ESP_IDF_VERSION
#endif
bool begin(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback)
{
return SensorCommon::begin(addr, readRegCallback, writeRegCallback);
}
void deinit()
{
// end();
}
void reset()
{
if (__rst != SENSOR_PIN_NONE) {
this->setGpioMode(__rst, OUTPUT);
this->setGpioLevel(__rst, HIGH);
delay(10);
}
if (__irq != SENSOR_PIN_NONE) {
this->setGpioMode(__irq, INPUT);
}
// writeRegister(GT911_COMMAND, 0x02);
writeCommand(0x02);
}
void sleep()
{
if (__irq != SENSOR_PIN_NONE) {
this->setGpioMode(__irq, OUTPUT);
this->setGpioLevel(__irq, LOW);
}
// writeRegister(GT911_COMMAND, 0x05);
writeCommand(0x05);
/*
* Depending on the chip and platform, setting it to input after removing sleep will affect power consumption.
* The chip platform determines whether
*
* * */
// if (__irq != SENSOR_PIN_NONE) {
// this->setGpioLevel(__irq, INPUT);
// }
}
void wakeup()
{
if (__irq != SENSOR_PIN_NONE) {
this->setGpioMode(__irq, OUTPUT);
this->setGpioLevel(__irq, HIGH);
delay(8);
} else {
reset();
}
}
void idle()
{
}
uint8_t getSupportTouchPoint()
{
return 5;
}
uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t size = 1)
{
uint8_t buffer[39];
uint8_t touchPoint = 0;
GT911Point_t p[5];
if (!x_array || !y_array || size == 0)
return 0;
touchPoint = getPoint();
if (touchPoint == 0) {
return 0;
}
// GT911_POINT_1 0X814F
uint8_t write_buffer[2] = {0x81, 0x4F};
if (writeThenRead(write_buffer, SENSORLIB_COUNT(write_buffer),
buffer, 39) == DEV_WIRE_ERR) {
return 0;
}
for (uint8_t i = 0; i < size; i++) {
p[i].trackID = buffer[i * 8];
p[i].x = buffer[0x01 + i * 8] ;
p[i].x |= (buffer[0x02 + i * 8] << 8 );
p[i].y = buffer[0x03 + i * 8] ;
p[i].y |= (buffer[0x04 + i * 8] << 8);
p[i].size = buffer[0x05 + i * 8] ;
p[i].size |= (buffer[0x06 + i * 8] << 8) ;
x_array[i] = p[i].x;
y_array[i] = p[i].y;
}
#ifdef LOG_PORT
LOG_PORT.println("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
LOG_PORT.println("Touched [0]ID [0]Size [0]X [0]Y [1]ID [1]Size [1]X [1]Y [2]ID [2]Size [2]X [2]Y [3]ID [3]Size [3]X [3]Y [4]ID [4]Size [4]X [4]Y ");
LOG_PORT.print(touchPoint); LOG_PORT.print("\t");
for (int i = 0; i < size; ++i) {
LOG_PORT.print(p[i].trackID); LOG_PORT.print("\t");
LOG_PORT.print(p[i].size); LOG_PORT.print("\t");
LOG_PORT.print( p[i].x); LOG_PORT.print("\t");
LOG_PORT.print( p[i].y); LOG_PORT.print("\t");
}
LOG_PORT.println();
#endif
updateXY(touchPoint, x_array, y_array);
return touchPoint;
}
bool isPressed()
{
if (__irq != SENSOR_PIN_NONE) {
if (__irq_mode == FALLING) {
return this->getGpioLevel(__irq) == LOW;
} else if (__irq_mode == RISING ) {
return this->getGpioLevel(__irq) == HIGH;
}
} else {
return getPoint();
}
return false;
}
//In the tested GT911 only the falling edge is valid to use, the rest are incorrect
bool setInterruptMode(uint8_t mode)
{
// GT911_MODULE_SWITCH_1 0x804D
uint8_t val = readGT911(GT911_MODULE_SWITCH_1);
val &= 0XFC;
if (mode == FALLING) {
val |= 0x03;
} else if (mode == RISING ) {
val |= 0x02;
}
__irq_mode = mode;
return writeGT911(GT911_MODULE_SWITCH_1, val) != DEV_WIRE_ERR;
}
uint8_t getPoint()
{
// GT911_POINT_INFO 0X814E
uint8_t val = readGT911(GT911_POINT_INFO) & 0x0F;
clearBuffer();
return val & 0x0F;
}
uint32_t getChipID()
{
char product_id[4] = {0};
// GT911_PRODUCT_ID 0x8140
for (int i = 0; i < 4; ++i) {
product_id[i] = readGT911(GT911_PRODUCT_ID + i);
}
return atoi(product_id);
}
uint16_t getFwVersion()
{
uint8_t fw_ver[2] = {0};
// GT911_FIRMWARE_VERSION 0x8144
for (int i = 0; i < 2; ++i) {
fw_ver[i] = readGT911(GT911_FIRMWARE_VERSION + i);
}
return fw_ver[0] | (fw_ver[1] << 8);
}
bool getResolution(int16_t *x, int16_t *y)
{
uint8_t x_resolution[2] = {0}, y_resolution[2] = {0};
for (int i = 0; i < 2; ++i) {
x_resolution[i] = readGT911(GT911_X_RESOLUTION + i);
}
for (int i = 0; i < 2; ++i) {
y_resolution[i] = readGT911(GT911_Y_RESOLUTION + i);
}
*x = x_resolution[0] | (x_resolution[1] << 8);
*y = y_resolution[0] | (y_resolution[1] << 8);
return true;
}
int getVendorID()
{
return readGT911(GT911_VENDOR_ID);
}
const char *getModelName()
{
return "GT911";
}
void setGpioCallback(gpio_mode_fptr_t mode_cb,
gpio_write_fptr_t write_cb,
gpio_read_fptr_t read_cb)
{
SensorCommon::setGpioModeCallback(mode_cb);
SensorCommon::setGpioWriteCallback(write_cb);
SensorCommon::setGpioReadCallback(read_cb);
}
private:
uint8_t readGT911(uint16_t cmd)
{
uint8_t value = 0x00;
uint8_t write_buffer[2] = {highByte(cmd), lowByte(cmd)};
writeThenRead(write_buffer, SENSORLIB_COUNT(write_buffer),
&value, 1);
return value;
}
int writeGT911(uint16_t cmd, uint8_t value)
{
uint8_t write_buffer[3] = {highByte(cmd), lowByte(cmd), value};
return writeBuffer(write_buffer, SENSORLIB_COUNT(write_buffer));
}
void writeCommand(uint8_t command)
{
// GT911_COMMAND 0x8040
uint8_t write_buffer[3] = {0x80, 0x40, command};
writeBuffer(write_buffer, SENSORLIB_COUNT(write_buffer));
}
void inline clearBuffer()
{
writeGT911(GT911_POINT_INFO, 0x00);
}
bool initImpl()
{
int16_t x = 0, y = 0;
if (__addr == GT911_SLAVE_ADDRESS_H &&
__rst != SENSOR_PIN_NONE &&
__irq != SENSOR_PIN_NONE) {
log_i("GT911 using 0x28 address!\n");
this->setGpioMode(__rst, OUTPUT);
this->setGpioMode(__irq, OUTPUT);
this->setGpioLevel(__rst, LOW);
this->setGpioLevel(__irq, HIGH);
delayMicroseconds(120);
this->setGpioLevel(__rst, HIGH);
delay(18);
this->setGpioMode(__irq, INPUT);
} else if (__addr == GT911_SLAVE_ADDRESS_L &&
__rst != SENSOR_PIN_NONE &&
__irq != SENSOR_PIN_NONE) {
log_i("GT911 using 0xBA address!\n");
this->setGpioMode(__rst, OUTPUT);
this->setGpioMode(__irq, OUTPUT);
this->setGpioLevel(__rst, LOW);
this->setGpioLevel(__irq, LOW);
delayMicroseconds(120);
this->setGpioLevel(__rst, HIGH);
delay(18);
this->setGpioMode(__irq, INPUT);
} else {
reset();
}
// For variants where the GPIO is controlled by I2C, a delay is required here
delay(20);
__chipID = getChipID();
log_i("Product id:%ld\n", __chipID);
if (__chipID != 911) {
log_i("Not find device GT911\n");
return false;
}
log_i("Firmware version: 0x%x\n", getFwVersion());
getResolution(&x, &y);
log_i("Resolution : X = %d Y = %d\n", x, y);
log_i("Vendor id:%d\n", getVendorID());
return true;
}
int getReadMaskImpl()
{
return -1;
}
protected:
int __irq_mode;
};

View File

@ -0,0 +1,100 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file TouchDrvInterface.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-21
*
*/
#include "TouchDrvInterface.hpp"
TouchDrvInterface::TouchDrvInterface() :
__resX(0),
__resY(0),
__xMax(0),
__yMax(0),
__swapXY(false),
__mirrorX(false),
__mirrorY(false),
__rst(-1),
__irq(-1),
__chipID(0x00),
__homeButtonCb(NULL),
__userData(NULL)
{
}
TouchDrvInterface::~TouchDrvInterface()
{
}
uint32_t TouchDrvInterface::getChipID()
{
return __chipID;
}
void TouchDrvInterface::setPins(int rst, int irq)
{
__irq = irq;
__rst = rst;
}
void TouchDrvInterface::setSwapXY(bool swap)
{
__swapXY = swap;
}
void TouchDrvInterface::setMirrorXY(bool mirrorX, bool mirrorY)
{
__mirrorX = mirrorX;
__mirrorY = mirrorY;
}
void TouchDrvInterface::setMaxCoordinates(uint16_t x, uint16_t y)
{
__xMax = x;
__yMax = y;
}
void TouchDrvInterface::updateXY(uint8_t pointNum, int16_t *xBuffer, int16_t *yBuffer)
{
if (!pointNum)
return;
for (int i = 0; i < pointNum; ++i) {
if (__swapXY) {
uint16_t tmp = xBuffer[i];
xBuffer[i] = yBuffer[i];
yBuffer[i] = tmp;
}
if (__mirrorX && __xMax ) {
xBuffer[i] = __xMax - xBuffer[i];
}
if (__mirrorY && __yMax) {
yBuffer[i] = __yMax - yBuffer[i];
}
}
}

View File

@ -0,0 +1,145 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* 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.
*
* @file TouchDrvInterface.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-17
*
*/
#pragma once
#include <stdint.h>
#include <stdio.h>
#include "SensorLib.h"
#include "SensorCommon.tpp"
typedef void (*home_button_callback_t)(void *user_data);
class TouchData
{
public:
TouchData() {}
~TouchData() {};
uint8_t available;
uint8_t id[5];
int16_t x[5];
int16_t y[5];
uint8_t status[5];
uint8_t pressure[5];
uint16_t getX(uint8_t index = 0)
{
return x[index];
}
uint16_t getY(uint8_t index = 0)
{
return y[index];
}
uint16_t getPressure(uint8_t index = 0)
{
return pressure[index];
}
uint16_t getStatus(uint8_t index = 0)
{
return status[index];
}
};
class TouchDrvInterface
{
public:
TouchDrvInterface();
virtual ~TouchDrvInterface();
#if defined(ARDUINO)
virtual bool begin(PLATFORM_WIRE_TYPE &wire, uint8_t address, int sda, int scl) = 0;
#elif defined(ESP_PLATFORM) && !defined(ARDUINO)
#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API))
virtual bool begin(i2c_master_bus_handle_t i2c_dev_bus_handle, uint8_t addr) = 0;
#else
virtual bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl) = 0;
#endif //ESP_IDF_VERSION
#endif //defined(ESP_PLATFORM) && !defined(ARDUINO)
virtual bool begin(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback) = 0;
virtual void reset() = 0;
virtual uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t get_point) = 0;
virtual bool isPressed() = 0;
virtual const char *getModelName() = 0;
virtual void sleep() = 0;
virtual void wakeup() = 0;
virtual void idle() = 0;
virtual uint8_t getSupportTouchPoint() = 0;
virtual bool getResolution(int16_t *x, int16_t *y) = 0;
virtual void setGpioCallback(gpio_mode_fptr_t mode_cb,
gpio_write_fptr_t write_cb,
gpio_read_fptr_t read_cb) = 0;
uint32_t getChipID();
void setPins(int rst, int irq);
void setSwapXY(bool swap);
void setMirrorXY(bool mirrorX, bool mirrorY);
void setMaxCoordinates(uint16_t x, uint16_t y);
void updateXY(uint8_t pointNum, int16_t *xBuffer, int16_t *yBuffer);
protected:
uint16_t __resX, __resY, __xMax, __yMax;
bool __swapXY, __mirrorX, __mirrorY;
int __rst;
int __irq;
uint32_t __chipID;
home_button_callback_t __homeButtonCb;
void *__userData;
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,479 @@
/**
* Copyright (c) 2020 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 bmm150.h
* @date 2020-06-03
* @version v2.0.0
*
*/
/*!
* @defgroup bmm150 BMM150
*/
#ifndef _BMM150_H
#define _BMM150_H
/*! CPP guard */
#ifdef __cplusplus
extern "C" {
#endif
/********************************************************************/
/* header files */
#include "bmm150_defs.h"
/********************************************************************/
/* (extern) variable declarations */
/********************************************************************/
/* function prototype declarations */
/**
* \ingroup bmm150
* \defgroup bmm150ApiInit Initialization
* @brief Initialize the sensor and device structure
*/
/*!
* \ingroup bmm150ApiInit
* \page bmm150_api_bmm150_init bmm150_init
* \code
* int8_t bmm150_init(struct bmm150_dev *dev);
* \endcode
* @details This API is the entry point, Call this API before using other APIs.
* This API reads the chip-id of the sensor which is the first step to
* verify the sensor and also it configures the read mechanism of SPI and
* I2C interface.
*
* @param[in,out] dev : Structure instance of bmm150_dev
* @note : Refer user guide for detailed info.
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_init(struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiRegs Registers
* @brief Read / Write data to the given register address of the sensor
*/
/*!
* \ingroup bmm150ApiRegs
* \page bmm150_api_bmm150_set_regs bmm150_set_regs
* \code
* int8_t bmm150_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, struct bmm150_dev *dev);
* \endcode
* @details 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 reg_addr of sensor.
* @param[in] len : No of bytes of data to write..
* @param[in] dev : Structure instance of bmm150_dev.
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, struct bmm150_dev *dev);
/*!
* \ingroup bmm150ApiRegs
* \page bmm150_api_bmm150_get_regs bmm150_get_regs
* \code
* int8_t bmm150_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bmm150_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] dev : Structure instance of bmm150_dev.
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiSoftreset Soft reset
* @brief Perform soft reset of the sensor
*/
/*!
* \ingroup bmm150ApiSoftreset
* \page bmm150_api_bmm150_soft_reset bmm150_soft_reset
* \code
* int8_t bmm150_soft_reset(struct bmm150_dev *dev);
* \endcode
* @details This API is used to perform soft-reset of the sensor
* where all the registers are reset to their default values except 0x4B.
*
* @param[in] dev : Structure instance of bmm150_dev.
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_soft_reset(struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiPowermode Power mode
* @brief Set / Get power mode of the sensor
*/
/*!
* \ingroup bmm150ApiPowermode
* \page bmm150_api_bmm150_set_op_mode bmm150_set_op_mode
* \code
* int8_t bmm150_set_op_mode(const struct bmm150_settings *settings, struct bmm150_dev *dev);
* \endcode
* @details This API is used to set the power mode of the sensor.
*
* @param[in] settings : Structure instance of bmm150_settings.
* @param[in] dev : Structure instance of bmm150_dev.
*
*@verbatim
* settings->pwr_mode | Power mode
* ------------------------|-----------------------
* 0x00 | BMM150_POWERMODE_NORMAL
* 0x01 | BMM150_POWERMODE_FORCED
* 0x03 | BMM150_POWERMODE_SLEEP
* 0x04 | BMM150_POWERMODE_SUSPEND
*@endverbatim
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_set_op_mode(const struct bmm150_settings *settings, struct bmm150_dev *dev);
/*!
* \ingroup bmm150ApiPowermode
* \page bmm150_api_bmm150_get_op_mode bmm150_get_op_mode
* \code
* int8_t bmm150_get_op_mode(uint8_t *op_mode, struct bmm150_dev *dev);
* \endcode
* @details This API is used to get the power mode of the sensor.
*
* @param[out] op_mode : power mode of the sensor.
* @param[in] dev : Structure instance of bmm150_dev.
*
*@verbatim
* op_mode | Power mode
* -------------|-----------------------
* 0x00 | BMM150_POWERMODE_NORMAL
* 0x01 | BMM150_POWERMODE_FORCED
* 0x03 | BMM150_POWERMODE_SLEEP
* 0x04 | BMM150_POWERMODE_SUSPEND
*@endverbatim
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_get_op_mode(uint8_t *op_mode, struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiPresetmode Preset mode
* @brief Set preset mode of the sensor
*/
/*!
* \ingroup bmm150ApiPresetmode
* \page bmm150_api_bmm150_set_presetmode bmm150_set_presetmode
* \code
* int8_t bmm150_set_presetmode(struct bmm150_settings *settings, struct bmm150_dev *dev);
* \endcode
* @details This API is used to set the preset mode of the sensor.
*
* @param[in] settings : Structure instance of bmm150_settings.
* @param[in] dev : Structure instance of bmm150_dev.
*
*@verbatim
* settings->preset_mode | Preset mode
* ---------------------------|----------------------------------
* 0x01 | BMM150_PRESETMODE_LOWPOWER
* 0x02 | BMM150_PRESETMODE_REGULAR
* 0x03 | BMM150_PRESETMODE_HIGHACCURACY
* 0x04 | BMM150_PRESETMODE_ENHANCED
*@endverbatim
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_set_presetmode(struct bmm150_settings *settings, struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiSensorSettings Sensor Settings
* @brief Set / Get sensor settings of the sensor
*/
/*!
* \ingroup bmm150ApiSensorSettings
* \page bmm150_api_bmm150_set_sensor_settings bmm150_set_sensor_settings
* \code
* int8_t bmm150_set_sensor_settings(uint16_t desired_settings, const struct bmm150_settings *settings, struct bmm150_dev *dev);
* \endcode
* @details This API sets the sensor settings based on the desired_settings
* and the dev structure configuration
*
* @param[in] desired_settings : Selection macro for selecting the setting.
* @param[in] settings : Structure instance of bmm150_settings.
* @param[in] dev : Structure instance of bmm150_dev.
*
* @note Assign the sensor setting macros (multiple macros can be
* set by doing a bitwise-OR operation) to the desired_settings parameter
* of this API to perform the corresponding setting.
*
* @note threshold interrupt for each axes are set by using bitwise AND
* operation of the following macros
* - BMM150_THRESHOLD_X
* - BMM150_THRESHOLD_Y
* - BMM150_THRESHOLD_Z
*
*@verbatim
* desired_settings | Selected sensor setting macros
* -------------------|--------------------------------
* 0x0001 | BMM150_SEL_DATA_RATE
* 0x0002 | BMM150_SEL_CONTROL_MEASURE
* 0x0004 | BMM150_SEL_XY_REP
* 0x0008 | BMM150_SEL_Z_REP
* 0x0010 | BMM150_SEL_DRDY_PIN_EN
* 0x0020 | BMM150_SEL_INT_PIN_EN
* 0x0040 | BMM150_SEL_DRDY_POLARITY
* 0x0080 | BMM150_SEL_INT_LATCH
* 0x0100 | BMM150_SEL_INT_POLARITY
* 0x0200 | BMM150_SEL_DATA_OVERRUN_INT
* 0x0400 | BMM150_SEL_OVERFLOW_INT
* 0x0800 | BMM150_SEL_HIGH_THRESHOLD_INT
* 0x1000 | BMM150_SEL_LOW_THRESHOLD_INT
* 0x2000 | BMM150_SEL_LOW_THRESHOLD_SETTING
* 0x4000 | BMM150_SEL_HIGH_THRESHOLD_SETTING
*@endverbatim
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_set_sensor_settings(uint16_t desired_settings,
const struct bmm150_settings *settings,
struct bmm150_dev *dev);
/*!
* \ingroup bmm150ApiSensorSettings
* \page bmm150_api_bmm150_get_sensor_settings bmm150_get_sensor_settings
* \code
* int8_t bmm150_get_sensor_settings(struct bmm150_settings *settings, struct bmm150_dev *dev);
* \endcode
* @details This API gets all the sensor settings and updates the dev structure
*
* @param[in] settings : Structure instance of bmm150_settings.
* @param[in] dev : Structure instance of bmm150_dev.
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_get_sensor_settings(struct bmm150_settings *settings, struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiMagData Read magnetometer data
* @brief Read magnetometer data
*/
/*!
* \ingroup bmm150ApiMagData
* \page bmm150_api_bmm150_read_mag_data bmm150_read_mag_data
* \code
* int8_t bbmm150_read_mag_data(struct bmm150_mag_data *mag_data, struct bmm150_dev *dev);
* \endcode
* @details This API reads the magnetometer data from registers 0x42 to 0x49
* and updates the dev structure with compensated mag data in micro-tesla
*
* @param[in] mag_data : Structure instance of bmm150_mag_data.
* @param[in,out] dev : Structure instance of bmm150_dev.
*
* @note The output mag data can be obtained either in int16_t or float format
* using this API.
* @note Enable the macro "BMM150_USE_FLOATING_POINT" in the bmm150_defs.h
* file and call this API to get the mag data in float,
* disable this macro to get the mag data in int16_t format
*
*@verbatim
* Mag data output(micro-tesla) | Mag data in dev structure(int16_t/float)
* --------------------------------|------------------------------------------
* X-axis data | mag_data->x
* Y-axis data | mag_data->y
* Z-axis data | mag_data->z
*@endverbatim
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_read_mag_data(struct bmm150_mag_data *mag_data, struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiSelftest Self test
* @brief Perform self test
*/
/*!
* \ingroup bmm150ApiSelftest
* \page bmm150_api_bmm150_perform_self_test bmm150_perform_self_test
* \code
* int8_t bmm150_perform_self_test(uint8_t self_test_mode, struct bmm150_dev *dev);
* \endcode
* @details This API is used to perform the complete self test
* (both normal and advanced) for the BMM150 sensor
*
* @param[in] self_test_mode : The type of self test to be performed
* @param[in] dev : Structure instance of bmm150_dev.
*
*@verbatim
* self_test_mode | Self test enabled
* --------------------|--------------------------
* 0 | BMM150_SELF_TEST_NORMAL
* 1 | BMM150_SELF_TEST_ADVANCED
*@endverbatim
*
* @note The return value of this API gives us the result of self test.
*
* @note Performing advanced self test does soft reset of the sensor, User can
* set the desired settings after performing the advanced self test.
*
* @return Result of API execution status and self test result.
* @retval 0 BMM150_OK
* @retval 1 BMM150_W_NORMAL_SELF_TEST_YZ_FAIL
* @retval 2 BMM150_W_NORMAL_SELF_TEST_XZ_FAIL
* @retval 3 BMM150_W_NORMAL_SELF_TEST_Z_FAIL
* @retval 4 BMM150_W_NORMAL_SELF_TEST_XY_FAIL
* @retval 5 BMM150_W_NORMAL_SELF_TEST_Y_FAIL
* @retval 6 BMM150_W_NORMAL_SELF_TEST_X_FAIL
* @retval 7 BMM150_W_NORMAL_SELF_TEST_XYZ_FAIL
* @retval 8 BMM150_W_ADV_SELF_TEST_FAIL
*/
int8_t bmm150_perform_self_test(uint8_t self_test_mode, struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiInt Interrupt status
* @brief Obtain interrupt staus flags
*/
/*!
* \ingroup bmm150ApiInt
* \page bmm150_api_bmm150_get_interrupt_status bmm150_get_interrupt_status
* \code
* int8_t bmm150_get_interrupt_status(struct bmm150_dev *dev);
* \endcode
* @details This API obtains the status flags of all interrupt
* which is used to check for the assertion of interrupts
*
* @param[in,out] dev : Structure instance of bmm150_dev.
*
* @note The status flags of all the interrupts are stored in the
* dev->int_status.
*
* @note The value of dev->int_status is performed a bitwise AND operation
* with predefined interrupt status macros to find the interrupt status
* which is either set or reset.
*
* Ex.
* if (dev->int_status & BMM150_INT_ASSERTED_DRDY)
* {
* Occurrence of data ready interrupt
* } else {
* No interrupt occurred
* }
*
* @return Result of API execution status and self test result.
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_get_interrupt_status(struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiAux Compensate magnetometer data
* @brief Compensation of magnetometer data
*/
/*!
* \ingroup bmm150ApiAux
* \page bmm150_api_bmm150_aux_mag_data bmm150_aux_mag_data
* \code
* int8_t bmm150_aux_mag_data(uint8_t *aux_data, struct bmm150_mag_data *mag_data, const struct bmm150_dev *dev);
* \endcode
* @details This API is used to compensate the raw mag data
*
* @param[in] aux_data : Raw mag data obtained from BMI160 registers
* @param[in] mag_data : Structure instance of bmm150_mag_data.
* @param[in,out] dev : Structure instance of bmm150_dev.
*
* @return Result of API execution status and self test result.
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_aux_mag_data(uint8_t *aux_data, struct bmm150_mag_data *mag_data, const struct bmm150_dev *dev);
#ifdef __cplusplus
}
#endif /* End of CPP guard */
#endif /* _BMM150_H */

View File

@ -0,0 +1,643 @@
/**
* Copyright (c) 2020 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 bmm150_defs.h
* @date 2020-06-03
* @version v2.0.0
*
*/
/*! \file bmm150_defs.h */
#ifndef _BMM150_DEFS_H
#define _BMM150_DEFS_H
/******************************************************************************/
/*! @name Header includes */
/******************************************************************************/
#ifdef __KERNEL__
#include <linux/types.h>
#else
#include <stdint.h>
#include <stddef.h>
#endif
/******************************************************************************/
/*! @name Common macros */
/******************************************************************************/
#ifdef __KERNEL__
#if (LONG_MAX) > 0x7fffffff
#define __have_long64 1
#elif (LONG_MAX) == 0x7fffffff
#define __have_long32 1
#endif
#endif
#if !defined(UINT8_C)
#define INT8_C(x) x
#if (INT_MAX) > 0x7f
#define UINT8_C(x) x
#else
#define UINT8_C(x) x##U
#endif
#endif
#if !defined(UINT16_C)
#define INT16_C(x) x
#if (INT_MAX) > 0x7fff
#define UINT16_C(x) x
#else
#define UINT16_C(x) x##U
#endif
#endif
#if !defined(INT32_C) && !defined(UINT32_C)
#if __have_long32
#define INT32_C(x) x##L
#define UINT32_C(x) x##UL
#else
#define INT32_C(x) x
#define UINT32_C(x) x##U
#endif
#endif
#if !defined(INT64_C) && !defined(UINT64_C)
#if __have_long64
#define INT64_C(x) x##L
#define UINT64_C(x) x##UL
#else
#define INT64_C(x) x##LL
#define UINT64_C(x) x##ULL
#endif
#endif
/*! @name C standard macros */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *) 0)
#endif
#endif
/******************************************************************************/
/*! @name Compiler switch macros Definitions */
/******************************************************************************/
#ifndef BMM150_USE_FLOATING_POINT /*< Check if floating point (using BMM150_USE_FLOATING_POINT) is enabled */
#ifndef BMM150_USE_FIXED_POINT /*< If floating point is not enabled then enable BMM150_USE_FIXED_POINT */
#define BMM150_USE_FIXED_POINT
#endif
#endif
/******************************************************************************/
/*! @name General Macro Definitions */
/******************************************************************************/
/*! @name API success code */
#define BMM150_OK INT8_C(0)
/*! @name To define TRUE or FALSE */
#define BMM150_TRUE UINT8_C(1)
#define BMM150_FALSE UINT8_C(0)
/*! @name API error codes */
#define BMM150_E_NULL_PTR INT8_C(-1)
#define BMM150_E_DEV_NOT_FOUND INT8_C(-2)
#define BMM150_E_INVALID_CONFIG INT8_C(-3)
#define BMM150_E_COM_FAIL INT8_C(-4)
/*! @name API warning codes */
#define BMM150_W_NORMAL_SELF_TEST_YZ_FAIL INT8_C(1)
#define BMM150_W_NORMAL_SELF_TEST_XZ_FAIL INT8_C(2)
#define BMM150_W_NORMAL_SELF_TEST_Z_FAIL INT8_C(3)
#define BMM150_W_NORMAL_SELF_TEST_XY_FAIL INT8_C(4)
#define BMM150_W_NORMAL_SELF_TEST_Y_FAIL INT8_C(5)
#define BMM150_W_NORMAL_SELF_TEST_X_FAIL INT8_C(6)
#define BMM150_W_NORMAL_SELF_TEST_XYZ_FAIL INT8_C(7)
#define BMM150_W_ADV_SELF_TEST_FAIL INT8_C(8)
/*! @name CHIP ID & SOFT RESET VALUES */
#define BMM150_CHIP_ID UINT8_C(0x32)
#define BMM150_SET_SOFT_RESET UINT8_C(0x82)
/*! @name POWER MODE DEFINTIONS */
#define BMM150_POWERMODE_NORMAL UINT8_C(0x00)
#define BMM150_POWERMODE_FORCED UINT8_C(0x01)
#define BMM150_POWERMODE_SLEEP UINT8_C(0x03)
#define BMM150_POWERMODE_SUSPEND UINT8_C(0x04)
/*! @name Power mode settings */
#define BMM150_POWER_CNTRL_DISABLE UINT8_C(0x00)
#define BMM150_POWER_CNTRL_ENABLE UINT8_C(0x01)
/*! @name Sensor delay time settings */
#define BMM150_DELAY_SOFT_RESET UINT8_C(1000)
#define BMM150_DELAY_NORMAL_SELF_TEST UINT8_C(2000)
#define BMM150_START_UP_TIME UINT8_C(3000)
#define BMM150_DELAY_ADV_SELF_TEST UINT8_C(4000)
/*! @name ENABLE/DISABLE DEFINITIONS */
#define BMM150_XYZ_CHANNEL_ENABLE UINT8_C(0x00)
#define BMM150_XYZ_CHANNEL_DISABLE UINT8_C(0x07)
/*! @name Register Address */
#define BMM150_REG_CHIP_ID UINT8_C(0x40)
#define BMM150_REG_DATA_X_LSB UINT8_C(0x42)
#define BMM150_REG_DATA_READY_STATUS UINT8_C(0x48)
#define BMM150_REG_INTERRUPT_STATUS UINT8_C(0x4A)
#define BMM150_REG_POWER_CONTROL UINT8_C(0x4B)
#define BMM150_REG_OP_MODE UINT8_C(0x4C)
#define BMM150_REG_INT_CONFIG UINT8_C(0x4D)
#define BMM150_REG_AXES_ENABLE UINT8_C(0x4E)
#define BMM150_REG_LOW_THRESHOLD UINT8_C(0x4F)
#define BMM150_REG_HIGH_THRESHOLD UINT8_C(0x50)
#define BMM150_REG_REP_XY UINT8_C(0x51)
#define BMM150_REG_REP_Z UINT8_C(0x52)
/*! @name Macros to select the sensor settings to be set by the user
* These values are internal for API implementation. Don't relate this to
* data sheet.
*/
#define BMM150_SEL_DATA_RATE UINT16_C(1)
#define BMM150_SEL_CONTROL_MEASURE UINT16_C(1 << 1)
#define BMM150_SEL_XY_REP UINT16_C(1 << 2)
#define BMM150_SEL_Z_REP UINT16_C(1 << 3)
#define BMM150_SEL_DRDY_PIN_EN UINT16_C(1 << 4)
#define BMM150_SEL_INT_PIN_EN UINT16_C(1 << 5)
#define BMM150_SEL_DRDY_POLARITY UINT16_C(1 << 6)
#define BMM150_SEL_INT_LATCH UINT16_C(1 << 7)
#define BMM150_SEL_INT_POLARITY UINT16_C(1 << 8)
#define BMM150_SEL_DATA_OVERRUN_INT UINT16_C(1 << 9)
#define BMM150_SEL_OVERFLOW_INT UINT16_C(1 << 10)
#define BMM150_SEL_HIGH_THRESHOLD_INT UINT16_C(1 << 11)
#define BMM150_SEL_LOW_THRESHOLD_INT UINT16_C(1 << 12)
#define BMM150_SEL_LOW_THRESHOLD_SETTING UINT16_C(1 << 13)
#define BMM150_SEL_HIGH_THRESHOLD_SETTING UINT16_C(1 << 14)
/*! @name DATA RATE DEFINITIONS */
#define BMM150_DATA_RATE_10HZ UINT8_C(0x00)
#define BMM150_DATA_RATE_02HZ UINT8_C(0x01)
#define BMM150_DATA_RATE_06HZ UINT8_C(0x02)
#define BMM150_DATA_RATE_08HZ UINT8_C(0x03)
#define BMM150_DATA_RATE_15HZ UINT8_C(0x04)
#define BMM150_DATA_RATE_20HZ UINT8_C(0x05)
#define BMM150_DATA_RATE_25HZ UINT8_C(0x06)
#define BMM150_DATA_RATE_30HZ UINT8_C(0x07)
#define BMM150_ODR_MAX UINT8_C(0x07)
#define BMM150_ODR_MSK UINT8_C(0x38)
#define BMM150_ODR_POS UINT8_C(0x03)
/*! @name TRIM REGISTERS */
/* Trim Extended Registers */
#define BMM150_DIG_X1 UINT8_C(0x5D)
#define BMM150_DIG_Y1 UINT8_C(0x5E)
#define BMM150_DIG_Z4_LSB UINT8_C(0x62)
#define BMM150_DIG_Z4_MSB UINT8_C(0x63)
#define BMM150_DIG_X2 UINT8_C(0x64)
#define BMM150_DIG_Y2 UINT8_C(0x65)
#define BMM150_DIG_Z2_LSB UINT8_C(0x68)
#define BMM150_DIG_Z2_MSB UINT8_C(0x69)
#define BMM150_DIG_Z1_LSB UINT8_C(0x6A)
#define BMM150_DIG_Z1_MSB UINT8_C(0x6B)
#define BMM150_DIG_XYZ1_LSB UINT8_C(0x6C)
#define BMM150_DIG_XYZ1_MSB UINT8_C(0x6D)
#define BMM150_DIG_Z3_LSB UINT8_C(0x6E)
#define BMM150_DIG_Z3_MSB UINT8_C(0x6F)
#define BMM150_DIG_XY2 UINT8_C(0x70)
#define BMM150_DIG_XY1 UINT8_C(0x71)
/*! @name Threshold interrupt setting macros for x,y,z axes selection */
#define BMM150_THRESHOLD_X UINT8_C(0x06)
#define BMM150_THRESHOLD_Y UINT8_C(0x05)
#define BMM150_THRESHOLD_Z UINT8_C(0x03)
#define BMM150_HIGH_THRESHOLD_INT_MSK UINT8_C(0x38)
#define BMM150_HIGH_THRESHOLD_INT_POS UINT8_C(0x03)
#define BMM150_LOW_THRESHOLD_INT_MSK UINT8_C(0x07)
/*! @name User configurable interrupt setting macros */
#define BMM150_INT_ENABLE UINT8_C(0x01)
#define BMM150_INT_DISABLE UINT8_C(0x00)
#define BMM150_ACTIVE_HIGH_POLARITY UINT8_C(0x01)
#define BMM150_ACTIVE_LOW_POLARITY UINT8_C(0x00)
#define BMM150_LATCHED UINT8_C(0x01)
#define BMM150_NON_LATCHED UINT8_C(0x00)
/*! @name Interrupt status */
#define BMM150_INT_THRESHOLD_X_LOW UINT16_C(0x0001)
#define BMM150_INT_THRESHOLD_Y_LOW UINT16_C(0x0002)
#define BMM150_INT_THRESHOLD_Z_LOW UINT16_C(0x0004)
#define BMM150_INT_THRESHOLD_X_HIGH UINT16_C(0x0008)
#define BMM150_INT_THRESHOLD_Y_HIGH UINT16_C(0x0010)
#define BMM150_INT_THRESHOLD_Z_HIGH UINT16_C(0x0020)
#define BMM150_INT_DATA_OVERFLOW UINT16_C(0x0040)
#define BMM150_INT_DATA_OVERRUN UINT16_C(0x0080)
#define BMM150_INT_DATA_READY UINT16_C(0x0100)
#define BMM150_DRDY_EN_MSK UINT8_C(0x80)
#define BMM150_DRDY_EN_POS UINT8_C(0x07)
#define BMM150_DRDY_POLARITY_MSK UINT8_C(0x04)
#define BMM150_DRDY_POLARITY_POS UINT8_C(0x02)
#define BMM150_INT_PIN_EN_MSK UINT8_C(0x40)
#define BMM150_INT_PIN_EN_POS UINT8_C(0x06)
#define BMM150_INT_LATCH_MSK UINT8_C(0x02)
#define BMM150_INT_LATCH_POS UINT8_C(0x01)
#define BMM150_INT_POLARITY_MSK UINT8_C(0x01)
#define BMM150_DRDY_STATUS_MSK UINT8_C(0x01)
/*! @name Interrupt status macros */
#define BMM150_INT_ASSERTED_DRDY UINT16_C(0x0100)
#define BMM150_INT_ASSERTED_LOW_THRES UINT16_C(0x0007)
#define BMM150_INT_ASSERTED_HIGH_THRES UINT16_C(0x0380)
/*! @name Power control bit macros */
#define BMM150_PWR_CNTRL_MSK UINT8_C(0x01)
#define BMM150_CONTROL_MEASURE_MSK UINT8_C(0x38)
#define BMM150_CONTROL_MEASURE_POS UINT8_C(0x03)
#define BMM150_POWER_CONTROL_BIT_MSK UINT8_C(0x01)
#define BMM150_POWER_CONTROL_BIT_POS UINT8_C(0x00)
/*! @name Data macros */
#define BMM150_DATA_X_MSK UINT8_C(0xF8)
#define BMM150_DATA_X_POS UINT8_C(0x03)
#define BMM150_DATA_Y_MSK UINT8_C(0xF8)
#define BMM150_DATA_Y_POS UINT8_C(0x03)
#define BMM150_DATA_Z_MSK UINT8_C(0xFE)
#define BMM150_DATA_Z_POS UINT8_C(0x01)
#define BMM150_DATA_RHALL_MSK UINT8_C(0xFC)
#define BMM150_DATA_RHALL_POS UINT8_C(0x02)
#define BMM150_DATA_OVERRUN_INT_MSK UINT8_C(0x80)
#define BMM150_DATA_OVERRUN_INT_POS UINT8_C(0x07)
#define BMM150_OVERFLOW_INT_MSK UINT8_C(0x40)
#define BMM150_OVERFLOW_INT_POS UINT8_C(0x06)
/*! @name OVERFLOW DEFINITIONS */
#define BMM150_OVERFLOW_ADCVAL_XYAXES_FLIP INT16_C(-4096)
#define BMM150_OVERFLOW_ADCVAL_ZAXIS_HALL INT16_C(-16384)
#define BMM150_OVERFLOW_OUTPUT INT16_C(-32768)
#define BMM150_NEGATIVE_SATURATION_Z INT16_C(-32767)
#define BMM150_POSITIVE_SATURATION_Z INT16_C(32767)
#ifdef BMM150_USE_FLOATING_POINT
#define BMM150_OVERFLOW_OUTPUT_FLOAT 0.0f
#endif
/*! @name PRESET MODE DEFINITIONS */
#define BMM150_PRESETMODE_LOWPOWER UINT8_C(0x01)
#define BMM150_PRESETMODE_REGULAR UINT8_C(0x02)
#define BMM150_PRESETMODE_HIGHACCURACY UINT8_C(0x03)
#define BMM150_PRESETMODE_ENHANCED UINT8_C(0x04)
#define BMM150_OP_MODE_MSK UINT8_C(0x06)
#define BMM150_OP_MODE_POS UINT8_C(0x01)
/*! @name PRESET MODES - REPETITIONS-XY RATES */
#define BMM150_REPXY_LOWPOWER UINT8_C(0x01)
#define BMM150_REPXY_REGULAR UINT8_C(0x04)
#define BMM150_REPXY_ENHANCED UINT8_C(0x07)
#define BMM150_REPXY_HIGHACCURACY UINT8_C(0x17)
/*! @name PRESET MODES - REPETITIONS-Z RATES */
#define BMM150_REPZ_LOWPOWER UINT8_C(0x01)
#define BMM150_REPZ_REGULAR UINT8_C(0x07)
#define BMM150_REPZ_ENHANCED UINT8_C(0x0D)
#define BMM150_REPZ_HIGHACCURACY UINT8_C(0x29)
/*! @name Self test settings */
#define BMM150_DISABLE_XY_AXIS UINT8_C(0x03)
#define BMM150_SELF_TEST_REP_Z UINT8_C(0x04)
/*! @name Self test selection macros */
#define BMM150_SELF_TEST_NORMAL UINT8_C(0)
#define BMM150_SELF_TEST_ADVANCED UINT8_C(1)
/*! @name Advanced self-test current settings */
#define BMM150_DISABLE_SELF_TEST_CURRENT UINT8_C(0x00)
#define BMM150_ENABLE_NEGATIVE_CURRENT UINT8_C(0x02)
#define BMM150_ENABLE_POSITIVE_CURRENT UINT8_C(0x03)
/*! @name Normal self-test status */
#define BMM150_SELF_TEST_STATUS_XYZ_FAIL UINT8_C(0x00)
#define BMM150_SELF_TEST_STATUS_SUCCESS UINT8_C(0x07)
#define BMM150_SELF_TEST_MSK UINT8_C(0x01)
#define BMM150_ADV_SELF_TEST_MSK UINT8_C(0xC0)
#define BMM150_ADV_SELF_TEST_POS UINT8_C(0x06)
/*! @name Register read lengths */
#define BMM150_LEN_SELF_TEST UINT8_C(5)
#define BMM150_LEN_SETTING_DATA UINT8_C(8)
#define BMM150_LEN_XYZR_DATA UINT8_C(8)
/*! @name Boundary check macros */
#define BMM150_BOUNDARY_MAXIMUM UINT8_C(0)
#define BMM150_BOUNDARY_MINIMUM UINT8_C(1)
/*! @name Macro to SET and GET BITS of a register*/
#define BMM150_SET_BITS(reg_data, bitname, data) \
((reg_data & ~(bitname##_MSK)) | \
((data << bitname##_POS) & bitname##_MSK))
#define BMM150_GET_BITS(reg_data, bitname) ((reg_data & (bitname##_MSK)) >> \
(bitname##_POS))
#define BMM150_SET_BITS_POS_0(reg_data, bitname, data) \
((reg_data & ~(bitname##_MSK)) | \
(data & bitname##_MSK))
#define BMM150_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK))
/********************************************************/
/*!
* @brief Interface selection Enums
*/
enum bmm150_intf {
/*! SPI interface */
BMM150_SPI_INTF,
/*! I2C interface */
BMM150_I2C_INTF
};
/******************************************************************************/
/*! @name Function Pointers */
/******************************************************************************/
#ifndef BMM150_INTF_RET_TYPE
#define BMM150_INTF_RET_TYPE int8_t
#endif
#ifndef BMM150_INTF_RET_SUCCESS
#define BMM150_INTF_RET_SUCCESS INT8_C(0)
#endif
/*!
* @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 BMM150_INTF_RET_TYPE (*bmm150_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 BMM150_INTF_RET_TYPE (*bmm150_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 (*bmm150_delay_us_fptr_t)(uint32_t period, void *intf_ptr);
/******************************************************************************/
/*! @name Structure Declarations */
/******************************************************************************/
/*!
* @brief bmm150 trim data structure
*/
struct bmm150_trim_registers {
/*! trim x1 data */
int8_t dig_x1;
/*! trim y1 data */
int8_t dig_y1;
/*! trim x2 data */
int8_t dig_x2;
/*! trim y2 data */
int8_t dig_y2;
/*! trim z1 data */
uint16_t dig_z1;
/*! trim z2 data */
int16_t dig_z2;
/*! trim z3 data */
int16_t dig_z3;
/*! trim z4 data */
int16_t dig_z4;
/*! trim xy1 data */
uint8_t dig_xy1;
/*! trim xy2 data */
int8_t dig_xy2;
/*! trim xyz1 data */
uint16_t dig_xyz1;
};
/*!
* @brief bmm150 interrupt pin settings
*/
struct bmm150_int_ctrl_settings {
/*! Data ready interrupt enable */
uint8_t drdy_pin_en;
/*! Threshold and overflow interrupts enable */
uint8_t int_pin_en;
/*! Data ready interrupt polarity Active high/low */
uint8_t drdy_polarity;
/*! Interrupt pin - Latched or Non-latched */
uint8_t int_latch;
/*! Interrupt polarity Active high/low */
uint8_t int_polarity;
/*! Data overrun interrupt enable */
uint8_t data_overrun_en;
/*! Overflow interrupt enable */
uint8_t overflow_int_en;
/*! high interrupt enable/disable axis selection */
uint8_t high_int_en;
/*! low interrupt enable/disable axis selection */
uint8_t low_int_en;
/*! low threshold limit */
uint8_t low_threshold;
/*! high threshold limit */
uint8_t high_threshold;
};
/*!
* @brief bmm150 sensor settings
*/
struct bmm150_settings {
/*! Control measurement of XYZ axes */
uint8_t xyz_axes_control;
/*! Power mode of sensor */
uint8_t pwr_mode;
/*! Data rate value (ODR) */
uint8_t data_rate;
/*! XY Repetitions */
uint8_t xy_rep;
/*! Z Repetitions */
uint8_t z_rep;
/*! Preset mode of sensor */
uint8_t preset_mode;
/*! Interrupt configuration settings */
struct bmm150_int_ctrl_settings int_settings;
};
/*!
* @brief bmm150 un-compensated (raw) magnetometer data
*/
struct bmm150_raw_mag_data {
/*! Raw mag X data */
int16_t raw_datax;
/*! Raw mag Y data */
int16_t raw_datay;
/*! Raw mag Z data */
int16_t raw_dataz;
/*! Raw mag resistance value */
uint16_t raw_data_r;
};
#ifdef BMM150_USE_FLOATING_POINT
/*!
* @brief bmm150 compensated magnetometer data in float
*/
struct bmm150_mag_data {
/*! compensated mag X data */
float x;
/*! compensated mag Y data */
float y;
/*! compensated mag Z data */
float z;
};
#else
/*!
* @brief bmm150 compensated magnetometer data in int16_t format
*/
struct bmm150_mag_data {
/*! compensated mag X data */
int16_t x;
/*! compensated mag Y data */
int16_t y;
/*! compensated mag Z data */
int16_t z;
};
#endif
/*!
* @brief bmm150 device structure
*/
struct bmm150_dev {
/*! Chip Id */
uint8_t chip_id;
/*! SPI/I2C Interface */
enum bmm150_intf intf;
/*!
* 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;
/*! Variable that holds result of read/write function */
BMM150_INTF_RET_TYPE intf_rslt;
/*! Bus read function pointer */
bmm150_read_fptr_t read;
/*! Bus write function pointer */
bmm150_write_fptr_t write;
/*! delay(in us) function pointer */
bmm150_delay_us_fptr_t delay_us;
/*! Trim registers */
struct bmm150_trim_registers trim_data;
/*! Interrupt status */
uint16_t int_status;
/*! Power control bit value */
uint8_t pwr_cntrl_bit;
};
#endif /* BMM150_DEFS_H_ */

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