David Smart
/
PUB_RA875_Dial
Demo touching the perimeter of a circle
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 /// 00002 /// RA8875 display library example where a user touch on the perimeter 00003 /// of a circle should be detected. 00004 /// 00005 /// 00006 /// 0 deg 00007 /// -+- 00008 /// - - 00009 /// 00010 /// / \ 00011 /// 00012 /// 00013 /// | | 00014 /// -90 deg + + + +90 deg 00015 /// | | 00016 /// 00017 /// 00018 /// \ / 00019 /// 00020 /// 00021 /// - - 00022 /// -+- 00023 /// +180 deg 00024 /// 00025 /// 00026 /// NOTE NOTE NOTE NOTE NOTE NOTE 00027 /// 00028 /// The code in this example would greatly benefit by refactoring to 00029 /// use radians, rather than degrees. Further, the coordinate system 00030 /// desired here is more like a clock-face, with 0 degrees is straight 00031 /// up and increasing angle in the clockwise direction. 00032 /// 00033 /// There are a few transformations (direction of rotation and angle 00034 /// offset) that didn't "feel right", even with the right result. 00035 /// 00036 /// NOTE NOTE NOTE NOTE NOTE NOTE 00037 /// 00038 /// I didn't pay too much attention to managing int, float, and double 00039 /// to avoid unnecessary promotion or math complexity. 00040 /// 00041 #include "mbed.h" 00042 #include "RA8875.h" 00043 00044 // Display with Capacitive Touch panel on I2C 00045 RA8875 lcd(p5,p6,p7,p12,NC, p9,p10,p13, "tft"); // MOSI,MISO,SCK,/ChipSelect,/reset, SDA,SCL,/IRQ, name 00046 //RA8875 lcd(p5,p6,p7,p8,NC, p28,p27,p30, "tft"); 00047 00048 // debug serial for printf. 00049 // Some versions of the OS don't support the baud initializer here, then use device.baud(460800) in main. 00050 Serial device(USBTX,USBRX, 460800); // Initialize to a fast baud 00051 //Serial device(p26,p25); 00052 00053 // Screen size and color depth 00054 #define LCD_W 800 00055 #define LCD_H 480 00056 #define LCD_C 8 // color - bits per pixel 00057 00058 #define BL_NORM 100 // Backlight Normal setting (0 to 255) 00059 00060 // 00061 // The Circle definition around which touches are relevant 00062 // 00063 const point_t center = {200,250}; 00064 const dim_t radius = 125; 00065 const dim_t touch_tolerance = 30; 00066 00067 00068 // 00069 // Checkbox to turn on/off the touch-point 00070 // 00071 const rect_t check_tonoff = {400, 150, LCD_W-1, 182}; // Height based on double-size font 00072 const char * check_tonoff_msg = "[%c] Visible touchpoints"; 00073 bool touchVisible = false; // default hidden 00074 00075 00076 // 00077 // Radio buttons to select between pie pieces 00078 // and a dial-indent 00079 // 00080 const rect_t radio_pie = {400, 250, LCD_W-1, 282}; 00081 const char * radio_pie_msg = "(%c) Pie-slice rendering"; 00082 const rect_t radio_dial = {400, 300, LCD_W-1, 332}; 00083 const char * radio_dial_msg = "(%c) Dial rendering"; 00084 int renderOption = 0; // pie-slice 00085 00086 color_t edgeColor = BrightBlue; 00087 color_t fillColor = Black; 00088 00089 void DrawCircle() { 00090 // Draw a thickened circle 00091 lcd.fillellipse(center.x, center.y, radius, radius, fillColor); 00092 for (int r = 0; r <= 3; r++) { 00093 lcd.ellipse(center.x, center.y, radius + r, radius + r, edgeColor); 00094 } 00095 } 00096 00097 void ShowUserControls() { 00098 lcd.SetTextFontSize(2); // Bigger font; easier to touch 00099 // 00100 // [X] Enable visible touch-points 00101 // 00102 lcd.foreground(White); 00103 lcd.SetTextCursor(check_tonoff.p1); 00104 lcd.printf(check_tonoff_msg, (touchVisible) ? 'X' : ' '); 00105 lcd.rect(check_tonoff, Gray); 00106 // 00107 // (*) Pie-slice rendering 00108 // ( ) Dial rendering 00109 // 00110 lcd.foreground(White); 00111 lcd.SetTextCursor(radio_pie.p1); 00112 lcd.printf(radio_pie_msg, (renderOption == 0) ? '*' : ' '); 00113 lcd.rect(radio_pie, Gray); 00114 lcd.foreground(White); 00115 lcd.SetTextCursor(radio_dial.p1); 00116 lcd.printf(radio_dial_msg, (renderOption == 1) ? '*' : ' '); 00117 lcd.rect(radio_dial, Gray); 00118 lcd.SetTextFontSize(); 00119 } 00120 00121 void DrawInitialScreen() { 00122 lcd.cls(); 00123 lcd.foreground(White); // Change to white 00124 lcd.printf("RA8875 Touch Dial Example - Build " __DATE__ " " __TIME__ "\r\n"); 00125 lcd.printf("MBED v%d.%d.%d\r\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION); 00126 ShowUserControls(); 00127 DrawCircle(); 00128 } 00129 00130 void TestToggleHit(point_t t) { 00131 if (lcd.Intersect(check_tonoff, t)) { 00132 touchVisible = !touchVisible; 00133 DrawInitialScreen(); 00134 } 00135 } 00136 00137 void TestRenderHit(point_t t) { 00138 bool update = false; 00139 if (lcd.Intersect(radio_pie, t)) { 00140 renderOption = 0; 00141 edgeColor = BrightBlue; 00142 fillColor = Black; 00143 update = true; 00144 } else if (lcd.Intersect(radio_dial, t)) { 00145 renderOption = 1; 00146 edgeColor = BrightBlue; 00147 fillColor = Gray; 00148 update = true; 00149 } 00150 if (update) { 00151 DrawInitialScreen(); 00152 } 00153 } 00154 00155 00156 #define PI 3.14159265359f 00157 00158 // --------------- 00159 // radius = \ / x ^ 2 + y ^ 2 00160 // \/ 00161 int GetRadius(point_t touch, point_t center) 00162 { 00163 return sqrt(pow(touch.x - center.x, 2) + pow(touch.y - center.y, 2)); 00164 } 00165 00166 // (radians * 180) 00167 // degrees = --------------- 00168 // pi 00169 float Degrees(float radians) 00170 { 00171 return radians * 180 / PI; 00172 } 00173 00174 // (pi * degrees) 00175 // radians = -------------- 00176 // 180 00177 float Radians(float degrees) 00178 { 00179 return (degrees * PI)/180; 00180 } 00181 00182 int GetAngle(point_t touch, point_t center) 00183 { 00184 int angle = 180 - Degrees(atan2(touch.x - center.x, touch.y - center.y)); 00185 if (angle < 0) 00186 angle += 360; 00187 return angle; 00188 } 00189 00190 // From a starting point, and at a given angle (where 0 is straight up), 00191 // and clockwise is increasing angle, 00192 // project a given distance at that angle and return those coordinates. 00193 // 00194 point_t ProjectPoint(point_t start, int angle, dim_t distance) 00195 { 00196 point_t newPoint; 00197 float radians = Radians(angle); // radians are rooted in 0 to the right, and increasing counterclockwise 00198 radians = -radians + Radians(90); // reverse direction and 0 at the top 00199 //device.printf("adj Radians %4.3f\r\n", radians); 00200 newPoint.x = start.x + distance * sin(radians); 00201 newPoint.y = start.y - distance * cos(radians); 00202 return newPoint; 00203 } 00204 00205 00206 int main() 00207 { 00208 //device.baud(460800); 00209 printf("\r\n RA8875 Touch Dial Example - Build " __DATE__ " " __TIME__ "\r\n"); 00210 printf("MBED v%d.%d.%d\r\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION); 00211 00212 lcd.init(LCD_W,LCD_H,LCD_C,BL_NORM); 00213 lcd.TouchPanelInit(); 00214 00215 DrawInitialScreen(); 00216 00217 while (1) { 00218 TouchCode_t touched; 00219 static point_t lastTouch = {LCD_W, LCD_H}; // Init off-screen for easy detection 00220 touched = lcd.TouchPanelReadable(); 00221 if (touched) { 00222 point_t Touch = lcd.TouchCoordinates(); 00223 00224 if (touched == touch) { // Only "on-touch" 00225 TestToggleHit(Touch); 00226 TestRenderHit(Touch); 00227 } 00228 00229 lcd.foreground(White); 00230 lcd.SetTextCursor(LCD_W - 8 * 9, 0); 00231 lcd.printf("(%3d,%3d)", Touch.x,Touch.y); 00232 00233 // If the touch is near the drawn circle (+/- 30 pixels), 00234 // compute the angle to the touch from the center of the circle 00235 if (abs(GetRadius(Touch, center) - radius) <= touch_tolerance) { 00236 int angle = GetAngle(Touch, center); 00237 //printf("Touch at (%4d,%4d) is %3d degrees from (%4d,%4d)\r\n", 00238 // Touch.x, Touch.y, angle, center.x, center.y); 00239 00240 point_t lastP; 00241 switch (renderOption) { 00242 default: 00243 case 0: 00244 // Fill the circle using 6° pie slices up to the angle of the touch 00245 lastP = ProjectPoint(center, 90, radius); // seed it at angle 0 00246 for (int a=6; a<=360; a+=6) { 00247 point_t p = ProjectPoint(center, 90 - a, radius); 00248 color_t fillColor = (a <= angle) ? Blue : Black; 00249 //if ((a <= angle)) { // show the triangle coordinates (only the fill) 00250 // printf(" (%3d,%3d), (%3d,%3d), (%3d,%3d)\r\n", 00251 // lastP.x,lastP.y, p.x,p.y, center.x,center.y); 00252 //} 00253 lcd.filltriangle(center, p, lastP, fillColor); 00254 lastP = p; 00255 } 00256 lastTouch.x = LCD_W; // reset to untouched for a change to the dial 00257 break; 00258 case 1: 00259 lastP = ProjectPoint(center, 90 - angle, 0.75 * radius); 00260 if (lastTouch.x != LCD_W) { 00261 lcd.fillellipse(lastTouch, radius/5,radius/5, fillColor); 00262 } 00263 lcd.fillellipse(lastP, radius/5,radius/5, Black); 00264 lastTouch = lastP; 00265 break; 00266 } 00267 // Show the touch point (note we're not erasing the old one) 00268 if (touchVisible) { 00269 lcd.fillellipse(Touch.x, Touch.y, 5, 5, BrightRed); 00270 } 00271 } 00272 } 00273 } 00274 }
Generated on Tue Jul 19 2022 04:26:17 by 1.7.2