David Smart
/
PUB_RA875_Dial
Demo touching the perimeter of a circle
Diff: main.cpp
- Revision:
- 0:f2a6447e607c
- Child:
- 1:e4f92c21e329
diff -r 000000000000 -r f2a6447e607c main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun Apr 04 16:50:35 2021 +0000 @@ -0,0 +1,156 @@ +/// +/// RA8875 display library example where a user touch on the perimeter +/// of a circle should be detected. +/// +/// +/// 0 deg +/// -+- +/// - - +/// +/// / \ +/// +/// +/// | | +/// -90 deg + + + +90 deg +/// | | +/// +/// +/// \ / +/// +/// +/// - - +/// -+- +/// +180 deg +/// +/// +/// NOTE NOTE NOTE NOTE NOTE NOTE +/// +/// The code in this example would greatly benefit by refactoring to +/// use radians, rather than degrees. Further, the coordinate system +/// desired here is more like a clock-face, with 0 degrees is straight +/// up and increasing angle in the clockwise direction. +/// +/// There are a few transformations (direction of rotation and angle +/// offset) that didn't "feel right", even with the right result. +/// +#include "mbed.h" +#include "RA8875.h" + +/// Display with Capacitive Touch panel on I2C +RA8875 lcd(p5,p6,p7,p12,NC, p9,p10,p13, "tft"); // MOSI,MISO,SCK,/ChipSelect,/reset, SDA,SCL,/IRQ, name +//RA8875 lcd(p5,p6,p7,p8,NC, p28,p27,p30, "tft"); + + +Serial device(USBTX,USBRX); // Not required for display + +// Screen size and color depth +#define LCD_W 800 +#define LCD_H 480 +#define LCD_C 8 // color - bits per pixel + +#define BL_NORM 100 // Backlight Normal setting (0 to 255) + +// The Circle definition around which touches are relevant +const point_t center = {200,250}; +const dim_t radius = 125; +const dim_t touch_tolerance = 30; + +#define PI 3.14159265359f + +// --------------- +// radius = \ / x ^ 2 + y ^ 2 +// \/ +int GetRadius(point_t touch, point_t center) +{ + return sqrt(pow(touch.x - center.x, 2) + pow(touch.y - center.y, 2)); +} + +// (radians * 180) +// degrees = --------------- +// pi +float Degrees(float radians) +{ + return radians * 180 / PI; +} + +// (pi * degrees) +// radians = -------------- +// 180 +float Radians(float degrees) +{ + return (degrees * PI)/180; +} + +int GetAngle(point_t touch, point_t center) +{ + int angle = 180 - Degrees(atan2(touch.x - center.x, touch.y - center.y)); + if (angle < 0) + angle += 360; + return angle; +} + +// From a starting point, and at a given angle (where 0 is straight up), +// and clockwise is increasing angle, +// project a given distance at that angle and return those coordinates. +// +point_t ProjectPoint(point_t start, int angle, dim_t distance) +{ + point_t newPoint; + float radians = Radians(angle); // radians are rooted in 0 to the right, and increasing counterclockwise + radians = -radians + Radians(90); // reverse direction and 0 at the top + //device.printf("adj Radians %4.3f\r\n", radians); + newPoint.x = start.x + distance * sin(radians); + newPoint.y = start.y - distance * cos(radians); + return newPoint; +} + + +int main() +{ + device.baud(460800); + device.printf("\r\n RA8875 Touch Dial Example - Build " __DATE__ " " __TIME__ "\r\n"); + + lcd.init(LCD_W,LCD_H,LCD_C,BL_NORM); + lcd.TouchPanelInit(); + + lcd.foreground(White); // Change to white + lcd.printf("RA8875 Touch Dial Example - Build " __DATE__ " " __TIME__ "\r\n"); + lcd.printf("MBED v%d.%d.%d\r\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION); + + // Draw a thick circle + for (int r = -3; r <= 3; r++) { + lcd.ellipse(center.x, center.y, radius + r, radius + r, BrightBlue); + } + + while (1) { + TouchCode_t touched; + + touched = lcd.TouchPanelReadable(); + if (touched) { + point_t Touch = lcd.TouchCoordinates(); + + // If the touch is near the drawn circle (+/- 30 pixels), + // compute the angle to the touch from the center of the circle + if (abs(GetRadius(Touch, center) - radius) <= touch_tolerance) { + int angle = GetAngle(Touch, center); + device.printf("Touch at (%4d,%4d) is %3d degrees from (%4d,%4d)\r\n", + Touch.x, Touch.y, angle, center.x, center.y); + + // Fill the circle using 6° pie slices up to the angle of the touch + point_t lastP = ProjectPoint(center, 90, radius); // seed it at angle 0 + for (int a=6; a<=360; a+=6) { + point_t p = ProjectPoint(center, 90 - a, radius); + color_t fillColor = (a <= angle) ? Blue : Black; + if ((a <= angle)) { // show the triangle coordinates (only the fill) + device.printf(" (%3d,%3d), (%3d,%3d), (%3d,%3d)\r\n", + lastP.x,lastP.y, p.x,p.y, center.x,center.y); + } + lcd.filltriangle(center, p, lastP, fillColor); + lastP = p; + } + // Show the touch point (note we're not erasing the old one) + lcd.fillellipse(Touch.x, Touch.y, 5, 5, BrightRed); + } + } + } +} \ No newline at end of file