Skip to content

Commit ecc7782

Browse files
committed
Second round of refactoring. Isolate touch array logic in its own file,
make everything else more agnostic, and address PR comments.
1 parent 98a82c0 commit ecc7782

File tree

7 files changed

+81
-68
lines changed

7 files changed

+81
-68
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ add_library(puara_gestures
2929
include/puara/descriptors/roll.h
3030
include/puara/descriptors/shake.h
3131
include/puara/descriptors/tilt.h
32-
include/puara/descriptors/touch.h
32+
include/puara/descriptors/touchArrayGestureDetector.h
3333

3434
include/puara/utils/blobDetector.h
3535
include/puara/utils/calibration.h

exampleProjects/touch/src/TinyTouch.hpp

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,24 @@
22

33
#include <puara/gestures.h>
44

5-
#include <Adafruit_FT6206.h>
5+
#include <Adafruit_FT6206.h> // Touchscreen library
66
#include <Adafruit_GFX.h> // Core graphics library
7-
#include <Adafruit_ILI9341.h> // Hardware-specific library for ST7789
7+
#include <Adafruit_ILI9341.h> // Display library
88
#include <SPI.h>
99

1010
/**
1111
* @class TinyTouch
12-
* @brief A class to handle touchscreen interactions using the Adafruit ILI9341 and FT6206 libraries.
12+
* @brief A class to demonstrate how to detect gestures on a touch-array like device (here using
13+
* a capacitive touchscreen available in Wokwi) ran on a TinyPICO board.
1314
*
14-
* This class is designed to test the Puara gesture framework by providing a simple interface
15-
* for initializing the screen, displaying introductory messages, detecting touch events, and
16-
* drawing rectangles on the screen. It uses the Puara Gesture library to recognise gestures.
15+
* This class is designed to demonstrate how to use the Puara gesture framework by providing a
16+
* simple interface for displaying an introductory message, drawing rectangles on the screen to
17+
* simulate a touch array, and detecting touch events on this array. It uses the
18+
* TouchArrayGestureDetector to recognise gestures.
19+
*
20+
* The associated wokwi diagram has one `board-ili9341-cap-touch` touch screen device, which is
21+
* split into its display and touch components in class members `Adafruit_ILI9341 display`
22+
* and `Adafruit_FT6206 touchScreen`.
1723
*/
1824
class TinyTouch
1925
{
@@ -29,13 +35,15 @@ class TinyTouch
2935
*/
3036
void initScreen()
3137
{
32-
tft.begin();
33-
screenHeight = tft.height();
34-
screenWidth = tft.width();
38+
//initialize the display
39+
display.begin();
40+
screenHeight = display.height();
41+
screenWidth = display.width();
3542
rectangleHeight = screenHeight / RECT_COUNT;
3643
Serial.println(F("Touchscreen is initialized"));
3744

38-
if(!ctp.begin())
45+
//initialize the touchscreen
46+
if(!touchScreen.begin())
3947
{
4048
Serial.println("Couldn't start touchscreen controller");
4149
while(1)
@@ -49,56 +57,54 @@ class TinyTouch
4957
*/
5058
void printIntro()
5159
{
52-
tft.fillScreen(ILI9341_BLACK);
53-
tft.setTextColor(ILI9341_WHITE);
54-
tft.setTextSize(2);
55-
tft.setCursor(10, 100);
56-
tft.println("Puara Gesture Test!");
57-
tft.setTextSize(1);
58-
tft.setCursor(10, 130);
59-
tft.println("Touch the screen to begin.");
60+
display.fillScreen(ILI9341_BLACK);
61+
display.setTextColor(ILI9341_WHITE);
62+
display.setTextSize(2);
63+
display.setCursor(10, 100);
64+
display.println("Puara Gesture Test!");
65+
display.setTextSize(1);
66+
display.setCursor(10, 130);
67+
display.println("Touch the screen to begin.");
6068
}
6169

6270
/**
6371
* @brief Checks if the touchscreen is currently being touched.
6472
* @return True if the touchscreen is being touched, false otherwise.
6573
*/
66-
bool touched() { return ctp.touched(); }
74+
bool touched() { return touchScreen.touched(); }
6775

6876
/**
6977
* @brief Draws rectangles on the screen.
7078
*
7179
* This function divides the screen into a series of rectangles and draws them. These
72-
* discrete rectangles will be used by puara to calculate various touch gestures.
80+
* discrete rectangles will simulate stripes in a touch array, which will be used
81+
* by the TouchArrayGestureDetector to calculate various gestures.
7382
*/
7483
void drawRectangles()
7584
{
7685
// Draw rectangles
77-
tft.fillScreen(ILI9341_BLACK);
86+
display.fillScreen(ILI9341_BLACK);
7887
for(int i = 0; i < RECT_COUNT; i++)
79-
tft.drawRect(0, i * rectangleHeight, screenWidth, rectangleHeight, ILI9341_WHITE);
88+
display.drawRect(0, i * rectangleHeight, screenWidth, rectangleHeight, ILI9341_WHITE);
8089
}
8190

8291
/**
83-
* @brief Updates the touch state of rectangles and redraws them on the screen.
92+
* @brief Updates the touch state of rectangles and the gestures in the TouchArrayGestureDetector.
8493
*
85-
* This function resets the current touch states, checks for new touch inputs,
94+
* This function resets the current touched rectangles, checks for new touch inputs,
8695
* and updates the screen and internal state to reflect changes. Touched
8796
* rectangles are filled with white, while untapped ones are filled with black
8897
* and outlined in white.
89-
*
90-
* @pre `ctp` must be initialized, and rectangle dimensions must match screen setup.
91-
* @post The screen reflects the updated touch states.
9298
*/
93-
void updateRectangles()
99+
void update()
94100
{
95101
// Reset the current touch array
96102
std::fill_n(touchedRectangles, RECT_COUNT, 0);
97103

98104
// Check for touches
99-
if(ctp.touched())
105+
if(touchScreen.touched())
100106
{
101-
TS_Point p{ctp.getPoint()};
107+
TS_Point p{touchScreen.getPoint()};
102108
p.x = map(p.x, 0, 240, 240, 0);
103109
p.y = map(p.y, 0, 320, 320, 0);
104110

@@ -113,14 +119,14 @@ class TinyTouch
113119
{
114120
if(touchedRectangles[i] == 1 && previouslyTouchedRectangles[i] == 0)
115121
{
116-
// Rectangle is touched - make it white
117-
tft.fillRect(0, i * rectangleHeight, screenWidth, rectangleHeight, ILI9341_WHITE);
122+
// Rectangle was just touched - make it white
123+
display.fillRect(0, i * rectangleHeight, screenWidth, rectangleHeight, ILI9341_WHITE);
118124
}
119125
else if(touchedRectangles[i] == 0 && previouslyTouchedRectangles[i] == 1)
120126
{
121127
// Rectangle no longer touched - make it black
122-
tft.fillRect(0, i * rectangleHeight, screenWidth, rectangleHeight, ILI9341_BLACK);
123-
tft.drawRect(0, i * rectangleHeight, screenWidth, rectangleHeight, ILI9341_WHITE);
128+
display.fillRect(0, i * rectangleHeight, screenWidth, rectangleHeight, ILI9341_BLACK);
129+
display.drawRect(0, i * rectangleHeight, screenWidth, rectangleHeight, ILI9341_WHITE);
124130
}
125131
}
126132

@@ -149,8 +155,8 @@ class TinyTouch
149155
int screenWidth{-1};
150156
int rectangleHeight{-1};
151157

152-
Adafruit_ILI9341 tft{TinyTouch::PIN_CS, TinyTouch::PIN_DC};
153-
Adafruit_FT6206 ctp;
158+
Adafruit_ILI9341 display{TinyTouch::PIN_CS, TinyTouch::PIN_DC};
159+
Adafruit_FT6206 touchScreen;
154160

155161
//======================== setup puara =======================
156162
static constexpr int RECT_COUNT{16};

exampleProjects/touch/src/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ void setup(void)
2626

2727
void loop()
2828
{
29-
tinyTouch.updateRectangles();
29+
tinyTouch.update();
3030
tinyTouch.printUpdate();
3131
}

include/puara/descriptors/brushRub.h

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ namespace puara_gestures
1515
class ValueIntegrator
1616
{
1717
public:
18-
//TODO VB: we need at least this default constructor because of the non-default constructor for the tied value
1918
ValueIntegrator() = default;
2019
ValueIntegrator(const ValueIntegrator&) noexcept = default;
2120
ValueIntegrator(ValueIntegrator&&) noexcept = default;
@@ -44,7 +43,7 @@ class ValueIntegrator
4443
{
4544
const auto delta = newValue - prevValue;
4645
prevValue = newValue;
47-
//TODO VB: floating point comparison
46+
4847
// No delta since the last update -> potentially reset the value
4948
if(delta == 0.0)
5049
{
@@ -91,18 +90,10 @@ class ValueIntegrator
9190
/**
9291
* @brief Ties the feature to an external value.
9392
* @param new_tie Pointer to the external value to tie the feature to.
94-
* @return True if the tie was successful; false if `new_tie` is null.
9593
*/
96-
bool tie(double* new_tie)
94+
void tie(double& new_tie)
9795
{
98-
if(new_tie == nullptr)
99-
{
100-
assert(false && "tied_value cannot be null!");
101-
return false;
102-
}
103-
104-
tied_data = new_tie;
105-
return true;
96+
tied_data = &new_tie;
10697
}
10798

10899
protected:
@@ -198,7 +189,7 @@ class Rub : public ValueIntegrator
198189

199190
//======================================================================
200191

201-
class RubAndBrushDetector
192+
class BrushRubDetector
202193
{
203194
public:
204195
Brush brush;

include/puara/descriptors/touchArrayGestureDetector.h

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,27 @@ namespace puara_gestures
99

1010
// touchSizeEdge: number of stripes for top and bottom portions (arbitrary)
1111
//maxNumBlobs: maximum number of "blobs" that the blob detector can detect at once on the touch array
12+
13+
/**
14+
* @class TouchArrayGestureDetector
15+
* @brief A class to detect gestures on a touch-array device.
16+
*
17+
* This class is designed to detect various gestures on a touch-array device by analyzing touch data.
18+
* It detects blobs (contiguous touched stripes in the touch array), and for each blob, it calculates
19+
* the amount of "brushing" and "rubbing" gestures using a BrushRubDetector.
20+
*
21+
* @tparam maxNumBlobs The maximum number of blobs that the blob detector can detect at once on the touch array.
22+
* @tparam touchSizeEdge The number of stripes for the top and bottom portions of the touch array.
23+
*/
1224
template <int maxNumBlobs, int touchSizeEdge>
1325
class TouchArrayGestureDetector
1426
{
1527
public:
16-
float touchAll{}; // f, 0--1
17-
float touchTop{}; // f, 0--1
18-
float touchMiddle{}; // f, 0--1
19-
float touchBottom{}; // f, 0--1
28+
//these four values are the average amount of touch for the entire touch array, as well as the top, middle and bottom parts.
29+
float totalTouchAverage{}; // f, 0--1
30+
float topTouchAverage{}; // f, 0--1
31+
float middleTouchAverage{}; // f, 0--1
32+
float bottomTouchAverage{}; // f, 0--1
2033

2134
/** total amount of "brushing" gesture for all detected blobs on the touch array, in ~cm/s (distance between stripes = ~1.5cm) */
2235
float totalBrush{};
@@ -31,33 +44,35 @@ class TouchArrayGestureDetector
3144
{
3245
// Update the "amount of touch" for the entire touch sensor, as well as the top, middle and bottom parts.
3346
// All normalized between 0 and 1.
34-
touchAll = utils::arrayAverage(touchArray, 0, touchSize);
35-
touchTop = utils::arrayAverage(touchArray, 0, touchSizeEdge);
36-
touchMiddle = utils::arrayAverage(touchArray, (0 + touchSizeEdge), (touchSize - touchSizeEdge));
37-
touchBottom = utils::arrayAverage(touchArray, (touchSize - touchSizeEdge), touchSize);
47+
totalTouchAverage = utils::arrayAverage(touchArray, 0, touchSize);
48+
topTouchAverage = utils::arrayAverage(touchArray, 0, touchSizeEdge);
49+
middleTouchAverage = utils::arrayAverage(touchArray, (0 + touchSizeEdge), (touchSize - touchSizeEdge));
50+
bottomTouchAverage = utils::arrayAverage(touchArray, (touchSize - touchSizeEdge), touchSize);
3851

3952
//detect blobs on the touch array
4053
blobDetector.detect1D(touchArray, touchSize);
4154

55+
//based on the start position of detected blobs, update the brush and rub detector
4256
for(int i = 0; i < maxNumBlobs; ++i)
43-
rubAndBrushDetector[i].update(blobDetector.blobStartPos[i]);
57+
brushRubDetector[i].update(blobDetector.blobStartPos[i]);
4458

45-
updateBrushAndRub();
59+
//and finally update the total brush and rub values
60+
updateTotalBrushAndRub();
4661
}
4762

4863
private:
4964
BlobDetector<maxNumBlobs> blobDetector;
50-
RubAndBrushDetector rubAndBrushDetector[maxNumBlobs];
65+
BrushRubDetector brushRubDetector[maxNumBlobs];
5166

52-
void updateBrushAndRub()
67+
void updateTotalBrushAndRub()
5368
{
5469
// Calculate total brush and rub values
5570
double brushes[maxNumBlobs];
5671
double rubs[maxNumBlobs];
5772
for(int i = 0; i < maxNumBlobs; ++i)
5873
{
59-
brushes[i] = rubAndBrushDetector[i].brush.value;
60-
rubs[i] = rubAndBrushDetector[i].rub.value;
74+
brushes[i] = brushRubDetector[i].brush.value;
75+
rubs[i] = brushRubDetector[i].rub.value;
6176
}
6277

6378
totalBrush = utils::arrayAverageZero(brushes, maxNumBlobs);

include/puara/utils/blobDetector.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ namespace puara_gestures
1616
* - The size in terms of consecutive `1`s (`blobSize`)
1717
* - The center index (`blobCenter`)
1818
*
19+
* @tparam maxNumBlobs The maximum number of blobs that the blob detector can detect at once.
20+
*
1921
* @warning Most of these values are reset when a detection function, e.g., detect1D(), is called,
2022
* and calculated during the detection funtion calls -- so their value is only really valid right
2123
* after such a call. There is no locking mechanism on any of these values so it is on the client
2224
* to ensure there is no race conditions.
2325
*
2426
* @note
25-
* - The number of blobs processed is set by the template parameter `maxNumBlobs`.
2627
* - If the input contains more blobs than `maxNumBlobs`, the additional blobs are ignored.
2728
*/
2829
template <int maxNumBlobs>

tests/testing_touch.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ int main()
3333

3434
// Update the touch data and print the computed values
3535
touchArrayGD.update(touchArray, touchSize);
36-
std::cout << "touchAll: " << touchArrayGD.touchAll << std::endl;
36+
std::cout << "totalTouchAverage: " << touchArrayGD.totalTouchAverage << std::endl;
3737
std::cout << "brush: " << touchArrayGD.totalBrush << std::endl;
3838
std::cout << "rub: " << touchArrayGD.totalRub << std::endl;
3939

@@ -61,7 +61,7 @@ int main()
6161

6262
// Update the touch data and print the computed values
6363
touchArrayGD.update(touchArray, touchSize);
64-
std::cout << "touchAll: " << touchArrayGD.touchAll << std::endl;
64+
std::cout << "totalTouchAverage: " << touchArrayGD.totalTouchAverage << std::endl;
6565
std::cout << "brush: " << touchArrayGD.totalBrush << std::endl;
6666
std::cout << "rub: " << touchArrayGD.totalRub << std::endl;
6767
}

0 commit comments

Comments
 (0)