Dual CANbus monitor and instrumentation cluster. Presently tuned for the Nissan Leaf EV.

Dependencies:   SPI_TFTx2_ILI9341 TFT_fonts TOUCH_TFTx2_ILI9341 mbed

Fork of CANary_corrupt by Tick Tock

After adding the LPC1768 platform, import as a program and do not select the "update to latest revision" box

User Guide

Eagle Schematic and Board design

/media/uploads/TickTock/canaryr6.zip

/media/uploads/TickTock/canary_sch.jpg

/media/uploads/TickTock/canaryr6brd.jpg

For LCD Rev 1.01:

/media/uploads/TickTock/lcdsch.jpg

For VCD Rev 2.00:

/media/uploads/TickTock/lcdr2.jpg

Parts List

qtyinstancepart #packagesupplierDescription
1BAT3Vhttp://www.ebay.com/itm/10x-CR2032-SMD-Battery-Holder-for-CR2032-Battery-/180938057979?pt=LH_DefaultDomain_0&hash=item2a20bfa8fbLithium 2032 coin battery holder
4C1-C4ECST1DC106R6032Tantalium capacitor 10uF
3FC1-FC3ZF1-20-01-T-WThttp://www.samtec.com/cable-systems/idc-ffc/ffc/zero-insertion.aspx20 conductor 1mm pitch flex cable connector (optional)
1FJ-20-R-08.00-4http://www.samtec.com/cable-systems/idc-ffc/ffc/zero-insertion.aspx8\" 20 conductor 1mm pitch flex connector, end reversed (optional)
2H1-H4(DON'T populate H1-H4 headers - solder mbed directly)
1H5http://www.ebay.com/itm/221186042943?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1497.l26491x12 .1\" pitch header (optional)
1H62x6 .1\" pitch header (optional)
2IC1,IC2VP230LMDSOP8http://www.ebay.com/itm/130488665247?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1497.l2649canbus transciever
1IC3LM1117-5VSOT2235V regulator
5JP*2 pin .1\" jumper header
1mbedLPC1768http://www.ebay.com/itm/200830573509?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1497.l2649mbed uC
2Q1,Q22N2222SOT23General purpose NPN transistor
1R1R393M120639K resistor
1R2R103M120610K resistor
4R4-R6R102M12061K resistor
1R3R500M120650 Ohm resistor
2TR1-TR5ZJYS81R5-2PL51TG01http://www.digikey.com/product-detail/en/ZJYS81R5-2PL51T-G01/445-2223-1-ND/765232CM Choke
1Z11N5340BGC1702-15http://www.ebay.com/itm/150878122425?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1497.l26496V, 5W Zener Diode
1Z1DC-DC conveterhttp://www.ebay.com/itm/251142727849?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1497.l264912V-7V, 3W DC-DC converter
1X1USBhttp://www.ebay.com/itm/New-Vertical-USB-2-0-A-pcb-connector-socket-USB-A-Type-/300553895292?pt=LH_DefaultDomain_0&hash=item45fa687d7cvertical USB connector
2LCD0,LCD1TFThttp://www.mikroe.com/add-on-boards/display/tft-proto/320x240 LCD with touch screen
1E0Enclosurehttp://www.shapeways.com/model/1077799/canary.html?li=user-profile&materialId=63d printed enclosure

Assembly

1) LCD Displays

I found ribbon cable is a nice way to organize the wires to the displays. There are two versions of the display and each must be wired differently. The original project used HW REV. 1.01. For that version, you'll need 12 conductors and I connected them in the following order:

1LED+
2LED-
3RST
4SDI
5WR/SCLK
6CS
7X+
8X-
9Y+
10Y-
11VDD
12GND

If, instead, you have HW REV 2.0, you will need 13 conductors with the following order:

1LED+
2LED-
3RST
4SDI
5RS (SCLK)
6WR (DC)
7CS
8X+
9X-
10Y+
11Y-
12VDD
13GND

First I connected all the GND connections (2 GND & IM0, IM1, IM3 for REV1.01 or 2 GND, RD, & IM0 for REV2.00). Do not connect the bottom GND until you have the ribbon cable connected. After making all the ribbon cable connections (connecting the GND of the ribbon cable to the bottom GND pad), solder the GND bar from the previous step to the back of the bottom GND connection. Finally, make a connection from the back side 3.3V pin to IM2 for REV1.01 or to IM1,IM2,&IM3 for REV2.00. Take a break and repeat for the second display.

Examples of REV1.01 boards:

/media/uploads/TickTock/lcdtop.jpg /media/uploads/TickTock/lcdbot.jpg

Examples of REV2.00:

/media/uploads/TickTock/rev2front.jpg /media/uploads/TickTock/rev2back.jpg

Once the two displays are complete combine all wires except CS0, CS1, X+, X-, Y+, and Y-. Connect X- of the left display to X+ of the right. Similarly connect Y- of the left display to Y+ of the right. Insulate any exposed wires.

2) PCB

Refer to the schematics to place all the components on the board. If you plan to install into the CANary 3D enclosure, DO NOT install the battery holder or the socket for the mbed and, instead, connect two wires to the VB and GND pads nearby. You will have to install the battery holder against the back wall to avoid interfering with the right-hand display and the mbed will have to be directly soldered. I have not found a socket with a low enough profile to fit in the space provided (depth of enclosure is limited by the space behind the center console). Also, I recommend keeping as much lead as possible on the Zener diode (bending it as shown to clear the back wall). Although it is operating well within parameters, the Zener gets quite hot during extended operation and the leads help dissipate the heat and keep it away from the PCB and other components.Update: Several Zeners have failed resulting in damage to some users boards so I recommend using a DC-DC converter instead to bring the 12V down to 7V.

/media/uploads/TickTock/pcbtop.jpg /media/uploads/TickTock/pcbbot.jpg

Once the PCB is populated, solder the LCDs to the PCB. CS0 connects to the right display and CS1 connects to the left. /media/uploads/TickTock/brddis.jpg

Update: The Zener diodes tended to fail after a few months so I am recommending removing them and replacing with a DC-DC converter. This will run cooler and waste less energy, too. To install, remove the left display panel to gain access to the Zener. From there, the Zener can be removed and it's pads used to connect to the DC-DC converter. I recommend setting the output voltage on the bench before installing since the trim pot is tricky to reach once installed. Set it to 7V. The input can be connected to the left pad previously occupied by the zener and the output can connect to the right. GND(-) can be connected to the bottom right pad on the 2x6 header below the flex cable connector. Make sure the GND wire lies flat so it doesn't interfere with the connection of the flex cable. /media/uploads/TickTock/dcdcinst2.jpg

Once soldered in place, the DC-DC converter can easily be mounted to the back wall with double sided tape above the battery holder. /media/uploads/TickTock/dcdcinst3.jpg

3) Testing

1)First step is to buzz out all connections from the LCDs to the pins in the main board
2)Next check the touch screen connections. On the main board, place an Ohm meter across X+ and X-. You should read 700 Ohms. Repeat for Y+ and Y-. Then test the resistance from X+ to Y+. With nothing touching the screens, it should read >100K Ohms and <1K when touching either screen.
3)When all connections are checked, solder in the mbed. Download and install the touch2 program http://mbed.org/users/TickTock/code/touch2/ to test the basic operation of the mbed and touch screens.
tips:
Touch screen is sensitive - excess flux on X+,X-,Y+,Y- connection on mbed can result in flakey operation
If touch is not working, double-check the LCD0_CS and LCD1_CS are not swapped. LCD0_CS must connect to the CS of the LCD that has X- & Y- connected to the mbed. LCD1_CS must connect to the CS of the LCD that has X+ & Y+ connected to the mbed.
4)Once touch2 works, it is time to connect to the OBD connector. I highly recommend double checking all connections from the OBD to the PCB with the cable in place before connecting to the Leaf. Buzz out all the pins in the OBS to make sure none are shorting to each other, Check that the 12V goes to the Zener (and nothing else) and the switched 12V to the resistor divider (and nothing else). Test the ground connection properly connects to ground and nothing else.
5)Once you are confident there are no shorts or wrong connections from the OBD connector, take a deep breath and plug it into your leaf. Touch2 program should come up and function. Unplug and install the latest CANary firmware. If you have the REV2.00 LCD boards, you will need to edit the precompile.h file in the TOUCH_TFTx2_w9341 library and set USE_ILI9341 to 1. Test all features before installing into the enclosure (gids, cellpair, menu system, logging) since installing and removing from the enclosure is a PITA.

/media/uploads/TickTock/pcbdone.jpg /media/uploads/TickTock/functioning.jpg

4) Enclosure

The 3D printer leaves a lot of powder behind - I used a strong spray of water to get it out of all the cracks. The enclosure comes with a rather rough finish. I recommend convincing yourself you like it, then simply lightly sand then paint before assembly. Sanding is very difficult - the nylon is very nicely fused and doesn't want to sand. I tried sandblasting and that didn't work either. I had some limited success with filler and then sanding, but only on the outside - it is too difficult to sand the face. /media/uploads/TickTock/enclosure.jpg

5) Final Assembly

Make sure you are well rested with lots of patience before attempting assembly. It is a puzzle figuring out how to get both displays and the PCB in place. Enclosure was too expensive for me to keep iterating to optimize for assembly. I ended up snipping the thin display posts shorter and using various tools to push the displays into place. Also, some USB connectors are taller than others. If you have one of the taller ones, you will have to deflect the back wall a bit while inserting the PCB (being careful not to bend the housing) to get it to it's opening in the back wall. Do use a screw in the provided post to secure the PCB as USB insertion will otherwise dislodge it.

I added an additional safety line which wraps around the center post to prevent the enclosure from becoming a projectile in the event of an accident. /media/uploads/TickTock/safety.jpg Installed: /media/uploads/TickTock/installed.jpg

Committer:
TickTock
Date:
Tue Feb 19 18:19:47 2013 +0000
Revision:
5:ebf6fa994b78
Parent:
4:8d7759f4fe7a
Child:
7:17bf9ceaf0aa
Added braking screen and improved config routine;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
TickTock 4:8d7759f4fe7a 1 //To Do:
TickTock 5:ebf6fa994b78 2 // USB device detect
TickTock 5:ebf6fa994b78 3 // config file on local fs
TickTock 5:ebf6fa994b78 4 // user programmable message decode
TickTock 5:ebf6fa994b78 5 // brake trainer
TickTock 4:8d7759f4fe7a 6 #include "CANary.h"
TickTock 2:71b1999a8ea5 7 // write and read the Mode Data
TickTock 2:71b1999a8ea5 8 LocalFileSystem local("local"); // test the local file system to write files
TickTock 2:71b1999a8ea5 9
TickTock 2:71b1999a8ea5 10 // to write to USB Flash Drives, or equivalent (SD card in Reader/Writer)
TickTock 2:71b1999a8ea5 11 MSCFileSystem fs("fs"); // to write to a USB Flash Drive
TickTock 2:71b1999a8ea5 12
TickTock 2:71b1999a8ea5 13 extern "C" void mbed_reset();
TickTock 0:1596b8644523 14
TickTock 1:9dcd70c32180 15 time_t seconds ;
TickTock 0:1596b8644523 16 Beep buzzer(p21);
TickTock 1:9dcd70c32180 17
TickTock 0:1596b8644523 18 Ticker ticker;
TickTock 1:9dcd70c32180 19 Timer timer;
TickTock 0:1596b8644523 20 DigitalOut led1(LED1);
TickTock 0:1596b8644523 21 DigitalOut led2(LED2);
TickTock 0:1596b8644523 22 DigitalOut led3(LED3);
TickTock 0:1596b8644523 23 DigitalOut led4(LED4);
TickTock 4:8d7759f4fe7a 24 PwmOut dled(p24);
TickTock 4:8d7759f4fe7a 25
TickTock 4:8d7759f4fe7a 26 InterruptIn touchpad(p17);
TickTock 4:8d7759f4fe7a 27
TickTock 1:9dcd70c32180 28 CAN can1(p9, p10); // CAN1 uses pins 9 and 10 (rx, tx) and pin 27 (rs)
TickTock 1:9dcd70c32180 29 DigitalOut can1_SleepMode(p8); // Use pin 8 to control the sleep mode of can1
TickTock 1:9dcd70c32180 30 CAN can2(p30, p29); // CAN2 uses pins 30 and 29 (rx, tx) and pin 28 (rs)
TickTock 1:9dcd70c32180 31 DigitalOut can2_SleepMode(p28); // Use pin 28 to control the sleep mode of can2
TickTock 2:71b1999a8ea5 32 bool logOpen = false;
TickTock 2:71b1999a8ea5 33 FILE *rfile;
TickTock 2:71b1999a8ea5 34 FILE *file;
TickTock 2:71b1999a8ea5 35 char fileName[35] = "" ;
TickTock 3:3e879b043bc5 36 char writeBuffer[maxBufLen][13]; // buffer for USB write
TickTock 3:3e879b043bc5 37 char indexLastMsg[0x800]={0}; // index table for last message
TickTock 3:3e879b043bc5 38 CANMessage lastMsg[100]; // table to store last message of eachtype
TickTock 2:71b1999a8ea5 39 char c;
TickTock 2:71b1999a8ea5 40 volatile int writePointer = 0;
TickTock 4:8d7759f4fe7a 41 volatile int secsNoMsg = 0, secsNoTouch = 0;
TickTock 4:8d7759f4fe7a 42 volatile bool canIdle = false, userIdle = false;
TickTock 4:8d7759f4fe7a 43 point lastTouch;
TickTock 0:1596b8644523 44 char counter = 0;
TickTock 5:ebf6fa994b78 45 int dMode[2] = {4,2}; //display mode
TickTock 4:8d7759f4fe7a 46 int sMode = 0; // setup mode
TickTock 4:8d7759f4fe7a 47 int lastDMode[2]; //last screen mode
TickTock 4:8d7759f4fe7a 48 int lastSMode = 0;
TickTock 4:8d7759f4fe7a 49 char displayLog[19][40];
TickTock 4:8d7759f4fe7a 50 int displayLoc = 0;
TickTock 5:ebf6fa994b78 51 int indexOffset = 1;
TickTock 1:9dcd70c32180 52
TickTock 1:9dcd70c32180 53 TOUCH_TFTx2 tt(p16, p17, p19, p20, p11, p12, p13, p6, p7, p5, "TFT"); // x+,x-,y+,y-,mosi, miso, sclk, cs0, cs1, reset
TickTock 1:9dcd70c32180 54
TickTock 2:71b1999a8ea5 55 extern "C" void RTC_IRQHandler() {
TickTock 2:71b1999a8ea5 56 timer.reset(); // zero ms at the-seconds-tic
TickTock 4:8d7759f4fe7a 57 canIdle=(++secsNoMsg>canTimeout);
TickTock 4:8d7759f4fe7a 58 userIdle=(++secsNoTouch>userTimeout);
TickTock 2:71b1999a8ea5 59 LPC_RTC->ILR |= (1<<0); // clear interrupt to prepare for next
TickTock 1:9dcd70c32180 60 }
TickTock 1:9dcd70c32180 61
TickTock 2:71b1999a8ea5 62 extern "C" void RTC_Init (void) {
TickTock 2:71b1999a8ea5 63 LPC_RTC->ILR=0x00; // set up the RTC interrupts
TickTock 2:71b1999a8ea5 64 LPC_RTC->CIIR=0x01; // interrupts each second
TickTock 2:71b1999a8ea5 65 LPC_RTC->CCR = 0x01; // Clock enable
TickTock 2:71b1999a8ea5 66 //NVIC_SetPriority( RTC_IRQn, 10 );
TickTock 1:9dcd70c32180 67 NVIC_EnableIRQ( RTC_IRQn );
TickTock 1:9dcd70c32180 68 }
TickTock 1:9dcd70c32180 69
TickTock 2:71b1999a8ea5 70 unsigned short getTimeStamp() {
TickTock 2:71b1999a8ea5 71 int msec = timer.read_ms() ; // read ms from the timer
TickTock 2:71b1999a8ea5 72 unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
TickTock 2:71b1999a8ea5 73 int isecs = secs%60 ; // modulo 60 for 0-59 seconds from RTC
TickTock 2:71b1999a8ea5 74 return ((isecs<<10)+msec) ; // return the two byte time stamp
TickTock 2:71b1999a8ea5 75 }
TickTock 2:71b1999a8ea5 76 void logCan (char mtype, CANMessage canRXmsg) {
TickTock 2:71b1999a8ea5 77 unsigned short ts = getTimeStamp();
TickTock 2:71b1999a8ea5 78 unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
TickTock 5:ebf6fa994b78 79 static char ii = 0; // indexindex
TickTock 2:71b1999a8ea5 80 if(canRXmsg.id>0) {
TickTock 2:71b1999a8ea5 81 writeBuffer[writePointer][0]=mtype;
TickTock 2:71b1999a8ea5 82 writeBuffer[writePointer][1]=((secs%60)<<2)+((ts&0x300)>>8);
TickTock 2:71b1999a8ea5 83 writeBuffer[writePointer][2]=ts&0xff;
TickTock 2:71b1999a8ea5 84 writeBuffer[writePointer][3]=canRXmsg.id&0xff;
TickTock 2:71b1999a8ea5 85 writeBuffer[writePointer][4]=(canRXmsg.id>>8)+(canRXmsg.len<<4);
TickTock 2:71b1999a8ea5 86 for (int i = 5; i<13; i++){
TickTock 2:71b1999a8ea5 87 writeBuffer[writePointer][i]=canRXmsg.data[i-5];
TickTock 2:71b1999a8ea5 88 }
TickTock 2:71b1999a8ea5 89 if (++writePointer >= maxBufLen) {
TickTock 2:71b1999a8ea5 90 writePointer = 0;
TickTock 2:71b1999a8ea5 91 led4 = !led4;
TickTock 2:71b1999a8ea5 92 }
TickTock 3:3e879b043bc5 93 if(indexLastMsg[canRXmsg.id]==0) { //Check if no entry
TickTock 3:3e879b043bc5 94 indexLastMsg[canRXmsg.id]=++ii; //Create entry if first message
TickTock 3:3e879b043bc5 95 if(ii>99) {
TickTock 3:3e879b043bc5 96 ii=0;
TickTock 3:3e879b043bc5 97 }
TickTock 3:3e879b043bc5 98 }
TickTock 3:3e879b043bc5 99 lastMsg[indexLastMsg[canRXmsg.id]]=canRXmsg; //Store in table
TickTock 1:9dcd70c32180 100 }
TickTock 1:9dcd70c32180 101 }
TickTock 0:1596b8644523 102
TickTock 2:71b1999a8ea5 103 void logTS () {
TickTock 2:71b1999a8ea5 104 CANMessage tsMsg;
TickTock 2:71b1999a8ea5 105 unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
TickTock 2:71b1999a8ea5 106 tsMsg.id=0xfff;
TickTock 2:71b1999a8ea5 107 tsMsg.len=0xf;
TickTock 2:71b1999a8ea5 108 tsMsg.data[0]=secs&0xff;
TickTock 2:71b1999a8ea5 109 tsMsg.data[1]=(secs>>8)&0xff;
TickTock 2:71b1999a8ea5 110 tsMsg.data[2]=(secs>>16)&0xff;
TickTock 2:71b1999a8ea5 111 tsMsg.data[3]=secs>>24;
TickTock 2:71b1999a8ea5 112 tsMsg.data[4]=0xff;
TickTock 2:71b1999a8ea5 113 tsMsg.data[5]=0xff;
TickTock 2:71b1999a8ea5 114 tsMsg.data[6]=0xff;
TickTock 2:71b1999a8ea5 115 tsMsg.data[7]=0xff;
TickTock 2:71b1999a8ea5 116 logCan(0,tsMsg);
TickTock 1:9dcd70c32180 117 }
TickTock 0:1596b8644523 118
TickTock 1:9dcd70c32180 119 void send1() {
TickTock 1:9dcd70c32180 120 static char counter = 0; // use for fake data
TickTock 1:9dcd70c32180 121
TickTock 1:9dcd70c32180 122 can1.write(CANMessage(0x350, &counter, 1));
TickTock 1:9dcd70c32180 123 counter++;
TickTock 1:9dcd70c32180 124 // test sending 3 quickly
TickTock 1:9dcd70c32180 125 //can1.write(CANMessage(0x351, &counter, 1));
TickTock 1:9dcd70c32180 126 //can1.write(CANMessage(0x352, &counter, 1));
TickTock 2:71b1999a8ea5 127 printf("Sending message %d \n",counter);
TickTock 1:9dcd70c32180 128
TickTock 0:1596b8644523 129 }
TickTock 0:1596b8644523 130
TickTock 0:1596b8644523 131
TickTock 0:1596b8644523 132 void recieve1() {
TickTock 2:71b1999a8ea5 133 CANMessage msg1;
TickTock 4:8d7759f4fe7a 134 secsNoMsg=0; // reset deadman switch
TickTock 0:1596b8644523 135 can1.read(msg1);
TickTock 2:71b1999a8ea5 136 //printf("Can1 rxd: %d\n", msg1.data[0]);
TickTock 2:71b1999a8ea5 137 if(logOpen)
TickTock 2:71b1999a8ea5 138 logCan(2, msg1);
TickTock 2:71b1999a8ea5 139 led1 = !led1;
TickTock 0:1596b8644523 140 }
TickTock 2:71b1999a8ea5 141
TickTock 0:1596b8644523 142 void recieve2() {
TickTock 2:71b1999a8ea5 143 CANMessage msg2;
TickTock 4:8d7759f4fe7a 144 secsNoMsg=0; // reset deadman switch
TickTock 0:1596b8644523 145 can2.read(msg2);
TickTock 2:71b1999a8ea5 146 //printf("Can2 rxd: %d\n", msg2.data[0]);
TickTock 2:71b1999a8ea5 147 if(logOpen)
TickTock 2:71b1999a8ea5 148 logCan(1, msg2);
TickTock 2:71b1999a8ea5 149 led2 = !led2;
TickTock 0:1596b8644523 150 }
TickTock 0:1596b8644523 151
TickTock 5:ebf6fa994b78 152 void logMsg (char *msg) {
TickTock 5:ebf6fa994b78 153 strcpy(displayLog[displayLoc],msg);
TickTock 5:ebf6fa994b78 154 displayLoc=displayLoc>17?0:displayLoc+1;
TickTock 5:ebf6fa994b78 155 }
TickTock 5:ebf6fa994b78 156
TickTock 4:8d7759f4fe7a 157 void touched(){
TickTock 4:8d7759f4fe7a 158 LPC_GPIOINT->IO2IntClr = (LPC_GPIOINT->IO2IntStatR | LPC_GPIOINT->IO2IntStatF);
TickTock 4:8d7759f4fe7a 159 lastTouch = tt.get_touch();
TickTock 4:8d7759f4fe7a 160 lastTouch = tt.to_pixel(lastTouch); // convert to pixel pos
TickTock 4:8d7759f4fe7a 161 secsNoTouch = 0;
TickTock 4:8d7759f4fe7a 162 }
TickTock 4:8d7759f4fe7a 163
TickTock 5:ebf6fa994b78 164 void printLast (bool force){
TickTock 5:ebf6fa994b78 165 CANMessage msg;
TickTock 5:ebf6fa994b78 166 if(force) tt.cls();
TickTock 5:ebf6fa994b78 167 tt.locate(0,6);
TickTock 5:ebf6fa994b78 168 tt.foreground(Red);
TickTock 5:ebf6fa994b78 169 tt.background(Yellow);
TickTock 5:ebf6fa994b78 170 if(force) tt.cls(); // Just clear screen if forced - always update display
TickTock 5:ebf6fa994b78 171 tt.set_font((unsigned char*) Arial12x12_prop); // select the font
TickTock 5:ebf6fa994b78 172 for(int i=0; i<19; i++){
TickTock 5:ebf6fa994b78 173 msg = lastMsg[i+indexOffset];
TickTock 5:ebf6fa994b78 174 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]);
TickTock 5:ebf6fa994b78 175 }
TickTock 5:ebf6fa994b78 176 }
TickTock 5:ebf6fa994b78 177
TickTock 5:ebf6fa994b78 178 void printLog (bool force){
TickTock 4:8d7759f4fe7a 179 static int lastDisplayLoc = 0;
TickTock 5:ebf6fa994b78 180 if(force||displayLoc!=lastDisplayLoc){ //only update if changed
TickTock 5:ebf6fa994b78 181 tt.foreground(Amber);
TickTock 5:ebf6fa994b78 182 tt.background(Black);
TickTock 5:ebf6fa994b78 183 tt.cls();
TickTock 5:ebf6fa994b78 184 tt.locate(0,6);
TickTock 5:ebf6fa994b78 185 tt.set_font((unsigned char*) Arial12x12);
TickTock 5:ebf6fa994b78 186 for(int i=0; i<19; i++){
TickTock 5:ebf6fa994b78 187 printf("%s",displayLog[displayLoc]);
TickTock 5:ebf6fa994b78 188 displayLoc=displayLoc>17?0:displayLoc+1;
TickTock 5:ebf6fa994b78 189 }
TickTock 5:ebf6fa994b78 190 }
TickTock 5:ebf6fa994b78 191 lastDisplayLoc=displayLoc;
TickTock 5:ebf6fa994b78 192 }
TickTock 5:ebf6fa994b78 193
TickTock 5:ebf6fa994b78 194 void dte (bool force){
TickTock 5:ebf6fa994b78 195 unsigned gids, SOC, packV;
TickTock 5:ebf6fa994b78 196 static unsigned lgids=0, lSOC=0, lpackV=0;
TickTock 5:ebf6fa994b78 197 CANMessage msg;
TickTock 5:ebf6fa994b78 198
TickTock 5:ebf6fa994b78 199 msg = lastMsg[indexLastMsg[0x5bc]]; //Get gids
TickTock 5:ebf6fa994b78 200 gids = (msg.data[0]<<2)+(msg.data[1]>>6);
TickTock 5:ebf6fa994b78 201 msg = lastMsg[indexLastMsg[0x55b]]; //Get SOC
TickTock 5:ebf6fa994b78 202 SOC = (msg.data[0]<<2)+(msg.data[1]>>6);
TickTock 5:ebf6fa994b78 203 msg = lastMsg[indexLastMsg[0x1db]]; //Get pack volts
TickTock 5:ebf6fa994b78 204 packV = (msg.data[2]<<2)+(msg.data[3]>>6);
TickTock 5:ebf6fa994b78 205
TickTock 5:ebf6fa994b78 206 tt.background(Navy);
TickTock 5:ebf6fa994b78 207 if(force) tt.cls();
TickTock 5:ebf6fa994b78 208 if(force||gids!=lgids){
TickTock 5:ebf6fa994b78 209 tt.foreground(Amber);
TickTock 5:ebf6fa994b78 210 tt.set_font((unsigned char*) Arial28x28);
TickTock 5:ebf6fa994b78 211 tt.locate(10,10);
TickTock 5:ebf6fa994b78 212 printf("%4d gids\n",gids);
TickTock 5:ebf6fa994b78 213 tt.locate(10,200);
TickTock 5:ebf6fa994b78 214 printf("%4.1f kWh\n",(float)gids*0.08);
TickTock 5:ebf6fa994b78 215 tt.set_font((unsigned char*) SCProSB31x55);
TickTock 5:ebf6fa994b78 216 tt.foreground(Green);
TickTock 5:ebf6fa994b78 217 tt.locate(60,96);
TickTock 5:ebf6fa994b78 218 printf("%4.1f mi\n",(float)gids*0.33); // Approx for now
TickTock 5:ebf6fa994b78 219 lgids=gids;
TickTock 5:ebf6fa994b78 220 }
TickTock 5:ebf6fa994b78 221 if(force||SOC!=lSOC){
TickTock 5:ebf6fa994b78 222 tt.foreground(Amber);
TickTock 5:ebf6fa994b78 223 tt.set_font((unsigned char*) Arial28x28);
TickTock 5:ebf6fa994b78 224 tt.locate(200,10);
TickTock 5:ebf6fa994b78 225 printf("%4.1f%s\n",(float)SOC/10,"%");
TickTock 5:ebf6fa994b78 226 lSOC=SOC;
TickTock 5:ebf6fa994b78 227 }
TickTock 5:ebf6fa994b78 228 if(force||packV!=lpackV){
TickTock 5:ebf6fa994b78 229 tt.foreground(Amber);
TickTock 5:ebf6fa994b78 230 tt.set_font((unsigned char*) Arial28x28);
TickTock 5:ebf6fa994b78 231 tt.locate(200,200);
TickTock 5:ebf6fa994b78 232 printf("%4.1fV\n",(float)packV/2);
TickTock 5:ebf6fa994b78 233 lpackV=packV;
TickTock 5:ebf6fa994b78 234 }
TickTock 5:ebf6fa994b78 235 }
TickTock 5:ebf6fa994b78 236
TickTock 5:ebf6fa994b78 237 void braking (bool force, bool prdata){
TickTock 5:ebf6fa994b78 238 unsigned short targetBraking, regenBraking, speed;
TickTock 5:ebf6fa994b78 239 static unsigned short maxTarget = 0, maxRegen = 0, tarDivReg = 0;
TickTock 5:ebf6fa994b78 240 short rpm;
TickTock 5:ebf6fa994b78 241 unsigned long temp;
TickTock 5:ebf6fa994b78 242 static unsigned char lastPressure[4] = {200,200,200,200};
TickTock 5:ebf6fa994b78 243 unsigned char i,r,t;
TickTock 5:ebf6fa994b78 244 static unsigned char lr, lt;
TickTock 5:ebf6fa994b78 245 CANMessage msg;
TickTock 5:ebf6fa994b78 246
TickTock 5:ebf6fa994b78 247 msg = lastMsg[indexLastMsg[0x1cb]]; //Get Target and Regen
TickTock 5:ebf6fa994b78 248 regenBraking = (msg.data[0]<<3)+(msg.data[1]>>5);
TickTock 5:ebf6fa994b78 249 targetBraking = (msg.data[2]<<3)+(msg.data[3]>>5);
TickTock 5:ebf6fa994b78 250 if (targetBraking>maxTarget) maxTarget=targetBraking;
TickTock 5:ebf6fa994b78 251 if (regenBraking>maxRegen) maxRegen=regenBraking;
TickTock 5:ebf6fa994b78 252 if (regenBraking>50) {
TickTock 5:ebf6fa994b78 253 temp = 1000*targetBraking;
TickTock 5:ebf6fa994b78 254 temp /= regenBraking;
TickTock 5:ebf6fa994b78 255 if (temp>tarDivReg) tarDivReg=temp;
TickTock 5:ebf6fa994b78 256 }
TickTock 5:ebf6fa994b78 257 msg = lastMsg[indexLastMsg[0x176]]; //Get rpms - not sure what this is but scales to mph with .0725
TickTock 5:ebf6fa994b78 258 rpm = ((short)msg.data[0]<<8)+msg.data[1];
TickTock 5:ebf6fa994b78 259 speed =rpm>0?rpm>>3:-rpm>>3; //Take absolute to get speed; div8
TickTock 5:ebf6fa994b78 260 msg = lastMsg[indexLastMsg[0x1ca]]; //Get brake pressure
TickTock 5:ebf6fa994b78 261
TickTock 5:ebf6fa994b78 262 tt.background(Navy);
TickTock 5:ebf6fa994b78 263 if (force) {
TickTock 5:ebf6fa994b78 264 tt.cls();
TickTock 5:ebf6fa994b78 265 tt.rect(0,111,170,239,White);
TickTock 5:ebf6fa994b78 266 tt.line(0,207,170,207,White);
TickTock 5:ebf6fa994b78 267 tt.line(0,175,170,175,White);
TickTock 5:ebf6fa994b78 268 tt.line(0,143,170,143,White);
TickTock 5:ebf6fa994b78 269 lastPressure[0] = 200;
TickTock 5:ebf6fa994b78 270 lastPressure[1] = 200;
TickTock 5:ebf6fa994b78 271 lastPressure[2] = 200;
TickTock 5:ebf6fa994b78 272 lastPressure[3] = 200;
TickTock 5:ebf6fa994b78 273 }
TickTock 5:ebf6fa994b78 274 // plot bar graph for each wheel pressure
TickTock 5:ebf6fa994b78 275 for (i=0; i<4; i++){
TickTock 5:ebf6fa994b78 276 if (msg.data[i]<239) {
TickTock 5:ebf6fa994b78 277 if (msg.data[i]>lastPressure[i]){
TickTock 5:ebf6fa994b78 278 tt.fillrect(10+40*i,239-msg.data[i],40+40*i,239,Red);
TickTock 5:ebf6fa994b78 279 } else if (msg.data[i]<lastPressure[i]) {
TickTock 5:ebf6fa994b78 280 tt.fillrect(10+40*i,238-lastPressure[i],40+40*i,238-msg.data[i],Navy);
TickTock 5:ebf6fa994b78 281 }
TickTock 5:ebf6fa994b78 282 lastPressure[i]=msg.data[i];
TickTock 5:ebf6fa994b78 283 }
TickTock 5:ebf6fa994b78 284 }
TickTock 5:ebf6fa994b78 285
TickTock 5:ebf6fa994b78 286 if(targetBraking>50){
TickTock 5:ebf6fa994b78 287 targetBraking *= speed;
TickTock 5:ebf6fa994b78 288 regenBraking *= speed;
TickTock 5:ebf6fa994b78 289 temp = 200*targetBraking/maxTarget;
TickTock 5:ebf6fa994b78 290 t = (char) temp;
TickTock 5:ebf6fa994b78 291 temp = 200*regenBraking*tarDivReg/maxTarget;
TickTock 5:ebf6fa994b78 292 r = (char) temp;
TickTock 5:ebf6fa994b78 293 if(lr!=r&&prdata){
TickTock 5:ebf6fa994b78 294 tt.foreground(Amber);
TickTock 5:ebf6fa994b78 295 tt.set_font((unsigned char*) Arial28x28);
TickTock 5:ebf6fa994b78 296 tt.locate(100,50);
TickTock 5:ebf6fa994b78 297 printf("%d %d \n",regenBraking,maxRegen);
TickTock 5:ebf6fa994b78 298 tt.locate(100,90);
TickTock 5:ebf6fa994b78 299 printf("%3.1f (%3.1f%s) \n",(float)tarDivReg/1000,(float)regenBraking*tarDivReg/targetBraking/1000,"%");
TickTock 5:ebf6fa994b78 300 }
TickTock 5:ebf6fa994b78 301 if(lt!=t&&prdata){
TickTock 5:ebf6fa994b78 302 tt.foreground(Amber);
TickTock 5:ebf6fa994b78 303 tt.set_font((unsigned char*) Arial28x28);
TickTock 5:ebf6fa994b78 304 tt.locate(100,10);
TickTock 5:ebf6fa994b78 305 printf("%d %d \n",targetBraking,maxTarget);
TickTock 5:ebf6fa994b78 306 }
TickTock 5:ebf6fa994b78 307 if((lr!=r||lt!=t)&&!prdata){
TickTock 5:ebf6fa994b78 308 tt.fillrect(200,239-t,300,238-r,Red);
TickTock 5:ebf6fa994b78 309 tt.fillrect(200,239-r,300,239,Green);
TickTock 5:ebf6fa994b78 310 lt=t;
TickTock 5:ebf6fa994b78 311 lr=r;
TickTock 5:ebf6fa994b78 312 }
TickTock 5:ebf6fa994b78 313 }
TickTock 5:ebf6fa994b78 314 }
TickTock 5:ebf6fa994b78 315
TickTock 5:ebf6fa994b78 316 void updateDisplay(){
TickTock 5:ebf6fa994b78 317 bool changed;
TickTock 4:8d7759f4fe7a 318 for (int i=0; i<2; i++){
TickTock 5:ebf6fa994b78 319 changed = dMode[i]!=lastDMode[i]||(lastSMode>0&&sMode==0);
TickTock 4:8d7759f4fe7a 320 tt.set_display(i);
TickTock 4:8d7759f4fe7a 321 switch (dMode[i]) {
TickTock 4:8d7759f4fe7a 322 case logMode:
TickTock 5:ebf6fa994b78 323 printLog(changed);
TickTock 4:8d7759f4fe7a 324 break;
TickTock 4:8d7759f4fe7a 325 case dteMode:
TickTock 5:ebf6fa994b78 326 dte(changed);
TickTock 5:ebf6fa994b78 327 break;
TickTock 4:8d7759f4fe7a 328 case brakeMode:
TickTock 5:ebf6fa994b78 329 braking(changed,true);
TickTock 4:8d7759f4fe7a 330 break;
TickTock 4:8d7759f4fe7a 331 case powerMode:
TickTock 5:ebf6fa994b78 332 braking(changed,false);
TickTock 4:8d7759f4fe7a 333 break;
TickTock 4:8d7759f4fe7a 334 case controlMode:
TickTock 4:8d7759f4fe7a 335 tt.background(Black);
TickTock 4:8d7759f4fe7a 336 if(dMode[i]!=lastDMode[i]||(lastSMode>0&&sMode==0)) tt.cls();
TickTock 4:8d7759f4fe7a 337 tt.fillcircle(100,100,15,Orange);
TickTock 4:8d7759f4fe7a 338 break;
TickTock 4:8d7759f4fe7a 339 case monitorMode:
TickTock 5:ebf6fa994b78 340 printLast(changed);
TickTock 4:8d7759f4fe7a 341 break;
TickTock 4:8d7759f4fe7a 342 default:
TickTock 4:8d7759f4fe7a 343 tt.background(Black);
TickTock 4:8d7759f4fe7a 344 if(dMode[i]!=lastDMode[i]||(lastSMode>0&&sMode==0)) tt.cls();
TickTock 4:8d7759f4fe7a 345 break;
TickTock 4:8d7759f4fe7a 346 }
TickTock 4:8d7759f4fe7a 347 lastDMode[i]=dMode[i];
TickTock 4:8d7759f4fe7a 348 } // for (i=0; i<1; i++)
TickTock 4:8d7759f4fe7a 349
TickTock 4:8d7759f4fe7a 350 switch (sMode) {
TickTock 4:8d7759f4fe7a 351 case 1:
TickTock 4:8d7759f4fe7a 352 tt.set_display(2); // select both displays
TickTock 4:8d7759f4fe7a 353 tt.foreground(Yellow);
TickTock 4:8d7759f4fe7a 354 tt.background(DarkCyan);
TickTock 4:8d7759f4fe7a 355 tt.set_font((unsigned char*) Arial12x12);
TickTock 4:8d7759f4fe7a 356 tt.fillrect(btn31x1,btn11y1,btn31x2,btn11y2,DarkCyan);
TickTock 4:8d7759f4fe7a 357 tt.locate(btn31x1+5,btn11y1+5);
TickTock 4:8d7759f4fe7a 358 printf("<-Prev\n");
TickTock 4:8d7759f4fe7a 359 tt.fillrect(btn32x1,btn11y1,btn32x2,btn11y2,DarkCyan);
TickTock 4:8d7759f4fe7a 360 tt.fillrect(btn33x1,btn11y1,btn33x2,btn11y2,DarkCyan);
TickTock 4:8d7759f4fe7a 361 tt.locate(btn33x2-50,btn11y1+5);
TickTock 4:8d7759f4fe7a 362 printf("Next->\n");
TickTock 4:8d7759f4fe7a 363 tt.set_display(0);
TickTock 4:8d7759f4fe7a 364 tt.locate(btn32x1+15,btn11y1+5);
TickTock 4:8d7759f4fe7a 365 printf("Select %d\n",dMode[0]);
TickTock 4:8d7759f4fe7a 366 tt.set_display(1);
TickTock 4:8d7759f4fe7a 367 tt.locate(btn32x1+15,btn11y1+5);
TickTock 4:8d7759f4fe7a 368 printf("Select %d\n",dMode[1]);
TickTock 4:8d7759f4fe7a 369 tt.background(Black);
TickTock 4:8d7759f4fe7a 370 break;
TickTock 4:8d7759f4fe7a 371 default:
TickTock 4:8d7759f4fe7a 372 break;
TickTock 4:8d7759f4fe7a 373 }
TickTock 4:8d7759f4fe7a 374 lastSMode=sMode;
TickTock 4:8d7759f4fe7a 375 }
TickTock 4:8d7759f4fe7a 376
TickTock 0:1596b8644523 377 int main() {
TickTock 2:71b1999a8ea5 378 int readPointer=0;
TickTock 2:71b1999a8ea5 379 int fmon;
TickTock 2:71b1999a8ea5 380 int fday;
TickTock 2:71b1999a8ea5 381 int ftime;
TickTock 4:8d7759f4fe7a 382 char sTemp[40];
TickTock 2:71b1999a8ea5 383 unsigned long secs;
TickTock 2:71b1999a8ea5 384 bool bit = false;
TickTock 4:8d7759f4fe7a 385 int i,j;
TickTock 4:8d7759f4fe7a 386
TickTock 2:71b1999a8ea5 387 can1.frequency(500000);
TickTock 2:71b1999a8ea5 388 can2.frequency(500000);
TickTock 1:9dcd70c32180 389 //can1_SleepMode = 0; // Enable TX
TickTock 1:9dcd70c32180 390 //can2_SleepMode = 0; // Enable TX
TickTock 1:9dcd70c32180 391 can1_SleepMode = 1; // Turn on Monitor_only Mode
TickTock 1:9dcd70c32180 392 can2_SleepMode = 1; // Turn on Monitor_only Mode
TickTock 2:71b1999a8ea5 393 //ticker.attach(&send1, 0.5);
TickTock 5:ebf6fa994b78 394 ticker.attach(&updateDisplay, 0.5); // Display messages
TickTock 0:1596b8644523 395 can1.attach(&recieve1);
TickTock 0:1596b8644523 396 can2.attach(&recieve2);
TickTock 4:8d7759f4fe7a 397
TickTock 3:3e879b043bc5 398 tt.set_orientation(1);
TickTock 3:3e879b043bc5 399 tt.set_font((unsigned char*) Arial12x12_prop); // select the font
TickTock 4:8d7759f4fe7a 400 tt.set_display(2); // select right display
TickTock 4:8d7759f4fe7a 401 tt.background(Black);
TickTock 3:3e879b043bc5 402 tt.cls();
TickTock 3:3e879b043bc5 403 tt.set_display(0); // select left display
TickTock 4:8d7759f4fe7a 404 tt.calibrate(); // calibrate the touch
TickTock 1:9dcd70c32180 405 tt.claim(stdout); // send stdout to the TFT display
TickTock 4:8d7759f4fe7a 406 touchpad.rise(&touched);
TickTock 4:8d7759f4fe7a 407 tt.wfi(); // enable interrupt on touch
TickTock 4:8d7759f4fe7a 408 dled = 1; // turn on display LED 80%
TickTock 2:71b1999a8ea5 409 timer.start() ;
TickTock 2:71b1999a8ea5 410 RTC_Init(); // start the RTC Interrupts that sync the timer
TickTock 1:9dcd70c32180 411 struct tm t; // pointer to a static tm structure
TickTock 1:9dcd70c32180 412
TickTock 1:9dcd70c32180 413 seconds = time(NULL);
TickTock 1:9dcd70c32180 414 t = *localtime(&seconds) ;
TickTock 2:71b1999a8ea5 415 strftime(sTemp, 32, "%a %m/%d/%Y %X", &t);
TickTock 3:3e879b043bc5 416 //tt.locate(0,0);
TickTock 3:3e879b043bc5 417 //printf("\nCurrent time : %s\n", sTemp); // DAY MM/DD/YYYY HH:MM:SS
TickTock 1:9dcd70c32180 418
TickTock 1:9dcd70c32180 419 // is it a date before 2012 ?
TickTock 1:9dcd70c32180 420 if ((t.tm_year + 1900) < 2012 ) {
TickTock 1:9dcd70c32180 421 // before 2012, so the RTC probably lost power
TickTock 1:9dcd70c32180 422 // So, set a near-recent date in 2012
TickTock 1:9dcd70c32180 423
TickTock 1:9dcd70c32180 424 // enter people-values here
TickTock 2:71b1999a8ea5 425 t.tm_year = 2013 ; // 28 May 2012
TickTock 2:71b1999a8ea5 426 t.tm_mon = 3 ; // 1 to 12
TickTock 2:71b1999a8ea5 427 t.tm_mday = 5;
TickTock 1:9dcd70c32180 428 t.tm_hour = 12; // 12:59:56 PM (after noon)
TickTock 1:9dcd70c32180 429 t.tm_min = 59;
TickTock 1:9dcd70c32180 430 t.tm_sec = 56;
TickTock 1:9dcd70c32180 431
TickTock 1:9dcd70c32180 432 // adjust for tm structure required values
TickTock 1:9dcd70c32180 433 t.tm_year = t.tm_year - 1900;
TickTock 1:9dcd70c32180 434 t.tm_mon = t.tm_mon - 1;
TickTock 1:9dcd70c32180 435
TickTock 1:9dcd70c32180 436 // set the RTC
TickTock 1:9dcd70c32180 437 set_time(mktime(&t));
TickTock 1:9dcd70c32180 438 seconds = time(NULL);
TickTock 1:9dcd70c32180 439
TickTock 1:9dcd70c32180 440 // printf("Set RTC to:\n" );
TickTock 1:9dcd70c32180 441 // strftime(sTemp, 32, "%a %m/%d/%Y %X", localtime(&seconds));
TickTock 1:9dcd70c32180 442 // printf("%s\n", sTemp); // DAY MM/DD/YYYY HH:MM:SS
TickTock 0:1596b8644523 443 }
TickTock 2:71b1999a8ea5 444 while (true) {
TickTock 4:8d7759f4fe7a 445 if (!logOpen) { // Open new file if one is not already open
TickTock 4:8d7759f4fe7a 446 seconds = time(NULL);
TickTock 4:8d7759f4fe7a 447 t = *localtime(&seconds) ;
TickTock 4:8d7759f4fe7a 448 strftime(fileName, 32, "/fs/%m%d%H%M.alc", &t); //mmddhhmm.alc
TickTock 2:71b1999a8ea5 449
TickTock 4:8d7759f4fe7a 450 tt.set_display(0); // select left display
TickTock 4:8d7759f4fe7a 451 tt.locate(0,0);
TickTock 4:8d7759f4fe7a 452 tt.foreground(Cyan); // set chars to Cyan
TickTock 4:8d7759f4fe7a 453 //printf("Using file %s\n",fileName);
TickTock 4:8d7759f4fe7a 454 sprintf(sTemp,"Using file %s\n",fileName);
TickTock 4:8d7759f4fe7a 455 logMsg(sTemp);
TickTock 4:8d7759f4fe7a 456 file = fopen(fileName, "ab");
TickTock 4:8d7759f4fe7a 457
TickTock 4:8d7759f4fe7a 458 if(file==NULL){
TickTock 4:8d7759f4fe7a 459 sprintf(sTemp,"\nUnable to open %s\n\n\n\n",fileName);
TickTock 4:8d7759f4fe7a 460 logMsg(sTemp);
TickTock 4:8d7759f4fe7a 461 } else {
TickTock 4:8d7759f4fe7a 462 logOpen = true;
TickTock 4:8d7759f4fe7a 463 readPointer=writePointer;
TickTock 4:8d7759f4fe7a 464 sprintf(sTemp,"Starting Can Log %s\n",fileName);
TickTock 4:8d7759f4fe7a 465 logMsg(sTemp);
TickTock 4:8d7759f4fe7a 466 logTS();
TickTock 4:8d7759f4fe7a 467 fclose(file);
TickTock 4:8d7759f4fe7a 468 file = fopen("/fs/loglog.txt", "a");
TickTock 4:8d7759f4fe7a 469 fprintf(file,"%s\r\n",fileName);
TickTock 4:8d7759f4fe7a 470 fclose(file);
TickTock 4:8d7759f4fe7a 471 }
TickTock 4:8d7759f4fe7a 472 } else { // if (!logOpen)
TickTock 4:8d7759f4fe7a 473 if (((writePointer+maxBufLen-readPointer)%maxBufLen)>(maxBufLen/2)||canIdle) {
TickTock 4:8d7759f4fe7a 474 // Dump buffer if > 1/2 full, canbus has stopped, or PB1 pressed
TickTock 4:8d7759f4fe7a 475 if (logOpen) {
TickTock 4:8d7759f4fe7a 476 file = fopen(fileName, "ab");
TickTock 4:8d7759f4fe7a 477 if (file == NULL) {
TickTock 4:8d7759f4fe7a 478 logOpen = false;
TickTock 4:8d7759f4fe7a 479 sprintf(sTemp,"Failed to append log file.\n\n");
TickTock 4:8d7759f4fe7a 480 logMsg(sTemp);
TickTock 4:8d7759f4fe7a 481 } else {
TickTock 4:8d7759f4fe7a 482 while (readPointer != writePointer) {
TickTock 4:8d7759f4fe7a 483 for (j = 0; j<13; j++){
TickTock 4:8d7759f4fe7a 484 fprintf(file,"%c",writeBuffer[readPointer][j]);
TickTock 4:8d7759f4fe7a 485 }
TickTock 4:8d7759f4fe7a 486 if(++readPointer >= maxBufLen)
TickTock 4:8d7759f4fe7a 487 readPointer=0;
TickTock 4:8d7759f4fe7a 488 }
TickTock 4:8d7759f4fe7a 489 led3 = !led3;
TickTock 4:8d7759f4fe7a 490 fclose(file);
TickTock 4:8d7759f4fe7a 491 }
TickTock 4:8d7759f4fe7a 492 } // if (logOpen)
TickTock 4:8d7759f4fe7a 493 } // if > 1/2 full, canbus has stopped, or PB1 pressed
TickTock 4:8d7759f4fe7a 494 } // if logOpen
TickTock 4:8d7759f4fe7a 495 if (canIdle&&userIdle) { // canbus idle --> sleep to save power
TickTock 4:8d7759f4fe7a 496 if (logOpen){
TickTock 4:8d7759f4fe7a 497 // First take advantage of the idle time to clear some room
TickTock 4:8d7759f4fe7a 498 bit = false;
TickTock 4:8d7759f4fe7a 499 rfile = fopen("/fs/loglog.txt", "r");
TickTock 4:8d7759f4fe7a 500 file = fopen("/fs/loglog.new", "w");
TickTock 4:8d7759f4fe7a 501 while (!feof(rfile)) {
TickTock 4:8d7759f4fe7a 502 fscanf(rfile,"/fs/%2d%2d%4d.alc\r\n",&fmon,&fday,&ftime);
TickTock 4:8d7759f4fe7a 503 //if ((fmon<t.tm_mon)&&(fday<=t.tm_mday)){ // Delete all files more than 1 month old
TickTock 4:8d7759f4fe7a 504 if ((fmon < 12) || (t.tm_mon > 1)){
TickTock 4:8d7759f4fe7a 505 fday = fday + fmon*31; //crude - february will store 3 extra days of data
TickTock 4:8d7759f4fe7a 506 }
TickTock 4:8d7759f4fe7a 507 if ((fday+14)<(t.tm_mday+t.tm_mon*31)){ // Delete all files more than ~14 days old
TickTock 4:8d7759f4fe7a 508 bit=true;
TickTock 4:8d7759f4fe7a 509 sprintf(sTemp,"/fs/%02d%02d%04d.alc",fmon,fday,ftime);
TickTock 4:8d7759f4fe7a 510 if ((remove(sTemp)==NULL)) {
TickTock 4:8d7759f4fe7a 511 sprintf(sTemp,"Removed file %s\n",sTemp);
TickTock 4:8d7759f4fe7a 512 logMsg(sTemp);
TickTock 4:8d7759f4fe7a 513 }
TickTock 4:8d7759f4fe7a 514 }else{
TickTock 4:8d7759f4fe7a 515 fprintf(file,"/fs/%02d%02d%04d.alc\r\n",fmon,fday,ftime);
TickTock 4:8d7759f4fe7a 516 }
TickTock 2:71b1999a8ea5 517 }
TickTock 4:8d7759f4fe7a 518 fclose (file);
TickTock 4:8d7759f4fe7a 519 fclose (rfile);
TickTock 4:8d7759f4fe7a 520 if (bit) {
TickTock 4:8d7759f4fe7a 521 remove ("/fs/loglog.txt");
TickTock 4:8d7759f4fe7a 522 //rename not working so do it the hard way
TickTock 4:8d7759f4fe7a 523 //rename ("/fs/loglog.new","/fs/loglog.txt");
TickTock 4:8d7759f4fe7a 524 rfile = fopen("/fs/loglog.new", "r");
TickTock 4:8d7759f4fe7a 525 file = fopen("/fs/loglog.txt", "w");
TickTock 2:71b1999a8ea5 526 while (!feof(rfile)) {
TickTock 4:8d7759f4fe7a 527 fscanf(rfile,"%s\r\n",&sTemp);
TickTock 4:8d7759f4fe7a 528 fprintf(file,"%s\r\n",sTemp);
TickTock 2:71b1999a8ea5 529 }
TickTock 2:71b1999a8ea5 530 fclose (file);
TickTock 2:71b1999a8ea5 531 fclose (rfile);
TickTock 4:8d7759f4fe7a 532 }
TickTock 4:8d7759f4fe7a 533 remove ("/fs/loglog.new");
TickTock 4:8d7759f4fe7a 534 wait(5); // wait a few seconds to ensure fsRAM is done
TickTock 4:8d7759f4fe7a 535 } // if (logOpen)
TickTock 4:8d7759f4fe7a 536 sprintf(sTemp,"Putting uC to sleep.\n");
TickTock 4:8d7759f4fe7a 537 logMsg(sTemp);
TickTock 4:8d7759f4fe7a 538 //LPC_RTC->CIIR=0x00; // block RTC interrupts
TickTock 4:8d7759f4fe7a 539 led1=0;
TickTock 4:8d7759f4fe7a 540 led2=0;
TickTock 4:8d7759f4fe7a 541 led3=0;
TickTock 4:8d7759f4fe7a 542 led4=0;
TickTock 4:8d7759f4fe7a 543 dled=0; // turn off display
TickTock 4:8d7759f4fe7a 544 secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
TickTock 4:8d7759f4fe7a 545 while (secsNoMsg>canTimeout && secsNoTouch>userTimeout) {
TickTock 4:8d7759f4fe7a 546 //DeepPowerDown();
TickTock 4:8d7759f4fe7a 547 tt.wfi(); //enable touchpad input
TickTock 4:8d7759f4fe7a 548 //__wfi(); // freeze CPU and wait for interrupt (from canbus or touch)
TickTock 4:8d7759f4fe7a 549 Sleep();
TickTock 4:8d7759f4fe7a 550 //DeepPowerDown();
TickTock 4:8d7759f4fe7a 551 }
TickTock 4:8d7759f4fe7a 552 canIdle=secsNoMsg>canTimeout;
TickTock 4:8d7759f4fe7a 553 userIdle=userIdle>userTimeout;
TickTock 4:8d7759f4fe7a 554 dled=1; // turn on display LED
TickTock 4:8d7759f4fe7a 555 sprintf(sTemp,"Waking uC.\n");
TickTock 4:8d7759f4fe7a 556 logMsg(sTemp);
TickTock 4:8d7759f4fe7a 557 if (time(NULL)>(secs+1800)) {
TickTock 4:8d7759f4fe7a 558 logOpen = false; // Start new file if asleep for more than 30 minutes
TickTock 4:8d7759f4fe7a 559 if (secsNoTouch>100) secsNoTouch = 100; // also mostly reset user Idle counter
TickTock 4:8d7759f4fe7a 560 } else { // insert timestamp on each wake
TickTock 4:8d7759f4fe7a 561 logTS();
TickTock 4:8d7759f4fe7a 562 }
TickTock 4:8d7759f4fe7a 563 //LPC_RTC->CIIR=0x01; // re-enable RTC interrupts
TickTock 4:8d7759f4fe7a 564 } // if idle
TickTock 4:8d7759f4fe7a 565
TickTock 4:8d7759f4fe7a 566 if (!userIdle) {
TickTock 4:8d7759f4fe7a 567 if (secsNoTouch<2) {// Recently touched
TickTock 4:8d7759f4fe7a 568 secsNoTouch +=2; // increment to prevent double touch
TickTock 4:8d7759f4fe7a 569 if (lastTouch.x>320){
TickTock 4:8d7759f4fe7a 570 i=1;
TickTock 4:8d7759f4fe7a 571 lastTouch.x-=320;
TickTock 4:8d7759f4fe7a 572 } else {
TickTock 4:8d7759f4fe7a 573 i=0;
TickTock 4:8d7759f4fe7a 574 }
TickTock 4:8d7759f4fe7a 575 if (lastTouch.y>btn11y1 && lastTouch.y<btn11y2){
TickTock 5:ebf6fa994b78 576 if(sMode==1){
TickTock 5:ebf6fa994b78 577 if (lastTouch.x>btn31x1 && lastTouch.x<btn31x2) {
TickTock 5:ebf6fa994b78 578 dMode[i]=dMode[i]>0?dMode[i]-1:maxModes;
TickTock 5:ebf6fa994b78 579 } else if (lastTouch.x>btn32x1 && lastTouch.x<btn32x2) {
TickTock 5:ebf6fa994b78 580 secsNoTouch = userTimeout; // immediately exit config mode
TickTock 5:ebf6fa994b78 581 } else if (lastTouch.x>btn33x1 && lastTouch.x<btn33x2) {
TickTock 5:ebf6fa994b78 582 dMode[i]=dMode[i]<maxModes?dMode[i]+1:0;
TickTock 5:ebf6fa994b78 583 }
TickTock 5:ebf6fa994b78 584 } else sMode=1;
TickTock 5:ebf6fa994b78 585 } else {
TickTock 5:ebf6fa994b78 586 if (dMode[i]==monitorMode) {
TickTock 5:ebf6fa994b78 587 if (lastTouch.x>btn31x1 && lastTouch.x<btn31x2)
TickTock 5:ebf6fa994b78 588 indexOffset=indexOffset>4?indexOffset-4:1;
TickTock 5:ebf6fa994b78 589 else if (lastTouch.x>btn33x1 && lastTouch.x<btn33x2)
TickTock 5:ebf6fa994b78 590 indexOffset=indexOffset<77?indexOffset+4:80;
TickTock 2:71b1999a8ea5 591 }
TickTock 2:71b1999a8ea5 592 }
TickTock 4:8d7759f4fe7a 593 }
TickTock 5:ebf6fa994b78 594 secsNoMsg = 0;
TickTock 4:8d7759f4fe7a 595 } else { // userIdle
TickTock 4:8d7759f4fe7a 596 sMode=0;
TickTock 4:8d7759f4fe7a 597 }
TickTock 4:8d7759f4fe7a 598
TickTock 4:8d7759f4fe7a 599 wait(0.1); // We get >2K messages per second
TickTock 2:71b1999a8ea5 600 } //while (true)
TickTock 0:1596b8644523 601 }