- 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
main.cpp
- Committer:
- loopsva
- Date:
- 2012-01-31
- Revision:
- 0:fc70640071d2
File content as of revision 0:fc70640071d2:
/* 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