Skip to content

Commit 83ba14a

Browse files
committed
Master commit
0 parents  commit 83ba14a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+26330
-0
lines changed

GearIndicator/KBus.c

Lines changed: 392 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,392 @@
1+
/*
2+
* KBus.c
3+
* Part of project: GearIndicator
4+
* Created: 25.05.2015 8:54:04
5+
* Author: Andrej Hradnansky, 2022
6+
*
7+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU
8+
* (General Public License as published by the Free Software Foundation, either version 3 of the License,
9+
* or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12+
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13+
* See the GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License along with this program.
16+
* If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
19+
#include "global.h"
20+
#include <util/delay.h>
21+
#include <avr/interrupt.h>
22+
#include <avr/io.h>
23+
#include <avr/wdt.h>
24+
#include "uart.h"
25+
#include "bikes.h"
26+
#include "kbus.h"
27+
#include "timers.h"
28+
#include "eeproma.h"
29+
#include <string.h>
30+
31+
//State of the K-Bus communication
32+
tKBUS_state KBUS_state=KBUS_S_IDLE;
33+
34+
////////////////////////////////////////////
35+
//KBUS commands - partially :-)
36+
////////////////////////////////////////////
37+
//StartCommunication Request
38+
tKBUS_Msg KBUS_STC_req = {.form=ADDRESS_NO_LBYTE, //Message with address without additional message length byte
39+
.header={
40+
.HForm_MsgLen=PHYSICAL_ADDR + 1,//Physical addressing + message lenght (1 byte)
41+
.Tgt=0x11, //Target address -> ECU address (0x11 - Kawa)
42+
.Src=IND_ADDR //Source address = Indicator address
43+
},
44+
.data.Sld=STC, //startCommunication Request Service Id
45+
.cs=0x04 //Check sum
46+
};
47+
48+
49+
//Byte Name Value Description
50+
//-----------------------------------------------
51+
//0 Fmt 0x81 Physical addressing PHYSICAL_ADDR<<6 + length of information (1 byte) = 0x81
52+
//1 Tgt <Ttg> Address of target device (ECU)
53+
//2 Src IND_ADDR Address of source device (GEAR INDICATOR)
54+
//3 STC 0x81 startCommunication Request Service Id
55+
//4 CS <CS> Example: CHS = 04 = 81+11+F1+81 modulo 0x100 -> 0x81,0x11,0xF1,0x81,0x04
56+
//
57+
////////////////////////////////////////////
58+
//startCommunication Positive Response
59+
unsigned char KeyBytes[2]={0xEA,0x8F};
60+
61+
tKBUS_Msg KBUS_STC_res = {.form=ADDRESS_LBYTE, //Message with address and with extra length byte
62+
.header={
63+
.HForm_MsgLen=PHYSICAL_ADDR, //Physical addressing
64+
.Tgt=IND_ADDR, //Target address = Indicator address
65+
.Src=0x11, //Source address = ECU
66+
.Len=3 //Data length - number of data bytes
67+
},
68+
.data.Sld=STCPR, //startCommunication Positive Response Service Id
69+
.data.Data=KeyBytes,
70+
.cs=0xBF //Check sum
71+
};
72+
73+
//Byte Name Value Description
74+
//------------------------------------------------------------------------------
75+
//0 Fmt 0x80 Address mode: physical addressing + Len
76+
//1 Tgt IND_ADDR Address of target devide (GEAR INDICATOR)
77+
//2 Src <ADDR> Address of source device (ECU)
78+
//3 Len 0x03 3 Bytes following...
79+
//4 STCPR 0xC1 startCommunication Positive Response Service Id
80+
//5 KB1 0xEA Header with target and source address information
81+
//6 KB2 0x8F Additional length byte used
82+
//7 CS <CS> Example: CHS BF = 80+F1+...+8F modulo 0x100 ->0x80,0x11,0x03,0xC1,0xEA,0x8F,0xBF
83+
//
84+
////////////////////////////////////////////
85+
//StartDiagnosticSession Request
86+
unsigned char KBUS_START_DIAG[7] = {PHYSICAL_ADDR,0x11,IND_ADDR,0x02,SDS,0x80,0x14};
87+
88+
unsigned char diagnosticMode=0x80; //manufacterSpecific - 00-7F reserved, 80-FF for vehicle manufacturer specific use
89+
tKBUS_Msg KBUS_SDS_req = {.form=ADDRESS_LBYTE, //Message with address and with extra length byte
90+
.header={
91+
.HForm_MsgLen=PHYSICAL_ADDR, //Physical addressing
92+
.Tgt=0x11, //Target address -> ECU address (0x11 - Kawa)
93+
.Src=IND_ADDR, //Source address = Indicator address
94+
.Len=2 //Data length - number of data bytes
95+
},
96+
.data.Sld=SDS, //startDiagnosticSession Request Service Id
97+
.data.Data=&diagnosticMode, //manufacterSpecific - 00-7F reserved, 80-FF for vehicle manufacturer specific use
98+
.cs=0x14 //Check sum
99+
};
100+
101+
//Byte Name Value Description
102+
//-------------------------------------------------------------------------------------
103+
//0 Fmt 0x80 Address mode: physical addressing + Len
104+
//1 Tgt <ADDR> Address of target device (ECU)
105+
//2 Src IND_ADDR Address of source device (GEAR INDICATOR)
106+
//3 Len 0x02 2 Bytes following...
107+
//4 SDS 0x10 startDiagnosticSession Request Service Id
108+
//5 diagnosticMode 0x80 manufacterSpecific - 00-7F reserved, 80-FF for vehicle manufacturer specific use
109+
//6 CS <CS> Example: CHS = 14 = 80+11+F1+02+10+80 modulo 0x100 ->0x80,0x11,0xF1,0x02,0x10,0x80,0x14
110+
//
111+
////////////////////////////////////////////
112+
//startDiagnosticSession Positive Response
113+
unsigned char KBUS_START_DIAG_RPL[7] = {PHYSICAL_ADDR,IND_ADDR,0x11,0x02,SDSPR,0x80,0x54};
114+
115+
tKBUS_Msg KBUS_SDS_res = {.form=ADDRESS_LBYTE, //Message with address and with extra length byte
116+
.header={
117+
.HForm_MsgLen=PHYSICAL_ADDR, //Physical addressing
118+
.Tgt=IND_ADDR, //Target address = indicator address
119+
.Src=0x11, //Source address = ECU
120+
.Len=2 //Data length - number of data bytes
121+
},
122+
.data.Sld=SDSPR, //startDiagnosticSession Request Service Id
123+
.data.Data=&diagnosticMode, //manufacterSpecific - 00-7F reserved, 80-FF for vehicle manufacturer specific use
124+
.cs=0x54 //Check sum
125+
};
126+
127+
//Byte Name Value Description
128+
//-----------------------------------------------------------------------------------
129+
//0 Fmt 0x80 Address mode: physical addressing +Len
130+
//1 Tgt IND_ADDR Address of target device (GEAR INDICATOR)
131+
//2 Src <ADDR> Address of source device (ECU)
132+
//3 Len 0x02 2 Bytes following...
133+
//4 SDSPR 0x50 startDiagnosticSession Positive Response Service Id
134+
//5 Diagnostic mode 0x80 manufacterSpecific
135+
//6 Checksum <CS> Example: CS = 54 ->0x80,0xF1,0x11,0x02,0x50,0x80,0x54
136+
//
137+
////////////////////////////////////////////
138+
//readDataByLocalIdentifier Request
139+
unsigned char KBUS_READ_DATA[7] = {PHYSICAL_ADDR,0x11,IND_ADDR,0x02,RDBLID,0x0B,0xB0};
140+
141+
unsigned char RLOCID=0xB0;
142+
tKBUS_Msg KBUS_RDBLID_req = {.form=ADDRESS_LBYTE, //Message with address and with extra length byte
143+
.header={
144+
.HForm_MsgLen=PHYSICAL_ADDR, //Physical addressing
145+
.Tgt=0x11, //Target address = ECU
146+
.Src=IND_ADDR, //Source address = Indicator address
147+
.Len=2 //Data length - number of data bytes
148+
},
149+
.data.Sld=RDBLID, //readDataByLocalIdentifier Request Service Id
150+
.data.Data=&RLOCID, //recordLocalIdentifier (to be read)
151+
.cs=0xB0 //Check sum
152+
};
153+
154+
//Byte Name Value Description
155+
//-----------------------------------------------
156+
//0 Fmt 0x80 Address mode: physical addressing + Len
157+
//1 Tgt <ADDR> Address of target devide (ECU)
158+
//2 Src IND_ADDR Address of source device (GEAR INDICATOR)
159+
//3 Len 0x02 Two byte following...
160+
//4 RDBLID 0x21 readDataByLocalIdentifier Request Service Id
161+
//5 RLOCID <RLOCID> recordLocalIdentifier (to be read)
162+
//6 CS <CS> Example: CHS = B0 = 80+11+F1+02+21+0B modulo 0x100 ->0x80,0x11,0xF1,0x02,0x21,0x0B,0xB0
163+
//
164+
//////////////////////////////////////////////
165+
//READ REG - reply
166+
//Differs according to the manufacturer/model
167+
//This is defined in bikes.c & bikes.h
168+
tKBUS_Msg KBUS_reply_msg;
169+
170+
////////////////////////////////////////
171+
//KBus protocol check sum calculation
172+
unsigned char KBUS_checksum1(volatile unsigned char *msg, volatile unsigned char cnt)
173+
{
174+
unsigned char checksum=0, i;
175+
176+
for(i=0;i<cnt;i++)
177+
checksum+= *(msg+i);
178+
179+
return(checksum);
180+
}
181+
182+
unsigned char KBUS_checksum(tKBUS_Msg *msg)
183+
{
184+
unsigned char checksum=0;
185+
int i, MsgLen;
186+
187+
//Header byte always
188+
checksum+=msg->header.HForm_MsgLen;
189+
190+
//Addresses include only if necessary
191+
if(msg->form==ADDRESS_NO_LBYTE || msg->form==ADDRESS_LBYTE)
192+
{
193+
checksum+=msg->header.Src;
194+
checksum+=msg->header.Tgt;
195+
}
196+
197+
//Always there
198+
checksum+=msg->data.Sld;
199+
200+
//Length byte only if necessary
201+
if(msg->form==ADDRESS_LBYTE || msg->form==NO_ADDRESS_LBYTE)
202+
{
203+
checksum+=msg->header.Len;
204+
for(i=0;i<msg->header.Len-1;i++)
205+
checksum+=msg->data.Data[i];
206+
}
207+
else
208+
{
209+
MsgLen=msg->header.HForm_MsgLen & 0b00111111;
210+
for(i=0;i<MsgLen-1;i++)
211+
checksum+=msg->data.Data[i];
212+
}
213+
214+
msg->cs=checksum;
215+
return(checksum);
216+
}
217+
218+
////////////////////////////////////////
219+
//Performs KBus Fast Init
220+
//25ms pulse to KBUS - Initialization
221+
void KBUS_fast_init(void)
222+
{
223+
cli();
224+
wdt_disable(); //WDT would expire during fast init
225+
226+
//RX Disable
227+
CLB(UCSR0B, RXEN0);
228+
//TX Disable
229+
CLB(UCSR0B, TXEN0);
230+
231+
232+
STB(UARTDR,TX); //TXD is output
233+
STB(UARTPORT,TX); //TX high
234+
_delay_ms(400); //Just be sure we fulfill TIdle time - min.300ms first transmission after power up)
235+
236+
//KBUS FAST INIT
237+
//(--FIRST LOW--)
238+
CLB(UARTPORT,TX); //Keep TX Lo for min. 25ms +/- 1ms (TiniL according to ISO14230)
239+
_delay_ms(25);
240+
STB(UARTPORT,TX); //and TX Hi for another 25ms +/- 1ms (TWuP according to ISO14230)
241+
_delay_ms(25);
242+
//TX Enable
243+
STB(UCSR0B, TXEN0);
244+
sei(); //Enable all interrupts
245+
wdt_enable(WDTO_250MS); //Enable watch dog
246+
}
247+
248+
///////////////////////////////////////////////////
249+
//Store message to UART tx buffer
250+
251+
void KBUS_msg_to_uart(tKBUS_Msg *msg)
252+
{
253+
int MsgLen;
254+
unsigned char msgout[10];
255+
unsigned char *msgptr;
256+
int i;
257+
258+
msgptr=msgout;
259+
260+
//Fmt
261+
*msgptr++=msg->header.HForm_MsgLen;
262+
263+
//Address
264+
if(msg->form==ADDRESS_LBYTE || msg->form==ADDRESS_NO_LBYTE)
265+
{
266+
*msgptr++=msg->header.Tgt;
267+
*msgptr++=msg->header.Src;
268+
}
269+
270+
//Additional Length byte
271+
if(msg->form==ADDRESS_LBYTE || msg->form==NO_ADDRESS_LBYTE)
272+
{
273+
*msgptr++=msg->header.Len;
274+
}
275+
276+
//Sld
277+
*msgptr++=msg->data.Sld;
278+
279+
280+
//Data - Sld is first, so number of data = Len-1
281+
if(msg->form==ADDRESS_LBYTE || msg->form==NO_ADDRESS_LBYTE)
282+
{
283+
if(msg->header.Len>1)
284+
for(i=0;i<msg->header.Len-1;i++)
285+
*msgptr++=msg->data.Data[i];
286+
}
287+
else
288+
{
289+
//Get MsgLen from the header byte
290+
MsgLen = msg->header.HForm_MsgLen & 0b00111111;
291+
if(MsgLen>1)
292+
for(i=0;i<MsgLen-1;i++)
293+
*msgptr++=msg->data.Data[i];
294+
}
295+
296+
//Check sum
297+
*msgptr++=KBUS_checksum(msg);
298+
299+
//Send it to UART
300+
UARTsend(msgout,msgptr-msgout);
301+
}
302+
303+
//////////////////////////////////////////////////
304+
//Sends K-Bus message to ECU with particular ECUno
305+
void KBUS_send_msg(volatile unsigned char ECUno)
306+
{
307+
switch(KBUS_state)
308+
{
309+
case KBUS_S_IDLE:
310+
KBUS_STC_req.header.Tgt = BIKES_DATA[ECUno].ecu_addr;
311+
KBUS_fast_init();
312+
KBUS_msg_to_uart(&KBUS_STC_req);
313+
break;
314+
315+
case KBUS_S_COMM_STARTED:
316+
KBUS_RDBLID_req.header.Tgt = BIKES_DATA[ECUno].ecu_addr;
317+
RLOCID=BIKES_DATA[ECUno].local_id_gear;
318+
KBUS_msg_to_uart(&KBUS_RDBLID_req);
319+
break;
320+
321+
case KBUS_S_DATA_POOLING:
322+
//if GEAR localID is different from RPM localID, read that different localID and we need to read RPM (if RPM is programmed or we are in programming mode)
323+
if(BIKES_DATA[ECUno].local_id_gear!=BIKES_DATA[ECUno].local_id_rpm && (rpmValue.rpm>0 || rpmValue.prgmode==0))
324+
{
325+
if(RLOCID==BIKES_DATA[ECUno].local_id_gear)
326+
RLOCID=BIKES_DATA[ECUno].local_id_rpm;
327+
else
328+
RLOCID=BIKES_DATA[ECUno].local_id_gear;
329+
}
330+
KBUS_msg_to_uart(&KBUS_RDBLID_req);
331+
break;
332+
333+
default:
334+
break;
335+
}
336+
}
337+
338+
/////////////////////////////////////////////////////////////
339+
//Checks reply from remote ECU according to actual KBus state
340+
unsigned char KBUS_check_reply(volatile unsigned char ECUno, volatile unsigned char *msg)
341+
{
342+
int replylen;
343+
344+
// Reply length: <FMT> <IND_ADDR> <ECUaddr> <Bytes Follow> <Sdl> byte[0]...byte[Bytes Follow-1] <CHS> => replylen=<Bytes Follow>+5
345+
replylen = msg[3]+5;
346+
347+
switch(KBUS_state)
348+
{
349+
case KBUS_S_IDLE:
350+
//KBUS_START_COMM_RPL
351+
//{<FMT> <IND_ADDR> <ECUaddr> <0x03> <STCPR> <0xEA> <0x8F> <CHS>};
352+
if( msg[1]==IND_ADDR && \
353+
msg[2]==BIKES_DATA[ECUno].ecu_addr && \
354+
msg[4]==STCPR && \
355+
msg[replylen-1]==KBUS_checksum1(msg,replylen-1)
356+
)
357+
{
358+
KBUS_state = KBUS_S_COMM_STARTED;
359+
return(TRUE);
360+
break;
361+
}
362+
else
363+
return(FALSE);
364+
break;
365+
366+
case KBUS_S_COMM_STARTED:
367+
case KBUS_S_DATA_POOLING:
368+
//{<B0> <B1> <B2> <B3> <B4> <B5> <B6> <BN> <CHS>};
369+
//{<FMT> <IND_ADDR> <ECUaddr> <Bytes Follows> <RDBLIDPR> <Loc_Id> <B6>... ... ... ... ... ... <BN> <CHS>};
370+
//{<FMT> <IND_ADDR> <0x11> <0x03> <RDBLIDPR> <0x0B> <GEAR> <CHS>}; KAWASAKI01
371+
//{<FMT> <IND_ADDR> <0x11> <0x04> <RDBLIDPR> <0x09> <RPM1> <RPM2> <CHS>}; KAWASAKI01
372+
//{<FMT> <IND_ADDR> <0x12> <0x34> <RDBLIDPR> <0x08> <B6>...<B16> <RPM1> <RPM2> ...<B25>,<GEAR>,<B27>... ...<Byte55> <CHS>}; SUZUKI01
373+
if( msg[1]==IND_ADDR && \
374+
msg[2]==BIKES_DATA[ECUno].ecu_addr && \
375+
msg[4]==RDBLIDPR && \
376+
(msg[5]==BIKES_DATA[ECUno].local_id_gear || msg[5]==BIKES_DATA[ECUno].local_id_rpm) && \
377+
msg[replylen-1]==KBUS_checksum1(msg,replylen-1)
378+
)
379+
{
380+
KBUS_state=KBUS_S_DATA_POOLING;
381+
return(TRUE);
382+
break;
383+
}
384+
else
385+
return(FALSE);
386+
break;
387+
388+
default:
389+
return(FALSE);
390+
break;
391+
}
392+
}

0 commit comments

Comments
 (0)