?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 32

Line No. Rev Author Line
1 32 kaklik /*****************************************************************************
2 * Module for Microchip Graphics Library
3 * GOL Layer
4 * Round Dial
5 *****************************************************************************
6 * FileName: RoundDial.c
7 * Dependencies: math.h
8 * Processor: PIC24F, PIC24H, dsPIC, PIC32
9 * Compiler: MPLAB C30 Version 3.00, MPLAB C32
10 * Linker: MPLAB LINK30, MPLAB LINK32
11 * Company: Microchip Technology Incorporated
12 *
13 * Software License Agreement
14 *
15 * Copyright © 2008 Microchip Technology Inc. All rights reserved.
16 * Microchip licenses to you the right to use, modify, copy and distribute
17 * Software only when embedded on a Microchip microcontroller or digital
18 * signal controller, which is integrated into your product or third party
19 * product (pursuant to the sublicense terms in the accompanying license
20 * agreement).
21 *
22 * You should refer to the license agreement accompanying this Software
23 * for additional information regarding your rights and obligations.
24 *
25 * SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS” WITHOUT WARRANTY OF ANY
26 * KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY
27 * OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR
28 * PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR
29 * OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION,
30 * BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT
31 * DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL,
32 * INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA,
33 * COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY
34 * CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
35 * OR OTHER SIMILAR COSTS.
36 *
37 * Author Date Comment
38 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
39 * PAT 11/12/07 Version 1.0 release
40 * Pradeep Budagutta 03 Dec 2009 Added Object Header for Double Buffering Support
41 *****************************************************************************/
42 #include "Graphics\Graphics.h"
43 #include <math.h>
44  
45 #ifdef USE_ROUNDDIAL
46  
47 /*********************************************************************
48 * Function: ROUNDDIAL *RdiaCreate( WORD ID, SHORT x, SHORT y, SHORT radius,
49 * WORD state, SHORT res, SHORT value, SHORT max,
50 * GOL_SCHEME *pScheme)
51 *
52 *
53 * Notes: Creates a ROUNDDIAL object and adds it to the current active list.
54 * If the creation is successful, the pointer to the created Object
55 * is returned. If not successful, NULL is returned.
56 *
57 ********************************************************************/
58 ROUNDDIAL *RdiaCreate
59 (
60 WORD ID,
61 SHORT x,
62 SHORT y,
63 SHORT radius,
64 WORD state,
65 SHORT res,
66 SHORT value,
67 SHORT max,
68 GOL_SCHEME *pScheme
69 )
70 {
71 ROUNDDIAL *pDia = NULL;
72  
73 pDia = (ROUNDDIAL *)GFX_malloc(sizeof(ROUNDDIAL));
74 if(pDia == NULL)
75 return (NULL);
76  
77 pDia->hdr.ID = ID; // unique id assigned for referencing
78 pDia->hdr.pNxtObj = NULL; // initialize pointer to NULL
79 pDia->hdr.type = OBJ_ROUNDDIAL; // set object type
80 pDia->xCenter = x; // x coordinate of center
81 pDia->yCenter = y; // y coordinate of center
82 pDia->radius = radius; // radius of dial
83 pDia->res = res;
84 pDia->value = value;
85 pDia->max = max;
86 pDia->hdr.state = state; // state
87 pDia->curr_xPos = x + radius * 2 / 3;
88 pDia->curr_yPos = y;
89  
90 pDia->hdr.left = x - radius; // left position
91 pDia->hdr.top = y - radius; // top position
92 pDia->hdr.right = x + radius; // right position
93 pDia->hdr.bottom = y + radius; // bottom position
94  
95 // Set the color scheme to be used
96 if(pScheme == NULL)
97 pDia->hdr.pGolScheme = _pDefaultGolScheme;
98 else
99 pDia->hdr.pGolScheme = (GOL_SCHEME *)pScheme;
100  
101 GOLAddObject((OBJ_HEADER *)pDia);
102  
103 return (pDia);
104 }
105  
106 /*********************************************************************
107 * Function: RdiaMsgDefault(WORD translatedMsg, ROUNDDIAL *pDia, GOL_MSG* pMsg)
108 *
109 *
110 * Notes: This the default operation to change the state of the dial.
111 * Called inside GOLMsg() when GOLMsgCallback() returns a 1.
112 *
113 ********************************************************************/
114 void RdiaMsgDefault(WORD translatedMsg, ROUNDDIAL *pDia, GOL_MSG *pMsg)
115 {
116 switch(translatedMsg)
117 {
118 case RD_MSG_CLOCKWISE: SetState(pDia, RDIA_ROT_CW | RDIA_DRAW); // set rotate left and redraw
119 break;
120 case RD_MSG_CTR_CLOCKWISE: SetState(pDia, RDIA_ROT_CCW | RDIA_DRAW); // set rotate right and redraw
121 break;
122 }
123 }
124  
125 /*********************************************************************
126 * Function: SHORT RdiaCosine( SHORT v )
127 *
128 *
129 * Notes: Returns the cosine of the dial position.
130 *
131 ********************************************************************/
132 #ifdef USE_KEYBOARD
133  
134 // Dimple position table for 15 degree increments
135 // #define QUADRANT_POSITIONS 6
136 // SHORT _cosine[QUADRANT_POSITIONS] = { 100, 97, 87, 71, 50, 26 };
137 SHORT _cosine[RDIA_QUADRANT_POSITIONS] = { 100, 97, 87, 71, 50, 26};
138 #endif
139  
140 /* */
141 SHORT RdiaCosine(SHORT v)
142 {
143 if(v >= RDIA_QUADRANT_POSITIONS * 3)
144 {
145 v -= RDIA_QUADRANT_POSITIONS * 3;
146 return (_cosine[RDIA_QUADRANT_POSITIONS - 1 - v]);
147 }
148 else if(v >= RDIA_QUADRANT_POSITIONS * 2)
149 {
150 v -= RDIA_QUADRANT_POSITIONS * 2;
151 return (-(_cosine[v]));
152 }
153 else if(v >= RDIA_QUADRANT_POSITIONS)
154 {
155 v -= RDIA_QUADRANT_POSITIONS;
156 return (-(_cosine[RDIA_QUADRANT_POSITIONS - 1 - v]));
157 }
158 else
159 {
160 return (_cosine[v]);
161 }
162 }
163  
164 /*********************************************************************
165 * Function: SHORT RdiaSine( SHORT v )
166 *
167 *
168 * Notes: Returns the sine of the dial position.
169 *
170 ********************************************************************/
171 SHORT RdiaSine(SHORT v)
172 {
173 if(v >= RDIA_QUADRANT_POSITIONS * 3)
174 {
175 v -= RDIA_QUADRANT_POSITIONS * 3;
176 return (-(_cosine[v]));
177 }
178 else if(v >= RDIA_QUADRANT_POSITIONS * 2)
179 {
180 v -= RDIA_QUADRANT_POSITIONS * 2;
181 return (-(_cosine[RDIA_QUADRANT_POSITIONS - 1 - v]));
182 }
183 else if(v >= RDIA_QUADRANT_POSITIONS)
184 {
185 v -= RDIA_QUADRANT_POSITIONS;
186 return (_cosine[v]);
187 }
188 else
189 {
190 return (_cosine[RDIA_QUADRANT_POSITIONS - 1 - v]);
191 }
192 }
193  
194 /*********************************************************************
195 * Function: WORD RdiaTranslateMsg(ROUNDDIAL *pDia, GOL_MSG *pMsg)
196 *
197 *
198 * Notes: Evaluates the message if the object will be affected by the
199 * message or not.
200 *
201 ********************************************************************/
202 WORD RdiaTranslateMsg(ROUNDDIAL *pDia, GOL_MSG *pMsg)
203 {
204 #ifdef USE_TOUCHSCREEN
205  
206 SHORT touchRadius, touchX, touchY;
207 static SHORT prevX = -1, prevY = -1;
208 WORD messageID = OBJ_MSG_INVALID;
209  
210 // Evaluate if the message is for the button
211 // Check if disabled first
212 if(GetState(pDia, RDIA_DISABLED))
213 return (OBJ_MSG_INVALID);
214  
215 if((pMsg->type == TYPE_TOUCHSCREEN) && (pMsg->uiEvent == EVENT_MOVE))
216 {
217  
218 // Check if it falls in the dial's face
219 // to check this the x,y position must be within the circle
220 // (x - xCenter)^2 + (y - yCenter)^2 = r^2 where x and y are the points
221 // to test, the distance between x,y position of touch and center must be
222 // greater than or equal to the radius of the dial
223 if
224 (
225 ((pDia->xCenter - pDia->radius) < pMsg->param1) &&
226 ((pDia->xCenter + pDia->radius) > pMsg->param1) &&
227 ((pDia->yCenter - pDia->radius) < pMsg->param2) &&
228 ((pDia->yCenter + pDia->radius) > pMsg->param2)
229 )
230 {
231  
232 // first get the radius of the touch point
233 touchX = pMsg->param1 - pDia->xCenter;
234 touchY = pMsg->param2 - pDia->yCenter;
235 touchRadius = sqrt(touchX * touchX + touchY * touchY);
236  
237 if(touchRadius <= pDia->radius)
238 {
239  
240 // difference of 3 is used to remove jitter caused by noise or sensitivity of the touchscreen
241 if((abs(prevX - pMsg->param1) > 3) || (abs(prevY - pMsg->param2) > 3))
242 {
243  
244 // The first MOVE event is used to record the current position only. The second MOVE event
245 // will be used together with the previous MOVE and determine if the movement is in the
246 // clockwise or counter clockwise direction.
247 if((prevX == -1) || (prevY == -1))
248 {
249 prevX = pMsg->param1;
250 prevY = pMsg->param2;
251 messageID = OBJ_MSG_INVALID;
252 }
253 else
254 {
255  
256 // this makes the sampling area a ring where the max radius is the dial radius
257 // and min radius is 5
258 if(touchRadius > 5)
259 {
260 pDia->new_xPos = (pDia->radius * 2 / 3) * (pMsg->param1 - pDia->xCenter) / touchRadius;
261 pDia->new_yPos = (pDia->radius * 2 / 3) * (pMsg->param2 - pDia->yCenter) / touchRadius;
262  
263 // check if moving in clockwise direction or counter clockwise direction
264 if((pDia->xCenter >= pMsg->param1) && (pDia->yCenter > pMsg->param2))
265 {
266 if((prevX < pMsg->param1) && (prevY >= pMsg->param2))
267 messageID = RD_MSG_CLOCKWISE;
268 else if((prevX >= pMsg->param1) && (prevY < pMsg->param2))
269 messageID = RD_MSG_CTR_CLOCKWISE;
270 }
271  
272 if((pDia->xCenter < pMsg->param1) && (pDia->yCenter > pMsg->param2))
273 {
274 if((prevX < pMsg->param1) && (prevY <= pMsg->param2))
275 messageID = RD_MSG_CLOCKWISE;
276 else if((prevX >= pMsg->param1) && (prevY > pMsg->param2))
277 messageID = RD_MSG_CTR_CLOCKWISE;
278 }
279  
280 if((pDia->xCenter < pMsg->param1) && (pDia->yCenter <= pMsg->param2))
281 {
282 if((prevX > pMsg->param1) && (prevY <= pMsg->param2))
283 messageID = RD_MSG_CLOCKWISE;
284 else if((prevX <= pMsg->param1) && (prevY > pMsg->param2))
285 messageID = RD_MSG_CTR_CLOCKWISE;
286 }
287  
288 if((pDia->xCenter >= pMsg->param1) && (pDia->yCenter <= pMsg->param2))
289 {
290 if((prevX > pMsg->param1) && (prevY >= pMsg->param2))
291 messageID = RD_MSG_CLOCKWISE;
292 else if((prevX <= pMsg->param1) && (prevY < pMsg->param2))
293 messageID = RD_MSG_CTR_CLOCKWISE;
294 }
295 }
296 else
297 messageID = OBJ_MSG_INVALID;
298  
299 prevX = pMsg->param1;
300 prevY = pMsg->param2;
301 }
302 }
303 else
304 messageID = OBJ_MSG_INVALID;
305  
306 // determine the movement clockwise or counter clockwise
307 // this is important to update the value variable
308 return (messageID);
309 }
310 else
311 {
312 prevX = -1;
313 prevY = -1;
314 }
315 }
316 }
317  
318 #endif
319 #ifdef USE_KEYBOARD
320  
321 SHORT newValue;
322  
323 // Evaluate if the message is for the button
324 // Check if disabled first
325 if(GetState(pDia, RDIA_DISABLED))
326 return (OBJ_MSG_INVALID);
327  
328 if((pMsg->type == TYPE_KEYBOARD) && (pMsg->param1 == pDia->hdr.ID) && (pMsg->uiEvent == EVENT_KEYSCAN))
329 {
330 if(pMsg->param2 == SCAN_RIGHT_PRESSED)
331 {
332 newValue = pDia->value + pDia->res;
333 if(newValue > pDia->max)
334 {
335 newValue -= (pDia->max + 1);
336 }
337  
338 pDia->new_xPos = pDia->radius * 2 * RdiaCosine(newValue) / 100 / 3;
339 pDia->new_yPos = pDia->radius * 2 * RdiaSine(newValue) / 100 / 3;
340 return (RD_MSG_CLOCKWISE);
341 }
342  
343 if(pMsg->param2 == SCAN_LEFT_PRESSED)
344 {
345 newValue = pDia->value - pDia->res;
346 if(newValue < 0)
347 {
348 newValue += (pDia->max + 1);
349 }
350  
351 pDia->new_xPos = pDia->radius * 2 * RdiaCosine(newValue) / 100 / 3;
352 pDia->new_yPos = pDia->radius * 2 * RdiaSine(newValue) / 100 / 3;
353 return (RD_MSG_CTR_CLOCKWISE);
354 }
355 }
356  
357 #endif
358 return (OBJ_MSG_INVALID);
359 }
360  
361 /*********************************************************************
362 * Function: WORD RdiaDraw(ROUNDDIAL *pDia)
363 *
364 *
365 * Notes: This is the state machine to draw the dial.
366 *
367 ********************************************************************/
368 WORD RdiaDraw(ROUNDDIAL *pDia)
369 {
370 typedef enum
371 {
372 REMOVE,
373 RND_PANEL_DRAW,
374 RND_PANEL_TASK,
375 ERASE_POSITION,
376 DRAW_POSITION
377 } RDIA_DRAW_STATES;
378  
379 static RDIA_DRAW_STATES state = REMOVE;
380 static SHORT dimpleRadius;
381 WORD faceClr;
382  
383 switch(state)
384 {
385 case REMOVE:
386 if(IsDeviceBusy())
387 return (0);
388  
389 if(GetState(pDia, RDIA_HIDE))
390 { // Hide the dial (remove from screen)
391 SetColor(pDia->hdr.pGolScheme->CommonBkColor);
392 if
393 (
394 !Bar
395 (
396 pDia->xCenter - pDia->radius,
397 pDia->yCenter - pDia->radius,
398 pDia->xCenter + pDia->radius,
399 pDia->yCenter + pDia->radius
400 )
401 ) return (0);
402 return (1);
403 }
404  
405 dimpleRadius = (pDia->radius >> 3) + 1;
406  
407 if(GetState(pDia, RDIA_ROT_CCW | RDIA_ROT_CW))
408 {
409 state = ERASE_POSITION;
410 goto erase_current_pos;
411 }
412  
413 state = RND_PANEL_DRAW;
414  
415 case RND_PANEL_DRAW:
416 if(!GetState(pDia, RDIA_DISABLED))
417 {
418 faceClr = pDia->hdr.pGolScheme->Color0;
419 }
420 else
421 {
422 faceClr = pDia->hdr.pGolScheme->ColorDisabled;
423 }
424  
425 SetLineThickness(NORMAL_LINE);
426 SetLineType(SOLID_LINE);
427 GOLPanelDraw
428 (
429 pDia->xCenter,
430 pDia->yCenter,
431 pDia->xCenter,
432 pDia->yCenter,
433 pDia->radius,
434 faceClr,
435 pDia->hdr.pGolScheme->EmbossLtColor,
436 pDia->hdr.pGolScheme->EmbossDkColor,
437 NULL,
438 GOL_EMBOSS_SIZE
439 );
440 state = RND_PANEL_TASK;
441  
442 case RND_PANEL_TASK:
443 if(!GOLPanelDrawTsk())
444 {
445 return (0);
446 }
447  
448 state = DRAW_POSITION;
449 goto draw_current_pos;
450  
451 case ERASE_POSITION:
452 erase_current_pos : SetColor(pDia->hdr.pGolScheme->Color0);
453 if
454 (
455 !Bar
456 (
457 pDia->curr_xPos - dimpleRadius,
458 pDia->curr_yPos - dimpleRadius,
459 pDia->curr_xPos + dimpleRadius,
460 pDia->curr_yPos + dimpleRadius
461 )
462 ) return (0);
463  
464 // determine if the value will increment or decrement
465 #if defined USE_TOUCHSCREEN
466 if(GetState(pDia, RDIA_ROT_CW))
467 {
468 pDia->value = pDia->value + pDia->res;
469 if(pDia->value > pDia->max)
470 pDia->value = pDia->max;
471 }
472 else if(GetState(pDia, RDIA_ROT_CCW))
473 {
474 pDia->value = pDia->value - pDia->res;
475 if(pDia->value < 0)
476 pDia->value = 0;
477 }
478 #elif defined USE_KEYBOARD
479 if(GetState(pDia, RDIA_ROT_CW))
480 {
481 pDia->value = pDia->value + pDia->res;
482 if(pDia->value > pDia->max)
483 {
484 pDia->value -= (pDia->max + 1);
485 }
486 }
487 else if(GetState(pDia, RDIA_ROT_CCW))
488 {
489 pDia->value = pDia->value - pDia->res;
490 if(pDia->value < 0)
491 {
492 pDia->value += (pDia->max + 1);
493 }
494 }
495 #endif
496  
497 // else do not update counter yet
498 // locate the new position of the dimple
499 pDia->curr_xPos = pDia->xCenter + pDia->new_xPos;
500 pDia->curr_yPos = pDia->yCenter + pDia->new_yPos;
501  
502 ClrState(pDia, RDIA_ROT_CW | RDIA_ROT_CCW); // make sure this is cleared to avoid
503  
504 // unwanted redraw
505 state = DRAW_POSITION;
506  
507 case DRAW_POSITION:
508 draw_current_pos : if(IsDeviceBusy()) return (0);
509  
510 SetColor(pDia->hdr.pGolScheme->EmbossLtColor);
511 SetLineThickness(NORMAL_LINE);
512 SetLineType(SOLID_LINE);
513 if(!Circle(pDia->curr_xPos, pDia->curr_yPos, dimpleRadius))
514 return (0);
515 SetColor(pDia->hdr.pGolScheme->EmbossDkColor);
516 if(!FillCircle(pDia->curr_xPos, pDia->curr_yPos, dimpleRadius - 1))
517 return (0);
518  
519 state = REMOVE;
520 return (1);
521 }
522  
523 return (1);
524 }
525  
526 #endif // USE_ROUNDDIAL
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3