?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 * Meter
5 *****************************************************************************
6 * FileName: Meter.c
7 * Dependencies: Meter.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 * Paolo A. Tamayo 11/12/07 Version 1.0 release
40 * Albert Z. 07/31/08 Added arc colors options
41 * P. A. Tamayo 08/20/08 Added accuracy option for displaying values
42 *****************************************************************************/
43 #include "Graphics\Graphics.h"
44 #include <math.h>
45 #include <stdio.h>
46  
47 #ifdef USE_METER
48  
49 /*********************************************************************
50 * This is the sine lookup table used to draw the meter and update
51 * the position of the needle.
52 *********************************************************************/
53 const char _sineTable[] __attribute__((aligned(2))) =
54 {
55 0x00,
56 0x03,
57 0x06,
58 0x09,
59 0x0c,
60 0x10,
61 0x13,
62 0x16,
63 0x19,
64 0x1c,
65 0x1f,
66 0x22,
67 0x25,
68 0x28,
69 0x2b,
70 0x2e,
71 0x31,
72 0x33,
73 0x36,
74 0x39,
75 0x3c,
76 0x3f,
77 0x41,
78 0x44,
79 0x47,
80 0x49,
81 0x4c,
82 0x4e,
83 0x51,
84 0x53,
85 0x55,
86 0x58,
87 0x5a,
88 0x5c,
89 0x5e,
90 0x60,
91 0x62,
92 0x64,
93 0x66,
94 0x68,
95 0x6a,
96 0x6b,
97 0x6d,
98 0x6f,
99 0x70,
100 0x71,
101 0x73,
102 0x74,
103 0x75,
104 0x76,
105 0x78,
106 0x79,
107 0x7a,
108 0x7a,
109 0x7b,
110 0x7c,
111 0x7d,
112 0x7d,
113 0x7e,
114 0x7e,
115 0x7e,
116 0x7f,
117 0x7f,
118 0x7f,
119 0x7f
120 };
121  
122 /* Internal Functions */
123 void MtrCalcDimensions(METER *pMtr); // used to calculate the meter dimensions
124  
125 // which is dependent on meter type
126  
127 /*********************************************************************
128 * Function: METER *MtrCreate(WORD ID, SHORT left, SHORT top, SHORT right,
129 * SHORT bottom, WORD state, SHORT value,
130 * SHORT minValue, SHORT maxValue, XCHAR *pText,
131 * GOL_SCHEME *pScheme)
132 *
133 *
134 * Notes: Creates a METER object and adds it to the current active list.
135 * If the creation is successful, the pointer to the created Object
136 * is returned. If not successful, NULL is returned.
137 *
138 ********************************************************************/
139 METER *MtrCreate
140 (
141 WORD ID,
142 SHORT left,
143 SHORT top,
144 SHORT right,
145 SHORT bottom,
146 WORD state,
147 SHORT value,
148 SHORT minValue,
149 SHORT maxValue,
150 void *pTitleFont,
151 void *pValueFont,
152 XCHAR *pText,
153 GOL_SCHEME *pScheme
154 )
155 {
156 METER *pMtr = NULL;
157  
158 pMtr = (METER *)GFX_malloc(sizeof(METER));
159 if(pMtr == NULL)
160 return (NULL);
161  
162 pMtr->hdr.ID = ID; // unique id assigned for referencing
163 pMtr->hdr.pNxtObj = NULL; // initialize pointer to NULL
164 pMtr->hdr.type = OBJ_METER; // set object type
165 pMtr->hdr.left = left; // left,top coordinate
166 pMtr->hdr.top = top; //
167 pMtr->hdr.right = right; // right,bottom coordinate
168 pMtr->hdr.bottom = bottom; //
169 pMtr->minValue = minValue;
170 pMtr->maxValue = maxValue;
171 pMtr->value = value;
172 pMtr->hdr.state = state; // state
173 pMtr->pText = pText;
174  
175 // set the default scale colors
176 MtrSetScaleColors(pMtr, LIGHTGREEN, YELLOW, BRIGHTGREEN, BRIGHTBLUE, RED, BRIGHTRED);
177  
178 // Set the color scheme to be used
179 if(pScheme == NULL)
180 pMtr->hdr.pGolScheme = _pDefaultGolScheme;
181 else
182 pMtr->hdr.pGolScheme = pScheme;
183  
184 // Set the Title Font to be used
185 if(pTitleFont == NULL)
186 pMtr->pTitleFont = (void *) &FONTDEFAULT;
187 else
188 pMtr->pTitleFont = pTitleFont;
189  
190 // Set the Value Font to be used
191 if(pValueFont == NULL)
192 pMtr->pValueFont = (void *) &FONTDEFAULT;
193 else
194 pMtr->pValueFont = pValueFont;
195  
196 // calculate dimensions of the meter
197 MtrCalcDimensions(pMtr);
198  
199 GOLAddObject((OBJ_HEADER *)pMtr);
200  
201 return (pMtr);
202 }
203  
204 /*********************************************************************
205 * Function: MtrCalcDimensions(void)
206 *
207 * Notes: Calculates the dimension of the meter. Dependent on the
208 * meter type set.
209 *
210 ********************************************************************/
211 void MtrCalcDimensions(METER *pMtr)
212 {
213 SHORT tempHeight, tempWidth;
214 SHORT left, top, right, bottom;
215 XCHAR tempChar[2] = {'8',0};
216  
217 left = pMtr->hdr.left;
218 right = pMtr->hdr.right;
219 top = pMtr->hdr.top;
220 bottom = pMtr->hdr.bottom;
221  
222 // get the text width reference. This is used to scale the meter
223 if(pMtr->pText != NULL)
224 {
225 tempHeight = (GOL_EMBOSS_SIZE << 1) + GetTextHeight(pMtr->hdr.pGolScheme->pFont);
226 }
227 else
228 {
229 tempHeight = (GOL_EMBOSS_SIZE << 1);
230 }
231  
232 tempWidth = (GOL_EMBOSS_SIZE << 1) + (GetTextWidth(tempChar, pMtr->hdr.pGolScheme->pFont) * SCALECHARCOUNT);
233  
234 // Meter size is dependent on the width or height.
235 // The radius is also adjusted to add space for the scales
236 #if (METER_TYPE == MTR_WHOLE_TYPE)
237  
238 // choose the radius
239 if((right - left - tempWidth) > (bottom - top - tempHeight - GetTextHeight(pMtr->pTitleFont)))
240 {
241 pMtr->radius = ((bottom - top - tempHeight - GetTextHeight(pMtr->pTitleFont)) >> 1) - ((tempHeight + bottom - top) >> 3);
242 }
243 else
244 pMtr->radius = ((right - left) >> 1) - (tempWidth + ((right - left) >> 3));
245  
246 // center the meter on the given dimensions
247 pMtr->xCenter = (left + right) >> 1;
248 pMtr->yCenter = ((bottom + top) >> 1) - (tempHeight >> 1);
249  
250 #elif (METER_TYPE == MTR_HALF_TYPE)
251  
252 // choose the radius
253 if((right - left) >> 1 > (bottom - top))
254 {
255 pMtr->radius = (bottom - top) - ((tempHeight << 1) + ((bottom - top) >> 3));
256 pMtr->yCenter = ((bottom + top) >> 1) + ((pMtr->radius + ((bottom - top) >> 3)) >> 1);
257 }
258 else
259 {
260 pMtr->radius = ((right - left) >> 1) - (tempWidth + ((right - left) >> 3));
261 pMtr->yCenter = ((bottom + top) >> 1) + ((pMtr->radius + ((right - left) >> 3)) >> 1);
262 }
263  
264 // center the meter on the given dimensions
265 pMtr->xCenter = (left + right) >> 1;
266  
267 #elif (METER_TYPE == MTR_QUARTER_TYPE)
268  
269 // choose the radius
270 if
271 (
272 (right - left - tempWidth) >
273 (bottom - top - (GetTextHeight(pMtr->pTitleFont) + GetTextHeight(pMtr->hdr.pGolScheme->pFont))) -
274 (GOL_EMBOSS_SIZE << 1)
275 )
276 {
277 pMtr->radius = bottom - top - (GetTextHeight(pMtr->pTitleFont) + GetTextHeight(pMtr->hdr.pGolScheme->pFont) + (GOL_EMBOSS_SIZE << 1));
278 }
279 else
280 {
281 pMtr->radius = right -
282 left -
283 (GetTextWidth(tempChar, pMtr->hdr.pGolScheme->pFont) * (SCALECHARCOUNT + 1)) -
284 GOL_EMBOSS_SIZE;
285 }
286  
287 pMtr->radius -= (((pMtr->radius) >> 2) + GOL_EMBOSS_SIZE);
288  
289 // center the meter on the given dimensions
290 pMtr->xCenter = ((left + right) >> 1) - ((pMtr->radius + tempWidth + (pMtr->radius >> 2)) >> 1);
291 pMtr->yCenter = ((top + bottom) >> 1) + ((pMtr->radius + (pMtr->radius >> 2)) >> 1);
292 #endif
293 }
294  
295 /*********************************************************************
296 * Function: MtrSetVal(METER *pMtr, SHORT newVal)
297 *
298 * Notes: Sets the value of the meter to newVal. If newVal is less
299 * than 0, 0 is assigned. If newVal is greater than range,
300 * range is assigned.
301 *
302 ********************************************************************/
303 void MtrSetVal(METER *pMtr, SHORT newVal)
304 {
305 if((newVal < 0) || (newVal < pMtr->minValue))
306 {
307 pMtr->value = pMtr->minValue;
308 return;
309 }
310  
311 if(newVal > pMtr->maxValue)
312 {
313 pMtr->value = pMtr->maxValue;
314 return;
315 }
316  
317 pMtr->value = newVal;
318 }
319  
320 /*********************************************************************
321 * Function: MtrMsgDefault(WORD translatedMsg, METER *pMtr, GOL_MSG* pMsg)
322 *
323 * Notes: This the default operation to change the state of the meter.
324 * Called inside GOLMsg() when GOLMsgCallback() returns a 1.
325 *
326 ********************************************************************/
327 void MtrMsgDefault(WORD translatedMsg, METER *pMtr, GOL_MSG *pMsg)
328 {
329 if(translatedMsg == MTR_MSG_SET)
330 {
331 MtrSetVal(pMtr, pMsg->param2); // set the value
332 SetState(pMtr, MTR_DRAW_UPDATE); // update the meter
333 }
334 }
335  
336 /*********************************************************************
337 * Function: WORD MtrTranslateMsg(METER *pMtr, GOL_MSG *pMsg)
338 *
339 * Notes: Evaluates the message if the object will be affected by the
340 * message or not.
341 *
342 ********************************************************************/
343 WORD MtrTranslateMsg(METER *pMtr, GOL_MSG *pMsg)
344 {
345  
346 // Evaluate if the message is for the meter
347 // Check if disabled first
348 if(GetState(pMtr, MTR_DISABLED))
349 return (OBJ_MSG_INVALID);
350  
351 if(pMsg->type == TYPE_SYSTEM)
352 {
353 if(pMsg->param1 == pMtr->hdr.ID)
354 {
355 if(pMsg->uiEvent == EVENT_SET)
356 {
357 return (MTR_MSG_SET);
358 }
359 }
360 }
361  
362 return (OBJ_MSG_INVALID);
363 }
364  
365 /*********************************************************************
366 * Function: WORD MtrDraw(METER *pMtr)
367 *
368 * Notes: This is the state machine to draw the meter.
369 *
370 ********************************************************************/
371 WORD MtrDraw(METER *pMtr)
372 {
373 typedef enum
374 {
375 IDLE,
376 FRAME_DRAW,
377 NEEDLE_DRAW,
378 NEEDLE_ERASE,
379 TEXT_DRAW,
380 TEXT_DRAW_RUN,
381 ARC_DRAW_SETUP,
382 ARC_DRAW,
383 SCALE_COMPUTE,
384 SCALE_LABEL_DRAW,
385 SCALE_DRAW,
386 VALUE_ERASE,
387 VALUE_DRAW,
388 VALUE_DRAW_RUN,
389 } MTR_DRAW_STATES;
390  
391 static MTR_DRAW_STATES state = IDLE;
392 static SHORT x1, y1, x2, y2;
393 static SHORT temp, j, i, angle;
394 static XCHAR strVal[SCALECHARCOUNT + 1]; // add one more space here for the NULL character
395 static XCHAR tempXchar[2] = {'8',0}; // NULL is pre-defined here
396 static float radian;
397 static DWORD_VAL dTemp, dRes;
398  
399 if(IsDeviceBusy())
400 return (0);
401  
402 switch(state)
403 {
404 case IDLE:
405 if(GetState(pMtr, MTR_HIDE))
406 { // Hide the meter (remove from screen)
407 SetColor(pMtr->hdr.pGolScheme->CommonBkColor);
408 if(!Bar(pMtr->hdr.left, pMtr->hdr.top, pMtr->hdr.right, pMtr->hdr.bottom))
409 return (0);
410 return (1);
411 }
412  
413 // Check if we need to draw the whole object
414 SetLineThickness(NORMAL_LINE);
415 SetLineType(SOLID_LINE);
416 if(GetState(pMtr, MTR_DRAW))
417 {
418  
419 // set parameters to draw the frame
420 GOLPanelDraw
421 (
422 pMtr->hdr.left, pMtr->hdr.top, pMtr->hdr.right, pMtr->hdr.bottom, 0, pMtr->hdr.pGolScheme->Color0,
423 pMtr->hdr.pGolScheme->EmbossLtColor, pMtr->hdr.pGolScheme->EmbossDkColor, NULL,
424 GOL_EMBOSS_SIZE - 1
425 );
426 state = FRAME_DRAW;
427 }
428 else
429 {
430 state = NEEDLE_ERASE;
431 goto mtr_needle_draw_st;
432 }
433  
434 case FRAME_DRAW:
435 if(!GOLPanelDrawTsk())
436 {
437 return (0);
438 }
439  
440 state = TEXT_DRAW;
441  
442 case TEXT_DRAW:
443  
444 // draw the meter title
445 SetColor(pMtr->hdr.pGolScheme->TextColor1);
446 SetFont(pMtr->pTitleFont);
447 temp = GetTextWidth(pMtr->pText, pMtr->pTitleFont);
448  
449 // set the start location of the meter title
450 #if (METER_TYPE == MTR_WHOLE_TYPE)
451 #ifdef METER_DISPLAY_VALUES_ENABLE
452 MoveTo(pMtr->xCenter - (temp >> 1), pMtr->yCenter + pMtr->radius + GetTextHeight(pMtr->pValueFont));
453 #else
454 MoveTo(pMtr->xCenter - (temp >> 1), pMtr->yCenter + pMtr->radius + GetTextHeight(pMtr->hdr.pGolScheme->pFont));
455 #endif
456 #elif (METER_TYPE == MTR_HALF_TYPE)
457 MoveTo(pMtr->xCenter - (temp >> 1), pMtr->yCenter + 3);
458  
459 #elif (METER_TYPE == MTR_QUARTER_TYPE)
460 MoveTo
461 (
462 ((pMtr->hdr.right + pMtr->hdr.left) >> 1) - (temp >> 1), pMtr->hdr.bottom - GOL_EMBOSS_SIZE - GetTextHeight
463 (pMtr->pTitleFont)
464 );
465 #endif
466 state = TEXT_DRAW_RUN;
467  
468 case TEXT_DRAW_RUN:
469  
470 // render the title of the meter
471 if(!OutText(pMtr->pText))
472 return (0);
473 state = ARC_DRAW_SETUP;
474  
475 //case ARC0_DRAW:
476 case ARC_DRAW_SETUP:
477  
478 // check if we need to draw the arcs
479 if(!GetState(pMtr, MTR_RING))
480 {
481  
482 // if meter is not RING type, for scale label colors use
483 // the three colors (normal, critical and danger)
484 i = DEGREE_END;
485 state = SCALE_COMPUTE;
486 goto mtr_scale_compute;
487 }
488 else
489 {
490  
491 // set the arc radii: x1 smaller radius and x2 as the larger radius
492 x1 = pMtr->radius + 2;
493 x2 = pMtr->radius + (pMtr->radius >> 2) + 2;
494 #if (METER_TYPE == MTR_WHOLE_TYPE)
495 temp = 6;
496 #elif (METER_TYPE == MTR_HALF_TYPE)
497 temp = 5;
498 #elif (METER_TYPE == MTR_QUARTER_TYPE)
499 temp = 3;
500 #endif
501 state = ARC_DRAW;
502 }
503  
504 case ARC_DRAW:
505  
506 // draw the arcs
507 #if (METER_TYPE == MTR_WHOLE_TYPE)
508 while(temp)
509 {
510 #elif (METER_TYPE == MTR_HALF_TYPE)
511 while(temp > 1)
512 {
513 #elif (METER_TYPE == MTR_QUARTER_TYPE)
514 while(temp > 1)
515 {
516 #endif
517  
518 // decide which arc will be drawn
519 switch(temp)
520 {
521 case 6:
522 SetColor(pMtr->arcColor1);
523 if(!Arc(pMtr->xCenter, pMtr->yCenter, pMtr->xCenter, pMtr->yCenter, x1, x2, 0x20))
524 return (0);
525 break;
526  
527 case 5:
528 SetColor(pMtr->arcColor2);
529 if(!Arc(pMtr->xCenter, pMtr->yCenter, pMtr->xCenter, pMtr->yCenter, x1, x2, 0x40))
530 return (0);
531 break;
532  
533 case 4:
534 SetColor(pMtr->arcColor3);
535 if(!Arc(pMtr->xCenter, pMtr->yCenter, pMtr->xCenter, pMtr->yCenter, x1, x2, 0x80))
536 return (0);
537 break;
538  
539 case 3:
540 SetColor(pMtr->arcColor4);
541 if(!Arc(pMtr->xCenter, pMtr->yCenter, pMtr->xCenter, pMtr->yCenter, x1, x2, 0x01))
542 return (0);
543 break;
544  
545 case 2:
546 SetColor(pMtr->arcColor5);
547 if(!Arc(pMtr->xCenter, pMtr->yCenter, pMtr->xCenter, pMtr->yCenter, x1, x2, 0x02))
548 return (0);
549 break;
550  
551 case 1:
552 SetColor(pMtr->arcColor6);
553 if(!Arc(pMtr->xCenter, pMtr->yCenter, pMtr->xCenter, pMtr->yCenter, x1, x2, 0x04))
554 return (0);
555 break;
556  
557 default:
558 break;
559 }
560  
561 temp--;
562 }
563  
564 // set the color for the scale labels
565 SetColor(pMtr->hdr.pGolScheme->Color1);
566 i = DEGREE_END;
567 state = SCALE_COMPUTE;
568  
569 case SCALE_COMPUTE:
570 mtr_scale_compute : if(i >= DEGREE_START)
571 {
572 radian = i * .0175;
573  
574 if(!GetState(pMtr, MTR_RING))
575 {
576 if(i >= ARC1_DEGREE)
577 {
578 SetColor(pMtr->arcColor1);
579 }
580 else if(i >= ARC2_DEGREE)
581 {
582 SetColor(pMtr->arcColor2);
583 }
584 else if(i >= ARC3_DEGREE)
585 {
586 SetColor(pMtr->arcColor3);
587 }
588 else if(i >= ARC4_DEGREE)
589 {
590 SetColor(pMtr->arcColor4);
591 }
592 else if(i >= ARC5_DEGREE)
593 {
594 SetColor(pMtr->arcColor5);
595 }
596 else
597 {
598 SetColor(pMtr->arcColor6);
599 }
600 }
601  
602 // compute for the effective radius of the scales
603 if((i % 45) == 0)
604 x2 = pMtr->radius + (pMtr->radius >> 2) + 2;
605 else
606 x2 = pMtr->radius + (pMtr->radius >> 3) + 3;
607  
608 // compute the starting x1 and y1 position of the scales
609 // x2 here is the distance from the center to the x1, y1
610 // position. Sin and cos is used here since computation speed in initial
611 // drawing is not yet critical.
612 x1 = x2 * cos(radian);
613 y1 = (-1) * (x2 * sin(radian));
614  
615 // using ratio and proportion we get the x2,y2 position
616 dTemp.Val = 0;
617 dTemp.w[1] = (pMtr->radius + 3);
618 dTemp.Val /= x2;
619  
620 dRes.Val = dTemp.Val * x1;
621 x2 = dRes.w[1] + pMtr->xCenter; // adjusted to center
622 dRes.Val = dTemp.Val * y1;
623 y2 = dRes.w[1] + pMtr->yCenter; // adjusted to center
624 x1 += pMtr->xCenter;
625 y1 += pMtr->yCenter; // adjust x1, y1 to the center
626 state = SCALE_DRAW;
627 }
628 else
629 {
630 state = NEEDLE_ERASE;
631 goto mtr_needle_draw_st;
632 }
633  
634 case SCALE_DRAW:
635 if(!Line(x1, y1, x2, y2)) // now draw the scales
636 return (0);
637  
638 if((i % 45) == 0)
639 {
640  
641 // draw the scale labels
642 // reusing radian, x2 and y2
643 // compute for the actual angle of needle to be shown in screen
644 radian = (DEGREE_END - DEGREE_START) - (i - (DEGREE_START));
645  
646 // compute the values of the label to be shown per 45 degree
647 temp = (pMtr->maxValue - pMtr->minValue) * (radian / (DEGREE_END - DEGREE_START));
648  
649 // adjust for the minimum or offset value
650 temp += pMtr->minValue;
651  
652 // this implements sprintf(strVal, "%d", temp); faster
653 // note that this is just for values >= 0, while sprintf covers negative values.
654 j = 1;
655  
656 // get the ones value first and account for the required decimal point if enabled
657 if(GetState(pMtr, MTR_ACCURACY))
658 {
659  
660 // round off to nearest tens
661 dTemp.w[0] = (temp % RESOLUTION) / (RESOLUTION / 10);
662 if((dTemp.w[0]) > (RESOLUTION >> 1))
663 temp += (RESOLUTION - dTemp.w[0]);
664 temp /= RESOLUTION;
665 }
666  
667 do
668 {
669 strVal[SCALECHARCOUNT - j] = (temp % 10) + '0';
670 if(((temp /= 10) == 0) || (j >= SCALECHARCOUNT))
671 break;
672 j++;
673 } while(j <= SCALECHARCOUNT);
674  
675 // the (&strVal[SCALECHARCOUNT-j]) removes the leading zeros.
676 // if leading zeroes will be printed change (&strVal[SCALECHARCOUNT-j])
677 // to simply strVal and remove the break statement above in the do-while loop
678 x2 = GetTextWidth((&strVal[SCALECHARCOUNT - j]), pMtr->hdr.pGolScheme->pFont);
679 y2 = GetTextHeight(pMtr->hdr.pGolScheme->pFont);
680  
681 if(i == -45)
682 {
683 MoveTo(x1 + 3, y1);
684 }
685 else if(i == 0)
686 {
687 MoveTo(x1 + 3, y1 - (y2 >> 1));
688 }
689 else if(i == 45)
690 {
691 MoveTo(x1 + 3, y1 - (y2 >> 1) - 3);
692 }
693 else if(i == 90)
694 {
695 MoveTo(x1 - (x2 >> 1), y1 - (y2) - 3);
696 }
697 else if(i == 135)
698 {
699 MoveTo(x1 - (x2), y1 - (y2));
700 }
701 else if(i == 180)
702 {
703 MoveTo(x1 - (x2) - 3, y1 - (y2 >> 1));
704 }
705 else if(i == 225)
706 {
707 MoveTo(x1 - (x2 + 3), y1);
708 }
709  
710 state = SCALE_LABEL_DRAW;
711 }
712 else
713 {
714 i -= DEGREECOUNT;
715 state = SCALE_COMPUTE; //SCALE_LABEL_DRAW;
716 goto mtr_scale_compute;
717 }
718  
719 case SCALE_LABEL_DRAW:
720 SetFont(pMtr->hdr.pGolScheme->pFont);
721 if(!OutText(&strVal[SCALECHARCOUNT - j]))
722 return (0);
723 i -= DEGREECOUNT;
724 state = SCALE_COMPUTE;
725 goto mtr_scale_compute;
726  
727 case NEEDLE_ERASE:
728 mtr_needle_draw_st : if(GetState(pMtr, MTR_DRAW_UPDATE))
729 {
730  
731 // to update the needle, redraw the old position with background color
732 SetColor(pMtr->hdr.pGolScheme->Color0);
733 SetLineThickness(THICK_LINE);
734 if(!Line(pMtr->xCenter, pMtr->yCenter, pMtr->xPos, pMtr->yPos))
735 return (0);
736 }
737  
738 state = NEEDLE_DRAW;
739  
740 case NEEDLE_DRAW:
741 if(IsDeviceBusy())
742 return (0);
743  
744 // At this point, pMtr->value is assumed to contain the new value of the meter.
745 // calculate the new angle:
746 // equation is still ratio and proportion of angle and values.
747 dTemp.Val = 0;
748 dTemp.w[1] = pMtr->value - pMtr->minValue;
749 dTemp.Val /= (pMtr->maxValue - pMtr->minValue);
750 dTemp.Val *= (DEGREE_END - DEGREE_START);
751  
752 angle = DEGREE_END - (dTemp.w[1]);
753 temp = angle;
754  
755 /* The method uses a lookup table of pre-calculated sine values. The table
756 is derived from calculating sine values from 0 degrees to 90 degrees.
757 To save space, the entries are just a byte size. So 360/255 = 1.40625 degrees
758 increments is used for each entry. (i.e entry 0 is zero, entry i is 1.40625,
759 entry 2 is 2*1.40625,... entry n is n*1.40625.
760 Get the sine of the entries yields a float value. Since we only use a
761 byte for storage we can shift the values by 127 without overflowing the
762 storage. Thus we need to shift the computed values by 7 bits. Shifting now
763 permits us to work with integers which greatly reduces the execution time.
764 With this in mind, the input angles must be translated to 0-90 range with the
765 quadrant of the original angle stored to translate back the value from the
766 table to the correct quadrant. Also the quadrant number will determine if
767 the calculated x and y positions are to be swapped.
768 In summary:
769 Swap x and y when calculating points in quadrant 2 and 4
770 Negate x when in quadrant 2 and 3
771 Negate y when in quadrant 1 and 2
772 */
773  
774 // translate the angle to 0-90 range
775 while(temp < 0) // this is needed for negative
776 temp += 90; // for negative values
777 while(temp > 90)
778 temp -= 90;
779  
780 // determine which quadrant the angle is located
781 // i determines if x and y are swapped (0 no swapping, 1 swapping needed)
782 // y2 and x2 are the multiplier to negate or not the x and y values
783 if((180 < angle) && (angle <= 270))
784 { // quadrant 3
785 i = 0;
786 y2 = 1;
787 x2 = -1;
788 }
789 else if((90 < angle) && (angle <= 180))
790 { // quadrant 2
791 i = 1;
792 y2 = -1;
793 x2 = -1;
794 }
795 else if((0 <= angle) && (angle <= 90))
796 { // quadrant 1
797 i = 0;
798 y2 = -1;
799 x2 = 1;
800 }
801 else if((-90 < angle) && (angle < 0))
802 { // quadrant 4
803 i = 1;
804 y2 = 1;
805 x2 = 1;
806 }
807  
808 // Find Sine value from look up table
809 temp *= .71111; // value is derived from
810  
811 // 360/256 = 1.40625. To avoid
812 // division, the inverse is used
813 x1 = _sineTable[64 - temp] * pMtr->radius;
814 y1 = _sineTable[temp] * pMtr->radius;
815  
816 // calculate new positions, check if we need to reverse x and y values
817 pMtr->xPos = ((x2) * (((i == 0) ? x1 : y1) >> 7)) + pMtr->xCenter;
818 pMtr->yPos = ((y2) * (((i == 0) ? y1 : x1) >> 7)) + pMtr->yCenter;
819  
820 // now draw the needle with the new position
821 SetColor(BRIGHTRED);
822 SetLineThickness(THICK_LINE);
823 if(!Line(pMtr->xCenter, pMtr->yCenter, pMtr->xPos, pMtr->yPos))
824 return (0);
825 SetLineThickness(NORMAL_LINE);
826 #ifdef METER_DISPLAY_VALUES_ENABLE
827 state = VALUE_ERASE;
828 #else
829  
830 // reset the line to normal
831 SetLineThickness(NORMAL_LINE);
832 state = IDLE;
833 return (1);
834 #endif
835 #ifdef METER_DISPLAY_VALUES_ENABLE
836  
837 case VALUE_ERASE:
838 if(IsDeviceBusy())
839 return (0);
840  
841 // reset the line to normal
842 SetLineThickness(NORMAL_LINE);
843  
844 // display the value
845 // erase previous value first. The temp>>1 accomodates fonts with characters that has unequal widths
846 temp = GetTextWidth(tempXchar, pMtr->pValueFont);
847 temp = temp * SCALECHARCOUNT + (temp >> 1);
848  
849 //temp = GetTextWidth(tempXchar, pMtr->pValueFont)*SCALECHARCOUNT;
850 SetColor(pMtr->hdr.pGolScheme->Color0);
851  
852 #if (METER_TYPE == MTR_WHOLE_TYPE)
853 if
854 (
855 !Bar
856 (
857 pMtr->xCenter -
858 (temp >> 1), pMtr->yCenter +
859 pMtr->radius, pMtr->xCenter +
860 (temp >> 1), pMtr->yCenter +
861 pMtr->radius +
862 GetTextHeight(pMtr->pValueFont)
863 )
864 ) return (0);
865  
866 #elif (METER_TYPE == MTR_HALF_TYPE)
867 if
868 (
869 !Bar
870 (
871 pMtr->xCenter -
872 (temp >> 1), pMtr->yCenter -
873 GetTextHeight(pMtr->pValueFont), pMtr->xCenter +
874 (temp >> 1), pMtr->yCenter
875 )
876 ) return (0);
877  
878 #elif (METER_TYPE == MTR_QUARTER_TYPE)
879 if
880 (
881 !Bar
882 (
883 pMtr->xCenter -
884 1, pMtr->yCenter -
885 GetTextHeight(pMtr->pValueFont), pMtr->xCenter +
886 temp, pMtr->yCenter +
887 1
888 )
889 ) return (0);
890 #endif
891 state = VALUE_DRAW;
892  
893 case VALUE_DRAW:
894 if(IsDeviceBusy())
895 return (0);
896  
897 if(angle >= ARC1_DEGREE)
898 {
899 SetColor(pMtr->arcColor1);
900 }
901 else if(angle >= ARC2_DEGREE)
902 {
903 SetColor(pMtr->arcColor2);
904 }
905 else if(angle >= ARC3_DEGREE)
906 {
907 SetColor(pMtr->arcColor3);
908 }
909 else if(angle >= ARC4_DEGREE)
910 {
911 SetColor(pMtr->arcColor4);
912 }
913 else if(angle >= ARC5_DEGREE)
914 {
915 SetColor(pMtr->arcColor5);
916 }
917 else
918 {
919 SetColor(pMtr->arcColor6);
920 }
921  
922 // display the current value
923 SetFont(pMtr->pValueFont);
924  
925 // this implements sprintf(strVal, "%03d", pMtr->value); faster
926 // note that this is just for values >= 0, while sprintf covers negative values.
927 i = pMtr->value;
928 j = 1;
929  
930 // get the ones value first and account for the required decimal point if enabled
931 if(GetState(pMtr, MTR_ACCURACY))
932 {
933 strVal[SCALECHARCOUNT - j] = (((i % RESOLUTION)) / (RESOLUTION / 10)) + '0';
934 i /= RESOLUTION;
935 j++;
936 strVal[SCALECHARCOUNT - j] = '.';
937 j++;
938 }
939  
940 do
941 {
942 strVal[SCALECHARCOUNT - j] = (i % 10) + '0';
943 if(((i /= 10) == 0) || (j >= SCALECHARCOUNT))
944 break;
945 j++;
946 } while(j <= SCALECHARCOUNT);
947  
948 temp = GetTextWidth(&strVal[SCALECHARCOUNT - j], pMtr->pValueFont);
949  
950 #if (METER_TYPE == MTR_WHOLE_TYPE)
951 MoveTo(pMtr->xCenter - (temp >> 1), pMtr->yCenter + pMtr->radius);
952  
953 #elif (METER_TYPE == MTR_HALF_TYPE)
954 MoveTo(pMtr->xCenter - (temp >> 1), pMtr->yCenter - GetTextHeight(pMtr->pValueFont));
955  
956 #elif (METER_TYPE == MTR_QUARTER_TYPE)
957 MoveTo(pMtr->xCenter, pMtr->yCenter - GetTextHeight(pMtr->pValueFont));
958 #endif
959 state = VALUE_DRAW_RUN;
960  
961 case VALUE_DRAW_RUN:
962 if(!OutText(&strVal[SCALECHARCOUNT - j]))
963 return (0);
964 state = IDLE;
965 return (1);
966 #endif //METER_DISPLAY_VALUES_ENABLE
967 }
968  
969 return (1);
970 }
971  
972 #endif // USE_METER
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3