hondartp-1.2.0/src/comm.c

372 lines
10 KiB
C

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/***************************************************************************
* INCLUDES
***************************************************************************/
#include <avr/pgmspace.h>
#include "config.h"
#include "comm.h"
#include "memory.h"
#include "usart.h"
/***************************************************************************
* DEFINITIONS
***************************************************************************/
/* GLOBAL: tells how to treat byte_count in write W command */
BOOL b_bcnt_mode = false;
/* GLOBAL: indicates device status */
BOOL b_status_ready = false;
/* indicates whether last read byte from usart is ok */
static BOOL b_read_ok = false;
/* holds latest read byte */
static BYTE read_byte;
/* contains information about bytes to read/write in frame */
static UINT16 byte_count;
/***************************************************************************
* FUNCTIONS
***************************************************************************/
/* ----------------------------------------------------------------------- */
BYTE checksum(BYTE* buffer_ptr, const UINT16 length)
{
static UINT8 chksum;
static UINT16 buffer_idx;
chksum = 0;
/* sum all bytes with no carry */
for (buffer_idx = 0; buffer_idx < length; ++buffer_idx)
chksum += buffer_ptr[buffer_idx];
return (chksum);
}
/* ----------------------------------------------------------------------- */
void pcCommandBytecountMode()
{
/* 1: mode, 2: checksum */
data_buffer[0] = read_byte;
if (!usartRead(data_buffer + 1, 2, ROMULATOR_PROTOCOL_READ_TIMEOUT))
return;
/* if checksum is ok, set byte_count computation method flag */
if (checksum(data_buffer, 2) == data_buffer[2])
{
b_bcnt_mode = (data_buffer[1])?(true):(false);
/* acknowledge action */
usartSendByte('O');
}
/* otherwise inform that parameter modification failed */
else
usartSendByte('F');
}
/* ----------------------------------------------------------------------- */
void pcCommandFirmware()
{
if (!usartRead(data_buffer, 1, ROMULATOR_PROTOCOL_READ_TIMEOUT))
return;
if (read_byte == data_buffer[0])
{
/* respond with firmware version number ... */
usartSendString_P((BYTE*)PSTR("honda-rtp, ver. "));
usartSendString_P((BYTE*)PSTR(FIRMWARE_VERSION));
/* ... with compiler and library version number */
usartSendString_P((BYTE*)PSTR(", avr-libc: "));
usartSendString_P((BYTE*)PSTR(__AVR_LIBC_VERSION_STRING__));
usartSendString_P((BYTE*)PSTR(", avr-gcc: "));
usartSendString_P((BYTE*)PSTR(__VERSION__));
}
}
/* ----------------------------------------------------------------------- */
void pcCommandModify()
{
UINT16 baudrate;
UINT16 delay;
/* 1: baudrate hi byte, 2: baudrate lo byte, 3: double speed, 4: two stop bits, 5: parity, 6: checksum */
data_buffer[0] = read_byte;
if (!usartRead(data_buffer + 1, 6, ROMULATOR_PROTOCOL_READ_TIMEOUT))
return;
/* if checksum is ok, reinitialize usart */
if (checksum(data_buffer, 6) == data_buffer[6])
{
/* acknowledge action and wait for transmission completion */
usartSendByte('O');
for (delay = 0; delay < 0xFFFF; ++delay)
NOP_DELAY;
baudrate = (UINT16)(data_buffer[1] << 8) + (UINT16)(data_buffer[2]);
initUsart(baudrate, data_buffer[3], data_buffer[4], data_buffer[5]);
}
/* otherwise inform that parameter modification failed */
else
usartSendByte('F');
}
/* ----------------------------------------------------------------------- */
void pcCommandReadBlock()
{
/* indicate whether device is busy */
b_status_ready = false;
/* 1: bytes to read, 2: addr hi byte, 3: addr lo byte, 4: checksum */
data_buffer[0] = read_byte;
if (!usartRead(data_buffer + 1, 4, ROMULATOR_PROTOCOL_READ_TIMEOUT))
return;
/* if checksum is ok, read data from memory */
if (checksum(data_buffer, 4) == data_buffer[4])
{
/* 0 for 256 bytes of data */
byte_count = (data_buffer[1])?(data_buffer[1]):(256);
memoryReadBlock((UINT16)(data_buffer[2] << 8) + (UINT16)(data_buffer[3]), byte_count, data_buffer);
data_buffer[byte_count] = checksum(data_buffer, byte_count);
/* send data read from memory with checksum */
usartSend(data_buffer, byte_count + 1);
}
/* after all enable ECU to read from device */
setMemoryAccessEcuRead();
/* indicate whether device is ready */
b_status_ready = true;
}
/* ----------------------------------------------------------------------- */
void pcCommandReadByte()
{
/* indicate whether device is busy */
b_status_ready = false;
if (!usartRead(data_buffer, 2, ROMULATOR_PROTOCOL_READ_TIMEOUT))
return;
/* 1: addr hi byte, 2: addr lo byte */
data_buffer[2] = *(memoryRead((UINT16)(data_buffer[0] << 8) + (UINT16)(data_buffer[1])));
usartSendByte(data_buffer[2]);
/* after all enable ECU to read from device */
setMemoryAccessEcuRead();
/* indicate whether device is ready */
b_status_ready = true;
}
/* ----------------------------------------------------------------------- */
void pcCommandStatus()
{
/* respond with 'O' when device is ready or with 'B' when busy */
data_buffer[0] = (b_status_ready)?('O'):('B');
data_buffer[1] = checksum(data_buffer, 1);
usartSend(data_buffer, 2);
}
/* ----------------------------------------------------------------------- */
void pcCommandUnknown()
{
data_buffer[0] = UNKNOWN;
data_buffer[1] = checksum(data_buffer, 1);
usartSend(data_buffer, 2);
}
/* ----------------------------------------------------------------------- */
void pcCommandVersion()
{
if (!usartRead(data_buffer, 1, ROMULATOR_PROTOCOL_READ_TIMEOUT))
return;
if (read_byte == data_buffer[0])
{
data_buffer[1] = ROMULATOR_PROTOCOL_MAJOR;
data_buffer[2] = ROMULATOR_PROTOCOL_MINOR;
data_buffer[3] = ROMULATOR_PROTOCOL_ID;
usartSend(data_buffer + 1, 3);
}
}
/* ----------------------------------------------------------------------- */
void pcCommandVersionResp()
{
/* WORKAROUND: discard data received as response to version command */
usartRead(data_buffer, 4, 1);
}
/* ----------------------------------------------------------------------- */
void pcCommandWriteW()
{
/* indicate whether device is busy */
b_status_ready = false;
/* 0: command, 1: number of bytes to write, 2: addr hi byte, 3: addr lo byte */
data_buffer[0] = read_byte;
if (!usartRead(data_buffer + 1, 3, ROMULATOR_PROTOCOL_READ_TIMEOUT))
return;
/* WORKAROUND: due to flaw in TurboEDIT's byte count computatnion method */
if (!b_bcnt_mode)
byte_count = (data_buffer[1])?(data_buffer[1]):(256);
else
byte_count = data_buffer[1] + 1;
/* timeout waiting for byte after 50 ms */
if (!usartRead((data_buffer + 4), byte_count + 1, ROMULATOR_PROTOCOL_READ_TIMEOUT))
return;
if (checksum(data_buffer, byte_count + 4) != data_buffer[byte_count + 4])
return;
/* try to write block of bytes few times */
for (UINT8 i = 0; i < ROMULATOR_PROTOCOL_WRITE_RETRIES; ++i)
{
if (memoryWriteBlock((UINT16)(data_buffer[2] << 8) + (UINT16)(data_buffer[3]), byte_count, data_buffer + 4))
{
/* acknowledge that block was written properly */
usartSendByte('O');
break;
}
}
/* after all enable ECU to read from device */
setMemoryAccessEcuRead();
/* indicate whether device is ready */
b_status_ready = true;
}
/* ----------------------------------------------------------------------- */
void pcCommandWriteX()
{
static UINT16 wr_checksum;
/* indicate whether device is busy */
b_status_ready = false;
/* 0: command, 1: number of bytes to write, 2: addr hi byte, 3: addr lo byte */
data_buffer[0] = read_byte;
if (!usartRead(data_buffer + 1, 3, ROMULATOR_PROTOCOL_READ_TIMEOUT))
return;
byte_count = (data_buffer[1])?(data_buffer[1]):(256);
/* timeout waiting for byte after 50 ms */
if (!usartRead((data_buffer + 4), byte_count + 1, ROMULATOR_PROTOCOL_READ_TIMEOUT))
return;
if (checksum(data_buffer, byte_count + 4) != data_buffer[byte_count + 4])
return;
/* try to write block of bytes few times */
for (UINT8 i = 0; i < ROMULATOR_PROTOCOL_WRITE_RETRIES; ++i)
{
if (memoryWriteBlock((UINT16)(data_buffer[2] << 8) + (UINT16)(data_buffer[3]), byte_count, data_buffer + 4))
{
/* acknowledge that block was written properly - two byte checksum */
wr_checksum = 0;
for (UINT16 j = 0; j < byte_count; ++j)
wr_checksum += data_buffer[4 + j];
data_buffer[0] = wr_checksum;
data_buffer[1] = (wr_checksum >> 8);
usartSend(data_buffer, 2);
break;
}
}
/* after all enable ECU to read from device */
setMemoryAccessEcuRead();
/* indicate whether device is ready */
b_status_ready = true;
}
/* ----------------------------------------------------------------------- */
void pcCommand()
{
read_byte = usartReadByte(&b_read_ok);
if (b_read_ok)
{
/* treat each first incoming byte as command */
switch (read_byte)
{
case BYTECOUNT_MODE:
pcCommandBytecountMode();
break;
case FIRMWARE:
pcCommandFirmware();
break;
case MODIFY:
pcCommandModify();
break;
case READ_BLOCK:
pcCommandReadBlock();
break;
case READ_BYTE:
pcCommandReadByte();
break;
case STATUS:
pcCommandStatus();
break;
case VERSION:
pcCommandVersion();
break;
case VERSION_RESP:
pcCommandVersionResp();
break;
case WRITE_X:
pcCommandWriteX();
break;
case WRITE_W:
pcCommandWriteW();
break;
case WRITE_H:
/* treat as normal write to memory, due to hardware limitations */
pcCommandWriteW();
break;
default:
pcCommandUnknown();
}
}
}
/* END */