diff --git a/CST816S.cpp b/CST816S.cpp index 44fed92..71d66c3 100644 --- a/CST816S.cpp +++ b/CST816S.cpp @@ -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(); + } } /*! @@ -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(seconds); // Convert int to byte + i2c_write(CST816S_ADDRESS, 0xF9, &sleepTime, 1); } /*! @@ -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 callback) +{ + userISR = callback; +} + /*! @brief check for a touch event */ diff --git a/CST816S.h b/CST816S.h index 6044916..7878306 100644 --- a/CST816S.h +++ b/CST816S.h @@ -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 callback); void sleep(); bool available(); data_struct data; @@ -72,6 +75,8 @@ class CST816S { int _rst; int _irq; bool _event_available; + std::function userISR; + void IRAM_ATTR handleISR(); void read_touch(); diff --git a/README.md b/README.md index c4c19ee..8a05caa 100644 --- a/README.md +++ b/README.md @@ -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
- 0x01: Slide Up
- 0x02: Slide Down
- 0x03: Slide Left
- 0x04: Slide Right
- 0x05: Single Click
- 0x0B: Double Click
- 0x0C: Long Press | +| FingerNum | 0x02 | Number of fingers detected | N/A | - 0: No finger
- 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 | - | @@ -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)
- Bit 1: EnConUD (enable continuous up/down swipe)
- 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)
- Bit 6: EnTouch (Sends low pulse on touch detection)
- Bit 5: EnChange (Sends low pulse on touch state change)
- Bit 4: EnMotion (Sends low pulse on gesture detection)
- 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
- 1-5: Time in seconds before auto-reset | +| LongPressTime | 0xFC | Time (in seconds) for a long press to trigger reset | 10 seconds | - 0: Disable
- 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)
- Bit 1: IIC_OD (0: Pull-up resistor, 1: Open-drain)
- Bit 0: En1v8 (0: VDD, 1: 1.8V) | +| DisAutoSleep | 0xFE | Disable automatic entry into low-power mode | 0 (enabled) | - 0: Enable auto sleep
- Non-zero: Disable auto sleep | diff --git a/examples/auto_sleep/auto_sleep.ino b/examples/auto_sleep/auto_sleep.ino new file mode 100644 index 0000000..ca11965 --- /dev/null +++ b/examples/auto_sleep/auto_sleep.ino @@ -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 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); + } +} \ No newline at end of file diff --git a/examples/auto_standby/auto_standby.ino b/examples/auto_standby/auto_standby.ino deleted file mode 100644 index 7359af8..0000000 --- a/examples/auto_standby/auto_standby.ino +++ /dev/null @@ -1,19 +0,0 @@ -#include - -CST816S touch(21, 22, 5, 4); // sda, scl, rst, irq - -void setup() { - Serial.begin(115200); - touch.begin(); - touch.enable_auto_standby(5000); // Set auto standby mode to 5000 milliseconds (5 seconds) - Serial.println("Auto standby enabled for 5 seconds of inactivity."); -} - -void loop() { - // Check for touch events to reset inactivity timer - if (touch.available()) { - Serial.println("Touch detected, reset standby timer."); - } - // Standby mode will activate automatically based on inactivity - delay(100); // Small delay to avoid excessive loop cycles -} diff --git a/examples/double_click/double_click.ino b/examples/double_click/double_click.ino index d96cd15..2127118 100644 --- a/examples/double_click/double_click.ino +++ b/examples/double_click/double_click.ino @@ -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 touch(21, 22, 5, 4); // sda, scl, rst, irq @@ -17,4 +41,4 @@ void loop() { Serial.println(doubleClickCount); } } -} +} \ No newline at end of file diff --git a/examples/user_interrupt/user_interrupt.ino b/examples/user_interrupt/user_interrupt.ino new file mode 100644 index 0000000..eabb03e --- /dev/null +++ b/examples/user_interrupt/user_interrupt.ino @@ -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 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."); + } + } + } +} diff --git a/library.json b/library.json index 4f642ca..08018f8 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "CST816S", - "version": "1.2.0", + "version": "1.3.0", "keywords": "Arduino, ESP32, Touch, Hynitron, CST816S, I2C", "description": "An Arduino library for the CST816S capacitive touch screen IC", "repository": diff --git a/library.properties b/library.properties index 4a789b2..0d1b0bc 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=CST816S -version=1.2.0 +version=1.3.0 author=fbiego maintainer=fbiego,filipek92,georgemclaughlin sentence=Capacitive touch screen library