Skip to content

Commit

Permalink
Merge pull request #12 from georgemclaughlin/1.3.0
Browse files Browse the repository at this point in the history
Updated auto sleep functionality and added user interrupt
  • Loading branch information
fbiego authored Oct 27, 2024
2 parents 4238b84 + be41d45 commit 03e28b7
Show file tree
Hide file tree
Showing 9 changed files with 253 additions and 48 deletions.
52 changes: 46 additions & 6 deletions CST816S.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ void CST816S::read_touch() {
void IRAM_ATTR CST816S::handleISR(void) {
_event_available = true;

// Call user callback if it has been set
if (userISR != nullptr) {
userISR();
}
}

/*!
Expand All @@ -79,13 +83,40 @@ void CST816S::enable_double_click(void) {
}

/*!
@brief Enable auto standby mode with a specified delay.
@param milliseconds
Time in milliseconds before entering standby mode.
@brief Disable auto sleep mode
*/
void CST816S::disable_auto_sleep(void)
{
byte disableAutoSleep = 0xFE; // Non-zero value disables auto sleep
i2c_write(CST816S_ADDRESS, 0xFE, &disableAutoSleep, 1);
}

/*!
@brief Enable auto sleep mode
*/
void CST816S::enable_auto_sleep(void)
{
byte enableAutoSleep = 0x00; // 0 value enables auto sleep
i2c_write(CST816S_ADDRESS, 0xFE, &enableAutoSleep, 1);
}

/*!
@brief Set the auto sleep time
@param seconds Time in seconds (1-255) before entering standby mode after inactivity
*/
void CST816S::enable_auto_standby(uint16_t milliseconds) {
byte standbyTime = min(milliseconds / 1000, 255); // Convert milliseconds to seconds, max value 255
i2c_write(CST816S_ADDRESS, 0xF9, &standbyTime, 1);
void CST816S::set_auto_sleep_time(int seconds)
{
if (seconds < 1)
{
seconds = 1; // Enforce minimum value of 1 second
}
else if (seconds > 255)
{
seconds = 255; // Enforce maximum value of 255 seconds
}

byte sleepTime = static_cast<byte>(seconds); // Convert int to byte
i2c_write(CST816S_ADDRESS, 0xF9, &sleepTime, 1);
}

/*!
Expand Down Expand Up @@ -113,6 +144,15 @@ void CST816S::begin(int interrupt) {
attachInterrupt(_irq, std::bind(&CST816S::handleISR, this), interrupt);
}

/*!
@brief Attaches a user-defined callback function to be triggered on an interrupt event from the CST816S touch controller.
@param callback A function to be called when an interrupt event occurs, must have no parameters and return void.
*/
void CST816S::attachUserInterrupt(std::function<void(void)> callback)
{
userISR = callback;
}

/*!
@brief check for a touch event
*/
Expand Down
7 changes: 6 additions & 1 deletion CST816S.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ class CST816S {
CST816S(int sda, int scl, int rst, int irq);
void begin(int interrupt = RISING);
void enable_double_click();
void enable_auto_standby(uint16_t milliseconds);
void disable_auto_sleep();
void enable_auto_sleep();
void set_auto_sleep_time(int seconds);
void attachUserInterrupt(std::function<void(void)> callback);
void sleep();
bool available();
data_struct data;
Expand All @@ -72,6 +75,8 @@ class CST816S {
int _rst;
int _irq;
bool _event_available;
std::function<void(void)> userISR;


void IRAM_ATTR handleISR();
void read_touch();
Expand Down
65 changes: 46 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,41 @@

[![arduino-library-badge](https://www.ardu-badge.com/badge/CST816S.svg?)](https://www.arduinolibraries.info/libraries/cst816-s)

## Auto Sleep Control

Auto Sleep is referred to as Standby Mode in this [Waveshare document](https://www.waveshare.com/w/upload/5/51/CST816S_Datasheet_EN.pdf). Disabling of auto sleep or auto standby will keep the touch display in Dynamic mode. This will improve responsiveness, at the cost of about ~1.6mA.

By default, auto sleep is **enabled** with a timeout of 2 seconds. The following functions allow you to manage auto sleep behavior:

- **`void disable_auto_sleep();`**
Disables auto sleep, keeping the device active indefinitely.

- **`void enable_auto_sleep();`**
Re-enables auto sleep with the current timeout (default is 2 seconds).

- **`void set_auto_sleep_time(int seconds);`**
Sets the auto sleep timeout in seconds (1-255).
Example: `set_auto_sleep_time(10);` sets a 10-second timeout.

## User-Provided Interrupt

The CST816S library allows you to attach a custom interrupt function to handle touch events according to your application's needs. By providing a user-defined interrupt, you can trigger specific actions upon touch events, such as waking the device from a low-power state, checking gestures, or executing custom logic without constantly polling the device.

**Feature Highlights:**
- **Custom Event Handling**: Define and attach a user function that executes on each touch interrupt, allowing immediate responses to touch events.
- **Power Management**: Ideal for applications needing to manage power, such as waking from sleep modes, as the interrupt triggers only on touch.
- **Gesture-Based Logic**: Use the interrupt to wake, then analyze gestures to decide on further actions, enabling efficient and gesture-responsive behavior.



## Register Information

The following information was extracted from [this document](https://www.waveshare.com/w/upload/c/c2/CST816S_register_declaration.pdf) provided by Waveshare.

| Register Name | Address | Bit Description | Default Value | Configuration Options |
|-------------------|---------|-------------------------------------------------------|---------------|----------------------------------------------------------------|
| GestureID | 0x01 | Gesture code for detected gestures | N/A | 0x00: None, 0x01: Slide Up, 0x02: Slide Down, 0x0B: Double Click |
| FingerNum | 0x02 | Number of fingers detected | N/A | 0: No finger, 1: One finger |
| GestureID | 0x01 | Gesture code for detected gestures | N/A | - 0x00: None <br> - 0x01: Slide Up <br> - 0x02: Slide Down <br> - 0x03: Slide Left <br> - 0x04: Slide Right <br> - 0x05: Single Click <br> - 0x0B: Double Click <br> - 0x0C: Long Press |
| FingerNum | 0x02 | Number of fingers detected | N/A | - 0: No finger <br> - 1: One finger |
| XposH | 0x03 | High 4 bits of X coordinate | N/A | - |
| XposL | 0x04 | Low 8 bits of X coordinate | N/A | - |
| YposH | 0x05 | High 4 bits of Y coordinate | N/A | - |
Expand All @@ -22,22 +49,22 @@
| ChipID | 0xA7 | Chip model identifier | N/A | - |
| ProjID | 0xA8 | Project number | N/A | - |
| FwVersion | 0xA9 | Firmware version number | N/A | - |
| MotionMask | 0xEC | Enable gesture actions like double-click | 0x00 | Bit 0: EnDClick (enable double-click), Bit 1: EnConUD |
| MotionMask | 0xEC | Enable continuous gesture actions and double-click | 0x00 | - Bit 0: EnDClick (enable double-click) <br> - Bit 1: EnConUD (enable continuous up/down swipe) <br> - Bit 2: EnConLR (enable continuous left/right swipe) |
| IrqPluseWidth | 0xED | Interrupt pulse width (0.1 ms units) | 10 | 1-200 |
| NorScanPer | 0xEE | Normal scan period (10 ms units) | 1 | 1-30 |
| MotionSlAngle | 0xEF | Gesture detection sliding angle control | N/A | - |
| LpScanRaw1H | 0xF0 | High 8 bits of low-power scan channel 1 reference | N/A | - |
| LpScanRaw1L | 0xF1 | Low 8 bits of low-power scan channel 1 reference | N/A | - |
| LpScanRaw2H | 0xF2 | High 8 bits of low-power scan channel 2 reference | N/A | - |
| LpScanRaw2L | 0xF3 | Low 8 bits of low-power scan channel 2 reference | N/A | - |
| LpAutoWakeTime | 0xF4 | Auto recalibration time in low-power mode | 5 minutes | 1-5 minutes |
| LpScanTH | 0xF5 | Low-power scan wake threshold | 48 | 1-255 |
| LpScanWin | 0xF6 | Low-power scan range | 3 | 0-3 |
| LpScanFreq | 0xF7 | Low-power scan frequency | 7 | 1-255 |
| LpScanIdac | 0xF8 | Low-power scan current | N/A | 1-255 |
| AutoSleepTime | 0xF9 | Time in seconds before entering standby mode | 2 seconds | 1-255 seconds |
| IrqCtl | 0xFA | Control of interrupt behavior | N/A | EnTest, EnTouch, EnChange, EnMotion |
| AutoReset | 0xFB | Auto-reset time with no valid gesture detected | 5 seconds | 0-5 seconds (0 to disable) |
| LongPressTime | 0xFC | Time for long press to trigger reset | 10 seconds | 0-10 seconds (0 to disable) |
| IOCtl | 0xFD | IO control settings including soft reset | N/A | SOFT_RST, IIC_OD, En1v8 |
| DisAutoSleep | 0xFE | Disable auto sleep mode | 0 | Non-zero value disables auto sleep mode |
| MotionSlAngle | 0xEF | Gesture detection sliding angle control (Angle = tan(c) * 10, where c is the angle relative to the positive X-axis) | N/A | - |
| LpScanRaw1H | 0xF0 | High 8 bits of low-power scan channel 1 reference | N/A | - |
| LpScanRaw1L | 0xF1 | Low 8 bits of low-power scan channel 1 reference | N/A | - |
| LpScanRaw2H | 0xF2 | High 8 bits of low-power scan channel 2 reference | N/A | - |
| LpScanRaw2L | 0xF3 | Low 8 bits of low-power scan channel 2 reference | N/A | - |
| LpAutoWakeTime | 0xF4 | Low-power mode auto recalibration interval (in minutes) | 5 minutes | 1-5 minutes |
| LpScanTH | 0xF5 | Low-power scan wake threshold. The smaller the value, the more sensitive it is. | 48 | 1-255 |
| LpScanWin | 0xF6 | Low-power scan range. The larger the value, the more sensitive it is, but power consumption increases. | 3 | 0-3 |
| LpScanFreq | 0xF7 | Low-power scan frequency. The smaller the value, the more sensitive it is. | 7 | 1-255 |
| LpScanIdac | 0xF8 | Low-power scan current. The smaller the value, the more sensitive it is. | N/A | 1-255 |
| AutoSleepTime | 0xF9 | Time in seconds before entering standby mode after inactivity | 2 seconds | 1-255 seconds |
| IrqCtl | 0xFA | Control of interrupt behavior | N/A | - Bit 7: EnTest (Enable test, periodically sends low pulses) <br> - Bit 6: EnTouch (Sends low pulse on touch detection) <br> - Bit 5: EnChange (Sends low pulse on touch state change) <br> - Bit 4: EnMotion (Sends low pulse on gesture detection) <br> - Bit 0: OnceWLP (Sends one low pulse on long press) |
| AutoReset | 0xFB | Auto-reset time after detecting touch with no valid gesture | 5 seconds | - 0: Disable <br> - 1-5: Time in seconds before auto-reset |
| LongPressTime | 0xFC | Time (in seconds) for a long press to trigger reset | 10 seconds | - 0: Disable <br> - 1-10: Long press duration in seconds |
| IOCtl | 0xFD | IO control settings including soft reset and power options | N/A | - Bit 2: SOFT_RST (0: Disable soft reset, 1: Enable soft reset) <br> - Bit 1: IIC_OD (0: Pull-up resistor, 1: Open-drain) <br> - Bit 0: En1v8 (0: VDD, 1: 1.8V) |
| DisAutoSleep | 0xFE | Disable automatic entry into low-power mode | 0 (enabled) | - 0: Enable auto sleep <br> - Non-zero: Disable auto sleep |
69 changes: 69 additions & 0 deletions examples/auto_sleep/auto_sleep.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
MIT License
Copyright (c) 2021 Felix Biego
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.
*/

#include <CST816S.h>

CST816S touch(21, 22, 5, 4); // sda, scl, rst, irq

void setup() {
Serial.begin(115200);

touch.begin();

// Print version information
Serial.print("Touch Firmware Version: ");
Serial.print(touch.data.version);
Serial.print("\t");
Serial.print(touch.data.versionInfo[0]);
Serial.print("-");
Serial.print(touch.data.versionInfo[1]);
Serial.print("-");
Serial.println(touch.data.versionInfo[2]);

// Disable auto sleep to keep the device active (useful during debugging or testing)
touch.disable_auto_sleep();
Serial.println("Auto sleep disabled");

// Optionally, set a custom auto sleep time (e.g., 10 seconds)
touch.set_auto_sleep_time(10);
Serial.println("Auto sleep timeout set to 10 seconds");

// Setting the auto sleep time does not automatically reenable auto sleep
touch.enable_auto_sleep();
}

void loop() {
if (touch.available()) {
Serial.print("Gesture: ");
Serial.print(touch.gesture());
Serial.print("\tPoints: ");
Serial.print(touch.data.points);
Serial.print("\tEvent: ");
Serial.print(touch.data.event);
Serial.print("\tX: ");
Serial.print(touch.data.x);
Serial.print("\tY: ");
Serial.println(touch.data.y);
}
}
19 changes: 0 additions & 19 deletions examples/auto_standby/auto_standby.ino

This file was deleted.

26 changes: 25 additions & 1 deletion examples/double_click/double_click.ino
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
/*
MIT License
Copyright (c) 2021 Felix Biego
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.
*/

#include <CST816S.h>

CST816S touch(21, 22, 5, 4); // sda, scl, rst, irq
Expand All @@ -17,4 +41,4 @@ void loop() {
Serial.println(doubleClickCount);
}
}
}
}
59 changes: 59 additions & 0 deletions examples/user_interrupt/user_interrupt.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
MIT License
Copyright (c) 2021 Felix Biego
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.
*/

#include <CST816S.h>

CST816S touch(21, 22, 5, 4); // sda, scl, rst, irq

// Flag to indicate a touch interrupt has occurred
volatile bool touchEventFlag = false;

// Interrupt function to set the flag
void IRAM_ATTR onTouchInterrupt() {
touchEventFlag = true;
}

void setup() {
Serial.begin(9600);
touch.begin();
touch.attachUserInterrupt(onTouchInterrupt);
touch.enable_double_click(); // Enable double-click detection
}

void loop() {
// Check if the interrupt flag has been set by the interrupt handler
if (touchEventFlag) {
touchEventFlag = false; // Clear the flag

// Check if there’s touch data available
if (touch.available()) {
// Check if the gesture is a double touch
if (touch.gesture() == "DOUBLE CLICK") {
Serial.println("Double touch detected!");
} else {
Serial.println("Touch event detected, but not a double touch.");
}
}
}
}
Loading

0 comments on commit 03e28b7

Please sign in to comment.