Sophie Dexter
/
Just4Trionic
Just4Trionic - CAN and BDM FLASH programmer for Saab cars
Diff: can232.cpp
- 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; +}