- ANALOG METER, initial offering - Emulation of an analog/mechanical meter using the SPI TFT display \"http://mbed.org/cookbook/SPI-driven-QVGA-TFT\" (touch not used) Meter takes an integer number from 0 - 100 and uses that number to position the meter\'s needle - An additional auto-scaling feature allows for + floating numbers from 0.0 - 10000.0 in \"NewfNumb\" Scaling is noted two ways a. Color of the meter body changes b. A text scale factor is displayed in the upper, right-hand corner, near the full scale reading Value of \"NewfNumb\" Meter_Body Scale_Factor < -0.0 Blue 0 0.1 - 9.9 Green x1 10.0 - 99.0 Yellow x10 100.0 - 999.0 Orange x100 1000.0 - 9990.0 Red x1k >= 10000.0 Red peg! - If NewfNumb is > 600.0, a flashing yellow warning message appears in the center of the meter movement - The date and time are displayed in the lower right corner of the display - The value of NewfNumb being shown in the movement is also displayed in the lower left coener of the display - A timer ISR automatically updates the meter\'s movement Other Stuff: - Additional demo test program, walks analog meter up and down through all auto scales by manipulating the value of NewfNumb - USB serial port used to dump a few messages. Not needed, set to 921600 BAUD - LED1 slowly gets brighter and dimmer as main loop runs - If for some reason, the \"MeterNumber\" int register ends up >100 or <0, a Purple display appears at 50% movement with a \"bad#\" scale factor - There is NO provision for setting the RTC. Note that TimeZone and DST are added to the RTC number

Dependencies:   mbed

Revision:
0:fc70640071d2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jan 31 19:40:57 2012 +0000
@@ -0,0 +1,396 @@
+/*
+Rev Date        Changes:
+------------------------------------------------------------------------------------------------------------------------------------------
+100 1/30/12     - ANALOG METER, initial offering
+                - Emulation of an analog/mechanical meter using the SPI TFT display "http://mbed.org/cookbook/SPI-driven-QVGA-TFT" (touch not used)
+                  Meter takes an integer number from 0 - 100 and uses that number to position the meter's needle
+                - An additional auto-scaling feature allows for + floating numbers from 0.0 - 10000.0 in "NewfNumb"
+                  Scaling is noted two ways
+                    a. Color of the meter body changes
+                    b. A text scale factor is displayed in the upper, right-hand corner, near the full scale reading
+                      Value of "NewfNumb"       Meter_Body  Scale_Factor
+                      < -0.0                    Blue           0
+                      0.1 - 9.9                 Green         x1
+                      10.0 - 99.0               Yellow       x10
+                      100.0 - 999.0             Orange      x100
+                      1000.0 - 9990.0           Red         x1k
+                      >= 10000.0                Red         peg!
+                - If NewfNumb is > 600.0, a flashing yellow warning message appears in the center of the meter movement
+                - The date and time are displayed in the lower right corner of the display
+                - The value of NewfNumb being shown in the movement is also displayed in the lower left coener of the display
+                - A timer ISR automatically updates the meter's movement
+               Other Stuff: 
+                - Additional demo test program, walks analog meter up and down through all auto scales by manipulating the value of NewfNumb
+                - USB serial port used to dump a few messages.  Not needed, set to 921600 BAUD
+                - LED1 slowly gets brighter and dimmer as main loop runs
+                - If for some reason, the "MeterNumber" int register ends up >100 or <0, 
+                    a Purple display appears at 50% movement with a "bad#" scale factor
+------------------------------------------------------------------------------------------------------------------------------------------
+*/
+int revision = 100;                     // revision of this code
+#include "mbed.h"
+#include "SPI_TFT.h"
+#include "Arial12x12.h"
+#include "BookAntiqua19x19-14.h"        // kb modified font created by GLCD_Font_Creator.1.20.exe
+#include "touch_tft.h"
+
+#define Orange 0xFBE0                   // I like this orange better than SPI_TFT.h
+
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+//I/O Pin Definitions
+
+PwmOut led1(LED1, "led1");              // pwm LED1
+DigitalOut led2(LED2, "led2");          // simple on/off for LED2 - 4
+DigitalOut led3(LED3, "led3");
+DigitalOut led4(LED4, "led4");
+Serial pc(USBTX, USBRX);                // Serial USB communications over mbed USB port
+touch_tft tt(p19, p15, p16, p17, p5, p6, p7, p9, p14,"TFT"); // x+,x-,y+,y-,mosi, miso, sclk, cs, reset
+
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+// Global Variables
+
+int gDebug = 1;                         // display debog level (0 - 3)
+float Led1Pwm = 0.01;                   // LED1 brightness
+bool Led1Up = true;                     // LED1 auto up-down
+float gWait = 0.005;                    // Main loop wait timeout
+float const DISP_SLOW(2.0);             // Long wait for LCD display
+float const DISP_FAST(0.5);             // Faster wait for LCD
+char timebuf[16];                       // local time format buffer hh:mm:ss
+char datebuf[16];                       // local date format buffer mm/dd/yy
+int DST = 0;                            // Daylight Saving Time (or as defined in tft.ini)
+int TZone = -8;                         // Time Zone from UTC (or as defined in tft.ini)
+time_t ctTime;                          // get time structure
+
+
+// For analog meter
+int LineEndX = 0;                       // end of new line
+int LineEndY = 0;                       // end of new line
+bool onceBlack = true;                  // overwrite to black out text
+int MeterText = 3;                      // index pointer into MeterTextArray[]
+int MeterTextOld = 5;
+int MeterColor = Yellow;                // Meter frame color
+int OldMeterText = MeterText;           // Previous meter frame color
+int MeterTic = Green;                   // Meter tic color
+int MoveColor = White;                  // Meter armature color
+int MeterNumber = 0;                    // Meter scale (0 - 100)
+bool UpdateMove = true;                 // semifore between calling pgm and interrupt
+float NewfNumb = -1.0;                  // + floating number from 0.0 to 10000.0
+
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+// Analog meter scale text display
+const unsigned char MeterTextArray[] = {
+    0x20, 0x20, 0x20, 0x30,     //    0
+    0x20, 0x20, 0x78, 0x31,     //   x1
+    0x20, 0x78, 0x31, 0x30,     //  x10
+    0x78, 0x31, 0x30, 0x30,     // x100
+    0x20, 0x78, 0x31, 0x4b,     //  x1K
+    0x70, 0x65, 0x67, 0x21,     // peg!
+    0x62, 0x61, 0x64, 0x23 };   // bad#
+
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+// Analog meter text display
+void DispMeterText() {
+    for(int i = MeterText * 4; i < MeterText * 4 + 4; i++) {
+        tt.printf("%c", MeterTextArray[i]);
+        if(gDebug > 2) pc.printf("%c", MeterTextArray[i]);
+    }
+}
+
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+// Analog metet text display black-out
+void EraseMeterText() {
+    for(int i = MeterTextOld * 4; i < MeterTextOld * 4 + 4; i++) {
+        tt.printf("%c", MeterTextArray[i]);
+        if(gDebug > 2) pc.printf("%c", MeterTextArray[i]);
+    }
+}
+
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+//position the meter's movement
+void MeterMovement() {
+    LineEndX = 240 * MeterNumber / 100 + 40;  // ((280 - 40) * MeterNumber / 100) + 40;
+    if(MeterNumber < 50) {
+        LineEndY = 56 * MeterNumber / 100 + 177; // (((205 - 177) * 2) * MeterNumber / 100) + 177;
+    } else {
+        LineEndY = 56 * (100 - MeterNumber) / 100 + 177; // (((205 - 177) * 2) * (100 - MeterNumber) / 100) + 177;
+    }
+}
+
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+//set up analog meter's inner guts
+void DispMeterTics() {
+    tt.rect(20,130,50,190,MeterColor);
+    tt.circle(35,160,10,MeterColor);
+
+//inner box and cenerting circle are done, now paint the 11 tics in desired color
+    tt.line(200,160,210,160,MeterTic);  //50%
+    tt.line(197,136,207,135,MeterTic);  //40%
+    tt.line(193,112,203,110,MeterTic);
+    tt.line(188,88,198,84,MeterTic);
+    tt.line(181,65,191,59,MeterTic);
+    tt.line(172,45,182,36,MeterTic);    // 0%
+    tt.line(197,184,207,185,MeterTic);  // 60%
+    tt.line(193,208,203,210,MeterTic);
+    tt.line(188,232,198,236,MeterTic);
+    tt.line(181,255,191,261,MeterTic);  // 90%
+    tt.line(172,275,182,284,MeterTic);  // 100%
+}
+
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+//set up analog meter's frame
+void DispMeterFrame() {
+//first erase and display the meter's scale number in upper-right corner
+    tt.set_font((unsigned char*) Arial12x12);
+    tt.foreground (Black);
+    tt.set_orientation(1);
+    tt.locate(260,30);
+    EraseMeterText();
+    tt.foreground (MeterColor);
+    tt.locate(260,30);
+    DispMeterText();
+    MeterTextOld = MeterText;
+
+//now paint the outer frame in the desired color    
+    tt.set_orientation(0);
+    tt.rect(18,18,222,302,MeterColor);
+    tt.rect(19,19,221,301,MeterColor);
+    tt.rect(20,20,220,300,MeterColor);
+    DispMeterTics();
+}
+
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+//Test program for the analog meter
+void DispMeterShell() {
+    tt.cls();
+    DispMeterFrame();
+    MeterNumber = 0;
+    for(int i = 0; i < 21; i++) {
+        MeterMovement();
+        DispMeterTics();
+        tt.line(35,160,LineEndY,LineEndX,MoveColor);
+        wait(DISP_FAST);
+        tt.line(35,160,LineEndY,LineEndX,Black);  //erase previous line
+        MeterNumber = MeterNumber + 5;
+    }
+    MeterNumber = 0;
+    MeterMovement();
+    DispMeterTics();
+    tt.line(35,160,LineEndY,LineEndX,MoveColor);
+    wait(DISP_SLOW);
+}
+
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+// timer interrupt.  Changes the position of the meter movement
+int oln = 0 ;
+int tmp = 0 ;
+int UpdateTics = 0;
+
+void myIRQ() {
+    LPC_TIM0->IR |= 1 << 0;
+    if(UpdateMove == true) {
+        UpdateMove = false;
+        tt.set_orientation(0);
+        tmp = MeterNumber;
+        MeterNumber = oln;
+        tt.line(35,160,LineEndY,LineEndX,Black);        //erase previous line
+        MeterNumber = tmp;
+        MeterMovement();                                //calculate new position
+        tt.line(35,160,LineEndY,LineEndX,MoveColor);
+        UpdateTics++;
+        if(UpdateTics >= 3) {                           //only update tics every few int's
+            DispMeterTics();
+            UpdateTics = 0;
+        }   
+    }
+    oln = MeterNumber;
+}
+
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+// Updates the date/time and Number values on bottom of TFT and on Text LCD every second
+bool flashtext = false;
+
+void UpdateLowerDisplayEverySec() {
+    flashtext = !flashtext;
+    tt.set_font((unsigned char*) Arial12x12);
+    tt.foreground (Cyan);
+    tt.set_orientation(1);
+
+//first print date/time in lower-left side of analog meter
+    tt.locate(238,205);
+    tt.printf("%s", timebuf);
+    tt.locate(238,192);
+    tt.printf("%s", datebuf);
+
+//display text number in lower-right corner
+    tt.foreground (DarkGrey);
+    tt.locate(30,205);
+    tt.printf("%.1f YYZ ", NewfNumb);
+
+//display WARNING!! if Number too high
+    if((NewfNumb > 600.0) && (flashtext == false)) {
+        tt.set_font((unsigned char*) Book_Antiqua19x19);
+        tt.foreground (Yellow);
+        tt.locate(80,110);
+        tt.printf("Get the HELL");
+        tt.locate(80,130);
+        tt.printf("out of here !!!");
+        onceBlack = false;
+    } else if(((NewfNumb <= 600.0) && (onceBlack == false)) || ((NewfNumb > 600.0) && (flashtext == true))) {
+        tt.set_font((unsigned char*) Book_Antiqua19x19);
+        tt.foreground (Black);
+        tt.locate(80,110);
+        tt.printf("Get the HELL");
+        tt.locate(80,130);
+        tt.printf("out of here !!!");
+        onceBlack = true;
+    }
+    tt.set_orientation(0);
+
+//set color of meter frame (and meter scaling factor) based on NewfNumb scale       
+    if(NewfNumb < 10000.0) {
+        MeterNumber =  (int)(NewfNumb / 100.0);
+        MeterColor = Red;
+        MeterText = 4;
+    } else {
+        MeterNumber =  100;
+        MeterColor = Red;
+        MeterText = 5;
+    }
+    if(NewfNumb < 1000.0) {
+        MeterNumber =  (int)(NewfNumb / 10.0);
+        MeterColor = Orange;
+        MeterText = 3;
+    }
+    if(NewfNumb < 100.0) {
+        MeterNumber =  (int)(NewfNumb);
+        MeterColor = Yellow;
+        MeterText = 2;
+    }
+    if(NewfNumb < 10.0) {
+        MeterNumber =  (int)(NewfNumb * 10.0);
+        MeterColor = DarkGreen;
+        MeterText = 1;
+    }
+    if(NewfNumb <= 0.0) {
+        MeterNumber = 0;
+        MeterColor = Blue;
+        MeterText = 0;
+    }   
+    if((MeterNumber > 100) | (MeterNumber < 0)) {
+        MeterNumber = 50;
+        MeterColor = Purple;
+        MeterText = 6;
+    }
+//change meter frame color only if it's different from the previous color
+    if(OldMeterText != MeterText) {
+        OldMeterText = MeterText;
+        tt.set_orientation(0);
+        DispMeterFrame();
+    }
+    UpdateMove = true;          // allow interrupt to make change to movement
+    if(gDebug > 2) pc.printf("NewfNumb: %.3f   MeterNumber: %d\n", NewfNumb, MeterNumber);
+}
+
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+// Test routing puts analog meter through its pases
+bool MeterUp = true;
+void TestMeter() {
+    if(MeterUp == true) {
+        if(NewfNumb >= 11000.0) {
+            MeterUp = false;
+            return;
+        }else if(NewfNumb >= 1000.0) {
+            NewfNumb = NewfNumb + 500.0;
+            return;
+        }else if(NewfNumb >= 100.0) {
+            NewfNumb = NewfNumb + 50.0;
+            return;
+        }else if(NewfNumb >= 10.0) {
+            NewfNumb = NewfNumb + 5.0;
+            return;
+        }else {
+            NewfNumb = NewfNumb + 0.5;
+        }
+    }else {
+        if(NewfNumb <= -1.5) {
+            MeterUp = true;
+            return;
+        }else if(NewfNumb > 1000.0) {
+            NewfNumb = NewfNumb - 500.0;
+            return;
+        }else if(NewfNumb > 100.0) {
+            NewfNumb = NewfNumb - 50.0;
+            return;
+        }else if(NewfNumb > 10.0) {
+            NewfNumb = NewfNumb - 5.0;
+            return;
+        }else {
+            NewfNumb = NewfNumb - 0.5;
+        }
+    }
+    if(gDebug > 1) pc.printf("RTN: %.1f\n",NewfNumb);      
+}
+
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+int main() {
+    int ResetState = LPC_WDT->WDMOD;
+    pc.baud(921600);                    //set up USB serial speed
+    ctTime = time(NULL);
+    ctTime = ctTime + ((TZone + DST) * 3600);
+    pc.printf("\n\n");
+    pc.printf("-------------------------------------------------------------------\n");
+    pc.printf("Scalable Analog Meter using TFT  Rev: %d   K Braun\n", revision);
+    tt.cls();   
+    wait(DISP_FAST);
+    int StartTime = ctTime;
+    int xTime = ctTime;
+    int LedDelay = 0;
+
+    pc.printf("Enabling Timer Interrupt\n");    
+    // LPC_SC->PCONP |= 1<<1; // Timer0 Power On
+    LPC_TIM0->MR0 = 4800000;  // Match count for 200ms (24000 per 1mS)
+    LPC_TIM0->MCR = 3;     // Interrupt and Reset on Match
+    LPC_TIM0->TCR = 1;     // Enable Timer0
+    NVIC_SetVector(TIMER0_IRQn,(uint32_t)&myIRQ);
+    NVIC_EnableIRQ(TIMER0_IRQn);
+    pc.printf("Ready...\n"); 
+       
+/*--------------------------------------------------------------------------------------------------------------------------------------*/
+    while (1) {
+        wait_ms(3);
+        ctTime = time(NULL);
+        ctTime = ctTime + ((TZone + DST) * 3600);
+        strftime(timebuf, 16, "%H:%M:%S", localtime(&ctTime));
+        strftime(datebuf, 16, "%m/%d/%y", localtime(&ctTime));
+        if(xTime != ctTime) {
+            xTime = ctTime;
+            if(gDebug > 1) pc.printf("%s  ", timebuf);
+            if(gDebug > 1) pc.printf("%s  ", datebuf);
+            TestMeter();
+            UpdateLowerDisplayEverySec();
+            if(gDebug > 1) pc.printf("cT: %d   sT: %d\n", ctTime, StartTime);
+        }
+       
+// Winking LED1      
+        LedDelay++;
+        if(LedDelay >= 24) {
+            LedDelay = 0;
+            if(Led1Up == true) {
+                Led1Pwm = Led1Pwm + 0.005;
+                led1 = Led1Pwm;
+                if(Led1Pwm >= 0.20) {
+                    Led1Up = false;
+                }
+            } else {
+                Led1Pwm = Led1Pwm - 0.005;
+                led1 = Led1Pwm;
+                if(Led1Pwm <= 0.005) {
+                    Led1Up = true;
+                }
+            } //brighter else dimmer
+        } //LedDelay > 24 (* 3ms from while loop)
+    } //while loop
+} //main
+