Just4Trionic - CAN and BDM FLASH programmer for Saab cars

Dependencies:   mbed

Revision:
1:d5452e398b76
Child:
4:682d96ff6d79
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/can232.cpp	Tue Sep 14 21:02:04 2010 +0000
@@ -0,0 +1,205 @@
+/*******************************************************************************
+
+can232.cpp
+(c) 2010 by Sophie Dexter
+portions (c) 2009, 2010 by Janis Silins (johnc)
+
+Lawicel CAN232 type functions for Just4Trionic by Just4pLeisure
+
+********************************************************************************
+
+WARNING: Use at your own risk, sadly this software comes with no guarantees.
+This software is provided 'free' and in good faith, but the author does not
+accept liability for any damage arising from its use.
+
+*******************************************************************************/
+
+#include "can232.h"
+
+// constants
+#define CMD_BUF_LENGTH      32              ///< command buffer size
+
+// command characters
+
+#define CMD_CLOSE           'C'             ///< Close the CAN device
+#define CMD_OPEN            'O'             ///< Open the CAN device (do this before an S/s command)
+
+#define CMD_PRESET_SPEED    'S'             ///< Sn: set preconfigured speeds 
+#define CMD_SPEED_0         '0'             ///< 10 kbits
+#define CMD_SPEED_1         '1'             ///< 20 kbits
+#define CMD_SPEED_2         '2'             ///< 50 kbits
+#define CMD_SPEED_3         '3'             ///< 100 kbits
+#define CMD_SPEED_4         '4'             ///< 125 kbits
+#define CMD_SPEED_5         '5'             ///< 250 kbits
+#define CMD_SPEED_6         '6'             ///< 500 kbits
+#define CMD_SPEED_7         '7'             ///< 800 kbits
+#define CMD_SPEED_8         '8'             ///< 1 mbits
+#define CMD_DIRECT_SPEED    's'             ///< sxxyy: set the CAN bus speed registers directly
+///< xx: BTR0 register setting
+///< yy: BTR1 register setting
+
+#define CMD_SEND_11BIT      't'             ///< tiiildd..: send 11 bit id CAN frame
+///< iii: identfier 0x0..0x7ff
+///< l: Number of data bytes in CAN frame 0..8
+///< dd..: data byte values 0x0..0xff (l pairs)
+#define CMD_SEND_29BIT      'T'             ///< Tiiiiiiiildd..: send 29 bit id CAN frame
+///< iiiiiiii: identifier 0x0..0x1fffffff
+///< l: Number of data bytes in CAN frame 0..8
+///< dd..: data byte values 0x0..0xff (l pairs)
+
+
+#define CMD_READ_FLAGS      'F'             ///< Read flags !?!
+
+#define CMD_ACCEPT_CODE     'M'             ///< Mxxxxxxxx: Acceptance code e.g. 0x00000000 } accept
+#define CMD_ACCEPT_MASK     'm'             ///< mxxxxxxxx: Acceptance mask e.g. 0xffffffff } all
+
+#define CMD_VERSION         'V'             ///< Replies with Firmware and hardware version numbers; 2 bytes each
+#define CMD_SERIAL_NUMBER   'N'             ///< Replies with serial number; 4 bytes
+
+#define CMD_TIMESTAMP       'Z'             ///< Zn: n=0 means timestamp off, n=1 means timestamp is on
+///< Replies a value in milliseconds with two bytes 0x0..0xfa5f
+///< equivalent to 0..60 seconds
+
+
+
+// static variables
+static char cmd_buffer[CMD_BUF_LENGTH];     ///< command string buffer
+static uint32_t can_id;                     ///< can message id
+static uint32_t can_len;                    ///< can message length
+static uint8_t can_msg[8];                  ///< can message frame - up to 8 bytes
+
+// private functions
+uint8_t execute_can_cmd();
+
+// command argument macros
+#define CHECK_ARGLENGTH(len) \
+    if (cmd_length != len + 2) \
+        return TERM_ERR
+
+#define GET_NUMBER(target, offset, len)    \
+    if (!ascii2int(target, cmd_buffer + 2 + offset, len)) \
+        return TERM_ERR
+
+
+
+void can232() {
+
+    // main loop
+    *cmd_buffer = '\0';
+    char ret;
+    char rx_char;
+    can_open();
+    can.attach(&show_can_message);
+//    bool (*reset_func)();
+    while (true) {
+        // read chars from USB
+//        Trionic5ShowCANMessage();
+        if (pc.readable()) {
+            rx_char = pc.getc();
+            switch (rx_char) {
+                // 'ESC' key to go back to mbed Just4Trionic 'home' menu
+                case '\e':
+                    can_close();
+                    can.attach(NULL);
+                    return;
+                // end-of-command reached
+                case TERM_OK :
+                    // execute command and return flag via USB
+                    ret = execute_can_cmd();
+                    pc.putc(ret);
+                    // reset command buffer
+                    *cmd_buffer = '\0';
+                    // light up LED
+//                    ret == TERM_OK ? led_on(LED_ACT) : led_on(LED_ERR);
+                    ret == TERM_OK ? led3 = 1 : led4 = 1;
+                    break;
+                // another command char
+                default:
+                    // store in buffer if space permits
+                    if (StrLen(cmd_buffer) < CMD_BUF_LENGTH - 1) {
+                        StrAddc(cmd_buffer, rx_char);
+                    }
+                    break;
+            }
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------
+/**
+    Executes a command and returns result flag (does not transmit the flag
+    itself).
+
+    @return                    command flag (success / failure)
+*/
+
+uint8_t execute_can_cmd() {
+    uint8_t cmd_length = strlen(cmd_buffer);
+    char cmd = *(cmd_buffer + 1);
+
+    // command groups
+    switch (*cmd_buffer) {
+            // adapter commands
+        case CMD_SEND_11BIT:
+            if (cmd_length < 7) return TERM_ERR;
+            GET_NUMBER(&can_id, -1, 3);
+            GET_NUMBER(&can_len, 2, 1);
+            if (cmd_length < (4 + (can_len * 2))) return TERM_ERR;
+            for (uint8_t i = 0; i < (uint8_t)can_len; i++) {
+                uint32_t result;
+                GET_NUMBER(&result, (3 + (i * 2)), 2);
+                can_msg[i] = (uint8_t)result;
+            }
+            return (can_send_timeout (can_id, (char*)can_msg, (uint8_t)can_len, 500)) ? TERM_OK : TERM_ERR;
+
+        case CMD_SEND_29BIT:
+            break;
+            
+        case CMD_CLOSE:
+            can_close();
+            return TERM_OK;
+        case CMD_OPEN:
+            can_open();
+            return TERM_OK;
+            
+        case CMD_PRESET_SPEED:
+            CHECK_ARGLENGTH(0);
+            switch (cmd) {
+                    // get firmware version
+                case CMD_SPEED_0:
+                    return (can.frequency(10000)) ? TERM_OK : TERM_ERR;
+                case CMD_SPEED_1:
+                    return (can.frequency(20000)) ? TERM_OK : TERM_ERR;
+                case CMD_SPEED_2:
+                    return (can.frequency(50000)) ? TERM_OK : TERM_ERR;
+                case CMD_SPEED_3:
+                    return (can.frequency(100000)) ? TERM_OK : TERM_ERR;
+                case CMD_SPEED_4:
+                    return (can.frequency(125000)) ? TERM_OK : TERM_ERR;
+                case CMD_SPEED_5:
+                    return (can.frequency(250000)) ? TERM_OK : TERM_ERR;
+                case CMD_SPEED_6:
+                    return (can.frequency(500000)) ? TERM_OK : TERM_ERR;
+                case CMD_SPEED_7:
+                    return (can.frequency(800000)) ? TERM_OK : TERM_ERR;
+                case CMD_SPEED_8:
+                    return (can.frequency(1000000)) ? TERM_OK : TERM_ERR;
+            }
+            break;
+            
+        case CMD_DIRECT_SPEED:
+            CHECK_ARGLENGTH(0);
+            switch (cmd) {
+                case CMD_SPEED_0:
+                    return (can.frequency(47619)) ? TERM_OK : TERM_ERR;
+                case CMD_SPEED_1:
+                    return (can.frequency(500000)) ? TERM_OK : TERM_ERR;
+                case CMD_SPEED_2:
+                    return (can.frequency(615000)) ? TERM_OK : TERM_ERR;
+            }
+            break;
+    }
+
+    // unknown command
+    return TERM_ERR;
+}