Library to control Dodge LX (83.3k) CAN devices

Dependencies:   DodgeRadioLib EthernetWrapperLib OBDIILib mbed

Files at this revision

API Documentation at this revision

Comitter:
rtgree01
Date:
Sat Aug 20 14:20:13 2011 +0000
Child:
1:90487a39d54e
Commit message:
First Rev with OBDII enabled, calculates mpg, but no transmission

Changed in this revision

EthernetNetIf.lib Show annotated file Show diff for this revision Revisions of this file
FATFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
RadioState.h Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
WatchDogTimer.cpp Show annotated file Show diff for this revision Revisions of this file
WatchDogTimer.h Show annotated file Show diff for this revision Revisions of this file
ecu_reader.cpp Show annotated file Show diff for this revision Revisions of this file
ecu_reader.h 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
mbed.lib Show annotated file Show diff for this revision Revisions of this file
radioEmulator.cpp Show annotated file Show diff for this revision Revisions of this file
radioEmulator.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EthernetNetIf.lib	Sat Aug 20 14:20:13 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mamezu/libraries/EthernetNetIf/ljksa8
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FATFileSystem.lib	Sat Aug 20 14:20:13 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.co.uk/projects/libraries/svn/FATFileSystem/trunk@28
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RadioState.h	Sat Aug 20 14:20:13 2011 +0000
@@ -0,0 +1,67 @@
+#ifndef RADIOSTATE_H
+#define RADIOSTATE
+
+enum radioMode { AM, FM, CD, SAT, VES, MAX_MODE };
+
+struct RadioState
+{
+    char marker1;
+    char marker2;
+    char marker3;
+    char marker4;
+    radioMode _radioMode;
+    
+    int _amPreset;
+    int _amFreq;
+    
+    int _fmPreset;
+    int _fmFreq;
+    
+    int _cdNum;
+    int _cdTrackNum;
+    int _cdHours;
+    int _cdMinutes;
+    int _cdSeconds;
+    char _cdTime[8];
+    
+    int _siriusPreset;
+    int _siriusChan;
+    char _siriusTextLine[8][64];
+    
+    int _evicMode;
+    int _evicPreset;
+    int _evicFreq;
+    
+    int _volume;
+    int _balance;
+    int _fade;
+    int _bass;
+    int _mid;
+    int _treble;
+    
+    float _batteryVoltage;
+    int _driverHeatedSeatLevel;
+    int _passHeatedSeatLevel;
+    char _vin[24];
+    int _headlights;
+    int _dimmerMode;
+    int _dimmer;
+    int _gear;
+    int _brake;
+    int _parkingBrake;
+    char _vesControls[32];
+    int _keyPosition;
+    int _rpm;
+    int _fanRequested;
+    int _fanOn;
+    int _rearDefrost;
+    int _fuel;
+    int _speed;
+    
+    int SWCButtons;
+        
+    int count ;
+};
+
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem.lib	Sat Aug 20 14:20:13 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/simon/programs/SDFileSystem/5yj8f
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WatchDogTimer.cpp	Sat Aug 20 14:20:13 2011 +0000
@@ -0,0 +1,18 @@
+#include "WatchDogTimer.h"
+
+void WatchDogTimer::kick(float s)
+{
+    LPC_WDT->WDCLKSEL = 0x1;                // Set CLK src to PCLK
+    uint32_t clk = SystemCoreClock / 16;    // WD has a fixed /4 prescaler, PCLK default is /4
+    LPC_WDT->WDTC = s * (float)clk;
+    LPC_WDT->WDMOD = 0x3;                   // Enabled and Reset
+    kick();
+}
+
+// "kick" or "feed" the dog - reset the watchdog timer
+// by writing this required bit pattern
+void WatchDogTimer::kick()
+{
+    LPC_WDT->WDFEED = 0xAA;
+    LPC_WDT->WDFEED = 0x55;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WatchDogTimer.h	Sat Aug 20 14:20:13 2011 +0000
@@ -0,0 +1,19 @@
+#ifndef WATCHDOGTIMER_H
+#define WATCHDOGTIMER_H
+
+#include "mbed.h"
+
+// Simon's Watchdog code from
+// http://mbed.org/forum/mbed/topic/508/
+class WatchDogTimer
+{
+public:
+// Load timeout value in watchdog timer and enable
+    void kick(float s);
+
+// "kick" or "feed" the dog - reset the watchdog timer
+// by writing this required bit pattern
+    void kick();
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ecu_reader.cpp	Sat Aug 20 14:20:13 2011 +0000
@@ -0,0 +1,85 @@
+#include "mbed.h"
+#include "ecu_reader.h"
+
+
+// Use a timer to see if things take too long
+Timer CANTimer;  
+namespace mbed { 
+
+
+ecu_reader::ecu_reader(CAN *c, int can_speed)
+{
+    can = c;
+    can->frequency(can_speed);
+    data.mafSensor = -1;
+    data.speed = -1;
+}
+
+void ecu_reader::request(unsigned char pid)
+{
+    char can_msg[8];
+        
+    can_msg[0] = 0x02;  
+    can_msg[1] = 0x01;
+    can_msg[2] = pid;  
+    can_msg[3] = 0;
+    can_msg[4] = 0;  
+    can_msg[5] = 0;
+    can_msg[6] = 0;  
+    can_msg[7] = 0;
+
+   if (can->write(CANMessage(PID_REQUEST, can_msg, 8)))
+   {
+   }
+}
+
+void ecu_reader::readCAN()
+{   
+    CANMessage can_MsgRx;
+
+    while (can->read(can_MsgRx))
+    {
+        if (can_MsgRx.id == PID_REPLY)
+        {
+            switch (can_MsgRx.data[2])
+            {
+                case ENGINE_RPM:
+                    data.rpm = (int)(((can_MsgRx.data[3]*256) + can_MsgRx.data[4])/4);
+                break;
+                
+                case ENGINE_COOLANT_TEMP:
+                    data.coolantTemp =  (int)(can_MsgRx.data[3] * 0.621371192);
+                break;
+
+                case MAF_SENSOR:
+                    data.mafSensor =  (int)(((can_MsgRx.data[3]*256) + can_MsgRx.data[4])/100);
+                break;
+                
+                case O2_VOLTAGE:
+                    data.o2Voltage = (int)(can_MsgRx.data[3]*0.005);
+                break;
+                
+                case THROTTLE:            //
+                    data.throttle = (int) ((can_MsgRx.data[3]*100)/255);
+                break;
+                
+                case VEHICLE_SPEED:
+                    data.speed = (int)can_MsgRx.data[3];
+                break;
+                
+                case FUEL_LEVEL:
+                    data.fuel = 100 * can_mMsgRx.data[3] / 255;
+                break;
+            }
+        }
+    }
+    
+    if ((data.mafSensor != -1) && (data.speed != -1))
+    {
+        float mph = 0.621371192 * data.speed;
+        data.mpg = mph / (data.mafSensor * 0.0804988);
+        
+        printf("Current MPG = %f\n\r", data.mpg);
+    }
+}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ecu_reader.h	Sat Aug 20 14:20:13 2011 +0000
@@ -0,0 +1,54 @@
+#ifndef ECU_READER_H
+#define ECU_READER_H
+
+#define CANSPEED_125      125000        // CAN speed at 125 kbps
+#define CANSPEED_250      250000        // CAN speed at 250 kbps
+#define CANSPEED_500      500000        // CAN speed at 500 kbps
+
+ /* Details from http://en.wikipedia.org/wiki/OBD-II_PIDs */
+#define ENGINE_COOLANT_TEMP 0x05
+#define ENGINE_RPM          0x0C
+#define VEHICLE_SPEED       0x0D
+#define MAF_SENSOR          0x10
+#define THROTTLE            0x11
+#define O2_VOLTAGE          0x14
+#define FUEL_LEVEL          0x2f
+
+#define PID_REQUEST         0x7DF
+#define PID_REPLY           0x7E8
+
+namespace mbed { 
+
+class ecu_reader{
+
+public:
+
+    ecu_reader( CAN *c, int can_speed);
+
+    void request(unsigned char pid);
+    void readCAN();
+
+private: 
+
+    CAN *can;
+    
+    struct ecu_info {
+        int coolantTemp;
+        int rpm;
+        int speed;
+        int mafSensor;
+        int throttle;
+        int o2Voltage;
+        float mpg;
+    } data;
+};
+
+
+
+
+
+    } 
+
+
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Aug 20 14:20:13 2011 +0000
@@ -0,0 +1,47 @@
+#include "mbed.h"
+#include "radioEmulator.h"
+#include "WatchDogTimer.h"
+#include "ecu_reader.h"
+
+WatchDogTimer wdt;
+
+RadioEmulator *radio;
+
+Ticker obdTicker;
+ecu_reader *obdii;
+char buffer[128];
+void readOBD(void);
+
+int main()
+{
+    CAN can1(p9,p10);
+    obdii = new ecu_reader(&can1, CANSPEED_500);     //Create object and set CAN speed
+    
+    obdTicker.attach(readOBD, 5);
+
+    wdt.kick(2);
+    radio = new RadioEmulator();
+    while (1)
+    {
+        radio->readCANbus();
+        radio->HostComm();
+        
+        obdii->readCAN();
+        
+        wdt.kick();        
+    }
+}
+
+void readOBD(void)
+{
+    printf("Trying OBD-II data\n\r");
+    
+    obdii->request(VEHICLE_SPEED);
+    obdii->request(MAF_SENSOR);
+    obdii->request(FUEL_LEVEL);
+
+    obdii->request(ENGINE_RPM);
+    obdii->request(ENGINE_COOLANT_TEMP);
+    obdii->request(THROTTLE);
+    obdii->request(O2_VOLTAGE);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.lib	Sat Aug 20 14:20:13 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/projects/libraries/svn/mbed/trunk@28
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/radioEmulator.cpp	Sat Aug 20 14:20:13 2011 +0000
@@ -0,0 +1,823 @@
+#include "mbed.h"
+#include "radioEmulator.h"
+
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+
+Timer timer;
+int begin, end;
+Serial pc(USBTX, USBRX); // tx, rx
+
+#undef CHECK_HW_SHUTDOWN
+
+//LocalFileSystem local("local");
+#include "SDFileSystem.h"
+
+SDFileSystem sd(p5, p6, p7, p8, "sd"); // the pinout on the mbed Cool Components workshop board
+
+char RadioEmulator::unlock[6] = {0x03,0x02,0x00,0x40,0x87,0xa5};
+char RadioEmulator::lock[6] = {0x01, 0x02, 0x00, 0x40, 0x87, 0xa5};
+char RadioEmulator::trunk[6] = {0x05, 0x02, 0x00, 0x40, 0x87, 0xa5};
+
+RadioEmulator::RadioEmulator()
+{
+    ethBusy = false;
+    eth = new EthernetNetIf(IpAddr(10,10,10,2), IpAddr(255,255,255,0), IpAddr(10,10,10,1), IpAddr(10,10,10,1));
+    EthernetErr ethErr = eth->setup();
+    if(ethErr)
+    {
+        printf("Error %d in setup.\n", ethErr);
+        return;
+    }
+    printf("Setup OK\r\n");
+    printf("Size of radiostate = %d\r\n", sizeof(RadioState));
+    
+    multicast = new Host(IpAddr(239, 192, 1, 100), 50000, NULL); //Join multicast group on port 50000
+    
+    udp.setOnEvent(this, &RadioEmulator::onUDPSocketEvent);
+    
+    udp.bind(*multicast);
+        
+    can2 = new CAN(p30,p29);
+    can_RS = new DigitalOut(p28);
+    canIRQ = new InterruptIn(p27);
+
+    serialCounter = 0;
+    prevSWC = 0;
+    radioOn = false;
+    for (int i = 0; i < 8; i++)
+    {
+        for (int j = 0; j < 8; j++)
+        {
+            memset(siriusText[i][j], 0, 8);
+        }
+    }
+    
+    printf("starting\r\n");
+    
+    memset(&status, 0, sizeof(status));  
+    status.marker1 = 0x42;  
+    status.marker2 = 0x42;  
+    status.marker3 = 0x42;  
+    status.marker4 = 0x42;  
+    status._radioMode = SAT;
+//    readInitFile();
+    status._volume = 10;
+    status._bass = 15;
+    status._mid = 13;
+    status._treble = 14;
+    status._balance = 10;
+    status._fade = 10;
+
+    for (int i = 0; i < 8; i++)
+    {
+        sprintf(status._siriusTextLine[i], "Fun line text # %d", i);
+    }
+
+    PowerUp();
+    
+    ReceivedHostMsg = false;
+    statusTicker.attach(this, &RadioEmulator::SendStatusToHost, 0.1);
+
+    opMode = standalone;
+    HostTimeout.attach(this, &RadioEmulator::CheckHostTimeout, 1);
+}
+
+void RadioEmulator::readInitFile()
+{
+    FILE *fp = fopen("/sd/stereo.txt", "r");  // Open "out.txt" on the local file system for writing
+    char temp[100];
+        
+    while ( fscanf(fp, "%s", temp) > 0)
+    {
+        if (strcmp(temp, "volume") == 0)
+        {
+            fscanf(fp, "%d", &status._volume);
+        }
+        if (strcmp(temp, "bass") == 0)
+        {
+            fscanf(fp, "%d", &status._bass);
+        }
+        if (strcmp(temp, "mid") == 0)
+        {
+            fscanf(fp, "%d", &status._mid);
+        }
+        if (strcmp(temp, "treble") == 0)
+        {
+            fscanf(fp, "%d", &status._treble);
+        }
+        if (strcmp(temp, "balance") == 0)
+        {
+            fscanf(fp, "%d", &status._balance);
+        }
+        if (strcmp(temp, "fade") == 0)
+        {
+            fscanf(fp, "%d", &status._fade);
+        }
+        if (strcmp(temp, "MAC") == 0)
+        {
+            char temp2[64];
+            fscanf(fp, "%s", temp2);
+            char *pEnd;
+            hostMACAddress[0] = strtoul(temp2, &pEnd, 16);
+            hostMACAddress[1] = strtoul(pEnd, &pEnd, 16);
+            hostMACAddress[2] = strtoul(pEnd, &pEnd, 16);
+            hostMACAddress[3] = strtoul(pEnd, &pEnd, 16);
+            hostMACAddress[4] = strtoul(pEnd, &pEnd, 16);
+            hostMACAddress[5] = strtoul(pEnd, &pEnd, 16);
+        }
+    }
+    
+    fclose(fp);
+}
+
+void RadioEmulator::writeInitFile()
+{
+    FILE *fp = fopen("/sd/stereo.txt", "w");  // Open "out.txt" on the local file system for writing
+
+    fprintf(fp,"volume %d\r\n", status._volume);
+    fprintf(fp,"bass %d\r\n", status._bass);
+    fprintf(fp,"mid %d\r\n", status._mid);
+    fprintf(fp,"treble %d\r\n", status._treble);
+    fprintf(fp,"balance %d\r\n", status._balance);
+    fprintf(fp,"fade %d\r\n", status._fade);
+    fclose(fp);
+}
+
+void RadioEmulator::WriteCANMessages()
+{
+    if (radioOn)
+    {
+        led2 = !led2;
+        SendRadioModeMsg();
+        SendEVICMsg();
+        SendStereoSettingsMsg();
+        SendHostMessages();
+    }
+}
+
+void RadioEmulator::SendOnMsg()
+{
+    CANMessage msg;
+    msg.id = 0x416;
+    msg.len = 8;
+    char temp[8] = {0xfe, 0x1b, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff};
+    memcpy(msg.data, temp, 8);
+    can2->write(msg);
+}
+
+void RadioEmulator::SendRadioModeMsg()
+{
+    CANMessage msg;
+    msg.id = 0x09F;
+    msg.len = 8;
+
+    msg.data[7] = 0x0f;
+    msg.data[6] = 0xff;
+    msg.data[5] = 0xff;
+    msg.data[4] = 0xff;
+    msg.data[3] = 0x07;
+    msg.data[2] = 0x00;
+    msg.data[1] = 0x00;
+    msg.data[0] = 0x00;
+
+    if (status._radioMode == AM)
+    {
+        if (status._amPreset != 0)
+        {
+            msg.data[0] = (status._amPreset + 1) << 4;
+        }
+        msg.data[1] = (status._amFreq & 0xFF00) >> 8;
+        msg.data[2] = (status._amFreq & 0x00FF);
+    }
+    else if (status._radioMode == FM)
+    {
+        if (status._fmPreset != 0)
+        {
+            msg.data[0] = (status._fmPreset + 1) << 4;
+        }
+        msg.data[0] |= 0x01;
+        msg.data[1] = (status._fmFreq & 0xFF00) >> 8;
+        msg.data[2] = (status._fmFreq & 0x00FF);
+    }
+    else if (status._radioMode == CD)
+    {
+        msg.data[0] = status._cdNum << 4;
+        msg.data[1] = 0x20;
+        msg.data[0] |= 0x03;
+        msg.data[2] = status._cdTrackNum;
+        msg.data[4] = status._cdHours;
+        msg.data[5] = status._cdMinutes;
+        msg.data[6] = status._cdSeconds;
+    }
+    else if (status._radioMode == SAT)
+    {
+        if (status._siriusPreset != 0)
+        {
+            msg.data[0] = (status._siriusPreset + 1) << 4;
+        }
+        msg.data[0] |= 0x04;
+        msg.data[1] = 0;
+        msg.data[2] = status._siriusChan;
+    }
+    else if (status._radioMode == VES)
+    {
+        msg.data[0] = 0x16;
+        msg.data[1] = 0x10;
+        msg.data[2] = 0x01;
+    }
+
+    msg.data[1] |= 0x10;
+
+    can2->write(msg);
+}
+
+void RadioEmulator::SendEVICMsg()
+{
+    CANMessage msg;
+    msg.id = 0x394;
+    msg.len = 6;
+    
+    memset(msg.data, 0, 8);
+
+    if (status._radioMode == AM)
+    {
+        if (status._amPreset != 0)
+        {
+            msg.data[0] = (status._amPreset + 1) << 4;
+        }
+        msg.data[1] = (status._amFreq & 0xFF00) >> 8;
+        msg.data[2] = (status._amFreq & 0x00FF);
+    }
+    else
+    {
+        if (status._fmPreset != 0)
+        {
+            msg.data[0] = (status._fmPreset + 1) << 4;
+        }
+        msg.data[0] |= 0x01;
+        msg.data[1] = (status._fmFreq & 0xFF00) >> 8;
+        msg.data[2] = (status._fmFreq & 0x00FF);
+    }
+
+    can2->write(msg);
+}
+
+void RadioEmulator::SendStereoSettingsMsg()
+{
+    CANMessage msg;
+    msg.id = 0x3D0;
+    msg.len = 7;
+
+    msg.data[0] = status._volume;
+    msg.data[1] = status._balance;
+    msg.data[2] = status._fade;
+    msg.data[3] = status._bass;
+    msg.data[4] = status._mid;
+    msg.data[5] = status._treble;
+
+    can2->write(msg);
+}
+
+void RadioEmulator::SendHostMessages()
+{
+    can2->write(hostMessages.front());
+    
+    hostMessages.pop_front();
+}
+
+void RadioEmulator::ChangeSiriusStation(int station, bool turn_on)
+{
+    CANMessage msg;
+    msg.id = 0x3B0;
+    msg.len = 6;
+
+    if (turn_on)
+    {
+        msg.data[0] = 21;
+    }
+    else
+    {
+        msg.data[0] = 23;
+    }
+    msg.data[1] = station;
+
+    can2->write(msg);
+
+    memset(msg.data, 0, 8);
+    msg.data[1] = station;
+
+    can2->write(msg);
+    
+    status._siriusChan = station;
+}
+
+void RadioEmulator::ParseCANMessage(CANMessage can_MsgRx)
+{
+    if (can_MsgRx.id == 0x000)
+    {
+        if (can_MsgRx.data[0] > 1)
+        {
+            radioOn = true;
+        }
+        else
+        {
+            radioOn = false;
+        }
+    }
+    
+    // this message seems to be a message requesting all other devices
+    // to start announcing their presence
+    if ((can_MsgRx.id >= 0x400) && (can_MsgRx.data[0] == 0xfd))
+    {
+//      SendOnMsg();
+    }
+    
+    if (can_MsgRx.id == 0x012)
+    {
+        if (memcmp(can_MsgRx.data, unlock, 6) == 0)
+        {
+        }
+        else if (memcmp(can_MsgRx.data, lock, 6) == 0)
+        {
+        }
+        else if (memcmp(can_MsgRx.data, trunk, 6) == 0)
+        {
+        }
+    }
+
+    if (can_MsgRx.id == 0x1bd)
+    {
+        // SDAR status
+        
+        if (status._siriusChan == 0)
+        {
+            status._siriusChan = can_MsgRx.data[1];
+        }
+
+        if (can_MsgRx.data[0] == 0x85)
+        {
+            ChangeSiriusStation(status._siriusChan, true);
+        }
+        
+        if (status._siriusChan != can_MsgRx.data[1])
+        {
+            ChangeSiriusStation(status._siriusChan, true);
+        }
+    }
+    
+    if (can_MsgRx.id == 0x3bd)
+    {
+        ReadSiriusText((char *)can_MsgRx.data);
+    }
+
+    if (can_MsgRx.id == 0x3a0)
+    {        
+        // note = 0x01
+        // volume up = 0x02
+        // volume down = 0x04
+        // up arrow = 0x08
+        // down arrow = 0x10
+        // right arrow = 0x20
+               
+        status.SWCButtons = can_MsgRx.data[0];
+    }
+
+    if (can_MsgRx.id == 0x000)
+    {
+        status._keyPosition = can_MsgRx.data[0];
+    }
+    else if (can_MsgRx.id == 0x002)
+    {
+        status._rpm = (can_MsgRx.data[0] << 8) + can_MsgRx.data[1];
+        status._speed = ((can_MsgRx.data[2] << 8) + can_MsgRx.data[3]) / 200;
+    }
+    else if (can_MsgRx.id == 0x003)
+    {
+        status._brake = can_MsgRx.data[3] & 0x01;
+        status._gear = can_MsgRx.data[4];
+    }
+    else if (can_MsgRx.id == 0x15)
+    {
+        status._batteryVoltage = (float)(can_MsgRx.data[1]) / 10;
+    }
+    else if (can_MsgRx.id == 0x01b)
+    {
+        // vin number
+        int part = can_MsgRx.data[0];
+        if (part < 3)
+        {
+            for (int i = 1; i < 8; i++)
+            {
+                status._vin[(part*8) + i-1] = can_MsgRx.data[i];
+            }
+        }
+    }
+    else if (can_MsgRx.id == 0x0d0)
+    {
+        if (can_MsgRx.data[0] == 0x80)
+        {
+            status._parkingBrake = true;
+        }
+        else
+        {
+            status._parkingBrake = false;
+        }                    
+    }
+    else if (can_MsgRx.id == 0x0EC)
+    {
+        if ((can_MsgRx.data[0] & 0x40) == 0x40)
+        {
+            status._fanRequested = true;
+        }
+        else
+        {
+            status._fanRequested = false;
+        }
+
+        if ((can_MsgRx.data[0] & 0x01) == 0x01)
+        {
+            status._fanOn = true;
+        }
+        else
+        {
+            status._fanOn = false;
+        }
+    }
+    else if (can_MsgRx.id == 0x159)
+    {
+        status._fuel = can_MsgRx.data[5];
+    }
+    else if (can_MsgRx.id == 0x1a2)
+    {
+        if ((can_MsgRx.data[0] & 0x80) == 0x80)
+        {
+            status._rearDefrost = true;
+        }
+        else
+        {
+            status._rearDefrost = false;
+        }
+
+        if ((can_MsgRx.data[0] & 0x40) == 0x40)
+        {
+            status._fanRequested = true;
+        }
+        else
+        {
+            status._fanRequested = false;
+        }
+
+        if ((can_MsgRx.data[0] & 0x01) == 0x01)
+        {
+            status._fanOn = true;
+        }
+        else
+        {
+            status._fanOn = false;
+        }
+    }
+    else if (can_MsgRx.id == 0x1c8)
+    {
+        status._headlights = can_MsgRx.data[0];
+    }
+    else if (can_MsgRx.id == 0x210)
+    {
+        status._dimmerMode = can_MsgRx.data[0];
+        if (can_MsgRx.data[0] == 0x03)
+        {
+            status._dimmer = -1;
+        }
+        else if (can_MsgRx.data[0] == 0x02)
+        {
+            status._dimmer = can_MsgRx.data[1];
+        }
+    }
+}
+
+void RadioEmulator::ReadSiriusText(char *data)
+{
+    int num = (data[0] & 0xF0) >> 4;
+    if (num > 7)
+    {
+        return;
+    }
+    
+    if ((data[0] & 0x01) == 1)
+    {
+        for (int i = 0; i < 8; i++)
+        {
+            memset(siriusText[num][i], 0, 8);
+        }
+    }
+    int part = (data[0] & 0x0E) >> 1;
+    if (part > 7)
+    {
+        return;
+    }
+    
+    memset(siriusText[num][part], 0, 8);
+    char tempString[8] = "";
+    memset(tempString,0,8);
+    
+    for (int i = 1; i < 8; i++)
+    {
+        tempString[i-1] = data[i];
+    }
+    
+    strncpy(siriusText[num][part],tempString,7);
+
+    int cls = (data[0] & 0x0F) >> 1;
+    if (cls - 1 == 0)
+    {
+        for (int i = 0; i < 8; i++)
+        {
+            memset(status._siriusTextLine[i], 0, 64);
+            for (int j = 0; j < 8; j++)
+            {
+                strcat(status._siriusTextLine[i], siriusText[i][j]);
+            }
+            
+            printf("%d: %s\r\n", i, status._siriusTextLine[i]);
+        }
+    }
+}
+
+void RadioEmulator::readCANbus(void)
+{
+    if (can2->read(can_MsgRx))
+    {
+        led3 = !led3;
+        needToParseCANMessage = true;
+        ReceivedCANMsg = true;
+        
+        
+        char buffer[11];
+        buffer[0] = (can_MsgRx.id & 0xFF00) >> 8;
+        buffer[1] = can_MsgRx.id & 0x00FF;
+        buffer[2] = can_MsgRx.len;
+        memcpy(&buffer[3], can_MsgRx.data, 8);
+        
+        static Host multicast3(IpAddr(239, 192, 1, 100), 41000, NULL); //Join multicast group on port 50000
+        
+        while (ethBusy == true) {};
+        ethBusy = true;
+        udp.sendto(buffer, 11, &multicast3);
+        ethBusy = false;
+    }
+    
+    if (needToParseCANMessage)
+    {           
+        needToParseCANMessage = false;   
+        
+        ParseCANMessage(can_MsgRx);
+    }
+}
+
+void RadioEmulator::HostComm(void)
+{
+    Net::poll();              
+}
+
+void RadioEmulator::onUDPSocketEvent(UDPSocketEvent e)
+{
+    switch(e)
+    {
+        case UDPSOCKET_READABLE: //The only event for now
+            char buf[64] = {0};
+            Host host;
+            while( int len = udp.recvfrom( buf, 63, &host ) )
+            {
+                if( len <= 0 )
+                    break;
+                    
+                HandleHostComm(buf, len);
+            }
+        break;
+    }
+}
+
+void RadioEmulator::HandleHostComm(char *msg, int len)
+{
+    if ((msg[0] == 0x42) && (msg[1] == 0x42) && (msg[2] == 0x42) && (msg[3] == 0x42))
+    {
+        ReceivedHostMsg = true;
+        
+        switch (msg[4])
+        {
+            case 0x00:
+                opMode = slave;
+            break;
+            
+            case 0x01:
+                status._volume = msg[5];
+                status._balance = msg[6];
+                status._fade = msg[7];
+                status._bass = msg[8];
+                status._mid = msg[9];
+                status._treble = msg[10];
+                
+//              writeInitFile();
+            break;
+            
+            case 0x02:
+                status._siriusChan = msg[5];
+                ChangeSiriusStation(msg[5], false);
+            break;
+            
+            case 0x03:
+                status._radioMode = (radioMode)msg[5];
+                
+                switch (status._radioMode)
+                {
+                    case AM:
+                        status._amPreset = msg[6];
+                        status._amFreq = msg[7] + (msg[8] << 8);
+                    break;
+                    
+                    case FM:
+                        status._fmPreset = msg[6];
+                        status._fmFreq = msg[7] + (msg[8] << 8);
+                    break;
+                    
+                    case SAT:
+                        status._siriusPreset = msg[6];
+                        status._siriusChan = msg[7];
+                    break;
+                    
+                    case CD:
+                        status._cdNum = msg[6];
+                        status._cdTrackNum = msg[7];
+                        status._cdHours = msg[8];
+                        status._cdMinutes = msg[9];
+                        status._cdSeconds =  msg[10];
+                    break;
+                    
+                    case VES:
+                    break;
+                }
+            break;
+            
+            case 0x04:
+                CANMessage canMsg;
+                canMsg.id = msg[5] + (msg[6] << 8);
+                canMsg.len = msg[7];
+                memcpy(canMsg.data, msg + 8, canMsg.len);
+                
+                hostMessages.push_back(canMsg);
+            break;
+                
+        }
+
+    }
+}
+
+void RadioEmulator::SendStatusToHost(void)
+{
+    int size = sizeof(status);
+    
+    if (opMode == standalone)
+    {
+        if (status.SWCButtons == 0)
+        {
+            if ((prevSWC & 0x00000004) != 0)
+            {
+                if (status._volume > 0)
+                    status._volume --;
+            }
+            else if ((prevSWC & 0x00000002) != 0)
+            {
+                if (status._volume < 40)
+                    status._volume ++;
+            }
+            else if ((prevSWC & 0x00000010) != 0)
+            {
+                if (status._siriusChan > 0)
+                    ChangeSiriusStation(status._siriusChan-1, false);
+            }
+            else if ((prevSWC & 0x00000008) != 0)
+            {
+                if (status._siriusChan < 256)
+                    ChangeSiriusStation(status._siriusChan+1, false);
+            }
+            else if ((prevSWC & 0x00000001) != 0)
+            {
+                for (int i = 0; i < 5; i++)
+                {
+//                    SendWOLPacket();
+                }
+            }
+        }
+    }
+
+    prevSWC = status.SWCButtons;
+
+    status.count++;    
+    RadioState tempStatus;
+    memcpy(&tempStatus, &status, size);
+    char *data = (char *)&tempStatus;
+ 
+    static Host multicast2(IpAddr(239, 192, 1, 100), 51000, NULL); //Join multicast group on port 50000
+    while (ethBusy == true) {};
+    ethBusy = true;
+    udp.sendto(data, size, &multicast2);
+    ethBusy = false;
+}
+
+void RadioEmulator::PowerUp(void)
+{
+    led1 = 1;
+    poweredDown = 0;
+    needToParseCANMessage = false;   
+    LPC_CAN2->BTR = 0x52001C;
+    *can_RS = 0;
+    ReceivedCANMsg = false;
+
+/*
+#ifdef CHECK_HW_SHUTDOWN
+    canIRQ->rise(this, &RadioEmulator::StartEmulation);
+#else
+*/
+    StartEmulation();
+//#endif
+}
+
+void RadioEmulator::StartEmulation(void)
+{
+//    canIRQ->rise(0);
+    
+    CANBusTicker.attach(this, &RadioEmulator::WriteCANMessages, 0.5);
+
+    ChangeSiriusStation(status._siriusChan, true);
+    
+//    CANTimeout.attach(this, &RadioEmulator::CheckCANTimeout, 1);
+
+/*    
+    for (int i = 0; i < 5; i++)
+    {
+        SendWOLPacket();
+    }
+*/
+}
+
+void RadioEmulator::CheckCANTimeout(void)
+{
+    if (!ReceivedCANMsg)
+    {
+        led1 = 0;
+        // Need to Power Down
+       
+        CANBusTicker.detach();
+        CANTimeout.detach(); 
+                
+        *can_RS = 1;
+        
+        canIRQ->rise(this, &RadioEmulator::RestartCAN);
+    }
+    
+    ReceivedCANMsg = false;
+}
+
+void RadioEmulator::CheckHostTimeout(void)
+{
+    if (!ReceivedHostMsg)
+    {
+        led4 = 1;
+        opMode = standalone;
+    }
+    else
+    {
+        led4 = 0;
+    }
+
+    ReceivedHostMsg = false;
+}
+
+void RadioEmulator::RestartCAN(void)
+{
+    if (poweredDown == 5)
+    {
+        canIRQ->rise(NULL);
+        PowerUp();
+    }
+    poweredDown++;
+}
+
+void RadioEmulator::SendWOLPacket(void)
+{
+    unsigned char data[102];
+    memset(data, 0xff, 6);
+    
+    for (int i = 0; i < 16; i++)
+    {
+        memcpy(data + 6 + (16 * i), hostMACAddress, 6);
+    }
+    static Host wol(IpAddr(10, 10, 10, 255), 7, NULL);
+
+    while (ethBusy == true) {};
+    ethBusy = true;    
+    udp.sendto((char *)data, 102, &wol);
+    ethBusy = false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/radioEmulator.h	Sat Aug 20 14:20:13 2011 +0000
@@ -0,0 +1,107 @@
+#ifndef RADIOEMULATOR_H
+#define RADIOEMULATOR_H
+
+#include "mbed.h"
+
+#include "EthernetNetIf.h"
+#include "UDPSocket.h"
+
+#include "RadioState.h"
+
+class RadioEmulator
+{
+public:
+    RadioEmulator();
+    ~RadioEmulator() {};
+    
+    void readCANbus(void);
+    void HostComm(void);
+
+//private:
+
+    void serialReceiver(void);
+    
+    void StartEmulation();
+    void SendOnMsg();
+    void SendEVICMsg();
+    void SendRadioModeMsg();
+    void SendStereoSettingsMsg();
+    void SendHostMessages();
+    
+    void ChangeSiriusStation(int station, bool turn_on);
+    
+    void readInitFile();
+    void writeInitFile();
+    void PowerUp(void);
+    
+    void WriteCANMessages();
+    Ticker CANBusTicker;
+    
+    void SendStatusToHost();
+    Ticker statusTicker;
+    
+    CAN *can2;
+    CANMessage can_MsgRx;
+    DigitalOut *can_RS;
+    InterruptIn *canIRQ;
+    void RestartCAN(void);
+    
+
+    EthernetNetIf *eth;
+    UDPSocket udp;
+    Host *multicast;
+    Host *multicast2;
+
+    bool ethBusy;
+    void HandleHostComm(char *msg, int len);
+    void onUDPSocketEvent(UDPSocketEvent e);
+
+    int poweredDown;
+      
+    bool radioOn;
+    
+    void ParseCANMessage(CANMessage can_MsgRx);
+    void ReadSiriusText(char *data);    
+    char siriusText[8][8][8];
+    
+    
+    char serialCounter;
+    char msg[14];    
+
+    static char unlock[6];
+    static char lock[6];
+    static char trunk[6];
+    
+    
+    RadioState status;    
+    
+    std::list<CANMessage> hostMessages;
+    
+/*
+    Timeout buttonTimeout;
+    void ClickTimeout(void);
+    int prevSWC;
+    int buttonClicks[6];
+    bool buttonHeld[6];
+    bool reportButtonClick;
+    bool buttonClickTimedOut;
+*/
+
+    bool ReceivedCANMsg;
+    void CheckCANTimeout(void);
+    Ticker CANTimeout;
+    bool needToParseCANMessage;
+
+    bool ReceivedHostMsg;
+    void CheckHostTimeout(void);
+    Ticker HostTimeout;
+    
+    enum {standalone, slave} opMode;
+    
+    void SendWOLPacket(void);
+    unsigned char hostMACAddress[6];
+    
+    int prevSWC;
+};
+
+#endif
\ No newline at end of file