Demo touching the perimeter of a circle

Dependencies:   RA8875

Committer:
WiredHome
Date:
Sun Apr 04 20:15:47 2021 +0000
Revision:
2:3077639f94fa
Parent:
1:e4f92c21e329
Child:
3:d259be26795b
Leverage the fix in the RA8875 library.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 0:f2a6447e607c 1 ///
WiredHome 0:f2a6447e607c 2 /// RA8875 display library example where a user touch on the perimeter
WiredHome 0:f2a6447e607c 3 /// of a circle should be detected.
WiredHome 0:f2a6447e607c 4 ///
WiredHome 0:f2a6447e607c 5 ///
WiredHome 0:f2a6447e607c 6 /// 0 deg
WiredHome 0:f2a6447e607c 7 /// -+-
WiredHome 0:f2a6447e607c 8 /// - -
WiredHome 0:f2a6447e607c 9 ///
WiredHome 0:f2a6447e607c 10 /// / \
WiredHome 0:f2a6447e607c 11 ///
WiredHome 0:f2a6447e607c 12 ///
WiredHome 0:f2a6447e607c 13 /// | |
WiredHome 0:f2a6447e607c 14 /// -90 deg + + + +90 deg
WiredHome 0:f2a6447e607c 15 /// | |
WiredHome 0:f2a6447e607c 16 ///
WiredHome 0:f2a6447e607c 17 ///
WiredHome 0:f2a6447e607c 18 /// \ /
WiredHome 0:f2a6447e607c 19 ///
WiredHome 0:f2a6447e607c 20 ///
WiredHome 0:f2a6447e607c 21 /// - -
WiredHome 0:f2a6447e607c 22 /// -+-
WiredHome 0:f2a6447e607c 23 /// +180 deg
WiredHome 0:f2a6447e607c 24 ///
WiredHome 0:f2a6447e607c 25 ///
WiredHome 0:f2a6447e607c 26 /// NOTE NOTE NOTE NOTE NOTE NOTE
WiredHome 0:f2a6447e607c 27 ///
WiredHome 0:f2a6447e607c 28 /// The code in this example would greatly benefit by refactoring to
WiredHome 0:f2a6447e607c 29 /// use radians, rather than degrees. Further, the coordinate system
WiredHome 0:f2a6447e607c 30 /// desired here is more like a clock-face, with 0 degrees is straight
WiredHome 0:f2a6447e607c 31 /// up and increasing angle in the clockwise direction.
WiredHome 0:f2a6447e607c 32 ///
WiredHome 0:f2a6447e607c 33 /// There are a few transformations (direction of rotation and angle
WiredHome 0:f2a6447e607c 34 /// offset) that didn't "feel right", even with the right result.
WiredHome 0:f2a6447e607c 35 ///
WiredHome 1:e4f92c21e329 36 /// NOTE NOTE NOTE NOTE NOTE NOTE
WiredHome 1:e4f92c21e329 37 ///
WiredHome 1:e4f92c21e329 38 /// I didn't pay too much attention to managing int, float, and double
WiredHome 1:e4f92c21e329 39 /// to avoid unnecessary promotion or math complexity.
WiredHome 1:e4f92c21e329 40 ///
WiredHome 0:f2a6447e607c 41 #include "mbed.h"
WiredHome 0:f2a6447e607c 42 #include "RA8875.h"
WiredHome 0:f2a6447e607c 43
WiredHome 1:e4f92c21e329 44 // Display with Capacitive Touch panel on I2C
WiredHome 0:f2a6447e607c 45 RA8875 lcd(p5,p6,p7,p12,NC, p9,p10,p13, "tft"); // MOSI,MISO,SCK,/ChipSelect,/reset, SDA,SCL,/IRQ, name
WiredHome 0:f2a6447e607c 46 //RA8875 lcd(p5,p6,p7,p8,NC, p28,p27,p30, "tft");
WiredHome 0:f2a6447e607c 47
WiredHome 1:e4f92c21e329 48 // debug serial for printf.
WiredHome 1:e4f92c21e329 49 // Some versions of the OS don't support the baud initializer here, then use device.baud(460800) in main.
WiredHome 1:e4f92c21e329 50 Serial device(USBTX,USBRX, 460800); // Initialize to a fast baud
WiredHome 1:e4f92c21e329 51 //Serial device(p26,p25);
WiredHome 0:f2a6447e607c 52
WiredHome 0:f2a6447e607c 53 // Screen size and color depth
WiredHome 0:f2a6447e607c 54 #define LCD_W 800
WiredHome 0:f2a6447e607c 55 #define LCD_H 480
WiredHome 1:e4f92c21e329 56 #define LCD_C 8 // color - bits per pixel
WiredHome 1:e4f92c21e329 57
WiredHome 1:e4f92c21e329 58 #define BL_NORM 100 // Backlight Normal setting (0 to 255)
WiredHome 0:f2a6447e607c 59
WiredHome 1:e4f92c21e329 60 //
WiredHome 0:f2a6447e607c 61 // The Circle definition around which touches are relevant
WiredHome 1:e4f92c21e329 62 //
WiredHome 0:f2a6447e607c 63 const point_t center = {200,250};
WiredHome 0:f2a6447e607c 64 const dim_t radius = 125;
WiredHome 0:f2a6447e607c 65 const dim_t touch_tolerance = 30;
WiredHome 0:f2a6447e607c 66
WiredHome 2:3077639f94fa 67
WiredHome 2:3077639f94fa 68 //
WiredHome 2:3077639f94fa 69 // Checkbox to turn on/off the touch-point
WiredHome 2:3077639f94fa 70 //
WiredHome 2:3077639f94fa 71 const rect_t check_tonoff = {400, 150, LCD_W-1, 182}; // Height based on double-size font
WiredHome 2:3077639f94fa 72 const char * check_tonoff_msg = "[%c] Visible touchpoints";
WiredHome 2:3077639f94fa 73 bool touchVisible = false; // default hidden
WiredHome 2:3077639f94fa 74
WiredHome 2:3077639f94fa 75
WiredHome 2:3077639f94fa 76 //
WiredHome 2:3077639f94fa 77 // Radio buttons to select between pie pieces
WiredHome 2:3077639f94fa 78 // and a dial-indent
WiredHome 2:3077639f94fa 79 //
WiredHome 2:3077639f94fa 80 const rect_t radio_pie = {400, 250, LCD_W-1, 282};
WiredHome 2:3077639f94fa 81 const char * radio_pie_msg = "(%c) Pie-slice rendering";
WiredHome 2:3077639f94fa 82 const rect_t radio_dial = {400, 300, LCD_W-1, 332};
WiredHome 2:3077639f94fa 83 const char * radio_dial_msg = "(%c) Dial rendering";
WiredHome 2:3077639f94fa 84 int renderOption = 0; // pie-slice
WiredHome 2:3077639f94fa 85
WiredHome 2:3077639f94fa 86 color_t edgeColor = BrightBlue;
WiredHome 2:3077639f94fa 87 color_t fillColor = Black;
WiredHome 2:3077639f94fa 88
WiredHome 2:3077639f94fa 89 void DrawCircle() {
WiredHome 2:3077639f94fa 90 // Draw a thickened circle
WiredHome 2:3077639f94fa 91 lcd.fillellipse(center.x, center.y, radius, radius, fillColor);
WiredHome 2:3077639f94fa 92 for (int r = 0; r <= 3; r++) {
WiredHome 2:3077639f94fa 93 lcd.ellipse(center.x, center.y, radius + r, radius + r, edgeColor);
WiredHome 2:3077639f94fa 94 }
WiredHome 2:3077639f94fa 95 }
WiredHome 2:3077639f94fa 96
WiredHome 2:3077639f94fa 97 void ShowUserControls() {
WiredHome 2:3077639f94fa 98 lcd.SetTextFontSize(2); // Bigger font; easier to touch
WiredHome 2:3077639f94fa 99 //
WiredHome 2:3077639f94fa 100 // [X] Enable visible touch-points
WiredHome 2:3077639f94fa 101 //
WiredHome 2:3077639f94fa 102 lcd.foreground(White);
WiredHome 2:3077639f94fa 103 lcd.SetTextCursor(check_tonoff.p1);
WiredHome 2:3077639f94fa 104 lcd.printf(check_tonoff_msg, (touchVisible) ? 'X' : ' ');
WiredHome 2:3077639f94fa 105 lcd.rect(check_tonoff, Gray);
WiredHome 2:3077639f94fa 106 //
WiredHome 2:3077639f94fa 107 // (*) Pie-slice rendering
WiredHome 2:3077639f94fa 108 // ( ) Dial rendering
WiredHome 2:3077639f94fa 109 //
WiredHome 2:3077639f94fa 110 lcd.foreground(White);
WiredHome 2:3077639f94fa 111 lcd.SetTextCursor(radio_pie.p1);
WiredHome 2:3077639f94fa 112 lcd.printf(radio_pie_msg, (renderOption == 0) ? '*' : ' ');
WiredHome 2:3077639f94fa 113 lcd.rect(radio_pie, Gray);
WiredHome 2:3077639f94fa 114 lcd.foreground(White);
WiredHome 2:3077639f94fa 115 lcd.SetTextCursor(radio_dial.p1);
WiredHome 2:3077639f94fa 116 lcd.printf(radio_dial_msg, (renderOption == 1) ? '*' : ' ');
WiredHome 2:3077639f94fa 117 lcd.rect(radio_dial, Gray);
WiredHome 2:3077639f94fa 118 lcd.SetTextFontSize();
WiredHome 2:3077639f94fa 119 }
WiredHome 2:3077639f94fa 120
WiredHome 2:3077639f94fa 121 void DrawInitialScreen() {
WiredHome 2:3077639f94fa 122 lcd.cls();
WiredHome 2:3077639f94fa 123 lcd.foreground(White); // Change to white
WiredHome 2:3077639f94fa 124 lcd.printf("RA8875 Touch Dial Example - Build " __DATE__ " " __TIME__ "\r\n");
WiredHome 2:3077639f94fa 125 lcd.printf("MBED v%d.%d.%d\r\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);
WiredHome 2:3077639f94fa 126 ShowUserControls();
WiredHome 2:3077639f94fa 127 DrawCircle();
WiredHome 2:3077639f94fa 128 }
WiredHome 2:3077639f94fa 129
WiredHome 2:3077639f94fa 130 void TestToggleHit(point_t t) {
WiredHome 2:3077639f94fa 131 if (lcd.Intersect(check_tonoff, t)) {
WiredHome 2:3077639f94fa 132 touchVisible = !touchVisible;
WiredHome 2:3077639f94fa 133 DrawInitialScreen();
WiredHome 2:3077639f94fa 134 }
WiredHome 2:3077639f94fa 135 }
WiredHome 2:3077639f94fa 136
WiredHome 2:3077639f94fa 137 void TestRenderHit(point_t t) {
WiredHome 2:3077639f94fa 138 bool update = false;
WiredHome 2:3077639f94fa 139 if (lcd.Intersect(radio_pie, t)) {
WiredHome 2:3077639f94fa 140 renderOption = 0;
WiredHome 2:3077639f94fa 141 edgeColor = BrightBlue;
WiredHome 2:3077639f94fa 142 fillColor = Black;
WiredHome 2:3077639f94fa 143 update = true;
WiredHome 2:3077639f94fa 144 } else if (lcd.Intersect(radio_dial, t)) {
WiredHome 2:3077639f94fa 145 renderOption = 1;
WiredHome 2:3077639f94fa 146 edgeColor = BrightBlue;
WiredHome 2:3077639f94fa 147 fillColor = Gray;
WiredHome 2:3077639f94fa 148 update = true;
WiredHome 2:3077639f94fa 149 }
WiredHome 2:3077639f94fa 150 if (update) {
WiredHome 2:3077639f94fa 151 DrawInitialScreen();
WiredHome 2:3077639f94fa 152 }
WiredHome 2:3077639f94fa 153 }
WiredHome 2:3077639f94fa 154
WiredHome 2:3077639f94fa 155
WiredHome 0:f2a6447e607c 156 #define PI 3.14159265359f
WiredHome 0:f2a6447e607c 157
WiredHome 0:f2a6447e607c 158 // ---------------
WiredHome 0:f2a6447e607c 159 // radius = \ / x ^ 2 + y ^ 2
WiredHome 0:f2a6447e607c 160 // \/
WiredHome 0:f2a6447e607c 161 int GetRadius(point_t touch, point_t center)
WiredHome 0:f2a6447e607c 162 {
WiredHome 0:f2a6447e607c 163 return sqrt(pow(touch.x - center.x, 2) + pow(touch.y - center.y, 2));
WiredHome 0:f2a6447e607c 164 }
WiredHome 0:f2a6447e607c 165
WiredHome 0:f2a6447e607c 166 // (radians * 180)
WiredHome 0:f2a6447e607c 167 // degrees = ---------------
WiredHome 0:f2a6447e607c 168 // pi
WiredHome 0:f2a6447e607c 169 float Degrees(float radians)
WiredHome 0:f2a6447e607c 170 {
WiredHome 0:f2a6447e607c 171 return radians * 180 / PI;
WiredHome 0:f2a6447e607c 172 }
WiredHome 0:f2a6447e607c 173
WiredHome 0:f2a6447e607c 174 // (pi * degrees)
WiredHome 0:f2a6447e607c 175 // radians = --------------
WiredHome 0:f2a6447e607c 176 // 180
WiredHome 0:f2a6447e607c 177 float Radians(float degrees)
WiredHome 0:f2a6447e607c 178 {
WiredHome 0:f2a6447e607c 179 return (degrees * PI)/180;
WiredHome 0:f2a6447e607c 180 }
WiredHome 0:f2a6447e607c 181
WiredHome 0:f2a6447e607c 182 int GetAngle(point_t touch, point_t center)
WiredHome 0:f2a6447e607c 183 {
WiredHome 0:f2a6447e607c 184 int angle = 180 - Degrees(atan2(touch.x - center.x, touch.y - center.y));
WiredHome 0:f2a6447e607c 185 if (angle < 0)
WiredHome 0:f2a6447e607c 186 angle += 360;
WiredHome 0:f2a6447e607c 187 return angle;
WiredHome 0:f2a6447e607c 188 }
WiredHome 0:f2a6447e607c 189
WiredHome 0:f2a6447e607c 190 // From a starting point, and at a given angle (where 0 is straight up),
WiredHome 0:f2a6447e607c 191 // and clockwise is increasing angle,
WiredHome 0:f2a6447e607c 192 // project a given distance at that angle and return those coordinates.
WiredHome 0:f2a6447e607c 193 //
WiredHome 0:f2a6447e607c 194 point_t ProjectPoint(point_t start, int angle, dim_t distance)
WiredHome 0:f2a6447e607c 195 {
WiredHome 0:f2a6447e607c 196 point_t newPoint;
WiredHome 0:f2a6447e607c 197 float radians = Radians(angle); // radians are rooted in 0 to the right, and increasing counterclockwise
WiredHome 0:f2a6447e607c 198 radians = -radians + Radians(90); // reverse direction and 0 at the top
WiredHome 0:f2a6447e607c 199 //device.printf("adj Radians %4.3f\r\n", radians);
WiredHome 0:f2a6447e607c 200 newPoint.x = start.x + distance * sin(radians);
WiredHome 0:f2a6447e607c 201 newPoint.y = start.y - distance * cos(radians);
WiredHome 0:f2a6447e607c 202 return newPoint;
WiredHome 0:f2a6447e607c 203 }
WiredHome 0:f2a6447e607c 204
WiredHome 0:f2a6447e607c 205
WiredHome 0:f2a6447e607c 206 int main()
WiredHome 0:f2a6447e607c 207 {
WiredHome 1:e4f92c21e329 208 //device.baud(460800);
WiredHome 1:e4f92c21e329 209 printf("\r\n RA8875 Touch Dial Example - Build " __DATE__ " " __TIME__ "\r\n");
WiredHome 1:e4f92c21e329 210 printf("MBED v%d.%d.%d\r\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);
WiredHome 0:f2a6447e607c 211
WiredHome 0:f2a6447e607c 212 lcd.init(LCD_W,LCD_H,LCD_C,BL_NORM);
WiredHome 0:f2a6447e607c 213 lcd.TouchPanelInit();
WiredHome 0:f2a6447e607c 214
WiredHome 2:3077639f94fa 215 DrawInitialScreen();
WiredHome 0:f2a6447e607c 216
WiredHome 0:f2a6447e607c 217 while (1) {
WiredHome 0:f2a6447e607c 218 TouchCode_t touched;
WiredHome 2:3077639f94fa 219 static point_t lastTouch = {LCD_W, LCD_H}; // Init off-screen for easy detection
WiredHome 0:f2a6447e607c 220 touched = lcd.TouchPanelReadable();
WiredHome 0:f2a6447e607c 221 if (touched) {
WiredHome 0:f2a6447e607c 222 point_t Touch = lcd.TouchCoordinates();
WiredHome 0:f2a6447e607c 223
WiredHome 2:3077639f94fa 224 if (touched == touch) { // Only "on-touch"
WiredHome 2:3077639f94fa 225 TestToggleHit(Touch);
WiredHome 2:3077639f94fa 226 TestRenderHit(Touch);
WiredHome 2:3077639f94fa 227 }
WiredHome 2:3077639f94fa 228
WiredHome 2:3077639f94fa 229 lcd.foreground(White);
WiredHome 2:3077639f94fa 230 lcd.SetTextCursor(LCD_W - 8 * 9, 0);
WiredHome 2:3077639f94fa 231 lcd.printf("(%3d,%3d)", Touch.x,Touch.y);
WiredHome 2:3077639f94fa 232
WiredHome 0:f2a6447e607c 233 // If the touch is near the drawn circle (+/- 30 pixels),
WiredHome 0:f2a6447e607c 234 // compute the angle to the touch from the center of the circle
WiredHome 0:f2a6447e607c 235 if (abs(GetRadius(Touch, center) - radius) <= touch_tolerance) {
WiredHome 0:f2a6447e607c 236 int angle = GetAngle(Touch, center);
WiredHome 1:e4f92c21e329 237 printf("Touch at (%4d,%4d) is %3d degrees from (%4d,%4d)\r\n",
WiredHome 0:f2a6447e607c 238 Touch.x, Touch.y, angle, center.x, center.y);
WiredHome 0:f2a6447e607c 239
WiredHome 2:3077639f94fa 240 point_t lastP;
WiredHome 2:3077639f94fa 241 switch (renderOption) {
WiredHome 2:3077639f94fa 242 default:
WiredHome 2:3077639f94fa 243 case 0:
WiredHome 2:3077639f94fa 244 // Fill the circle using 6° pie slices up to the angle of the touch
WiredHome 2:3077639f94fa 245 lastP = ProjectPoint(center, 90, radius); // seed it at angle 0
WiredHome 2:3077639f94fa 246 for (int a=6; a<=360; a+=6) {
WiredHome 2:3077639f94fa 247 point_t p = ProjectPoint(center, 90 - a, radius);
WiredHome 2:3077639f94fa 248 color_t fillColor = (a <= angle) ? Blue : Black;
WiredHome 2:3077639f94fa 249 //if ((a <= angle)) { // show the triangle coordinates (only the fill)
WiredHome 2:3077639f94fa 250 // printf(" (%3d,%3d), (%3d,%3d), (%3d,%3d)\r\n",
WiredHome 2:3077639f94fa 251 // lastP.x,lastP.y, p.x,p.y, center.x,center.y);
WiredHome 2:3077639f94fa 252 //}
WiredHome 2:3077639f94fa 253 lcd.filltriangle(center, p, lastP, fillColor);
WiredHome 2:3077639f94fa 254 lastP = p;
WiredHome 2:3077639f94fa 255 }
WiredHome 2:3077639f94fa 256 lastTouch.x = LCD_W; // reset to untouched for a change to the dial
WiredHome 2:3077639f94fa 257 break;
WiredHome 2:3077639f94fa 258 case 1:
WiredHome 2:3077639f94fa 259 lastP = ProjectPoint(center, 90 - angle, 0.75 * radius);
WiredHome 2:3077639f94fa 260 if (lastTouch.x != LCD_W) {
WiredHome 2:3077639f94fa 261 lcd.fillellipse(lastTouch, radius/5,radius/5, fillColor);
WiredHome 2:3077639f94fa 262 }
WiredHome 2:3077639f94fa 263 lcd.fillellipse(lastP, radius/5,radius/5, Black);
WiredHome 2:3077639f94fa 264 lastTouch = lastP;
WiredHome 2:3077639f94fa 265 break;
WiredHome 0:f2a6447e607c 266 }
WiredHome 0:f2a6447e607c 267 // Show the touch point (note we're not erasing the old one)
WiredHome 2:3077639f94fa 268 if (touchVisible) {
WiredHome 2:3077639f94fa 269 lcd.fillellipse(Touch.x, Touch.y, 5, 5, BrightRed);
WiredHome 2:3077639f94fa 270 }
WiredHome 0:f2a6447e607c 271 }
WiredHome 0:f2a6447e607c 272 }
WiredHome 0:f2a6447e607c 273 }
WiredHome 0:f2a6447e607c 274 }