Dashboard firmware for FBR2012
Dependencies: mbed TextLCD PinDetect
Revision 6:11b2bbbe14b2, committed 2012-10-17
- Comitter:
- intrinseca
- Date:
- Wed Oct 17 16:08:51 2012 +0000
- Parent:
- 5:177520d43c87
- Child:
- 7:78cb2263290a
- Commit message:
- Add CANComms
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/CANComms.h Wed Oct 17 16:08:51 2012 +0000 @@ -0,0 +1,23 @@ +#ifndef FBRDASH_CANCOMMS_H +#define FBRDASH_CANCOMMS_H + +#include "mbed.h" +#include "State.h" +#include "Comms.h" + +class CANComms : public Comms +{ + public: + CANComms(State* _values); + virtual void send(char message); + + private: + Ticker* pollTicker; + Ticker* readTicker; + CAN* can; + + void receive(); + void poll(); +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/MSCANHeader.h Wed Oct 17 16:08:51 2012 +0000 @@ -0,0 +1,31 @@ +#ifndef FBRDASH_MSCANHEADER_H +#define FBRDASH_MSCANHEADER_H + +#define MSCAN_CMD 0 //a command to set a variable on the receiving processor to the value in the subsequent data part of the message, or +#define MSCAN_REQ 1 //a request for data, i.e., the value of a specific variable (and where to store the reply) +#define MSCAN_RSP 2 //a push-type message in reply to the destination processor's request for a variable value, the requested values are in the data buffer (&CAN_RB_DSR0) in the received message, +#define MSCAN_XSUB 3 //a message to this processor from device 1 to execute subroutine immediately here (set flag if can execute in main loop), or +#define MSCAN_BURN 4 //a message to burn RAM data table into flash data table. + +#define MSCAN_ID_MS 0 +#define MSCAN_ID_DASH 1 + +#define MSCAN_BLOCK_OUTPC 7 + +class MSCANHeader +{ + public: + MSCANHeader(); + MSCANHeader(char to, char from, char type, char block, short offset); + + void parse(int id); + int build(); + + short var_offset; + char msg_type; + char from_id; + char to_id; + char var_blk; +}; + +#endif \ No newline at end of file
--- a/inc/PCComms.h Sun Oct 14 21:09:49 2012 +0000 +++ b/inc/PCComms.h Wed Oct 17 16:08:51 2012 +0000 @@ -12,7 +12,6 @@ virtual void send(char message); private: - State* values; Serial* pc; void receive();
--- a/inc/State.h Sun Oct 14 21:09:49 2012 +0000 +++ b/inc/State.h Wed Oct 17 16:08:51 2012 +0000 @@ -4,7 +4,7 @@ struct State { unsigned short int rpm; - unsigned char throttle_pos; + float throttle_pos; unsigned char manifold_pres; unsigned char air_temp; float coolant_temp;
--- a/main.cpp Sun Oct 14 21:09:49 2012 +0000 +++ b/main.cpp Wed Oct 17 16:08:51 2012 +0000 @@ -4,6 +4,7 @@ #include "Menu.h" #include "Comms.h" #include "PCComms.h" +#include "CANComms.h" #include "Gears.h" #include "LEDS.h" #include "bigchar.h" @@ -39,76 +40,52 @@ //Main car state structure State car; -//Initialise CAN -CAN can(p30, p29); - //Classes for various parts of the firmware Menu dashMenu(&lcd, p16, p17, p12); //*LCD, OK, Left, Right PCComms pc(&car); +CANComms *can; Gears gearButtons(p14, p13, p15, &car.gear, &pc); //Up, Neutral, Down, *Current Gear LEDS revs(leds); //Refresh the rev LEDs and warning LEDs void revRefresh() { - CANMessage msg; revs.refresh(car.rpm); - - if(car.voltage<12){ + + if(car.voltage < 12) { warn[0]=1; - }else{ + } else { warn[0]=0; } - if(car.coolant_temp>110){ + if(car.coolant_temp>110) { warn[1]=1; - }else{ + } else { warn[1]=0; } - if(car.rpm==0 and car.gear!=0){ + if(car.rpm==0 and car.gear!=0) { warn[2]=1; - }else{ + } else { warn[2]=0; } - if(can.read(msg)) { - if(msg.id==100 and msg.len==8){ - car.rpm = msg.data[0] + (msg.data[1] << 8); - car.throttle_pos = msg.data[2]; - car.manifold_pres = msg.data[3]; - car.air_temp = msg.data[4]; - car.coolant_temp = msg.data[5]; - car.lambda = msg.data[6]; - } - else if(msg.id==200 and msg.len==8){ - car.speed = msg.data[0]; - car.accel_x = msg.data[1]; - car.accel_y = msg.data[2]; - car.gear = msg.data[3]; - car.oil_temp = msg.data[4]; - car.voltage = msg.data[5]/16.0; - } - } - } //Refresh the LCD void lcdRefresh() { //If menu off screen, display HUD - if(dashMenu.display == false) - { + if(dashMenu.display == false) { lcd.locate(0, 0); - lcd.printf("%3.0fC%5.1dRPM", car.coolant_temp, car.rpm); + lcd.printf("R:%-5.1d S:%-3d", car.rpm, car.speed); lcd.locate(0, 1); - lcd.printf("%2dMPH %3.1fV", car.speed, car.voltage); - + lcd.printf("%-4.1fV %-4.1f\xDF\x43", car.voltage, car.coolant_temp); + write_bigchar(&lcd, 13, car.gear); } //Otherwise show menu - else - { + else { dashMenu.refresh(); - } - + } + //Blink heartbeat heartbeat = !heartbeat; } @@ -127,57 +104,36 @@ lcd.printf(" FBR 2012"); lcd.locate(0,1); lcd.printf(" Ready to drive"); - int offset = 0; - int type=1; - int blk=7; - int from=1; - int to=0; - int id = offset*262144+type*32768+from*2048+to*128+blk*8; - CANMessage msg; - msg = CANMessage(id,0,8,CANData,CANExtended); - lcd.cls(); - lcd.printf("%x",id); - can.reset(); - if(can.write(msg)){ - wait(0.01); - lcd.printf(" %d errors",can.tderror()); - can.reset(); - while(can.read(msg)==false){ - wait(0.1); - } - wait(0.5); - lcd.printf(" %d errors",can.tderror()); - } + //Light up LEDs - for(int i = 0; i < LEDS::NUM_LEDS; i++) - { + for(int i = 0; i < LEDS::NUM_LEDS; i++) { leds[i] = true; if(i < 4) warn[i] = true; - wait(0.2); + wait(0.1); } - + //Turn off LEDs - for(int i = LEDS::NUM_LEDS - 1; i >= 0; i--) - { + for(int i = LEDS::NUM_LEDS - 1; i >= 0; i--) { leds[i] = false; if(i < 4) warn[i] = false; - wait(0.2); + wait(0.1); } - + lcd.cls(); } int main() -{ - //Initialise CAN - can.frequency(500000); +{ + printf("\n"); + printf("FBRDash\n"); + //Initialise state car.rpm = 0; car.gear = 2; car.speed = 0; - car.coolant_temp = 0; + car.coolant_temp = 0; car.throttle_pos = 0; car.manifold_pres = 0; car.air_temp = 0; @@ -185,30 +141,31 @@ car.accel_x = 0; car.accel_y = 0; car.oil_temp = 0; - car.voltage = 0; + car.voltage = 10.0; //Set up menu dashMenu.addItem<float>("Coolant Temp ", "%12.1f\xDF\x43", &car.coolant_temp); // \xDF\x43 -> �C . Need code for C as otherwise it gets taken as hex digit. dashMenu.addItem<unsigned char>("Air Temp ", "%12d\xDF\x43", &car.air_temp); - dashMenu.addItem<unsigned char>("Throttle Pos ", "%13d\xDF", &car.throttle_pos); + dashMenu.addItem<float>("Throttle Pos ", "%12.1fd\xDF", &car.throttle_pos); dashMenu.addItem<unsigned char>("Manifold Pres ", "%10d psi", &car.manifold_pres); - dashMenu.addItem<unsigned char>("Lambda ", "%14d", &car.lambda); + dashMenu.addItem<unsigned char>("Lambda ", "%14d", &car.lambda); dashMenu.addItem<unsigned char>("Oil Temp ", "%12d\xDF\x43", &car.oil_temp); - + //Set up characters on LCS setup_bigchar(&lcd); - + //Do bootup animation selfTest(); - + //Start refresh tickers lcdRefreshTicker.attach_us(&lcdRefresh, LCD_REFRESH_TIME); revRefreshTicker.attach_us(&revRefresh, REV_REFRESH_TIME); //increment.attach(&doIncrement, 0.0005); + + can = new CANComms(&car); //Infinite loop - program is interrupt driven - while(true) - { + while(true) { __WFI(); } } \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/CANComms.cpp Wed Oct 17 16:08:51 2012 +0000 @@ -0,0 +1,92 @@ +#include "CANComms.h" +#include "mbed.h" +#include "State.h" + +#include "MSCANHeader.h" + +CANComms::CANComms(State* _values) : Comms(_values) +{ + can = new CAN(p30, p29); + can->frequency(500000); + + pollTicker = new Ticker(); + readTicker = new Ticker(); + + pollTicker->attach(this, &CANComms::poll, 0.05); + readTicker->attach(this, &CANComms::receive, 0.025); +} + +void CANComms::poll() +{ + char i; + + //start 6, 22 + //int ids[] = {0x00189838, 0x00589838}; + + short offsets[] = {6, 22}; + + MSCANHeader header(MSCAN_ID_MS, MSCAN_ID_DASH, MSCAN_REQ, MSCAN_BLOCK_OUTPC, 0); + + for(i = 0; i < 2; i++) + { + header.var_offset = offsets[i]; + CANMessage msg(header.build(), 0, 3, CANData, CANExtended); + + msg.data[0] = i; //Where to put the response - used when communicating between MS's to tell them where they wanted the data put + msg.data[1] = 0; //Offset into the table specified in data[0] + msg.data[2] = 8; //How many bytes of the source table we want + + /*printf("Polling %d\n", i);*/ + + if(can->write(msg)) + { + + } + } +} + +void CANComms::send(char message) +{ + +} + +void CANComms::receive() +{ + float tps; + char block; + + CANMessage msg; + MSCANHeader header; + + while(can->read(msg)) + { + /*printf("CAN Message %08X %d %02X%02X%02X%02X%02X%02X%02X%02X\n", msg.id, msg.len, + msg.data[0], + msg.data[1], + msg.data[2], + msg.data[3], + msg.data[4], + msg.data[5], + msg.data[6], + msg.data[7] + );*/ + + header.parse(msg.id); + + //printf("Processing data, block %d\n", block); + + if(header.var_blk == 0) + { + values->rpm = (msg.data[0] << 8) | msg.data[1]; + } + else + { + values->coolant_temp = (((msg.data[0] << 8) | msg.data[1]) - 320.0) * 0.05555; + values->throttle_pos = ((msg.data[2] << 8) | msg.data[3]) / 10.0; + values->voltage = ((msg.data[4] << 8) | msg.data[5]) / 10.0; + printf("TPS: %f\n", values->throttle_pos); + } + + //printf("Bat: %f\n", battery / 10.0); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/MSCANHeader.cpp Wed Oct 17 16:08:51 2012 +0000 @@ -0,0 +1,48 @@ +#include "MSCANHeader.h" + +MSCANHeader::MSCANHeader() +{ + +} + +MSCANHeader::MSCANHeader(char to, char from, char type, char block, short offset) +{ + to_id = to; + from_id = from; + msg_type = type; + var_blk = block; + var_offset = offset; +} + +//MS encodes most of the request params in the message ID. +//Alignment is weird because the ID really includes some non-data bits. MS worked round these, mBed just skips them + +//0-2 3 bits Spare on MSII +//3-6 4 bits Block to get data from. 7 = outpc, all the stuff that MS sends to the PC via serial +//7-10 4 bits To ID - 0 for MS +//11-14 4 bits From ID - Using 3 here for no good reason +//15-17 3 bits Message type. 1 to get data, response has 2 +//18-28 11 bits Offset into the block in bits 3-6. Look in the INI file for Tuner Studio to find these, +// [OutputChannels] section starting line 3036 + +void MSCANHeader::parse(int id) +{ + var_offset = (id & 0x1FFC0000) >> 18; + msg_type = (id & 0x00038000) >> 15; + from_id = (id & 0x00007800) >> 11; + to_id = (id & 0x00000780) >> 7; + var_blk = (id & 0x00000078) >> 3; +} + +int MSCANHeader::build() +{ + int id = 0; + + id |= (var_offset & 0x7FF) << 18; + id |= (msg_type & 0x7) << 15; + id |= (from_id & 0xF) << 11; + id |= (to_id & 0xF) << 7; + id |= (var_blk & 0xF) << 3; + + return id; +} \ No newline at end of file