Just4Trionic - CAN and BDM FLASH programmer for Saab cars

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
Just4pLeisure
Date:
Tue Dec 14 21:50:35 2010 +0000
Parent:
1:d5452e398b76
Child:
3:92dae9083c83
Commit message:
Update for change to BDM DSO connection (and removed DS) fixed a bug that prevented BDM mode detecting Trionic 7 ECUs

Changed in this revision

bdm.cpp Show annotated file Show diff for this revision Revisions of this file
bdmcpu32.cpp Show annotated file Show diff for this revision Revisions of this file
bdmcpu32.h Show annotated file Show diff for this revision Revisions of this file
bdmtrionic.cpp Show annotated file Show diff for this revision Revisions of this file
canutils.cpp Show annotated file Show diff for this revision Revisions of this file
common.h Show annotated file Show diff for this revision Revisions of this file
interfaces.cpp Show annotated file Show diff for this revision Revisions of this file
interfaces.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
--- a/bdm.cpp	Tue Sep 14 21:02:04 2010 +0000
+++ b/bdm.cpp	Tue Dec 14 21:50:35 2010 +0000
@@ -116,7 +116,7 @@
 // Set some initial values to help with checking if the BDM connector is plugged in
     PIN_PWR.mode(PullDown);
     PIN_NC.mode(PullUp);
-    PIN_DS.mode(PullUp);
+//    PIN_DS.mode(PullUp);
     PIN_FREEZE.mode(PullUp);
     PIN_DSO.mode(PullUp);
 
@@ -188,7 +188,7 @@
 //                    printf("%02x", (BDM_PIN & 0x3f));
                     printf("PWR %d, ", PIN_PWR.read());
                     printf("NC %d, ", PIN_NC.read());
-                    printf("DS %d, ", PIN_DS.read());
+//                    printf("DS %d, ", PIN_DS.read());
                     printf("FREEZE %d, ", PIN_FREEZE.read());
                     printf("DSO %d, ", PIN_DSO.read());
                     return TERM_OK;
--- a/bdmcpu32.cpp	Tue Sep 14 21:02:04 2010 +0000
+++ b/bdmcpu32.cpp	Tue Dec 14 21:50:35 2010 +0000
@@ -73,6 +73,7 @@
 bool bdm_write(const uint32_t* addr, uint16_t cmd, const uint32_t* value);
 //bool bdm_write_overlap(const uint32_t* addr, uint16_t cmd, const uint32_t* value, uint16_t next_cmd);
 void bdm_clk(uint16_t value, uint8_t num_bits);
+void bdm_clk_fast(uint16_t value, uint8_t num_bits);
 void bdm_clear();
 
 //-----------------------------------------------------------------------------
@@ -613,7 +614,7 @@
     if (!bdm_command(BDM_READ + BDM_BYTESIZE)) return TERM_ERR;
     // write the optional address
     if (addr) {
-        if(!bdm_address(addr)) return TERM_ERR;
+        if (!bdm_address(addr)) return TERM_ERR;
     }
 
     return TERM_OK;
@@ -636,7 +637,7 @@
     if (bdm_response > BDM_CMDCMPLTE) return TERM_ERR;
     // write the optional address
     if (addr) {
-        if(!bdm_address(addr)) return TERM_ERR;
+        if (!bdm_address(addr)) return TERM_ERR;
     }
 
     return TERM_OK;
@@ -659,7 +660,7 @@
     if (bdm_response > BDM_CMDCMPLTE) return TERM_ERR;
     // write the optional address
     if (addr) {
-        if(!bdm_address(addr)) return TERM_ERR;
+        if (!bdm_address(addr)) return TERM_ERR;
     }
 
     return TERM_OK;
@@ -675,12 +676,12 @@
 uint8_t memwrite_byte_cmd(const uint32_t* addr) {
 
     if (!IN_BDM) return TERM_ERR;
-    
+
     // write command code
     if (!bdm_command(BDM_WRITE + BDM_BYTESIZE)) return TERM_ERR;
     // write the optional address
     if (addr) {
-        if(!bdm_address(addr)) return TERM_ERR;
+        if (!bdm_address(addr)) return TERM_ERR;
     }
 
     return TERM_OK;
@@ -703,7 +704,7 @@
     if (bdm_response > BDM_CMDCMPLTE) return TERM_ERR;
     // write the optional address
     if (addr) {
-        if(!bdm_address(addr)) return TERM_ERR;
+        if (!bdm_address(addr)) return TERM_ERR;
     }
 
     return TERM_OK;
@@ -726,7 +727,7 @@
     if (bdm_response > BDM_CMDCMPLTE) return TERM_ERR;
     // write the optional address
     if (addr) {
-        if(!bdm_address(addr)) return TERM_ERR;
+        if (!bdm_address(addr)) return TERM_ERR;
     }
 
     return TERM_OK;
@@ -747,7 +748,7 @@
     if (!IN_BDM) return TERM_ERR;
     // write the optional address
     if (addr) {
-        if(!bdm_address(addr)) return TERM_ERR;
+        if (!bdm_address(addr)) return TERM_ERR;
     }
     // receive the response byte
     return (bdm_get ((uint32_t*)result, BDM_BYTESIZE, BDM_READ + BDM_BYTESIZE)) ? TERM_OK : TERM_ERR;
@@ -768,7 +769,7 @@
     if (!IN_BDM) return TERM_ERR;
     // write the optional address
     if (addr) {
-        if(!bdm_address(addr)) return TERM_ERR;
+        if (!bdm_address(addr)) return TERM_ERR;
     }
     // receive the response byte
     return (bdm_get((uint32_t*)result, BDM_BYTESIZE, BDM_WRITE + BDM_BYTESIZE)) ? TERM_OK : TERM_ERR;
@@ -789,7 +790,7 @@
     if (!IN_BDM) return TERM_ERR;
     // write the optional address
     if (addr) {
-        if(!bdm_address(addr)) return TERM_ERR;
+        if (!bdm_address(addr)) return TERM_ERR;
     }
     // receive the response byte
     return (bdm_get((uint32_t*)result, BDM_BYTESIZE, BDM_NOP)) ? TERM_OK : TERM_ERR;
@@ -810,7 +811,7 @@
     if (!IN_BDM) return TERM_ERR;
     // write the optional address
     if (addr) {
-        if(!bdm_address(addr)) return TERM_ERR;
+        if (!bdm_address(addr)) return TERM_ERR;
     }
     // write the value
     if (!bdm_put((uint32_t*)&value, BDM_BYTESIZE)) return TERM_ERR;
@@ -833,7 +834,7 @@
     if (!IN_BDM) return TERM_ERR;
     // write the optional address
     if (addr) {
-        if(!bdm_address(addr)) return TERM_ERR;
+        if (!bdm_address(addr)) return TERM_ERR;
     }
     // write the value
     if (!bdm_put((uint32_t*)&value, BDM_BYTESIZE)) return TERM_ERR;
@@ -856,7 +857,7 @@
     if (!IN_BDM) return TERM_ERR;
     // write the optional address
     if (addr) {
-        if(!bdm_address(addr)) return TERM_ERR;
+        if (!bdm_address(addr)) return TERM_ERR;
     }
     // write the value
     if (!bdm_put((uint32_t*)&value, BDM_BYTESIZE)) return TERM_ERR;
@@ -870,30 +871,21 @@
     Writes 2 words to the same address
     The BDM commands are overlapped to make things a bit faster
     A BDM_NOP command is then sent to end the sequence of overlapping commands
-    
+
     @param        addr          address
                   value1, 2     values to write
 
     @return                     status flag
 */
 uint8_t memwrite_word_write_word(const uint32_t* addr, const uint16_t value1, const uint16_t value2) {
-
-    if (!IN_BDM) return TERM_ERR;
-
-    // write command code
-    if (!bdm_command(BDM_WRITE + BDM_WORDSIZE)) return TERM_ERR;
-    // write the address
-    if (!bdm_address(addr)) return TERM_ERR;
-    // write the first value
-    if (!bdm_put((uint32_t*)&value1, BDM_WORDSIZE)) return TERM_ERR;
-    // wait until MCU responds and overlap the next write command
-    if (!bdm_ready(BDM_WRITE + BDM_WORDSIZE)) return TERM_ERR;
-    // write the address (same address for second word)
-    if (!bdm_address(addr)) return TERM_ERR;
-    // write the second value
-    if (!bdm_put((uint32_t*)&value2, BDM_WORDSIZE)) return TERM_ERR;
-    // wait until MCU responds
-    return (bdm_ready(BDM_NOP)) ? TERM_OK : TERM_ERR;
+    return (IN_BDM &&
+        bdm_command(BDM_WRITE + BDM_WORDSIZE) &&        // write command code
+        bdm_address(addr) &&                            // write the address
+        bdm_put((uint32_t*)&value1, BDM_WORDSIZE) &&    // write the first value
+        bdm_ready(BDM_WRITE + BDM_WORDSIZE) &&          // wait until MCU responds and overlap the next write command
+        bdm_address(addr) &&                            // write the address (same address for second word)
+        bdm_put((uint32_t*)&value2, BDM_WORDSIZE) &&    // write the second value
+        bdm_ready(BDM_NOP)) ? TERM_OK : TERM_ERR;       // wait until MCU responds
 }
 
 //-----------------------------------------------------------------------------
@@ -910,21 +902,13 @@
 */
 
 uint8_t memwrite_word_read_word(uint16_t* result, const uint32_t* addr, const uint16_t value) {
-
-    if (!IN_BDM) return TERM_ERR;
-
-    // write command code
-    if (!bdm_command(BDM_WRITE + BDM_WORDSIZE)) return TERM_ERR;
-    // write the address
-    if (!bdm_address(addr)) return TERM_ERR;
-    // write the value
-    if (!bdm_put((uint32_t*)&value, BDM_WORDSIZE)) return TERM_ERR;
-    // wait until MCU responds and overlap the next read command
-    if (!bdm_ready(BDM_READ + BDM_WORDSIZE)) return TERM_ERR;
-    // write the address (same address for reading the result)
-    if (!bdm_address(addr)) return TERM_ERR;
-    // receive the response word
-    return (bdm_get((uint32_t*)result, BDM_WORDSIZE, BDM_NOP)) ? TERM_OK : TERM_ERR;
+    return (IN_BDM &&
+        bdm_command(BDM_WRITE + BDM_WORDSIZE) &&        // write command code
+        bdm_address(addr) &&                            // write the address
+        bdm_put((uint32_t*)&value, BDM_WORDSIZE) &&     // write the value
+        bdm_ready(BDM_READ + BDM_WORDSIZE) &&           // wait until MCU responds and overlap the next read command
+        bdm_address(addr) &&                            // write the address (same address for reading the result)
+        bdm_get((uint32_t*)result, BDM_WORDSIZE, BDM_NOP)) ? TERM_OK : TERM_ERR;    // receive the response word
 }
 
 //-----------------------------------------------------------------------------
@@ -1169,19 +1153,19 @@
 
 bool bdm_command (uint16_t cmd) {
     // write command code
-    bdm_clk(cmd, CMD_BIT_COUNT);
+    bdm_clk_fast(cmd, CMD_BIT_COUNT);
     return (bdm_response > BDM_NOTREADY) ? false : true;
 }
 
 bool bdm_address (const uint32_t* addr) {
     // write an address
     // first word
-    bdm_clk((uint16_t)((*addr) >> 16), CMD_BIT_COUNT);
+    bdm_clk_fast((uint16_t)((*addr) >> 16), CMD_BIT_COUNT);
     if (bdm_response > BDM_NOTREADY) {
         return false;
     }
     // second word
-    bdm_clk((uint16_t)(*addr), CMD_BIT_COUNT);
+    bdm_clk_fast((uint16_t)(*addr), CMD_BIT_COUNT);
     return (bdm_response > BDM_NOTREADY) ? false : true;
 }
 
@@ -1194,7 +1178,7 @@
         // wait while MCU prepares the response
         wait_cnt = ERR_COUNT;
         do {
-            bdm_clk(next_cmd, CMD_BIT_COUNT);
+            bdm_clk_fast(next_cmd, CMD_BIT_COUNT);
         } while (bdm_response == BDM_NOTREADY && --wait_cnt > 0);
 
         // save the result
@@ -1212,12 +1196,12 @@
 bool bdm_put (const uint32_t* value, uint8_t size) {
     // write the value
     if (size & BDM_LONGSIZE) {
-        bdm_clk((uint16_t)((*value) >> 16), CMD_BIT_COUNT);
+        bdm_clk_fast((uint16_t)((*value) >> 16), CMD_BIT_COUNT);
         if (bdm_response > BDM_NOTREADY) {
             return false;
         }
     }
-    bdm_clk((uint16_t)(*value), CMD_BIT_COUNT);
+    bdm_clk_fast((uint16_t)(*value), CMD_BIT_COUNT);
     return (bdm_response > BDM_NOTREADY) ? false : true;
 }
 
@@ -1226,7 +1210,7 @@
     uint8_t wait_cnt = ERR_COUNT;
     do {
         // read response
-        bdm_clk(next_cmd, CMD_BIT_COUNT);
+        bdm_clk_fast(next_cmd, CMD_BIT_COUNT);
     } while (bdm_response == BDM_NOTREADY && --wait_cnt > 0);
 
     // check if command succeeded
@@ -1242,42 +1226,77 @@
 */
 void bdm_clk(uint16_t value, uint8_t num_bits) {
 //    PIN_BKPT.output();
-//    PIN_DSI.output();
-    LPC_GPIO2->FIODIR |= 0x00000004;
+    PIN_DSI.output();
     // clock the value via BDM
     bdm_response = ((uint32_t)value) << (32 - num_bits);
 //    bool dsi;
-
     while (num_bits--) {
 
         // falling edge on BKPT/DSCLK
         PIN_BKPT.write(0);
-
         // set DSI bit
         PIN_DSI.write(bdm_response & 0x80000000);
         bdm_response <<= 1;
-
         // read DSO bit
         bdm_response |= PIN_DSO.read();
-
         // short delay
 //        for (uint8_t c = 1; c; c--);
 //        wait_us(1);
-
         // rising edge on BKPT/DSCLK
         PIN_BKPT.write(1);
-
         // short delay
         for (uint8_t c = 1; c; c--);
 //        wait_us(1);
     }
-
     PIN_DSI.input();
-//    LPC_GPIO2->FIODIR &= 0xfffffffb;
 }
 
 //-----------------------------------------------------------------------------
 /**
+    Writes a word to target MCU via BDM line and gets the response.
+    This 'fast' version can be used once the 68332 has been 'prepped'
+    because the BDM interface can go twice as fast once the 68332
+    clock is increased from 8 MHz to 16 MHz
+
+    @param            value            value to write
+    @param            num_bits        value size, bits
+*/
+void bdm_clk_fast(uint16_t value, uint8_t num_bits) {
+
+    //Set BKPT
+//    PIN_BKPT.write(1);
+//    LPC_GPIO2->FIOSET = (1 << 4);
+//    PIN_BKPT.output();
+
+//    uint32_t mask = LPC_GPIO2->FIOMASK;
+//    LPC_GPIO2->FIOMASK = ~((1 << 4) | (1 << 2));
+    //Make DSI an output
+    LPC_GPIO2->FIODIR |= (1 << 2);
+    // clock the value via BDM
+    bdm_response = ((uint32_t)value) << (32 - num_bits);
+    while (num_bits--) {
+        // set DSI bit
+//        LPC_GPIO2->FIOPIN = ((bool)(bdm_response & 0x80000000) << 2);
+        if (bdm_response & 0x80000000) 
+            LPC_GPIO2->FIOSET = (1 << 2);
+        else
+            LPC_GPIO2->FIOCLR = (1 << 2);
+       // falling edge on BKPT/DSCLK
+        LPC_GPIO2->FIOCLR = (1 << 4);
+//        for (uint8_t c = 1; c; c--);
+//        // read DSO bit
+//        (bdm_response <<= 1) |= (bool)((LPC_GPIO0->FIOPIN) & (1 << 11));  -- OLD CONNECTION to PIN 27
+        (bdm_response <<= 1) |= (bool)((LPC_GPIO2->FIOPIN) & (1 << 1));
+        // rising edge on BKPT/DSCLK
+        LPC_GPIO2->FIOSET = (1 << 4);
+        for (uint8_t c = 1; c; c--);
+    }
+    //Make DSI an input
+    LPC_GPIO2->FIODIR &= ~(1 << 2);
+//    LPC_GPIO2->FIOMASK = mask;
+}
+//-----------------------------------------------------------------------------
+/**
     Clears the BDM interface after errors.
 */
 void bdm_clear() {
--- a/bdmcpu32.h	Tue Sep 14 21:02:04 2010 +0000
+++ b/bdmcpu32.h	Tue Dec 14 21:50:35 2010 +0000
@@ -30,13 +30,16 @@
 
 // MCU status macros
 #ifndef IGNORE_VCC_PIN
-    #define IS_CONNECTED    (PIN_PWR)
+//    #define IS_CONNECTED    (PIN_PWR)
+    #define IS_CONNECTED    (bool)((LPC_GPIO1->FIOPIN) & (1 << 30))     // PIN_POWER is p19 p1.30
 #else
     #define IS_CONNECTED    true
 #endif    // IGNORE_VCC_PIN
 
-#define IN_BDM              (PIN_FREEZE)
-#define IS_RUNNING          (PIN_RESET && !IN_BDM)
+//#define IN_BDM              (PIN_FREEZE)
+#define IN_BDM              (bool)((LPC_GPIO2->FIOPIN) & (1 << 0))      // FREEZE is p26 P2.0
+//#define IS_RUNNING          (PIN_RESET && !IN_BDM)
+#define IS_RUNNING          ((bool)((LPC_GPIO2->FIOPIN) & (1 << 3)) && !IN_BDM)          // PIN_RESET is P23 P2.3
 
 // MCU management
 uint8_t stop_chip();
--- a/bdmtrionic.cpp	Tue Sep 14 21:02:04 2010 +0000
+++ b/bdmtrionic.cpp	Tue Dec 14 21:50:35 2010 +0000
@@ -110,8 +110,7 @@
         if (curr_addr < *end_addr - 4) {
             pc.putc(TERM_OK);
             // light up the activity LED
-            //            led_on(LED_ACT);
-            led3 = 1;
+            ACTIVITYLEDON;
         }
 
         curr_addr += 4;
@@ -207,9 +206,9 @@
             file_buffer[byte_count+2] = ((uint8_t)(long_value >> 8));
             file_buffer[byte_count+3] = ((uint8_t)long_value);
             byte_count +=4;
+            // make the activity led twinkle
+            ACTIVITYLEDON; 
         }
-// make the activity led twinkle
-        led3 = 1;
         fwrite(file_buffer, 1, FILE_BUF_LENGTH, fp);
         if (ferror (fp)) {
             fclose (fp);
@@ -350,8 +349,7 @@
         curr_addr += 2;
 
         // light up the activity LED
-//        led_on(LED_ACT);
-        led3 = 1;
+        ACTIVITYLEDON; 
     }
 
     // reset flash
@@ -473,7 +471,7 @@
         case AMD29F400T:
         case AMD29F010:
             printf("Erasing 29F400/010 type FLASH chips...\r\n");
-            if (erase_am29() == TERM_ERR) {
+            if (!erase_am29()) {
                 printf("WARNING: An error occured when I tried to erase the FLASH chips :-(\r\n");
                 return TERM_ERR;
             }
@@ -484,7 +482,7 @@
         case AMD28F512:
         case INTEL28F512:
             printf("Erasing 28F010/512 type FLASH chips...\r\n");
-            if (erase_am28(&curr_addr, &flash_size) == TERM_ERR) {
+            if (!erase_am28(&curr_addr, &flash_size)) {
                 printf("WARNING: An error occured when I tried to erase the FLASH chips :-(\r\n");
                 return TERM_ERR;
             }
@@ -531,8 +529,7 @@
         curr_addr += 2;
 
         // make the activity LED twinkle
-        led3 = 1;
-
+        ACTIVITYLEDON; 
     }
 
     timer.stop();
@@ -666,8 +663,7 @@
 */
 bool reset_am28(void) {
     uint32_t start_addr = 0x0;
-    return (memwrite_word(&start_addr, 0xffff) == TERM_OK &&
-            memwrite_word(&start_addr, 0xffff) == TERM_OK);
+    return (memwrite_word_write_word(&start_addr, 0xffff, 0xffff) == TERM_OK);
 }
 
 //-----------------------------------------------------------------------------
@@ -697,15 +693,14 @@
 //        // feedback to host computer
 //        pc.putc(TERM_OK);
         // make the activity LED twinkle
-//        led3 = (addr & 0x400);
-        led3 = 1;
+        ACTIVITYLEDON; 
+
     }
 
     // erase flash
     addr = *start_addr;
     uint8_t verify_value;
 
-
     uint16_t pulse_cnt = 0;
     if (memwrite_byte_cmd(NULL) != TERM_OK) {
         reset_am28();
@@ -727,7 +722,7 @@
             // succeeded need to check next address
             addr++;
             // make the activity LED twinkle
-            led3 = 1;
+            ACTIVITYLEDON; 
         }
     }
     // the erase process ends with a BDM_WRITE + BDM_BYTESIZE command left in the BDM
@@ -768,13 +763,14 @@
     while (++pulse_cnt < 25) {
 
         // set a mask
-        if ((uint8_t)verify_value == (uint8_t)value) mask_value &= 0xff00;
-        if ((uint8_t)(verify_value >> 8) == (uint8_t)(value >> 8)) mask_value &= 0x00ff;
+        if ((uint8_t)verify_value == (uint8_t)value)
+            mask_value &= 0xff00;
+        if ((uint8_t)(verify_value >> 8) == (uint8_t)(value >> 8))
+            mask_value &= 0x00ff;
 
         // write the new value
         if (memwrite_word_write_word(addr, (0x4040 & mask_value), value) != TERM_OK) break;
         // NOTE the BDM interface is slow enough that there is no need for a 10us delay before verifying
-//        wait_us(10);
         // issue the verification command
         // NOTE the BDM interface is slow enough that there is no need for a 6us delay before reading back
         if (memwrite_word_read_word(&verify_value, addr, (0xc0c0 & mask_value)) != TERM_OK) break;
@@ -871,8 +867,10 @@
         if (memwrite_word(&am29_id[i].addr, am29_id[i].val) != TERM_OK) return false;
     }
     if (memread_long(&value, &addr) != TERM_OK) return false;
-    *make = (uint8_t)(value >> 24);
-    *type = (uint8_t)(value >> 8);
+//    *make = (uint8_t)(value >> 24);
+//    *type = (uint8_t)(value >> 8);
+    *make = (uint8_t)(value >> 16);
+    *type = (uint8_t)(value);
     printf("FLASH id bytes: %08x, make: %02x, type: %02x\r\n", value, *make, *type);
     switch (*type) {
         case AMD29F400B:
--- a/canutils.cpp	Tue Sep 14 21:02:04 2010 +0000
+++ b/canutils.cpp	Tue Dec 14 21:50:35 2010 +0000
@@ -67,7 +67,8 @@
     while (CANTimer.read_ms() < timeout) {
         if (can.write(CANMessage(id, frame, len))) {
             CANTimer.stop();
-            led1 = 1;
+            CANTXLEDON;
+//            led1 = 1;
             return TRUE;
         }
     }
@@ -100,7 +101,8 @@
             }
             printf("\n\r");
 //            */
-            led2 = 1;
+            CANRXLEDON;
+//            led2 = 1;
             if (CANMsgRx.id == id) {
                 CANTimer.stop();
 //                if (T5MsgRx.len != len)
--- a/common.h	Tue Sep 14 21:02:04 2010 +0000
+++ b/common.h	Tue Dec 14 21:50:35 2010 +0000
@@ -29,7 +29,7 @@
 
 // constants
 #define FW_VERSION_MAJOR    0x1     ///< firmware version
-#define FW_VERSION_MINOR    0x1        
+#define FW_VERSION_MINOR    0x2        
 
 #define CR 0x0D
 #define NL 0x0A
--- a/interfaces.cpp	Tue Sep 14 21:02:04 2010 +0000
+++ b/interfaces.cpp	Tue Dec 14 21:50:35 2010 +0000
@@ -38,9 +38,9 @@
 DigitalInOut    PIN_BKPT(p22);              // breakpoint/serial clock
 DigitalInOut    PIN_RESET(p23);             // reset signal
 DigitalInOut    PIN_DSI(p24);               // data input (to ECU) signal
-DigitalIn       PIN_DS(p25);                // data strobe signal (not used)
+DigitalIn       PIN_DSO(p25);               // data output (from ECU) signal
 DigitalIn       PIN_FREEZE(p26);            // freeze signal
-DigitalIn       PIN_DSO(p27);               // data output (from ECU) signal
+//DigitalIn       PIN_DS(p27);                // data strobe signal (not used)
 
 //LEDS
 
@@ -54,7 +54,7 @@
 Ticker ticker;
 
 void leds_off() {
-    led1 = 0;
-    led2 = 0;
-    led3 = 0;
+    CANTXLEDOFF;
+    CANRXLEDOFF;
+    ACTIVITYLEDOFF;
 }
\ No newline at end of file
--- a/interfaces.h	Tue Sep 14 21:02:04 2010 +0000
+++ b/interfaces.h	Tue Dec 14 21:50:35 2010 +0000
@@ -31,9 +31,9 @@
 extern DigitalInOut     PIN_BKPT;               // breakpoint/serial clock
 extern DigitalInOut     PIN_RESET;              // reset signal
 extern DigitalInOut     PIN_DSI;                // data input (to ECU) signal
-extern DigitalIn        PIN_DS;                 // data strobe signal (not used)
+extern DigitalIn        PIN_DSO;                // data output (from ECU) signal
 extern DigitalIn        PIN_FREEZE;             // freeze signal
-extern DigitalIn        PIN_DSO;                // data output (from ECU) signal
+//extern DigitalIn        PIN_DS;                 // data strobe signal (not used)
 
 //LEDS
 
@@ -47,4 +47,15 @@
 
 void leds_off(void);
 
+// led control macros
+// These macros use the fastio register method to control the leds
+#define CANTXLEDON      LPC_GPIO1->FIOSET = (1 << 18)   // Turn on the CAN bus transmitter activity led (led1, P1.18)
+#define CANTXLEDOFF     LPC_GPIO1->FIOCLR = (1 << 18)   // Turn off the CAN bus transmitter activity led (led1, P1.18)
+#define CANRXLEDON      LPC_GPIO1->FIOSET = (1 << 20)   // Turn on the CAN bus receiver activity led (led2, P1.20)
+#define CANRXLEDOFF     LPC_GPIO1->FIOCLR = (1 << 20)   // Turn off the CAN bus receiver activity led (led2, P1.20)
+#define ACTIVITYLEDON   LPC_GPIO1->FIOSET = (1 << 21)   // Turn on the activity led (led3, P1.21)
+#define ACTIVITYLEDOFF  LPC_GPIO1->FIOCLR = (1 << 21)   // Turn off the activity led (led3, P1.21)
+#define ERRORLEDON      LPC_GPIO1->FIOSET = (1 << 23)   // Turn on the ERROR led (led3, P1.23)
+#define ERRORLEDOFF     LPC_GPIO1->FIOCLR = (1 << 23)   // Turn off the ERROR led (led3, P1.23)
+
 #endif          // __INTERFACES_H__
\ No newline at end of file
--- a/main.cpp	Tue Sep 14 21:02:04 2010 +0000
+++ b/main.cpp	Tue Dec 14 21:50:35 2010 +0000
@@ -28,6 +28,25 @@
 
 ********************************************************************************
 
+Version 1.2 (12/2010) - Only a very small update
+
+Fixed since Version 1.1:
+    My method of detecting the FLASH type didn't work for T7 ECUs
+        Now that that I have corrected this bug it is possible to
+        FLASH Trionic 7 ECUs using the BDM connection
+        See the 'get_flash_id' function in bdmtrionic.cpp
+
+Changes since Verion 1.2
+    I have removed everything to do with the BDM DS connection
+    I have changed the mbed pin number for the BDM DSO connection
+        Now all BDM connections are part of the same MBED 'port'
+            Being part of one port makes it possible to change all
+            connections simulataneously so speeding up BDM
+        See 'interfaces.cpp' for details of how the mbed pins connect.
+            Uglybug's wiring circuit has these connections (thanks Uglybug)
+
+********************************************************************************
+
 Version 1.1 (09/2010) - Still very crude way of doing things
 
 Additions since Version 1: