372 lines
10 KiB
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 */
|