Demo touching the perimeter of a circle

Dependencies:   RA8875

main.cpp

Committer:
WiredHome
Date:
6 months ago
Revision:
1:e4f92c21e329
Parent:
0:f2a6447e607c
Child:
2:3077639f94fa

File content as of revision 1:e4f92c21e329:

///
/// 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.
///
/// NOTE NOTE NOTE NOTE NOTE NOTE
///
/// I didn't pay too much attention to managing int, float, and double
/// to avoid unnecessary promotion or math complexity.
///
#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");

// debug serial for printf. 
// Some versions of the OS don't support the baud initializer here, then use device.baud(460800) in main.
Serial device(USBTX,USBRX, 460800);    // Initialize to a fast baud
//Serial device(p26,p25);

// 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);
    printf("\r\n   RA8875 Touch Dial Example - Build " __DATE__ " " __TIME__ "\r\n");
    printf("MBED v%d.%d.%d\r\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);

    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 thickened circle
    for (int r = 0; 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);
                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)
                    //    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);
            }
        }
    }
}