A general demonstration color etch-a-sketch program using the QVGA TFT with HX8347D controller, Orange Board. Saves touchscreen calibaration data saved in tft.ini. Creates /local/tft.ini if missing. Also included is an Ethernet NTP client to update the RTC. Assumes all other Orange Board devices attached: Text LCD, SDHC Flash, Ethernet.
Dependencies: EthernetNetIf TextLCD mbed
Diff: main.cpp
- Revision:
- 0:e065ca40f28a
diff -r 000000000000 -r e065ca40f28a main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Aug 01 16:29:58 2011 +0000 @@ -0,0 +1,1011 @@ +/* +Rev Date Changes: +------------------------------------------------------------------------------------------------------------------------------------------ +100 7/19/11 - initial offering +101 7/25/11 - Adding RTC display-only functions. No provisions for setting the clock + - Added red "clear_drawing" box to TFT + - Added multi-color "change_pen_color" box + - Added blue, pen_fattness circle (1-8) + - Added "orange" color to pen_color selection + - Added hidden system_reset function w/pen touch near "TFT" text +102 7/26/11 - Added EthernetNetIF and TinySNTP for updating RTC over Ethernet + - Added a color choice palette after reset. Palette goes away after clear_screen +103 7/28/11 - Expqanded NTP service to two possible NTP servers. In and IP address, the other named + - Added tube symbol for display + - Modified the start-up splash screen +104 7/28/11 - Made tube display indepentent of rotation + - Added more NTP server options +------------------------------------------------------------------------------------------------------------------------------------------ +Known issues: +------------------------------------------------------------------------------------------------------------------------------------------ +*/ +int revision = 104; // revision of this code +#include "mbed.h" +#include "SDHCFileSystem.h" // MUST be before EthernetNetIf.h or compile error occurs!!!! +#include "adc.h" +#include "EthernetNetIf.h" +#include "TinySNTP.h" +#include "TextLCD.h" +#include "SPI_TFT.h" +#include "Arial12x12.h" +#include "Arial24x23.h" +#include "Arial28x28.h" +#include "font_big.h" +#include "Courier10x13-12B.h" // kb modified font created by GLCD_Font_Creator.1.20.exe +#include "Verdana22x21-16.h" // kb modified font created by GLCD_Font_Creator.1.20.exe +#include "BookAntiqua19x19-14.h" // kb modified font created by GLCD_Font_Creator.1.20.exe +#include "touch_tft.h" + +#define DEFAULTHOSTNAME "mbed-c3p1" +char *hostname = DEFAULTHOSTNAME; + +//#define RTCCOLOR "Red" +//char *JunkText = RTCCOLOR; +//char *RtcColor = RTCCOLOR; + +#define SAMPLE_RATE 150000 +#define CLS "\033[2J" +extern "C" void mbed_reset(); +#define Orange 0xF9E0 + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +//I/O Pin Definitions + +LocalFileSystem local("local"); +PwmOut led1(LED1, "led1"); +DigitalOut led2(LED2, "led2"); +DigitalOut led3(LED3, "led3"); +DigitalOut led4(LED4, "led4"); +EthernetNetIf eth; +Serial pc(USBTX, USBRX); // Serial USB communications over mbed USB port +SDFileSystem sd(p5, p6, p7, p8, "sd"); // mosi, miso, sclk, cs +touch_tft tt(p19, p15, p16, p17, p5, p6, p7, p9, p14,"TFT"); // x+,x-,y+,y-,mosi, miso, sclk, cs, reset +TextLCD lcdt(p24, /*p25, */p26, p27, p28, p29, p30, TextLCD::LCD16x2); // rs, rw, e, d0, d1, d2, d3 +DigitalOut LCDrw(p25, "LCDrw"); // new LCD code no longer requries R/W pin - tie low (J5 on Orange Board) + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +// Global Variables + +int gDebug = 1; // display debog level (0 - 3) +int OldgDebug = gDebug; // copy of gDebug for updating tft.ini +ADC adc(SAMPLE_RATE, 1); +bool use_sd = false; // flag for using SDHC file system +bool ZeroMinFlag = false; // alignment to 00:00:00 flag +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[32]; // local time format buffer +char timebuf_d[32]; // local time format buffer - date only +char timebufUTC[32]; // UTC time format buffer +int DST = 0; // Daylight Saving Time (or as defined in tft.ini) +int OldDST = DST; // Copy of DST for updating tft.ini +int TZone = -8; // Time Zone from UTC (or as defined in tft.ini) +int OldTZone = TZone; // copy for updating tft.ini +time_t ctTime; // get time structure +int StartTime; // time we powered up +int SysUpTime; // time we've been alive +int RTCstep; // value for NTP update interval timer +int NTPUpdateValue = 86400; // update RTC every 24 hours (or as defined in tft.ini) +int TftCalib = 1; // TFT touchpad calibration, 1=yes (as defined in tft.ini) +unsigned int SerialNum[5] = {58,0,0,0,0}; // mbed serial number data +int TftDrawColor = 0; // pick pencil color +int PenColor = 0xFFFF; // color of pen +int PenWidth = 3; // fattness of pen +bool PenSizeUp = true; // fatter or skinnier +char pOnce = 0; // display the palette only once +int CurRot = 0; // object rotation 0-3 +int PosX = 120; // object X location +int PosY = 160; // object Y location + +int RTCupdate = 0; // parameter update timer +int const RTCUpdateValue = 60; // 600; // update values every minute +unsigned int Align1Min=0; // used to align sensor access to exactly every minute, on the minute +unsigned int Align10Min=0; // same as above for 10 minute (i.e. 0:00min, 10:00min, 20:00min, etc. +int minuteAvg = 0.0; // number of minutes between accesses to storage of data + +unsigned short pp_txm = 0; // tft touchscreen calibration values +unsigned short pp_tym = 0; +unsigned short pp_txoff = 0; +unsigned short pp_tyoff = 0; + +float Press0Ft = 102.4; // altimeter - assumed pressure at sea level +float Saved0Ft = Press0Ft; // saved for later comparison if changed by HTTP +float OldPress0Ft = Press0Ft; // another copy for updating tft.ini + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +// initialize mbed "ini" configuration file if it doesn't already exist -or- updates the ini file if a change is made in s/w + +void InitIniFile() { + FILE *fp = fopen("/local/tft.ini", "w"); + if (fp == NULL) { + pc.printf("*** Cannot create tft.ini file!!!\n"); + } else { +// if(gDebug > 1) pc.printf("*** Updating/Creating tft.ini file...\n"); + fprintf(fp, "# mbed configuration file\r\n"); + fprintf(fp, "\r\n[NTP Servers]\r\n"); +// for (int i=0; i<sntp_num_servers; i++) { +// fprintf(f, "%s" CRLF, sntp_server_addresses[i]); +// } + fprintf(fp, "\r\n[Global]\r\n"); + char *hostname = DEFAULTHOSTNAME; + fprintf(fp, "xMyName=%s\r\n",hostname); //***MyName is broken*** + fprintf(fp, "TftCalib=%d\r\n", TftCalib); // 1= calibration required + fprintf(fp, "TftCalTxm=%d\r\n", pp_txm); + fprintf(fp, "TftCalTym=%d\r\n", pp_tym); + fprintf(fp, "TftCalTxOff=%d\r\n", pp_txoff); + fprintf(fp, "TftCalTyOff=%d\r\n", pp_tyoff); +// char *RtcColor = RTCCOLOR; +// char *JunkText = RTCCOLOR; +// fprintf(fp, "TftRtcColor=%s\r\n", RtcColor); + fprintf(fp, "Timezone(hrs)=%d\r\n", TZone); + fprintf(fp, "DstZone(hrs)=%d\r\n", DST); + fprintf(fp, "NTPRefresh(sec)=%d\r\n", NTPUpdateValue); + fprintf(fp, "PressureSeaLevel=%f\r\n", Press0Ft); + fprintf(fp, "gDebugLevel=%d\r\n", gDebug); + fprintf(fp, "\r\n##END\r\n"); + fclose(fp); + } + OldgDebug = gDebug; + OldDST = DST; + OldTZone = TZone; + OldPress0Ft = Press0Ft; +} + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +// Trim whitespace/CRLFs from both ends of a given string +// for use with routine below + +char * str_cleanup(char *in) { + char * out = in; + // Trim leading spaces and CR/LF + while (*out == ' ' || *out == '\t' || *out == '\r' || *out == '\n') + out ++; + // Trim trailing spaces and CR/LF + int len = strlen(out)-1; + while (out[len] == ' ' || out[len] == '\t' || out[len] == '\r' || out[len] == '\n') { + out[len] = '\0'; + len--; + } + return out; +} + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +// Simple ini file parser for SNTP configuration (Case-sensitive!) +// This function is intended to be called only before SNTPClientInit(). +// Returns: 0 if OK, errno otherwise + +enum { + SECT_NONE, + SECT_SERVERS, + SECT_GLOBAL, +}; + +//int _SNTPClrAddresses(); + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +// This routine reads the "ini" file and sets the appropriate variables + +int SNTPReadIniFile(const char* filename) { + if (gDebug > 1) pc.printf("Before: tz:%d dst:%d ntpupd:%d baroZ:%.1f name:%s\n", TZone, DST, NTPUpdateValue, Press0Ft, hostname); + FILE *f; + char buf[512]; +// bool addresses_cleared = false; + bool hname = false; + f = fopen(filename, "r"); + if (!f) + return -1; // errno not used? + char *buf1, *buf2; + int section=SECT_NONE; + int line = 0; + while (fgets(buf, sizeof(buf)/sizeof(buf[0]), f)) { + line++; + buf1 = str_cleanup(buf); + if (*buf1 == '#' || *buf1 == '\0') + continue; // Comment line or empty line - skip + if (*buf1 == '[') { + // New section + if (0 == strncmp(buf1,"[NTP Servers]", sizeof("[NTP Servers]")-1)) { + section=SECT_SERVERS; +/* if (!addresses_cleared) { + // Clear addresses only once. + _SNTPClrAddresses(); + addresses_cleared = true; + } +*/ } else if (0 == strncmp(buf1,"[Global]", sizeof("[Global]")-1)) { + section=SECT_GLOBAL; + } else { + section=SECT_NONE; + fprintf(stderr, "*** File \"%s\", line %d - section \"%s\" is not understood.\r\n", filename, line, buf1); + } + } else { + // Section values + switch (section) { + case SECT_SERVERS: +/* if (_SNTPAddAddress(buf1)) { + fprintf(stderr, "File \"%s\", line %d - cannot add server \"%s\" - exceeded allocated slots.\r\n", filename, line, buf1); + } + break; +*/ case SECT_GLOBAL: + buf2 = strchr(buf1, '='); + if (buf2) { + *buf2++ = '\0'; // Now buf1 has variable name, buf2 has value + buf2 = str_cleanup(buf2); + if (0 == strncmp(buf1, "Timezone(hrs)", sizeof("Timezone(hrs)")-1)) { + TZone = strtod(buf2, &buf2); + } else if (0 == strncmp(buf1, "NTPRefresh(sec)", sizeof("NTPRefresh(sec)")-1)) { + NTPUpdateValue = strtod(buf2, &buf2); + } else if (0 == strncmp(buf1, "gDebugLevel", sizeof("gDebugLevel")-1)) { + gDebug = strtod(buf2, &buf2); + } else if (0 == strncmp(buf1, "TftCalib", sizeof("TftCalib")-1)) { + TftCalib = strtod(buf2, &buf2); + } else if (0 == strncmp(buf1, "TftCalTxm", sizeof("TftCalTxm")-1)) { + pp_txm = strtod(buf2, &buf2); + } else if (0 == strncmp(buf1, "TftCalTym", sizeof("TftCalTym")-1)) { + pp_tym = strtod(buf2, &buf2); + } else if (0 == strncmp(buf1, "TftCalTxOff", sizeof("TftCalTxOff")-1)) { + pp_txoff = strtod(buf2, &buf2); + } else if (0 == strncmp(buf1, "TftCalTyOff", sizeof("TftCalTyOff")-1)) { + pp_tyoff = strtod(buf2, &buf2); +// } else if (0 == strncmp(buf1, "TftRtcColor", sizeof("TftRtcColor")-1)) { +// JunkText = buf2; //pp_tyoff = strtod(buf2, &buf2); +// RtcColor = JunkText; +// pc.printf("buf2 >> %s JunkText >> %s RtcColor >> %s\n", buf2, JunkText, RtcColor); + } else if (0 == strncmp(buf1, "MyName", sizeof("MyName")-1)) { + if (hname == false) { + hname = true; + hostname = buf2; + if (gDebug > 1) pc.printf("buf2:%s hn:%s\n", buf2, hostname); + } + } else if (0 == strncmp(buf1, "PressureSeaLevel", sizeof("PressureSeaLevel")-1)) { + Press0Ft = strtof(buf2, &buf2); + //} else if (0 == strncmp(buf1, "RtcUtc", sizeof("RtcUtc")-1)) { + // gSntpRtcUtc = (bool)strtol(buf2, &buf2, 10); + } else if (0 == strncmp(buf1, "DstZone(hrs)", sizeof("DstZone(hrs)")-1)) { + DST = strtod(buf2, &buf2); + } else { + pc.printf("*** File \"%s\", line %d - unrecognized variable \"%s\" in section [Global]\r\n", filename, line, buf1); + } + } else { + pc.printf("*** File \"%s\", line %d - unrecognized statement in section [Global]: %s\r\n", filename, line, buf1); + } + break; + default: + pc.printf("*** File \"%s\", line %d - unrecognized statement / no section: %s\r\n", filename, line, buf1); + } + } + } + fclose(f); + pc.printf("mbed configuration read from \"%s\", %d lines.\r\n", filename, line); + pc.printf("- gDebug display level: %d\n", gDebug); + pc.printf("- Time Zone: %d hours\n", TZone); + if (DST == 0) { + pc.printf("- Standard Time\n"); + } else { + pc.printf("- Daylight Saving Time\n"); + } + pc.printf("- NTC update: %d seconds\n", NTPUpdateValue); +// pc.printf("- Pressure at Seal Level: %.1f kPa\n", Press0Ft); + if (TftCalib == 1) { + pc.printf("- TFT touchpad calibration required\n"); + } else { + pc.printf("- No TFT touchpad calibration needed\n"); + } + pc.printf("- Touch Cal X Base %d\n", pp_txm); + pc.printf("- Touch Cal Y Base %d\n", pp_tym); + pc.printf("- Touch Cal X Offset %d\n", pp_txoff); + pc.printf("- Touch Cal Y Offset %d\n", pp_tyoff); +// pc.printf("- RTC Color %s\n", RtcColor); + + if (gDebug > 1) pc.printf("After: tz:%d dst:%d ntpupd:%d baroZ:%.1f name:%s\n", TZone, DST, NTPUpdateValue, Press0Ft, hostname); + + OldgDebug = gDebug; + OldDST = DST; + OldTZone = TZone; + OldPress0Ft = Press0Ft; + return 0; +} + + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +// This routine attempts to update the RTC via an Ethernet NTP server + +int SetEthTime() { + pc.printf("Getting Time from NTP Server\n- Old Time (UTC): %d %s", ctTime, ctime(&ctTime)); + int ntpFlag = 0; + if(gDebug) pc.printf("- Trying NTP Server: time-a.nist.gov... "); + ntpFlag = ntpdate("time-a.nist.gov", &ctTime); + if((gDebug) && (ntpFlag)) pc.printf("failed\n- Trying NTP Server: pool.ntp.org... "); + if(ntpFlag) { + ntpFlag = 0; + ntpFlag = ntpdate("pool.ntp.org", &ctTime); + if((gDebug) && (ntpFlag)) pc.printf("failed\n- Trying NTP Server: 10.77.127.1... "); + if(ntpFlag) { + ntpFlag = 0; + ntpFlag = ntpdate("10.77.127.1", &ctTime); + if((gDebug) && (ntpFlag)) pc.printf("failed\n"); + } + } + + +// pc.printf("ntpFlag: %d\n", ntpFlag); +/* +// +// Server selection code from HTTPS_618 +// + Host server(IpAddr(), 123, "time-a.nist.gov"); + if (gDebug > 1) pc.printf("NTP result 1 : %d time-a.nist.gov\n", ntp.setTime(server)); + if(ntp.setTime(server) == 4) { + server.setName("time-b.nist.gov"); + if (gDebug > 1) pc.printf("NTP result 2 : %d time-b.nist.gov\n", ntp.setTime(server)); + if(ntp.setTime(server) == 4) { + server.setName("pool.ntp.org"); + if (gDebug > 1) pc.printf("NTP result 3 : %d pool.ntp.org\n", ntp.setTime(server)); + if(ntp.setTime(server) == 4) { + server.setName("north-america.pool.ntp.org"); + if (gDebug > 1) pc.printf("NTP result 4 : %d north-america.pool.ntp.org\n", ntp.setTime(server)); + if(ntp.setTime(server) > 2) { + server.setName("10.77.127.1"); + if (gDebug > 1) pc.printf("NTP result 5 : %d 10.77.127.1\n", ntp.setTime(server)); + if(ntp.setTime(server) > 2) { + server.setName("74.218.141.2"); + if (gDebug > 1) pc.printf("NTP result 6 : %d 74.218.141.2\n", ntp.setTime(server)); + pc.printf(" No NTP Server found!!!\n"); + lcdt.locate(15,1); //column(0-15), row(0-1) + lcdt.printf("x"); //set no NTP flag on LCD + } + } + } + } + } +*/ + + + if(ntpFlag == 0) { + pc.printf("ok\nSuccessful Time Update\n"); + pc.printf("- Time post NTP (UTC): %d %s", ctTime, ctime(&ctTime)); + StartTime = ctTime; + set_time(ctTime); + ctTime = ctTime + ((TZone+DST)*3600); //timezone and dst offsets + pc.printf("- Time post NTP (local): %d %s", ctTime, ctime(&ctTime)); + RTCstep = ctTime + NTPUpdateValue; //next NTP update + ctTime = ctTime + NTPUpdateValue; //next NTP update + pc.printf("- Next Update (local): %d %s", ctTime, ctime(&ctTime)); + ctTime = ctTime - NTPUpdateValue; + return 0; + } else { + pc.printf("*** NTP Server not Found!!!\n"); + return -1; + } +} + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +// This routine is used to align "display events" at exactly RTC 60 second and 10 minute intervals + +void align_access_time() { + ctTime = time(NULL); + ctTime = ctTime + ((TZone+DST)*3600); //timezone and dst offsets + float getMod = fmod(ctTime, 600.0); // modulus count for exact 10 minute adjustments + Align1Min = (ctTime + (600 - int(getMod))); // init 10 minute ticker + minuteAvg = 1 + (Align1Min - ctTime) / 60; // how many access minutes before 1st store + pc.printf("Align10min ct: %d gM: %3d tsA: %d mA: %d \n", + ctTime, int(getMod), Align1Min, minuteAvg); + getMod = fmod(ctTime,60.0); + Align10Min = (ctTime + (60 - int(getMod))); + RTCupdate = Align10Min; //Align1Min; + pc.printf("Align1min gM: %3d lts: %d\n", int(getMod), Align10Min); +} + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +// This is the initial splash screen for the TEXT LCD + +void TextLCDTitle() { + lcdt.cls(); //init the LCD + lcdt.locate(0,0); //column(0-15), row(0-1) + lcdt.printf("TFT Driver %d", revision); //print revision on LCD + lcdt.locate(0,1); //column(0-15), row(0-1) + lcdt.printf("K Braun"); //print -me- on LCD +} + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +// This is the initial TFT splash screen -and- the follow-on screen if the pen selects the "clear_screen" box + +void InitTft() { + int CurrentColor = PenColor; + int CurrentTft = TftDrawColor; + tt.foreground(Yellow); // set chars to white + tt.cls(); // clear the screen + tt.set_font((unsigned char*) Arial12x12); // select the font +// tt.set_font((unsigned char*) FONT8x8); +// tt.set_font((unsigned char*) Courier10x13); +// tt.set_font((unsigned char*) Verdana22x21); +// tt.set_font((unsigned char*) Book_Antiqua19x19); +// tt.cls(); + tt.foreground(Yellow); // set chars to white + tt.set_orientation(0); + tt.locate(0,0); + tt.printf(" TFT Touch Test"); + tt.locate(0,1); + tt.printf(" K. Braun"); + tt.locate(0,2); + tt.printf(" Rev: %d", revision); + tt.locate(13,1); + tt.printf("%d", PenWidth); + tt.foreground(White); // set chars to white + tt.set_orientation(1); + tt.rect(5,5,30,30,Red); + tt.fillrect(5,35,30,60,CurrentColor); + if(CurrentColor == Black) { + tt.rect(5,35,30,60,White); // if black, put on white frame + } + tt.circle(16,80,10, Blue); +// PenColor = 0xFFFF; // color of pen +// TftDrawColor = 0; // pick pencil color + +// The following draws that color palette, but only once after a reset + if((gDebug >> 0) && (pOnce == 0)) { + pOnce = 1; + tt.set_orientation(0); + tt.set_font((unsigned char*) Arial24x23); + tt.locate(3,3); + tt.printf("Palette"); + tt.set_font((unsigned char*) Arial12x12); + int tX = 17; + int tY = 90; + int tB = 25; + tt.fillrect(tX,tY,tX+tB,tY+tB,White); + tX = tX+tB+1; + tt.fillrect(tX,tY,tX+tB,tY+tB,Orange); + tX = tX+tB+1; + tt.fillrect(tX,tY,tX+tB,tY+tB,Yellow); + tX = tX+tB+1; + tt.fillrect(tX,tY,tX+tB,tY+tB,Magenta); + tX = tX+tB+1; + tt.fillrect(tX,tY,tX+tB,tY+tB,Red); + tX = tX+tB+1; + tt.fillrect(tX,tY,tX+tB,tY+tB,Cyan); + tX = tX+tB+1; + tt.fillrect(tX,tY,tX+tB,tY+tB,Green); + tX = tX+tB+1; + tt.fillrect(tX,tY,tX+tB,tY+tB,Blue); + tY = tY+tB+1; + tX = 17; + tt.fillrect(tX,tY,tX+tB,tY+tB,LightGrey); + tX = tX+tB+1; + tt.fillrect(tX,tY,tX+tB,tY+tB,DarkGrey); + tX = tX+tB+1; + tt.fillrect(tX,tY,tX+tB,tY+tB,Olive); + tX = tX+tB+1; + tt.fillrect(tX,tY,tX+tB,tY+tB,Purple); + tX = tX+tB+1; + tt.fillrect(tX,tY,tX+tB,tY+tB,Maroon); + tX = tX+tB+1; + tt.fillrect(tX,tY,tX+tB,tY+tB,DarkCyan); + tX = tX+tB+1; + tt.fillrect(tX,tY,tX+tB,tY+tB,DarkGreen); + tX = tX+tB+1; + tt.fillrect(tX,tY,tX+tB,tY+tB,Navy); + tt.set_orientation(1); + } + + PenColor = CurrentColor; + TftDrawColor = CurrentTft; + + //wait for no-touch + point p; + do { + p = tt.get_touch(); + tt.is_touched(p); + } + while (p.y > 0x2000 | p.x > 0x2000); // { // wait for no touch +} + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +// The following draws an object of a triode tube. It's location is set by PosX and PosY and CurRot + +void DrawTubeX() { + int xx = PosX; + int yy = PosY; + if((CurRot == 0) || (CurRot == 2)) { + xx = PosX; + yy = PosY; + } else { + xx = PosY; + yy = PosX; + } + tt.set_orientation(CurRot); + tt.fillcircle(xx,yy,60,Orange); + tt.circle(xx,yy,60,Navy); + tt.circle(xx,yy,59,Blue); + tt.circle(xx,yy,58,Navy); + tt.fillrect(xx-2,yy+40,xx+2,yy+70,Purple); + tt.fillrect(xx-2,yy+10,xx+2,yy+30,Purple); + tt.fillrect(xx-2,yy-20,xx+2,yy+00,Purple); + tt.fillrect(xx-2,yy-50,xx+2,yy-30,Purple); + tt.fillrect(xx-80,yy-2,xx-30,yy+2,DarkGreen); + tt.fillrect(xx-30,yy-30,xx-25,yy+30,DarkGreen); + tt.fillrect(xx+25,yy-30,xx+30,yy+30,Maroon); + tt.fillrect(xx+25,yy-30,xx+40,yy-25,Maroon); + tt.fillrect(xx+25,yy+25,xx+75,yy+30,Maroon); +} + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +// The following draws the tube object in all for rotations, based on CurRot + +void DrawTube() { + CurRot = 2; + DrawTubeX(); + wait(DISP_SLOW); + wait(DISP_SLOW); + for(CurRot = 0 ; CurRot < 4 ; CurRot++) { + tt.cls(); + DrawTubeX(); + wait(DISP_FAST); +// wait(DISP_SLOW); + } +} + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +// Routine used to change the pen's color palette on the TFT + +void TftNewColor() { +// point p; + TftDrawColor++; + if(TftDrawColor >= 17) { + TftDrawColor = 0; + } + switch (TftDrawColor) { + case 0: { + tt.fillrect(5,35,30,60,White); + PenColor = White; + } + break; + case 1: { + tt.fillrect(5,35,30,60,Orange); + PenColor = Orange; + } + break; + case 2: { + tt.fillrect(5,35,30,60,Yellow); + PenColor = Yellow; + } + break; + case 3: { + tt.fillrect(5,35,30,60,Magenta); + PenColor = 0xF81F; + } + break; + case 4: { + tt.fillrect(5,35,30,60,Red); + PenColor = 0xF800; + } + break; + case 5: { + tt.fillrect(5,35,30,60,Cyan); + PenColor = 0x07FF; + } + break; + case 6: { + tt.fillrect(5,35,30,60,Green); + PenColor = 0x07E0; + } + break; + case 7: { + tt.fillrect(5,35,30,60,Blue); + PenColor = 0x001F; + } + break; + case 8: { + tt.fillrect(5,35,30,60,LightGrey); + PenColor = 0x7BEF; + } + break; + case 9: { + tt.fillrect(5,35,30,60,DarkGrey); + PenColor = 0xC618; + } + break; + case 10: { + tt.fillrect(5,35,30,60,Olive); + PenColor = 0x7BE0; + } + break; + case 11: { + tt.fillrect(5,35,30,60,Purple); + PenColor = 0x780F; + } + break; + case 12: { + tt.fillrect(5,35,30,60,Maroon); + PenColor = 0x7800; + } + break; + case 13: { + tt.fillrect(5,35,30,60,DarkCyan); + PenColor = 0x03EF; + } + break; + case 14: { + tt.fillrect(5,35,30,60,DarkGreen); + PenColor = 0x03E0; + } + break; + case 15: { + tt.fillrect(5,35,30,60,Navy); + PenColor = 0x000F; + } + break; + case 16: { + tt.fillrect(5,35,30,60,Black); + tt.rect(5,35,30,60,White); + PenColor = 0x0000; + } + break; + + } // end of switch + +//wait for no-touch + point p; + do { + p = tt.get_touch(); + tt.is_touched(p); +// pc.printf("pr1: %d %d\n", p.x, p.y); + } + while (p.y > 0x2000 | p.x > 0x2000); // { // wait for no touch +} + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +// Find the "secret spot" on the TFT, RESET the mbed + +void KillMbed() { + // text LCD + lcdt.cls(); // clear out text LCD + lcdt.locate(0,0); // column(0-15), row(0-1) + lcdt.printf("Pen select\n"); + lcdt.printf("resetting mbed!!"); + // CRT + pc.printf("### Pen detected reset area. Resetting mbed!!!! ###\n"); + + //wait for no-touch + point p; + do { + p = tt.get_touch(); + tt.is_touched(p); + } + while (p.y > 0x2000 | p.x > 0x2000); // { // wait for no touch + + // TFT LCD + tt.cls(); + tt.foreground(Yellow); + tt.set_orientation(1); + tt.set_font((unsigned char*) Book_Antiqua19x19); + tt.locate(2,5); // x,y + tt.printf("### Reset mbed ###"); + + wait(DISP_SLOW); + wait(DISP_SLOW); + mbed_reset(); +} + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +// This routing changes the "width" or "fatness" of the drawing pen on the TFT + +void TftNewPenSize() { + PenWidth++; + if(PenWidth > 8) { + PenWidth = 1; + } + tt.foreground(Yellow); // set chars to white + tt.set_orientation(0); + tt.locate(13,1); + tt.printf("%d", PenWidth); + tt.set_orientation(1); + tt.circle(16,80,10, Blue); + tt.foreground(PenColor); + +//wait for no-touch + point p; + do { + p = tt.get_touch(); + tt.is_touched(p); +// pc.printf("pr1: %d %d\n", p.x, p.y); + } + while (p.y > 0x2000 | p.x > 0x2000); // { // wait for no touch +} + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +//A generic QUICK BROWN FOX routine to check out various fonts + +void QuickBrownFox() { + tt.foreground(Yellow); // set chars to white + tt.cls(); // clear the screen +// tt.set_font((unsigned char*) Arial12x12); // select the font +// tt.set_font((unsigned char*) Courier10x13); // select the font +// tt.set_font((unsigned char*) Verdana22x21); // select the font +// tt.set_font((unsigned char*) Book_Antiqua19x19); // select the font + tt.set_orientation(1); + tt.locate(0,0); + tt.printf("THE QUICK BROWN FOX"); + tt.locate(0,1); + tt.printf("JUMPED OVER THE LAZY"); + tt.locate(0,2); + tt.printf("DOG'S BACK 0123456789"); + tt.locate(0,3); + tt.printf("!@#$%^&*(){|}[\]:;<,./?>"); + tt.locate(0,5); + tt.printf("the quick brown fox"); + tt.locate(0,6); + tt.printf("jumped over the lazy "); + tt.locate(0,7); + tt.printf("dog's back \n"); + tt.foreground(White); // set chars to white + tt.set_orientation(1); +} + +/*--------------------------------------------------------------------------------------------------------------------------------------*/ +int main() { + pc.baud(921600); //set up USB serial speed +// time_t ctTime; + ctTime = time(NULL); + StartTime = ctTime; //get time we started up + ctTime = ctTime + ((TZone+DST)*3600); //timezone and dst offsets + RTCstep = ctTime; + + pc.printf("\n\n"); + pc.printf("-------------------------------------------------------------------\n"); + pc.printf("TFT and Touch Screen Test Routines Rev: %d K Braun\n", revision); + TextLCDTitle(); + pc.printf("Graphic elements/text displayed\n"); +// point p; + +// tt.claim(stdout); // send stdout to the TFT display + tt.background(Black); // set background to black + tt.foreground(Yellow); // set chars to white + tt.cls(); // clear the screen + tt.set_font((unsigned char*) Arial12x12); // select the font + tt.set_orientation(0); + tt.locate(0,0); + tt.printf(" Revision: %d", revision); + + tt.foreground(White); // set chars to white + tt.set_orientation(1); + + tt.set_font((unsigned char*) Arial24x23); + tt.locate(3,9); // x,y + tt.printf("Graphic Test"); +// some graphics + tt.line(0,0,100,200,Green); + tt.rect(20,40,70,90,Red); + tt.fillrect(240,25,260,70,Blue); + tt.fillrect(265,25,285,70,Blue); + tt.circle(30,180,10,Purple); + tt.circle(55,175,10,DarkGreen); + tt.circle(40,155,10,DarkCyan); + DrawTube(); + CurRot = 1; + tt.cls(); + DrawTubeX(); + PosX = 40; + PosY = 50; + DrawTubeX(); + PosX = 190; + PosY = 50; + DrawTubeX(); + PosX = 40; + PosY = 280; + DrawTubeX(); + PosX = 190; + PosY = 280; + DrawTubeX(); + wait(DISP_SLOW); + wait(DISP_SLOW); + +// Check if we can use modify the http name of the mbed + FILE *fp = fopen("/local/whoami.ini", "r"); + if (fp == NULL) { + pc.printf("*** No /local/whoami.ini file, defaulting to: %s\n",hostname); + } else { + char localbuf[64]; + hostname = fgets(localbuf, sizeof(localbuf)-1, fp); + pc.printf("Found /local/whoami.ini file. my name is: %s\n",hostname); + fclose(fp); + } + +// Check for main ini file, create if does not exist + FILE *fpi = fopen("/local/tft.ini", "r"); + if (fpi == NULL) { + InitIniFile(); + pc.printf("*** rebooting after file creation...."); + wait(2.0); + mbed_reset(); + } else { + pc.printf("Found /local/tft.ini file...\n"); + fclose(fpi); + SNTPReadIniFile("/local/tft.ini"); + } + +/*See if INDEX.HTM can be created on SD micro drive */ +// +//NOTE: mbed hangs if no SD card installed - need to fix!!!!!! +// + lcdt.cls(); //init the LCD + lcdt.locate(0,0); //column(0-15), row(0-1) + lcdt.printf("SD Card Missing!"); //---in case SD drive hangs forever--- + + if (gDebug > 3) { +// char *WriteTest = "This is a Test!!!"; + fp = fopen("/sd/INDEX.HTM", "w+"); + if (fp == NULL) { + pc.printf("*** Cannot create INDEX.HTM file\n"); + } else { +// char localbuf[32]; +// localbuf = WriteTest; + fprintf(fp, "This is a Test!!!\n"); + pc.printf("Creating /sd/INDEX.HTM file\n"); + fclose(fp); + } + } + + fp = fopen("/sd/index.htm", "r"); + if (fp == NULL) { + use_sd = false; + if (gDebug) pc.printf("*** Found SD card, -no- INDEX.HTM file\n"); + } else { + use_sd = true; + fclose(fp); + if (gDebug) pc.printf("Found SD card with INDEX.HTM file\n"); + } + + lcdt.cls(); + +// if (0 != SNTPReadIniFile("/sd/sntp.ini") ) +// SNTPReadIniFile("/local/sntp.ini"); +// SNTPWriteIniFile(stdout); +// fclose(fpi); +// lcdt.cls(); //init the LCD + if ((use_sd == true) && (gDebug > 3)) pc.printf(" "); // to get rid of use_sd "never used" warning + +//Check RTC + ctTime = time(NULL); + ctTime = ctTime + ((TZone+DST)*3600); //timezone and dst offsets + if (RTCstep == ctTime) { + pc.printf("*** RTC stopped, initializing the RTC. !!CHECK BATTERY!!\n"); + pc.printf("*** Note: Time is incorrect, needs to be updated!!!\n"); + set_time(1296473737); + lcdt.cls(); //init the LCD + lcdt.locate(0,0); //column(0-15), row(0-1) + lcdt.printf("RTC Stopped!!"); + wait(DISP_SLOW); + + // strftime(timebuf, 32, "%H:%M\n", localtime(&ctTime)); + } else { + lcdt.cls(); //init the LCD + lcdt.locate(0,0); //column(0-15), row(0-1) + lcdt.printf("RTC running"); + pc.printf("RTC running\n"); + } + tt.cls(); + if(TftCalib == 1) { + lcdt.locate(0,1); //column(0-15), row(0-1) + lcdt.printf("Cal t-pad..."); + pc.printf("Calibrating touchpad....."); + tt.calibrate(); // calibrate the touch + pc.printf(" Updating /local/tft.ini file....."); + TftCalib = 0; //set -no cal reqd- flag + pp_txm = tt.getCalDataX(); //get calibration values + pp_tym = tt.getCalDataY(); + pp_txoff = tt.getCalOffX(); + pp_tyoff = tt.getCalOffY(); + InitIniFile(); //save in ini file + pc.printf(" done\n"); + pc.printf("New Touch Cal Values:\n- Touch Cal X Base %d\n- Touch Cal Y Base %d\n- Touch Cal X Offset %d\n- Touch Cal Y Offset %d\n" + , pp_txm, pp_tym, pp_txoff, pp_tyoff); + lcdt.cls(); + } else { + pc.printf("No touchpad cal needed\n"); + tt.setCalDataX(pp_txm); //set calibration values + tt.setCalDataY(pp_tym); + tt.setCalOffX(pp_txoff); + tt.setCalOffY(pp_tyoff); + } + + TextLCDTitle(); + + tt.cls(); + tt.foreground(Yellow); // set chars to white +// tt.cls(); // clear the screen +// tt.set_font((unsigned char*) Arial12x12); // select the font + tt.set_font((unsigned char*) Courier10x13); // select the font +// tt.set_font((unsigned char*) Verdana22x21); // select the font +// tt.set_font((unsigned char*) Book_Antiqua19x19); // select the font + pc.printf("Quick Brown Fox displayed\n"); + QuickBrownFox(); +// wait(DISP_SLOW); +// wait(DISP_SLOW); +// pc.printf("(before) ctTime %d\n", ctTime); + +//Set up Ethernet + EthernetErr ethErr; + pc.printf("Starting Ethernet...\n"); + ethErr = eth.setup(); + if(ethErr) { + pc.printf("*** No Ethernet Link!!!\n"); + } else { + IpAddr ethIp = eth.getIp(); + pc.printf("IP address : %d.%d.%d.%d\n", ethIp[0], ethIp[1], ethIp[2], ethIp[3]); + lcdt.cls(); + lcdt.printf("%d.%d.%d.%d\n", ethIp[0], ethIp[1], ethIp[2], ethIp[3]); + lcdt.locate(0,1); //column(0-15), row(0-1) + lcdt.printf("tft%d", revision); + SetEthTime(); + } + InitTft(); + point p; + int LedDelay = 0; + int xTime = ctTime; +// pc.printf("RtcColor %s\n", RtcColor); + pc.printf("Ready...\n"); +// pc.printf("(after) ctTime %d\ xTime %d\n", ctTime, xTime); + while (1) { + ctTime = time(NULL); + SysUpTime = ctTime - StartTime; //number of seconds we've been alive +// if(gDebug > 1) pc.printf("cT: %d sT: %d suT: %d\n", ctTime, StartTime, SysUpTime); + ctTime = ctTime + ((TZone + DST) * 3600); //timezone and dst offsets + strftime(timebuf, 32, "%H:%M:%S", localtime(&ctTime)); + if(xTime != ctTime) { + xTime = ctTime; + if(gDebug > 1) pc.printf("cT: %d sT: %d suT: %d\n", ctTime, StartTime, SysUpTime); + lcdt.locate(8,1); //column(0-15), row(0-1) + lcdt.printf("%s\n", timebuf); + lcdt.locate(15,1); + + tt.foreground (Cyan); + tt.set_orientation(0); + tt.locate(14,25); //25 + tt.printf("%s", timebuf ); + strftime(timebuf, 32, "%m/%d/%y", localtime(&ctTime)); + tt.locate(14,24); //24 + tt.printf("%s", timebuf ); + } +// 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; + } + } + } + tt.set_orientation(1); + p = tt.get_touch(); // read analog pos. + if (tt.is_touched(p)) { // test if touched +// pc.printf("p1: %d %d\n", p.x, p.y); + +// inside the red box tt.rect(5,5,30,30,Red); + if((p.x >= 10000) && (p.x <= 15500) && (p.y >= 10500) && (p.y <= 16300)) { // clear out TFT LCD red box + InitTft(); + } else if((p.x >= 10000) && (p.x <= 15500) && (p.y >= 16400) && (p.y <= 21300)) { // pen color select colored box + TftNewColor(); + } else if((p.x >= 10000) && (p.x <= 15500) && (p.y >= 21400) && (p.y <= 29000)) { // pen width select blue circle + TftNewPenSize(); + } else if((p.x >= 10000) && (p.x <= 12000) && (p.y >= 50000) && (p.y <= 55000)) { // hidden system-reboot near "TFT" text + KillMbed(); + } else { + p = tt.to_pixel(p); // convert to pixel pos + tt.fillcircle(p.x,p.y,PenWidth,PenColor); // print a blue dot on the screen + } +// pc.printf("p2: %d\n", p); + } + } +} +