- 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
Diff: main.cpp
- 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 +