SerialComm/SIPR (2007-11-14 17:10:29)

Introduction

SIP-R stands for Serial Interface Protocol - Reliable

This is a protocol designed by Michael Richards and Marcell. It is designed specifically so tuning software can efficiently communicate with the ECU using a standard reliable protocol over serial bus (RS232 or RS485, or even CAN).


Entering SIPR mode

On startup the ECU can switch to the SIPR protocol by sending the command 'Mas'. You can only enter this from the MENU_ZERO state because this does not make sense for a keyboard user. Upon entering the protocol the string "OK\r\n" will be sent. This response was chosen for it's appearance while communicating interactively with a terminal program. If already in the SIPR mode the command 'Mas' can still be entered for the same result. This allows a more graceful recovery when communications are lost.

Packet Format

Every packet must be sent in the following format:

Signature Sequence Type Size Data CRC-16
1 byte 1 byte 1 byte 1 byte variable length of Size bytes 2 bytes

Discussion: The signature byte serves as a trigger to the receiver that a new packet is starting. 0x0A is defined as the byte to use. If the receiver gets a corrupted packet or times out receiving one it will return to a state where it is looking for a packet signature.

The sequence byte is necessary to ensure that ACK packets are matched with the command they refer to. If the tuning software sends 2 commands and one ACK becomes corrupted then the software must be able to correctly determine which command was accepted. In our case it is the responsibility of the sender to increment the sequence number with every command sent to ensure no collisions occur.

The type byte allows up to 255 different types of packets to be defined. In reality we expect to see about 30 different types. Should the need for more than 255 types ever arrive then an "extended" packet type could be defined by carrying extra type definition bytes into the data area.

There is only one byte designated for the data size. This means the largest possible packet will be 261 bytes - more than sufficient for the limited resources of the ECU. As apparent from the description above, size in this context refers only to the number of bytes in the data segment. In some packets it may also be valid to have 0 bytes of data.

Size number of bytes comprise the data segment or payload of a packet.

The last 2 bytes in a packet are the checksum bytes. CRC-16 was chosen because of it's proven track record and library availability. The CRC is applied to the entire packet excluding the signature byte and obviously the CRC bytes! The CRC low order byte is sent first.

Packet Type Definitions

NAK

Sender: ECU
Sequence: Set the same as the packet it is responding to.
Type: 0x00
Size: 0 (no data necessary)
Response: none
Description: The NAK packet is always sent in response to receiving an invalid (wrong CRC) or unrecognised (type not found) packet. In the future it may be necessary to add a reason byte to the data.

ACK

Sender: ECU
Sequence: Set the same as the packet it is responding to.
Type: 0x01
Size: 0 (no data necessary)
Response: none
Description: The ACK packet is always sent in response to a command packet. The ACK packet tells the sender that the command was received, understood and processed.
.
Sender: Tuner
Sequence: Sequentially chosen by the sender.
Type: 0x01
Size: 0 (no data necessary)
Response: ACK
Description: As a special case the tuning software can send an ACK and expect an ACK to be returned. This functions as a "Ping".

GET_VERSION

Sender: Tuner
Sequence: Sequentially chosen by the sender.
Type: 0x02
Size: 0 (no data necessary)
Response: GET_VERSION
Description: The GET_VERSION packet is sent by the tuning software to determine the version of firmware it is communicating with. This detail is often necessary to determine the features available to the software.
.
Sender: ECU
Sequence: Set the same as the packet it is responding to.
Type: 0x02
Size: 3
Response: none
Data: The 3 data bytes returned are the Major, Revision and Build numbers of the firmware. 0x01 0x00 0x03 for example would mean version 1.0.3
Description: The GET_VERSION response packet provides the tuner with the firmware version.

SET_BAUD

Sender: Tuner
Sequence: Sequentially chosen by the sender.
Type: 0x03
Size: 1
Response: ACK
Data: The byte here represents the baudrate as chosen from the following table.
byte Baudrate
0x00 9600
0x01 19200 (default rate)
0x02 38400
0x03 57600
0x04 115200
Description: The SET_BAUD command is a particular one. The ECU must respond in the current baudrate with it's ACK packet before switching baudrates. The tuning software must take care as missing the ACK packet may result in it retrying in the wrong baudrate. Once sent, the tuning software should wait for an ACK. Then resend. If it still does not receive an ACK then it should try switching to the new baudrate and sending one or more pings (ACK). Previously the data would have been the divisor needed to form the new baudrate. In the interest of portability I have chosen constants. In the future with an ARM processor the divisors may be different.

Does it make sense to use the same baudrate=1000000/x that is used at other places in the firmware? This covers every baudrate that is currently possible. The ARM would have no problem using (or converting from) these very same values. In any case, 0xE0..0xFF can be reserved for future (eg. other speeds, that don't fit this well). Otherwise we must be _very_ careful to choose the baudrates.

Besides me forgetting to list important baudrates these are very unlikely to change. I've seen these as the common baudrates for at least the past 15 years. I feel the using pre-defined values is clearer and less prone to errors. Being off by one for example will still work on many serial implementations but oddly not on others.

GET_TABLESIZE

Sender: Tuner
Sequence: Sequentially chosen by the sender.
Type: 0x04
Size: 1
Response: GET_TABLESIZE
Data: Only 1 data byte is sent to specify the table we are querying.
byte table
0x01 RPM table
0x02 KPA table
0x03 ignition table
0x04 lambda table
0x05 VE table
0x06 EGO Correction table
0x09 LCD size
Description: The GET_TABLESIZE packet is sent by the tuning software to determine the dimensions of a given table. Compiled options can alter the size of certain tables and knowing the correct sizes is very important.
Not strictly needed. GET_TABLEDATA with Size=0 can be an instruction to send the whole table (there is no danger of data-loss, as that is prevented by a lower layer). The tuning software will query the whole table anyway in all cases it needs to know the size of the table.
Sender: ECU
Sequence: Set the same as the packet it is responding to.
Type: 0x04
Size: 2
Response: none
Data: the two data bytes correspond to the number of rows and columns respectively. a 5 row 2 column table would be sent as 0x05 0x02
Description: The GET_TABLESIZE response tells the tuning software the dimensions of the specified table.

GET_TABLEDATA

Sender: Tuner
Sequence: Sequentially chosen by the sender.
Type: 0x05
Size: 1
Response: GET_TABLEDATA
Data: Only 1 data byte is sent to specify the table we are querying.
byte table
0x01 RPM table
0x02 KPA table
0x03 ignition table
0x04 lambda table
0x05 VE table
0x06 EGO Correction table
0x07 config table 1
0x08 config table 2
Description: The GET_TABLEDATA packet is sent by the tuning software to retrieve all the data from the specified table. GET_TABLESIZE can be called to determine the rows and columns format of this data.

Config data can change from version to version of firmware. For this reason the config tables 1 and 2 will be rigidly defined below. This ensures that the config data can always be retrieved in a standard fashion.

config table1

offset config string
  

.

Sender: ECU
Sequence: Set the same as the packet it is responding to.
Type: 0x05
Size: (determined by the actual size of the table)
Response: none
Data: The table data is returned as a byte stream.
Description: The GET_TABLEDATA response sends the actual content of a table to the tuning software.

SET_TABLEDATA

Sender: Tuner
Sequence: Sequentially chosen by the sender.
Type: 0x06
Size: 3
Response: ACK
Data: The first data byte identifies the table we are modifying. The second byte contains the offset within that table and the third byte is the actual data.
byte table
0x01 RPM table
0x02 KPA table
0x03 ignition table
0x04 lambda table
0x05 VE table
0x06 EGO Correction table
0x07 config table 1
0x08 config table 2
Description: The SET_TABLEDATA packet is sent by the tuning software to modify an entry within a table. Ram constraints limit the size of the packet that can be sent to the ECU so modifications need to be performed one byte at a time.

READ_SENSORS

Sender: Tuner
Sequence: Sequentially chosen by the sender.
Type: 0x07
Size: 2
Response: READ_SENSORS
Data: The first data byte specifies the number of data sets to return. 0 means stop sending and 255 means send continuously.
The second byte specifies the delay between packets.

The third byte selects the page number. Sensor data is paged as we don't always need all the info and for rapid datalogging this would just slow us down.

Description: The READ_SENSORS packet is sent to request one or more sets of sensor data. The entire structure is returned in an effort to provide the maximum amount of data with a minimum amount of overhead. The repeat and delay bytes are very important for creating data logs as they allow the ECU to send the data at ECU determined intervals - more accurate and not subject to the stacking errors of the software generating the requests.
.
Sender: ECU
Sequence: Set the same as the packet it is responding to.
Type: 0x07
Size: varies according to the chosen page
Response: none
Data: Data format as specified in the following table
offset size meaning
0 1 Packets remaining
1 1 Delay between packets (not sure on units yet)
2 1 pagetype
3+ variable sensor data

Page0 Format

offset size meaning
3 2 RPM
5 2 MAP value
7 2 inj pulsewidth
9 2 AFR1
11 2 AFR2
13 2 target AFR
15 1 TPS value
16 1 CLT value
17 1 MAT value
18 1 battery voltage
19 1 ignition advance
20 2 EGT1
22 2 EGT2
24 1 target boost
25 1 boost duty cycle

GET_HWSIG

Sender: Tuner
Sequence: Chosen by the sender.
Type: 0x08
Size: 0
Response: HWSIG
Data:

This packet requests the hardware signature bytes from the ECU. These are stored in the bootloader area and are not always available (only if the bootloader was uploaded properly: for every v3.x since v3.2).

Sender: ECU
Sequence: Set the same as the packet it is responding to.
Type: 0x08
Size: 12
Response: none
Data: Data format as specified in the following table
offset size meaning
0 1 Signature byte (data valid when 0xAA
1 1 Board Revision Number
2 1 Reserved
3 1 Reserved
4 1 Hardware Options
5 1 Trigger Types
6 1 Reserved
7 1 Reserved
8 1 Reserved
9 1 Reserved
10 1 Reserved
11 2 Board serial number (16 bit)

BEGIN_FLASH

Sender: Tuner
Sequence: Chosen by the sender.
Type: 0x09
Size: 0
Response: NONE

This packet signals the ECU to enter bootloader mode. In order to do this the engine must be stopped. If this condition is not met then a NAK packet will be sent. It is up to the tuning software to determine this.

SAVE_CONFIG

Sender: Tuner
Sequence: Chosen by the sender.
Type: 0x0A
Size: 0
Response: ACK
Data:

This packet signals that the ECU should save the current config in the EEPROM.


SerialComm/SIPR/Ideas - Other work and ideas not currently part of SIPR.