Dual CANbus monitor and instrumentation cluster

Dependencies:   SPI_TFTx2 TFT_fonts TOUCH_TFTx2 beep mbed

Fork of CANary by Tick Tock

Files at this revision

API Documentation at this revision

Comitter:
TickTock
Date:
Sat Jun 15 12:23:36 2013 +0000
Parent:
96:a6c6a6fd1d28
Child:
99:c05abf8e1cdc
Commit message:
.

Changed in this revision

displayModes.cpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
utility.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/displayModes.cpp	Fri May 03 14:31:07 2013 +0000
+++ b/displayModes.cpp	Sat Jun 15 12:23:36 2013 +0000
@@ -55,19 +55,20 @@
 }
 
 void printLog (bool force, bool showButtons){
-    static unsigned char lastDisplayLoc = 0;
-    if(force||displayLoc!=lastDisplayLoc){ //only update if changed
+    static unsigned char lastldl = 0;
+    unsigned char ldl=displayLoc;
+    if(force||ldl!=lastldl){ //only update if changed
         tt.foreground(Amber);
         tt.background(Black);
         tt.cls();
         tt.locate(0,6);
         tt.set_font((unsigned char*) Arial12x12);
         for(int i=0; i<19; i++){
-            printf("%s",displayLog[displayLoc]);
-            displayLoc=displayLoc>17?0:displayLoc+1;
+            printf("%s",displayLog[ldl]);
+            ldl=ldl>17?0:ldl+1;
         }
     }
-    lastDisplayLoc=displayLoc;
+    lastldl=ldl;
 }
 
 void mainDisplay (bool force, bool showButtons){
@@ -321,6 +322,7 @@
 void cpData(bool force, bool showButtons){
     short unsigned max, min, jv, i, bd;
     unsigned avg;
+    static char step=0; // counter to allow incremental update
     if(force){
         tt.foreground(White);
         tt.background(Navy);
@@ -340,33 +342,44 @@
         } else { // Only compute judgement value if min cellpair meets <= 3712mV requirement
             jv=0;
         }
-        tt.cls();
-        tt.locate(0,6);
-        // BatDataBaseG4 * 7 = 224
-        printf(" MAX  MIN  AVG CVLI T1  T2  T3  T4\n %04d %04d %04d %04d %02dC %02dC %02dC %02dC\n\n",
-                    max,min,avg,jv, battData[224+5],battData[224+8],battData[224+11],battData[224+14]);
-        tt.locate(0,36);
-        for(i=0; i<16; i++){
-            printf("%02d-%02d : %04d %04d %04d %04d %04d %04d\n",
-                i*6+1,i*6+6,
-                (battData[i*12+3]<<8)+battData[i*12+4],(battData[i*12+5]<<8)+battData[i*12+6],
-                (battData[i*12+7]<<8)+battData[i*12+8],(battData[i*12+9]<<8)+battData[i*12+10],
-                (battData[i*12+11]<<8)+battData[i*12+12],(battData[i*12+13]<<8)+battData[i*12+14]);
+        switch(step){
+            case 0:
+                tt.cls();
+                showCP=true;
+                break;
+            case 1:
+                tt.locate(0,6);
+                // BatDataBaseG4 * 7 = 224
+                printf(" MAX  MIN  AVG CVLI T1  T2  T3  T4\n %04d %04d %04d %04d %02dC %02dC %02dC %02dC\n\n",
+                            max,min,avg,jv, battData[224+5],battData[224+8],battData[224+11],battData[224+14]);
+                tt.rect(8+0*41,16,40+0*41,28,Green);
+                tt.rect(8+1*41,16,40+1*41,28,Yellow);
+                //tt.rect(8+2*41,16,40+2*41,28,White);
+                tt.rect(8+3*41,16,40+3*41,28,Red);
+                break;
+            default:
+                tt.locate(0,36+(step-2)*48);
+                for(i=(step-2)*4; i<(step-1)*4; i++){
+                    printf("%02d-%02d : %04d %04d %04d %04d %04d %04d\n",
+                        i*6+1,i*6+6,
+                        (battData[i*12+3]<<8)+battData[i*12+4],(battData[i*12+5]<<8)+battData[i*12+6],
+                        (battData[i*12+7]<<8)+battData[i*12+8],(battData[i*12+9]<<8)+battData[i*12+10],
+                        (battData[i*12+11]<<8)+battData[i*12+12],(battData[i*12+13]<<8)+battData[i*12+14]);
+                }
+                for(i=(step-2)*24; i<(step-1)*24; i++){
+                    bd=(battData[i*2+3]<<8)+battData[i*2+4];
+                    if(bd>0){
+                        if(bd==max) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,Green);
+                        //if(bd==avg) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,White);
+                        if(bd==min) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,Yellow);
+                        if(bd<jv) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,Red);
+                    }
+                }
         }
-        tt.rect(8+0*41,16,40+0*41,28,Green);
-        tt.rect(8+1*41,16,40+1*41,28,Yellow);
-        //tt.rect(8+2*41,16,40+2*41,28,White);
-        tt.rect(8+3*41,16,40+3*41,28,Red);
-        for(i=0; i<96; i++){
-            bd=(battData[i*2+3]<<8)+battData[i*2+4];
-            if(bd>0){
-                if(bd==max) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,Green);
-                //if(bd==avg) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,White);
-                if(bd==min) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,Yellow);
-                if(bd<jv) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,Red);
-            }
+        step=step<5?step+1:0;
+        if(step==0){
+            showCP=false;
         }
-        showCP=false;
     }
     if((sMode==1)&&showButtons){
         tt.foreground(Yellow);
@@ -806,9 +819,8 @@
     tt.background(Navy);
     tt.foreground(Yellow);
     if(force){
+        tt.set_font((unsigned char*) Arial12x12);   
         tt.cls();
-        toVal=33;
-
         x=50+0*6;
         tt.locate(x-10,226);
         printf("sec\n");  
@@ -833,26 +845,30 @@
         //tt.locate(x-10,226);
         //printf("year\n");  
         //tt.line(x,10,x,220,DarkGrey);
+        toVal=33;
     } else {
-        toVal=18;// no need to constantly update the long tc values
+        toVal=24;// no need to constantly update the long tc values
     }
     if(force||lgids!=gids){ // update Y axis when kWh changes
-        tt.set_font((unsigned char*) Arial12x12);
-        for(i=0;i<10;i++){
-            y=200-i*20;
-            tt.locate(10,y-8);
+        //tt.set_font((unsigned char*) Arial12x12);
+        tt.set_font((unsigned char*) Arial24x23);
+        //for(i=0;i<10;i++){
+            //y=200-i*20;
+        for(i=3;i<8;i++){
+            y=200-(i-3)*40;
+            tt.locate(0,y-8);
             if (showMiles){
-                printf("%3.0f\n",i*((float)(gids-5)*.075));
+                printf("%2.0f  \n",i*((float)(gids-5)*.075));
             }else{
                 printf("%d.0\n",i);
             }
-            tt.line(40,y,toVal*6+56,y,DarkGrey);
+            tt.line(48,y,toVal*6+56,y,DarkGrey);
         }
         lgids=gids;    
     }
     if(updateDTE||force){
-        for(i=0;i<10;i++){
-            y=200-i*20;
+        for(i=3;i<8;i++){
+            y=200-(i-3)*40;
             tt.line(40,y,158,y,DarkGrey);
         }
 
@@ -883,17 +899,16 @@
                 tt.locate(151,8);
                 printf("    %2.1f\n",miles);
             }
+            tt.foreground(Cyan);
+            tt.set_font((unsigned char*) Arial24x23);
+            tt.locate(198,70);
+            printf("%3.1f \n",mpkWh[dtePeriod]);
         } else {
-            tt.locate(180,10);
+            tt.locate(200,10);
             printf("%3.1f \n",mpkWh[dtePeriod]);
         }
         lx=50;
-        ly=mpkWh[0]*20;
-        if(ly<200) {
-            ly=200-ly;
-        }else{
-            ly=0;
-        }
+        ly=mpkWh[0]*40;
         if(dtePeriod==0){
             radius=6;
             color=Yellow;
@@ -901,17 +916,20 @@
             radius=2;
             color=Green;
         }
+        if(ly<100){
+            ly=220;
+            color=Red;
+        }else if(ly<320) {
+            ly=320-ly;
+        }else{
+            ly=0;
+        }
         tt.fillcircle(lx,leff[0],radius,Navy);
         tt.fillcircle(lx,ly,radius,color);
 
         for(i=1;i<toVal;i++){
             x=50+i*6;
-            y=mpkWh[i]*20;
-            if(y<200) {
-                y=200-y;
-            }else{
-                y=0;
-            }
+            y=mpkWh[i]*40;
             if(i==dtePeriod){
                 radius=6;
                 color=Yellow;
@@ -919,6 +937,14 @@
                 radius=2;
                 color=Green;
             }
+            if(y<100){
+                y=220;
+                color=Red;
+            }else if(y<320) {
+                y=320-y;
+            }else{
+                y=0;
+            }
             tt.fillcircle(x,leff[i],radius,Navy);
             tt.line(x-6,leff[i-1],x,leff[i],Navy);
             leff[i-1]=ly;
--- a/main.cpp	Fri May 03 14:31:07 2013 +0000
+++ b/main.cpp	Sat Jun 15 12:23:36 2013 +0000
@@ -8,7 +8,8 @@
 // * Add 50% charge option
 // * Tire Pressure Sensor display
 // * Fix bug in playback while connected to canbus (hangs)
-// * Add temperature to Main screen
+// * Fix no power displayed while charging
+// * Force regen display to zero when in neutral
 
 #include "mbed.h"
 #include "CAN.h"
@@ -51,15 +52,15 @@
 // gg - revStr is used in 2 places
 // gg - and is easy to edit here
 // gg - added ZeroSecTick and revStr
-char revStr[7] = "96";
+char revStr[7] = "97";
 
 bool debugMode = false;
 bool logEn = false, logOpen = false; 
 bool yesBattLog = false ; // gg - Batt Log
 unsigned char tNavRow = 3 ; // gg - 4x4 touch
 
-FILE *cfile;
-FILE *file;
+FILE *hfile; // config file
+FILE *lfile; // log file
 char fileName[35] = "" ;
 char writeBuffer[maxBufLen][13] __attribute__ ((section("AHBSRAM1"))); // buffer for USB write
 char indexLastMsg[0x800]={0}; // index table for last message
@@ -173,8 +174,8 @@
     if (cfile!=NULL){ //found a new binary on the thumbdrive so copy it over
         sprintf(sTemp,"New binary found.\n");
         printMsg(sTemp); // new binary
-        file = fopen("/local/CANary.bin", "wb");
-        if (file==NULL){ //failed to open destination
+        lfile = fopen("/local/CANary.bin", "wb");
+        if (lfile==NULL){ //failed to open destination
             sprintf(sTemp,"Unable to open destination file.\n");
             printMsg(sTemp); // cannot open CANary.bin
         } else {
@@ -188,14 +189,14 @@
             printf("CANary will reset when complete.\n");
             wait(1); //Wait 1 sec for display DMA to finish before writing file
             while ( int size = fread( writeBuffer, sizeof(char), maxBufLen*13, cfile )){
-                fwrite( writeBuffer, sizeof(char), size, file );
+                fwrite( writeBuffer, sizeof(char), size, lfile );
                 led4=led3;
                 led3=led2;
                 led2=led1;
                 led1=!led4;
             }
         fclose(cfile);
-        fclose(file);
+        fclose(lfile);
         remove("/usb/CANary.bin"); // delete original
         mbed_reset(); //restart
         }
@@ -204,15 +205,15 @@
     secsNoMsg = 0;
 
     //read efficiency history data
-    cfile = fopen("/local/ehist.cny", "r");
-    if (cfile!=NULL){ // found a efficiency history file
+    hfile = fopen("/local/ehist.cny", "r");
+    if (hfile!=NULL){ // found a efficiency history file
         for(i=0;i<39;i++){
-            if(!feof(cfile)){
-                fscanf(cfile,"%f %f\r\n",&mph[i],&kW[i]);
+            if(!feof(hfile)){
+                fscanf(hfile,"%f %f\r\n",&mph[i],&kW[i]);
                 mpkWh[i]=mph[i]/kW[i];
             }
         }
-        fclose(cfile);
+        fclose(hfile);
         sprintf(sTemp,"History Loaded.\n");
         printMsg(sTemp); // History loaded
     } else { // create initial file
@@ -249,10 +250,10 @@
                 strftime(fileName, 32, "/usb/%m%d%H%M.alc", &t); //mmddhhmm.alc
                 //sprintf(sTemp,"Using file %s\n",fileName);
                 //printMsg(sTemp); // using alc file ...
-                file = fopen(fileName, "ab");
+                lfile = fopen(fileName, "ab");
                 lastDMode[0]=99;//force refresh
                 lastDMode[1]=99;//force refresh
-                if(file==NULL){
+                if(lfile==NULL){
                     sprintf(sTemp,"\nUnable to open %s\n\n\n\n",fileName);
                     printMsg(sTemp); // cannot open alc file
                     logEn=false;
@@ -275,7 +276,7 @@
             pointerSep=(writePointer+maxBufLen-readPointer)%maxBufLen;
             if (pointerSep>(maxBufLen/16)||canIdle||!logEn) {
                 // Dump buffer if > 1/16 full or canbus has stopped
-                if (file == NULL) {
+                if (lfile == NULL) {
                     logOpen = false;
                     sprintf(sTemp,"Failed to append log file.\n");
                     printMsg(sTemp); // failed to append 
@@ -284,7 +285,7 @@
                 } else {
                     while (readPointer != writePointer) {
                         for (j = 0; j<13; j++){
-                            fprintf(file,"%c",writeBuffer[readPointer][j]);
+                            fprintf(lfile,"%c",writeBuffer[readPointer][j]);
                         }
                         if(++readPointer >= maxBufLen){
                             readPointer=0;
@@ -296,7 +297,7 @@
             if (!logEn) {
                 sprintf(sTemp,"Stopping Can Log %s\n",fileName);
                 printMsg(sTemp); // stopping alc log file 
-                fclose(file);
+                fclose(lfile);
                 logOpen=false;
                 pointerSep=0;
             }
@@ -306,7 +307,7 @@
                 autoPoll.detach();
             }
             if (logOpen){
-                fclose(file);
+                fclose(lfile);
             } // if (logOpen)*/
             seconds = time(NULL);
             t = *localtime(&seconds) ;
@@ -327,6 +328,8 @@
                 //__wfi(); // freeze CPU and wait for interrupt (from canbus or touch)
                 Sleep();
             }
+            lastDMode[0]=99;
+            lastDMode[1]=99;
             secsNoTouch=2;
             canIdle=secsNoMsg>canTimeout;
             dled=0.8; // turn on display LED
@@ -338,7 +341,7 @@
                 logOpen = false; // Start new file if asleep for more than 30 minutes
                 if (secsNoTouch>100) secsNoTouch = 100; // also mostly reset user Idle counter
             } else if (logOpen){ // insert timestamp on each wake if logging enabled (disabled for now)
-                file = fopen(fileName, "ab");
+                lfile = fopen(fileName, "ab");
                 logEvent("WakingUp"); // gg - use messeges
                 logTS(); // Date-Time at wakeup
             }
@@ -538,9 +541,9 @@
                                     // Start/stop playback
                                     if(!playbackOpen){
                                         if(!logOpen){
-                                            file = fopen("/usb/playback.alc", "rb");                                          
+                                            lfile = fopen("/usb/playback.alc", "rb");                                          
                                             lastDMode[whichTouched]=99;//force refresh
-                                            if(file==NULL){
+                                            if(lfile==NULL){
                                                 sprintf(sTemp,"Unable to open /usb/playback.alc\n");
                                                 printMsg(sTemp); // no playback.alc
                                                 spkr.beep(1000,0.25);
@@ -560,7 +563,7 @@
                                         }
                                     } else {
                                         playback.detach();
-                                        fclose(file);
+                                        fclose(lfile);
                                         playbackOpen=false;
                                         playbackEn=false;
                                         can1.attach(&recieve1);// Restore CAN data recieve
@@ -684,19 +687,16 @@
             accOn=(accV>5)?true:false;
             if(laccOn&&!accOn){ // Car turned off
                 //write efficiency history data
-                cfile = fopen("/local/ehist.cny", "w");
-                if (cfile!=NULL){ // found a efficiency history file
+                hfile = fopen("/local/ehist.cny", "w");
+                if (hfile!=NULL){ // found a efficiency history file
                     for(i=0;i<39;i++){
-                        fprintf(cfile,"%f %f\r\n",mph[i],kW[i]);
+                        fprintf(hfile,"%f %f\r\n",mph[i],kW[i]);
                     }
-                    fclose(cfile);
+                    fclose(hfile);
                 }
             }
             laccOn=accOn;
-            if(!accOn&&!logEn&&userIdle&&!playbackEn){
-                //sprintf(sTemp,"Display Off %4.2f\n",accV);
-                //printMsg(sTemp); // display off - for debug
-                
+            if(!accOn&&!logEn&&userIdle&&!playbackEn){             
                 dled = 0; // turn off display if car off and logging disabled and no user activity
             }else if(!headlights){
                 dled = ledHi;
@@ -736,8 +736,10 @@
                     mph[i]+=mph[0];
                     mpkWh[i]=average;
                     average=kW[i]/timeConstant[i];
-                    kW[i]-=average;
-                    kW[i]+=kW[0];
+                    if((mph[0]>0)||(kW[0]>0)){ //Not charging - so include in efficiency data
+                        kW[i]-=average;
+                        kW[i]+=kW[0];
+                    }
                     mpkWh[i]/=average;
                     if (mpkWh[i]<0) {
                         mpkWh[i]=99;// negative means inf.
@@ -753,23 +755,16 @@
 
         display=display<1?display+1:0; // toggle display
         updateDisplay(display);
-
-        /*if(pollCP){ // We do this inside main loop instead of ticker so CAN RX will not be blocked
-            sendCPreq(); // send cellpair data request.
-            wait_ms(16);
-            sendTreq(); //send temperature request
-            pollCP=false;
-        }*/
         
         if(step){ // playback
             if(playbackOpen&&playbackEn){
                 for(i=0;i<120;i++){
-                    if(!feof(file)){
-                        fscanf(file,"%5c%8c",&header,&data);
+                    if(!feof(lfile)){
+                        fscanf(lfile,"%5c%8c",&header,&data);
                         logCan(header[0],CANMessage(0x7ff&((header[4]<<8)+header[3]), data, 8)); // Playback
                     } else {
-                        fclose(file); // restart
-                        file = fopen("/usb/playback.alc", "rb");                                          
+                        fclose(lfile); // restart
+                        lfile = fopen("/usb/playback.alc", "rb");                                          
                         lastDMode[whichTouched]=99;//force refresh
                         spkr.beep(2000,0.25);
                     }
--- a/utility.cpp	Fri May 03 14:31:07 2013 +0000
+++ b/utility.cpp	Sat Jun 15 12:23:36 2013 +0000
@@ -148,7 +148,7 @@
         }
     }else{ // not debugMode - keep code short
         if(logOpen){
-            NVIC_DisableIRQ(CAN_IRQn);  // Block interrupts until write pointer assigned
+            NVIC_DisableIRQ(CAN_IRQn); // Block interrupts until write pointer assigned
             int localWritePointer = writePointer++; // create local copy to make logCan reentrant
             // note that the static variables do not prevent safe reentry
             // since they are only used for msgId<0x800 which will never interrupt
@@ -157,7 +157,7 @@
                 writePointer = 0;
                 led3 = !led3;
             }
-            NVIC_EnableIRQ(CAN_IRQn);  // Unblock interrupts once local pointer set and global pointer incremented
+            NVIC_EnableIRQ(CAN_IRQn); // Unblock interrupts once local pointer set and global pointer incremented
             ts=getTimeStamp();
             writeBuffer[localWritePointer][0]=mType;
             writeBuffer[localWritePointer][1]=(ts&0xff00)>>8;
@@ -213,28 +213,38 @@
             if(canRXmsg.data[0]<0x20){
                 if(canRXmsg.data[3]==2){//Group 2 = cellpair data
                     bdi=BatDataBaseG2; // index offset for CP data (uses 00 - 1C)
-                    sprintf(sTemp,"  Getting cell pair data\n");
-                    printMsg(sTemp);
+                    if(debugMode){
+                        sprintf(sTemp,"  Getting cell pair data\n");
+                        printMsg(sTemp);
+                    }
                     
                 }else if(canRXmsg.data[3]==4){//Group 4 = temperature data
                     bdi=BatDataBaseG4; // index offset for Temperature data (uses 20 - 22)
-                    sprintf(sTemp,"  Getting temperature data\n");
-                    printMsg(sTemp);
+                    if(debugMode){
+                        sprintf(sTemp,"  Getting temperature data\n");
+                        printMsg(sTemp);
+                    }
                     
                 }else if(canRXmsg.data[3]==1){//Group 1 data
                     bdi=BatDataBaseG1; // index offset for Group 1 data (uses 20 - 22)
-                    sprintf(sTemp,"  Getting Group 1 data\n");
-                    printMsg(sTemp);
+                    if(debugMode){
+                        sprintf(sTemp,"  Getting Group 1 data\n");
+                        printMsg(sTemp);
+                    }
                     
                 }else if(canRXmsg.data[3]==3){//Group 3 data
                     bdi=BatDataBaseG3; // index offset for Group 3 data (uses 20 - 22)
-                    sprintf(sTemp,"  Getting Group 3 data\n");
-                    printMsg(sTemp);
+                    if(debugMode){
+                        sprintf(sTemp,"  Getting Group 3 data\n");
+                        printMsg(sTemp);
+                    }
                     
                 }else if(canRXmsg.data[3]==5){//Group 5 data
                     bdi=BatDataBaseG5; // index offset for Group 5 data (uses 20 - 22)
-                    sprintf(sTemp,"  Getting Group 5 data\n");
-                    printMsg(sTemp);
+                    if(debugMode){
+                        sprintf(sTemp,"  Getting Group 5 data\n");
+                        printMsg(sTemp);
+                    }
                     
                 }else bdi=0xff; // ignore other messages (for now)
                 lasti=0;
@@ -275,10 +285,10 @@
             packA -= 1; //Slight correction to value required (unique to my Leaf?)
             imWs_x4 = packV; // Volts*milliSeconds*2
             imWs_x4 *= -packA; // milliWattseconds*4
-            if (!((imotorRPM<2)&&(imWs_x4<0))){ //Ignore if charging from wall
+            //if (!((imotorRPM<2)&&(imWs_x4<0))){ //Ignore if charging from wall
                 mWs_x4 += imWs_x4; // total mWs_x4
                 numWsamples++;
-            }
+            //}
         }else if((mType==1)&&(canRXmsg.id==0x1da)){ //Motor Speed
             imotorRPM=((canRXmsg.data[4]<<8)|(canRXmsg.data[5]));
             if(imotorRPM<0){ // take absolute value
@@ -372,9 +382,9 @@
 }
 
 void autoPollISR(){
-    char sTemp[40]; // just for debug
-    sprintf(sTemp,"Requesting cp data\n"); // just for debug
-    printMsg(sTemp); // just for debug
+    //char sTemp[40]; // just for debug
+    //sprintf(sTemp,"Requesting cp data\n"); // just for debug
+    //printMsg(sTemp); // just for debug
     reqMsgCnt = 0; //reset message counter
     msgReq.attach(&sendReq,0.015);
 }
@@ -419,7 +429,6 @@
 void saveConfig(){
     FILE *cfile;
     cfile = fopen("/local/config.txt", "w");
-    //fprintf(cfile,"format 3\r\n");
     fprintf(cfile,"format 4\r\n");
     fprintf(cfile,"x0_off %d\r\n",tt.x0_off);
     fprintf(cfile,"y0_off %d\r\n",tt.y0_off);
@@ -621,3 +630,4 @@
     showCP=true;
 }
 
+