Dual CANbus monitor and instrumentation cluster supporting ILI9341 display controller

Dependencies:   SPI_TFTx2_ILI9341 TOUCH_TFTx2_ILI9341 TFT_fonts mbed

Fork of CANary by Tick Tock

Revision:
7:17bf9ceaf0aa
Parent:
5:ebf6fa994b78
Child:
8:67eed72f3e10
--- a/main.cpp	Tue Feb 19 18:22:21 2013 +0000
+++ b/main.cpp	Fri Feb 22 23:24:07 2013 +0000
@@ -1,11 +1,11 @@
+#include "CANary.h"
 //To Do:
 // USB device detect
 // config file on local fs
 // user programmable message decode
 // brake trainer
-#include "CANary.h"
 // write and read the Mode Data
-LocalFileSystem local("local"); // test the local file system to write files
+LocalFileSystem local("local");
 
 // to write to USB Flash Drives, or equivalent (SD card in Reader/Writer)
 MSCFileSystem fs("fs"); // to write to a USB Flash Drive
@@ -13,7 +13,7 @@
 extern "C" void mbed_reset();
 
 time_t seconds ;
-Beep buzzer(p21);
+Beep spkr(p21);
 
 Ticker ticker;
 Timer timer;
@@ -24,31 +24,33 @@
 PwmOut dled(p24);
 
 InterruptIn touchpad(p17);
-
 CAN can1(p9, p10);      // CAN1 uses pins 9 and 10 (rx, tx) and pin 27 (rs)
-DigitalOut can1_SleepMode(p8);     // Use pin 8 to control the sleep mode of can1
+DigitalOut can1SleepMode(p8);     // Use pin 8 to control the sleep mode of can1
 CAN can2(p30, p29);     // CAN2 uses pins 30 and 29 (rx, tx) and pin 28 (rs)
-DigitalOut can2_SleepMode(p28);     // Use pin 28 to control the sleep mode of can2
-bool logOpen = false;
+DigitalOut can2SleepMode(p28);     // Use pin 28 to control the sleep mode of can2
+bool logEn = true,logOpen = false;
 FILE *rfile;
 FILE *file;
 char fileName[35] = "" ;
 char writeBuffer[maxBufLen][13]; // buffer for USB write
 char indexLastMsg[0x800]={0}; // index table for last message
 CANMessage lastMsg[100]; // table to store last message of eachtype
+unsigned char battData[192];
+unsigned char msgChanged[100]; // inidcates which bytes changed
 char c;
 volatile int writePointer = 0;
 volatile int secsNoMsg = 0, secsNoTouch = 0;
 volatile bool canIdle = false, userIdle = false;
-point lastTouch;
+bool getXY=0; //flag to read touchscreen
 char counter = 0;
-int dMode[2] = {4,2}; //display mode
-int sMode = 0; // setup mode
-int lastDMode[2]; //last screen mode
-int lastSMode = 0;
+unsigned char dMode[2] = {4,2}; //display mode
+unsigned char sMode = 0; // setup mode
+unsigned char lastDMode[2]; //last screen mode
+unsigned char lastSMode = 0;
 char displayLog[19][40];
-int displayLoc = 0;
-int indexOffset = 1;
+unsigned char displayLoc = 0;
+unsigned char indexOffset = 1;
+unsigned char bdi; //battery data index
 
 TOUCH_TFTx2 tt(p16, p17, p19, p20, p11, p12, p13, p6, p7, p5, "TFT"); // x+,x-,y+,y-,mosi, miso, sclk, cs0, cs1, reset
 
@@ -67,37 +69,76 @@
     NVIC_EnableIRQ( RTC_IRQn );
 }
 
+void touched(){
+    LPC_GPIOINT->IO2IntClr = (LPC_GPIOINT->IO2IntStatR | LPC_GPIOINT->IO2IntStatF);
+    secsNoTouch = 0;
+    getXY=true;
+}
+
 unsigned short getTimeStamp() {
-    int msec = timer.read_ms() ; // read ms from the timer
+    unsigned short msec = timer.read_ms() ; // read ms from the timer
     unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
-    int isecs = secs%60 ; // modulo 60 for 0-59 seconds from RTC
+    unsigned short isecs = secs%60 ; // modulo 60 for 0-59 seconds from RTC
     return ((isecs<<10)+msec) ; // return the two byte time stamp
 }
+
 void logCan (char mtype, CANMessage canRXmsg) {
     unsigned short ts = getTimeStamp();
     unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
-    static char ii = 0; // indexindex
-    if(canRXmsg.id>0) {
-        writeBuffer[writePointer][0]=mtype;
-        writeBuffer[writePointer][1]=((secs%60)<<2)+((ts&0x300)>>8);
-        writeBuffer[writePointer][2]=ts&0xff;
-        writeBuffer[writePointer][3]=canRXmsg.id&0xff;
-        writeBuffer[writePointer][4]=(canRXmsg.id>>8)+(canRXmsg.len<<4);
-        for (int i = 5; i<13; i++){
-            writeBuffer[writePointer][i]=canRXmsg.data[i-5];
-        }
-        if (++writePointer >= maxBufLen) {
-            writePointer = 0;
-            led4 = !led4;
-        }
-        if(indexLastMsg[canRXmsg.id]==0) { //Check if no entry
-            indexLastMsg[canRXmsg.id]=++ii; //Create entry if first message
-            if(ii>99) {
-                ii=0;
+    static unsigned char ii = 0, lastMSB = 0; // indexindex
+    unsigned char changed,i;
+    if(logOpen){
+        if(canRXmsg.id>0) {
+            writeBuffer[writePointer][0]=mtype;
+            writeBuffer[writePointer][1]=((secs%60)<<2)+((ts&0x300)>>8);
+            writeBuffer[writePointer][2]=ts&0xff;
+            writeBuffer[writePointer][3]=canRXmsg.id&0xff;
+            writeBuffer[writePointer][4]=(canRXmsg.id>>8)+(canRXmsg.len<<4);
+            for(i=5;i<13;i++){
+                writeBuffer[writePointer][i]=canRXmsg.data[i-5];
+            }
+            if (++writePointer >= maxBufLen) {
+                writePointer = 0;
+                led3 = !led3;
             }
         }
-        lastMsg[indexLastMsg[canRXmsg.id]]=canRXmsg; //Store in table
+    }//if logOpen
+    if(indexLastMsg[canRXmsg.id]==0) { //Check if no entry
+        ii=ii<99?ii+1:0;
+        indexLastMsg[canRXmsg.id]=ii; //Create entry if first message
+    }
+    if(dMode[0]==changedMode||dMode[1]==changedMode){
+        changed=msgChanged[indexLastMsg[canRXmsg.id]];
+        for(i=0;i<8;i++){
+            if(lastMsg[indexLastMsg[canRXmsg.id]].data[i]!=canRXmsg.data[i]){
+                changed |= 1<<i;
+            }
+        }
+        msgChanged[indexLastMsg[canRXmsg.id]]=changed;
     }
+    lastMsg[indexLastMsg[canRXmsg.id]]=canRXmsg; //Store in table
+    if(canRXmsg.id==0x7bb){ // is battery data?  Need to store all responses
+        i=canRXmsg.data[0]&0x0f; //lower nibble of D0 is index
+        if(lastMSB>0&i<8){ //detect rolloever and offset index appropriately
+            bdi+=0x10;
+        }
+        if(canRXmsg.data[0]&0x10>0){ //clear lastMSB if new response.  bit4 of D0 set on first message of set
+            lastMSB=0;
+        } else {
+            lastMSB=i>>3; //remember the msb to detect rollover next time around
+        }
+        i+=bdi;
+        i*=7;
+        if(i<0xc0){
+            battData[i+0]=canRXmsg.data[1];
+            battData[i+1]=canRXmsg.data[2];
+            battData[i+2]=canRXmsg.data[3];
+            battData[i+3]=canRXmsg.data[4];
+            battData[i+4]=canRXmsg.data[5];
+            battData[i+5]=canRXmsg.data[6];
+            battData[i+6]=canRXmsg.data[7];
+        }
+    }//if 0x7bb
 }
 
 void logTS () {
@@ -116,26 +157,31 @@
     logCan(0,tsMsg);
 }
 
-void send1() {
-    static char counter = 0; // use for fake data
-
-    can1.write(CANMessage(0x350, &counter, 1));
-    counter++;
-    // test sending 3 quickly
-    //can1.write(CANMessage(0x351, &counter, 1));
-    //can1.write(CANMessage(0x352, &counter, 1));
-    printf("Sending message %d   \n",counter);
-
+void sendCPreq() {
+    char data[8] = {0x02, 0x21, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff};
+    bdi = 0; //reset battery data table index
+    //can2.monitor(false); // set to active mode
+    can2SleepMode = 0; // enable TX
+    can2.write(CANMessage(0x79b, data, 8));
+    can2SleepMode = 1; // disable TX
+    data[0]=0x30; //change to request next line message
+    data[1]=0x01;
+    data[2]=0x00;
+    for(int i=0;i<29;i++){
+        wait_ms(16); //wait 16ms
+        can2SleepMode = 0; // enable TX
+        can2.write(CANMessage(0x79b, data, 8));
+        can2SleepMode = 1; // disable TX
+    }
+    //can2.monitor(true); // set to snoop mode
 }
 
-
 void recieve1() {
     CANMessage msg1;
     secsNoMsg=0; // reset deadman switch
     can1.read(msg1);
     //printf("Can1 rxd: %d\n", msg1.data[0]);
-    if(logOpen)
-        logCan(2, msg1);
+    logCan(2, msg1);
     led1 = !led1;
 }
 
@@ -144,8 +190,7 @@
     secsNoMsg=0; // reset deadman switch
     can2.read(msg2);
     //printf("Can2 rxd: %d\n", msg2.data[0]);
-    if(logOpen)
-        logCan(1, msg2);
+    logCan(1, msg2);
     led2 = !led2;
 }
 
@@ -154,16 +199,8 @@
     displayLoc=displayLoc>17?0:displayLoc+1;
 }
 
-void touched(){
-    LPC_GPIOINT->IO2IntClr = (LPC_GPIOINT->IO2IntStatR | LPC_GPIOINT->IO2IntStatF);
-    lastTouch = tt.get_touch();       
-    lastTouch = tt.to_pixel(lastTouch);          // convert to pixel pos
-    secsNoTouch = 0;
-}
-
 void printLast (bool force){
     CANMessage msg;
-    if(force) tt.cls();
     tt.locate(0,6);
     tt.foreground(Red);
     tt.background(Yellow);
@@ -175,8 +212,28 @@
     }
 }
 
+void printChanged (bool force){
+    CANMessage msg;
+    unsigned char i,j;
+    tt.locate(0,6);
+    tt.foreground(Red);
+    tt.background(Yellow);
+    if(force) tt.cls(); // Just clear screen if forced - always update display
+    tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
+    i=0;
+    j=indexOffset;
+    do{
+        j=j<99?j+1:j;
+        if(msgChanged[j]>0){
+            msg = lastMsg[j];
+            printf("%03x : %02x %02x %02x %02x %02x %02x %02x %02x    \n",msg.id,msg.data[0],msg.data[1],msg.data[2],msg.data[3],msg.data[4],msg.data[5],msg.data[6],msg.data[7]);
+            i++;
+        }// if changed
+    }while(i<19&&j<99);
+}
+
 void printLog (bool force){
-    static int lastDisplayLoc = 0;
+    static unsigned char lastDisplayLoc = 0;
     if(force||displayLoc!=lastDisplayLoc){ //only update if changed
         tt.foreground(Amber);
         tt.background(Black);
@@ -192,8 +249,8 @@
 }
 
 void dte (bool force){
-    unsigned gids, SOC, packV;
-    static unsigned lgids=0, lSOC=0, lpackV=0;
+    unsigned short gids, SOC, packV;
+    static unsigned short lgids=0, lSOC=0, lpackV=0;
     CANMessage msg;
 
     msg = lastMsg[indexLastMsg[0x5bc]]; //Get gids
@@ -305,51 +362,68 @@
             printf("%d %d    \n",targetBraking,maxTarget);
         }
         if((lr!=r||lt!=t)&&!prdata){
-            tt.fillrect(200,239-t,300,238-r,Red);
-            tt.fillrect(200,239-r,300,239,Green);
+            if(r<lr)
+                tt.fillrect(200,239-lr,300,239-r,Red);
+            else
+                tt.fillrect(200,239-r,300,239,Green);
+            if(t<lt)
+                tt.fillrect(200,239-lt,300,239-t,Navy);
+            else
+                tt.fillrect(200,239-t,300,238-r,Red);
             lt=t;
             lr=r;
         }
     }
 }
 
-void updateDisplay(){
+void cpData(bool force){
+    tt.foreground(White);
+    tt.background(Maroon);
+    tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
+    tt.cls();
+    tt.locate(0,6);
+    printf("cellpair data\n\n");
+    if(force) tt.cls(); // Just clear screen if forced - always update display
+    for(int i=0; i<16; i++){
+        printf("%02d-%02d : %04d %04d %04d %04d %04d %04d\n",i*6,i*6+5,(battData[i*12+0]<<8)+battData[i*12+1],(battData[i*12+2]<<8)+battData[i*12+3],(battData[i*12+4]<<8)+battData[i*12+5],(battData[i*12+6]<<8)+battData[i*12+7],(battData[i*12+8]<<8)+battData[i*12+9],(battData[i*12+10]<<8)+battData[i*12+11]);
+    }
+}
+
+void updateDisplay(char display){
     bool changed;
-    for (int i=0; i<2; i++){
-        changed = dMode[i]!=lastDMode[i]||(lastSMode>0&&sMode==0);
-        tt.set_display(i);
-        switch (dMode[i]) {
-            case logMode:
-                printLog(changed);
-                break;
-            case dteMode:
-                dte(changed);
-                break;
-            case brakeMode:
-                braking(changed,true);
-                break;
-            case powerMode:
-                braking(changed,false);
-                break;
-            case controlMode:
-                tt.background(Black);
-                if(dMode[i]!=lastDMode[i]||(lastSMode>0&&sMode==0)) tt.cls();
-                tt.fillcircle(100,100,15,Orange);
-                break;
-            case monitorMode:
-                printLast(changed);
-                break;
-            default:
-                tt.background(Black);
-                if(dMode[i]!=lastDMode[i]||(lastSMode>0&&sMode==0)) tt.cls();
-                break;
-        }
-        lastDMode[i]=dMode[i];
-    } // for (i=0; i<1; i++)
+    changed = dMode[display]!=lastDMode[display]||(lastSMode>0&&sMode==0);
+    tt.set_display(display);
+    switch (dMode[display]) {
+        case logMode:
+            printLog(changed);
+            break;
+        case dteMode:
+            dte(changed);
+            break;
+        case brakeMode:
+            braking(changed,true);
+            break;
+        case powerMode:
+            braking(changed,false);
+            break;
+        case monitorMode:
+            printLast(changed);
+            break;
+        case changedMode:
+            printChanged(changed);
+            break;
+        case cpMode:
+            cpData(changed);
+            break;
+        default:
+            tt.background(Black);
+            if(dMode[display]!=lastDMode[display]||(lastSMode>0&&sMode==0)) tt.cls();
+            break;
+    }
+    lastDMode[display]=dMode[display];
 
     switch (sMode) {
         case 1:
-            tt.set_display(2); // select both displays
             tt.foreground(Yellow);
             tt.background(DarkCyan);
             tt.set_font((unsigned char*) Arial12x12);
@@ -376,22 +450,27 @@
 
 int main() {
     int readPointer=0;
-    int fmon;
-    int fday;
-    int ftime;
     char sTemp[40];
     unsigned long secs;
-    bool bit = false;
-    int i,j;
-    
+    char i,j,display=0;
+    point lastTouch;    
+
+    //can1.monitor(true); // set to snoop mode
+    //can2.monitor(true); // set to snoop mode
+    //LPC_CAN1->MOD |= 1;          // Disble CAN controller
+    //LPC_CAN1->MOD |= (1 << 1);   // Put into listen only mode
+    //LPC_CAN1->MOD &= ~(1);       // Re-enable CAN controller
+    //LPC_CAN2->MOD |= 1;          // Disble CAN controller
+    //LPC_CAN2->MOD |= (1 << 1);   // Put into listen only mode
+    //LPC_CAN2->MOD &= ~(1);       // Re-enable CAN controller
     can1.frequency(500000);
     can2.frequency(500000);
-    //can1_SleepMode = 0;         // Enable TX
-    //can2_SleepMode = 0;         // Enable TX
-    can1_SleepMode = 1;         // Turn on Monitor_only Mode
-    can2_SleepMode = 1;         // Turn on Monitor_only Mode
+    //can1SleepMode = 0;         // Enable TX
+    //can2SleepMode = 0;         // Enable TX
+    can1SleepMode = 1;         // Turn on Monitor_only Mode
+    can2SleepMode = 1;         // Turn on Monitor_only Mode
     //ticker.attach(&send1, 0.5);
-    ticker.attach(&updateDisplay, 0.5); // Display messages
+    //ticker.attach(&updateDisplay, 0.5); // Display messages
     can1.attach(&recieve1);
     can2.attach(&recieve2);
     
@@ -405,11 +484,12 @@
     tt.claim(stdout);        // send stdout to the TFT display
     touchpad.rise(&touched);
     tt.wfi();               // enable interrupt on touch
-    dled = 1; // turn on display LED 80%
+    dled = 0.8; // turn on display LED 80%
     timer.start() ;
     RTC_Init(); // start the RTC Interrupts that sync the timer
     struct tm t; // pointer to a static tm structure
-
+    //NVIC_SetPriority(TIMER3_IRQn, 1); //set ticker priority
+    //NVIC_SetPriority(CAN_IRQn, 2); //higher than can (so RTC sync works)
     seconds = time(NULL);
     t = *localtime(&seconds) ;
     strftime(sTemp, 32, "%a %m/%d/%Y %X", &t);
@@ -443,96 +523,53 @@
     }
     while (true) {
         if (!logOpen) { // Open new file if one is not already open
-            seconds = time(NULL);
-            t = *localtime(&seconds) ;
-            strftime(fileName, 32, "/fs/%m%d%H%M.alc", &t); //mmddhhmm.alc
-
-            tt.set_display(0);     // select left display
-            tt.locate(0,0);
-            tt.foreground(Cyan);    // set chars to Cyan
-            //printf("Using file %s\n",fileName);
-            sprintf(sTemp,"Using file %s\n",fileName);
-            logMsg(sTemp);
-            file = fopen(fileName, "ab");
-            
-            if(file==NULL){
-                sprintf(sTemp,"\nUnable to open %s\n\n\n\n",fileName);
-                logMsg(sTemp);
-            } else {
-                logOpen = true;
-                readPointer=writePointer;
-                sprintf(sTemp,"Starting Can Log %s\n",fileName);
+            if(logEn){ //logging enable
+                seconds = time(NULL);
+                t = *localtime(&seconds) ;
+                strftime(fileName, 32, "/fs/%m%d%H%M.alc", &t); //mmddhhmm.alc
+                sprintf(sTemp,"Using file %s\n",fileName);
                 logMsg(sTemp);
-                logTS();
-                fclose(file);
-                file = fopen("/fs/loglog.txt", "a");
-                fprintf(file,"%s\r\n",fileName);
-                fclose(file);
-            }
+                file = fopen(fileName, "ab");
+                
+                if(file==NULL){
+                    sprintf(sTemp,"\nUnable to open %s\n\n\n\n",fileName);
+                    logMsg(sTemp);
+                    logEn=false;
+                    spkr.beep(1000,0.2);
+                } else {
+                    logOpen = true;
+                    readPointer=writePointer;
+                    sprintf(sTemp,"Starting Can Log %s\n",fileName);
+                    logMsg(sTemp);
+                    logTS();
+                    spkr.beep(2000,0.2);
+                }
+            }//logging enabled
         } else { // if (!logOpen)
-            if (((writePointer+maxBufLen-readPointer)%maxBufLen)>(maxBufLen/2)||canIdle) {
-                // Dump buffer if > 1/2 full, canbus has stopped, or PB1 pressed
-                if (logOpen) {
-                    file = fopen(fileName, "ab");
-                    if (file == NULL) {
-                        logOpen = false;
-                        sprintf(sTemp,"Failed to append log file.\n\n");
-                        logMsg(sTemp);
-                    } else {
-                        while (readPointer != writePointer) {
-                            for (j = 0; j<13; j++){
-                                fprintf(file,"%c",writeBuffer[readPointer][j]);
-                            }
-                            if(++readPointer >= maxBufLen)
-                                readPointer=0;
+            if (((writePointer+maxBufLen-readPointer)%maxBufLen)>(maxBufLen/16)||canIdle) {
+                // Dump buffer if > 1/16 full or canbus has stopped
+                if (file == NULL) {
+                    logOpen = false;
+                    sprintf(sTemp,"Failed to append log file.\n\n");
+                    spkr.beep(1000,0.2);
+                    logMsg(sTemp);
+                    logEn=false;
+                } else {
+                    while (readPointer != writePointer) {
+                        for (j = 0; j<13; j++){
+                            fprintf(file,"%c",writeBuffer[readPointer][j]);
                         }
-                        led3 = !led3;
-                        fclose(file);
+                        if(++readPointer >= maxBufLen)
+                            readPointer=0;
                     }
-                } // if (logOpen)
-            } // if > 1/2 full, canbus has stopped, or PB1 pressed
+                    led4 = !led4;
+                }
+            } // if > 1/16 full, canbus has stopped, or PB1 pressed
         } // if logOpen
         if (canIdle&&userIdle) { // canbus idle --> sleep to save power
             if (logOpen){
-                // First take advantage of the idle time to clear some room
-                bit = false;
-                rfile = fopen("/fs/loglog.txt", "r");
-                file = fopen("/fs/loglog.new", "w");
-                while (!feof(rfile)) {
-                    fscanf(rfile,"/fs/%2d%2d%4d.alc\r\n",&fmon,&fday,&ftime);
-                    //if ((fmon<t.tm_mon)&&(fday<=t.tm_mday)){ // Delete all files more than 1 month old
-                    if ((fmon < 12) || (t.tm_mon > 1)){
-                        fday = fday + fmon*31; //crude - february will store 3 extra days of data
-                    }
-                    if ((fday+14)<(t.tm_mday+t.tm_mon*31)){ // Delete all files more than ~14 days old
-                        bit=true;
-                        sprintf(sTemp,"/fs/%02d%02d%04d.alc",fmon,fday,ftime);
-                        if ((remove(sTemp)==NULL)) {
-                            sprintf(sTemp,"Removed file %s\n",sTemp);
-                            logMsg(sTemp);
-                        }
-                    }else{
-                        fprintf(file,"/fs/%02d%02d%04d.alc\r\n",fmon,fday,ftime);
-                    }
-                }
-                fclose (file);
-                fclose (rfile);
-                if (bit) {
-                    remove ("/fs/loglog.txt");
-                    //rename not working so do it the hard way
-                    //rename ("/fs/loglog.new","/fs/loglog.txt");
-                    rfile = fopen("/fs/loglog.new", "r");
-                    file = fopen("/fs/loglog.txt", "w");
-                    while (!feof(rfile)) {
-                        fscanf(rfile,"%s\r\n",&sTemp);
-                        fprintf(file,"%s\r\n",sTemp);
-                    }
-                    fclose (file);
-                    fclose (rfile);
-                }
-                remove ("/fs/loglog.new");                    
-                wait(5); // wait a few seconds to ensure fsRAM is done
-            } // if (logOpen)
+                fclose(file);
+            } // if (logOpen)*/
             sprintf(sTemp,"Putting uC to sleep.\n");
             logMsg(sTemp);
             //LPC_RTC->CIIR=0x00; // block RTC interrupts
@@ -545,24 +582,29 @@
             while (secsNoMsg>canTimeout && secsNoTouch>userTimeout) {
                 //DeepPowerDown();
                 tt.wfi(); //enable touchpad input
-                //__wfi(); // freeze CPU and wait for interrupt (from canbus or touch)
-                Sleep();
+                __wfi(); // freeze CPU and wait for interrupt (from canbus or touch)
+                //Sleep();
                 //DeepPowerDown();
             }
             canIdle=secsNoMsg>canTimeout;
             userIdle=userIdle>userTimeout;
-            dled=1; // turn on display LED
+            dled=0.8; // turn on display LED
             sprintf(sTemp,"Waking uC.\n");
             logMsg(sTemp);
             if (time(NULL)>(secs+1800)) {
                 logOpen = false; // Start new file if asleep for more than 30 minutes
                 if (secsNoTouch>100) secsNoTouch = 100; // also mostly reset user Idle counter
-            } else { // insert timestamp on each wake
+            } else if (false){ // insert timestamp on each wake if logging enabled (disabled for now)
+                file = fopen(fileName, "ab");
                 logTS();
             }
-            //LPC_RTC->CIIR=0x01; // re-enable RTC interrupts
         } // if idle
         
+        if(getXY){
+            lastTouch = tt.get_touch();       
+            lastTouch = tt.to_pixel(lastTouch);          // convert to pixel pos
+            getXY = false; // clear interrupt flag
+        }
         if (!userIdle) {
             if (secsNoTouch<2) {// Recently touched
                 secsNoTouch +=2; // increment to prevent double touch
@@ -572,7 +614,7 @@
                 } else {
                     i=0;
                 }
-                if (lastTouch.y>btn11y1 && lastTouch.y<btn11y2){
+                if (lastTouch.y>btn11y1 && lastTouch.y<btn11y2) {
                     if(sMode==1){
                         if (lastTouch.x>btn31x1 && lastTouch.x<btn31x2) {
                             dMode[i]=dMode[i]>0?dMode[i]-1:maxModes;
@@ -583,19 +625,32 @@
                         }
                     } else sMode=1;
                 } else {
-                    if (dMode[i]==monitorMode) {
-                        if (lastTouch.x>btn31x1 && lastTouch.x<btn31x2)
+                    if (dMode[i]==monitorMode||dMode[i]==changedMode) {
+                        if (lastTouch.x>btn31x1 && lastTouch.x<btn31x2) {
                             indexOffset=indexOffset>4?indexOffset-4:1;
-                        else if (lastTouch.x>btn33x1 && lastTouch.x<btn33x2)
+                        } else if (lastTouch.x>btn32x1 && lastTouch.x<btn32x2) {
+                            for(j=0;j<100;j++) msgChanged[j]=0; // clear changed data
+                            lastDMode[i]=99;//force refresh
+                        } else if (lastTouch.x>btn33x1 && lastTouch.x<btn33x2) {
                             indexOffset=indexOffset<77?indexOffset+4:80;
+                        }
+                    } else if (dMode[i]==cpMode) {
+                        if (lastTouch.x>btn32x1 && lastTouch.x<btn32x2)
+                            sendCPreq(); // send CP data request.
+                            wait(0.1);
+                            fclose(file); // close and reopen file to force buffer empty
+                            wait(0.1);
+                            file = fopen(fileName, "ab");
+
                     }
                 }
             }
-            secsNoMsg = 0;
+            //secsNoMsg = 0;
         } else { // userIdle
             sMode=0;
         }
-        
-        wait(0.1); // We get >2K messages per second
+        display=display<1?display+1:0; // toggle display
+        updateDisplay(display);
+        //wait(0.1); // We get >2K messages per second
     } //while (true)
 }
\ No newline at end of file