Druhý díl tohoto seriálu se věnoval popisu formátu CID slovníku. Od vzniku tohoto dílu uplynula již nějaká voda a ve verzi programu PP2CAN s číslem 3.073 byla přidána podpora nového formátu souboru. Ten dostal koncovku ECID. Původní varianta slovníku byla navržena tak, že prováděla pojmenování podle nastavení, které bylo fixní pro všechny zprávy. Nebylo možné jednu zprávu pojmenovat jen podle identifikátoru a u druhé brát v úvahu i datové bajty. Tedy pokud bylo nastaveno pojmenování podle identifikátoru a prvního datového bajtu, bylo toto pevné pro všechny přijaté zprávy.
Z důvodu nepružnosti pro složitější protokoly jsme vytvořili nový formát, na který byly kladeny tyto požadavky:
- textový formát soubory, který jde rychle a snadno editovat
- soubor má úsporný zápis
- pro identifikátor a datové bajty lze používat masky
- možnost použití seznamů a rozsahu pro identifikátor
- možnost použití rozsahů pro datové bajty
- každé pravidlo pro pojmenování může používat různé položky zprávy
- možnost pracovat se šablonou a stackem šablony tak, aby nebylo nutno vypisovat všechny položky nutné pro pojmenování zprávy
V tomto díle si tak ukážeme jak s tímto formátem pracovat, nejprve se popíšeme filozofii s jakou tento formát pracuje a pojmy, které budeme používat.
Šablona
Aby jsme nemuseli neustále psát všechny parametry, které mají vliv na pojmenování, můžeme pracovat se šablonou. Pro pravidlo, které provádí pojmenování pak platí, že nejprve se do něj zkopíruje obsah nastavení šablony a následně se pouze zadá změněný parametr (například hodnota datového bajtu) či název.
Stack
Šablonu je možné ukládat do stacku, tím se můžeme snadno vracet k předchozím variantám šablony. Šablony a ukládání na stack mohou být vnořené do sebe.
Maska
V některých případech chceme pojmenovávat jen podle části identifikátoru nebo i datového bajtu, pak je možné nastavit masku bitů které mají na pojmenování vliv.
Nyní k syntaxi souboru. Každý řádek začíná řídícím znakem (před znakem mohou ležet mezery), zde je jejich přehled:
> tento znak vkládá nové pravidlo, za znakem následují parametry pravidla a název
% znak uvozuje řádek s parametry, které nastavují šablonu
+ znak taktéž uvozuje řádek s parametry, které nastavují šablonu avšak před nastavením šablony uloží předchozí verzi šablony na stack
{ začátek nové sekce, šablona se uloží na stack
} konec sekce, návrat k předchozí verzi šablony která je uložena na stacku
- návrat k předchozí verzi šablony pokud se nepoužívá sekce ale znak + (dvojce znaků -- pak maže celý stack - všechny položky stacku)
! mazání šablony nebo položek šablony je li uveden další znak
= nastavení jména do šablony
; komentář
Všechny řádky které nezačínají některým z těchto znaků se berou jako komentáře a nezpracovávají se. Protože však může dojít k dalšímu rozšíření syntaxe, používejte pro komentáře znak ; který je pro komentáře vyhrazen.
Začněme příkladem několika řádku na kterých si syntaxi dále vysvětlíme:
>I:xF00400,E,M:xFFFF00,#RPM
Řádek začíná znakem >, jedná se tak o vložení pojmenovávacího pravidla. Parser souboru řádek načte a rozdělí na části mezi čárkami. První část tak vypadá takto: I:xF00400, Prvním znakem je I, tedy nastavujeme konkrétní identifikátor, za znakem i je dvojtečka která odděluje parametry, Zde je parametrem identifikátor 0xF00400. Chceme li tedy zapisovat identifikátor hexadecimálně, začínáme znakem x, pokud znak x není uveden, hodnota se interpretuje jako dekadická. Další část obsahuje jen znak E, identifikátor je tak 29 bitový. Pokud by znak nebyl uveden, jednalo by se o 11 bitový identifikátor (což je ale v případě F00400 nesmysl). Třetí část začíná znakem M, ten nastavuje masku pro identifikátor, poslední čtvrtá část začíná znakem #, ten znamená že bezprostředně za tímto znakem začíná název s pojmenováním. Dvojtečka zde není použita, aby ji bylo případně možné použít pro oddělení názvů skládaných do šablony a čemž později. Znalci už tuší že se snažíme pojmenovat zprávu EEC1 dle SAE J1939 názvem RPM.
%I:xDA0000,E,M:xFF0000,#UDS
Tento řádek začíná znakem %, to znamená že se nevytváří přímo pojmenovávací pravidlo, ale nastavují se parametry do šablony. Platí, že pokud některý další řádek bude nastavovat šablonu, je případný další název za znakem # přidán k předchozímu.
+I:x7E4,#UDS
Příklad kdy je do šablony nastaven 11 bitový identifikátor, maska není použita. Protože je použit znak +, je předchozí verze šablony uložena na stack.
+L:x7E4:x7E8:x7EC,#UDS
Zde nastavujeme do šablony 3 identifikátory L (list) - seznam identifikátorů., identifikátory v seznamu jsou odděleny dvojtečkou.
+R:x7E0:x7EF,#UDS
Písmeno R pak specifikuje, že je zadán rozsah (range) identifikátorů.
Jak je vidět z předchozího, jednotlivé řádky za řídícím znakem obsahují parametry oddělené čárkou. O jaký parametr pro řídící znaky >%+ se jedná pak specifikují tyto příkazy:
I - samostatný identifikátor
R - rozsah identifikátorů od - do
L - seznam identifikátorů
M - maska identifikátoru (kombinuje se se samostatným identifikátorem, rozsahem i seznamem)
E - rozšířený identifikátor
0 až 7 - hodnota datového bajtu
m0 až m7 - maska datového bajtu
S - indikace velikosti dat v názvu - například je li uveden počet datových bajtů u nějakého multipaketového přenosu
# - název
Pro řídící znak - (mínus) ,který vrací šablonu na hodnotu z vrcholu stacku, platí že je li uvedeno -- (2x mínus), je stack vymazán a šablona resetována
Řídící znak ! (vykřičník) pak může mít také více variant:
! - reset šablony (šablony ve stacku zůstávají)
!N - reset názvu uloženého v šabloně
!S - reset nastavení indikace velikosti
!L - reset seznamu identifikátorů
!I - reset identifikátoru
!M - reset masky identifikátoru
!m - reset všech masek datových bajtů
!0 až !7 - reset datového bajtu a jeho masky
A teď prakticky, vytvoříme si jednoduchý soubor pro pojmenování zpráv OBD a UDS protokolu, nejprve si jej celý uvedeme a následně si vysvětlíme položky:
%R:x7E0:x7EF,#OBD %m0:xF0,0:x00,#Single %S:0:4:B { %1:x01,#OBD Show current data >2:x0,#PIDs supported [$01 - $20] >2:x1,#Monitor status since DTCs cleared >2:x2,#DTC that caused freeze frame to be stored >2:x3,#Fuel system status >2:x4,#Calculated engine load >2:x5,#Engine coolant temperature >2:x6,#Short term fuel trim—Bank 1 >2:x7,#Long term fuel trim—Bank 1 >2:x8,#Short term fuel trim—Bank 2 >2:x9,#Long term fuel trim—Bank 2 >2:xA,#Fuel pressure >2:xB,#Intake manifold absolute pressure >2:xC,#Engine speed >2:xD,#Vehicle speed } >1:x02,#OBD Show freeze frame data >1:x03,#OBD Show stored Diagnostic Trouble Codes { %1:x11,#ECU Reset >2:x1,#hardReset >2:x2,#keyOffOnReset >2:x3,#softReset >2:x4,#enableRapidPowerShutDown >2:x5,#disableRapidPowerShutDown >2:x40,#vehicleManufacturerSpecific >2:x60,#systemSupplierSpecific >2:*,#ISOSAEReserved } { %1:x22,%2:xF1,#Read Data By Identifier >3:x80,#bootSoftwareIdentificationDataIdentifier >3:x81,#applicationSoftwareIdentificationDataIdentifier >2:xFD:FE,3:x00:xFF,#SystemSupplierSpecific >2:xFF,3:x00:xFF,#ISOSAEReserved } >1:x22,#Unknown dataIdentifier >1:x7F,#Negative Response -- %R:x7E0:x7E8,#OBD %S:8:12:B >m0:xF0,0:x10,#First Frame -- %R:x7E0:x7E8,#OBD >m0:xF0,0:x20,#Consecutive Frame -- %R:x7E0:x7E8,#OBD >m0:xF0,0:x30,#Flow Frame
%R:x7E0:x7EF,#OBD
Do šablony nastavujeme rozsah identifikátorů 0x7E0 až 0x7EF a do názvu text OBD. Tedy identifikátor zprávy musí být v tomto rozsahu.
%m0:xF0,0:x00,#Single
Dále do šablony nastavujeme, že datový bajt DB0 má masku 0xF0 a hodnotu 0. Tedy horní 4 bity (maska 0xF0) musí mít hodnotu 0. Platí že porovnávány jsou hodnoty bitů které mají masku nastavenu na 1:
maska AND nastavená hodnota datového bajtu == maska AND hodnota přijatého datového bajtu
Pravidlo pak je splněno v uvedeném případě pokud datový bajt DB0 má hodnotu 0x00, 0x01, 0x02 ... , 0x0F. Cokoliv jiného (např 0x11) není akceptováno.
K názvu v šabloně je přidán text Single. Tedy pro předchozí 2 řádky by platilo že název obsahuje text "OBD Single" .
%S:0:4:B
Nastavujeme indikaci velikosti. Zadáváme polohu prvního bitu (zpráva má 8 bajtů - 64 bitů) , poloha je nultý bit, délka je 4 bity a hodnota je typu big endian. Zde nemá význam neboť bity nepřechází mezi datovými bajty. Více k problematice například u popisu EYE souborů. B či b zadává big endian, cokoliv jiného nebo pokud parametr není uveden, jedná se o little endian.
{
Současný stav šablony se ukládá na stack.
%1:x01,#OBD Show current data
Šablona je doplněna o pravidlo že hodnota DB1 se musí rovnat hodnotě 0x01 a název o OBD Show current data. Pojmenování uložené v šabloně tak obsahuje text "OBD Single OBD Show current data".
>2:x0,#PIDs supported [$01 - $20]
Nyní již nepracujeme se šablonou, ale vkládáme první pravidlo. To obsahuje požadavky uložené v šabloně plus požadavek že DB2 musí obsahovat hodnotu 0. Název zprávy, která bude vyhovovat pak obsahuje text uložený v šabloně doplněn o text "PIDs supported [$01 - $20] ".
Vyhovovat bude například zpráva:
0x7E1 0x00 0x01 0x00 x x x x x
Identifikátor je v zadaném rozsahu, DB0 vyhovuje masce a hodnotě, DB1 a DB2 mají zadanou hodnotu, ostatní datové bajty (x) nemají na pojmenování vliv.
>2:x1,#Monitor status since DTCs cleared
Další pravidlo, DB2 musí mít hodnotu 1.
>2:x2,#DTC that caused freeze frame to be stored
Další pravidlo, DB2 musí mít hodnotu 2.
Další řádky jsou analogií předchozího, dostáváme se k:
}
Vracíme se ke stavu šablony uložené na stacku. Tedy již není vyžadováno pravidlo:
%1:x01,#OBD Show current data
a tedy že hodnota DB1 musí mít hodnotu 1.
>1:x02,#OBD Show freeze frame data
Vkládáme další pravidlo, hodnota datového bajtu DB1 musí mít hodnotu 2.
Vyhovovat bude například zpráva:
0x7E3 0x02 0x02 x x x x x x
Název tak bude OBD Single OBD Show freeze frame data.
>1:x03,#OBD Show stored Diagnostic Trouble Codes
Vkládáme další pravidlo, hodnota datového bajtu DB1 musí mít hodnotu 2.
Název tak bude OBD Single Show stored Diagnostic Trouble Codes.
{
Uložení šablony na stack.
%1:x11,#ECU Reset
Šablona je doplněna o pravidlo že hodnota DB1 se musí rovnat hodnotě 0x11.
>2:x1,#hardReset
Pravidlo, DB2 musí obsahovat hodnotu 1.
Vyhovovat bude 0x7E1 0x00 0x11 0x01 x x x x x
>2:x2,#keyOffOnReset
Pravidlo, DB2 musí obsahovat hodnotu 2.
Po několika řádcích se dostáváme k:
>2:*,#ISOSAEReserved
Zde je uvedena jako hodnota datového bajtu hvězdička. Ta znamená všechny ostatní hodnoty tohoto bajtu, které nebyly uvedeny na předchozích řádcích. Je li toto pravidlo s hvězdičkou uvedeno, musí se nacházet až za ostatními hodnotami tohoto bajtu jako poslední.
}
Návrat ke stavu šablony před jejím uložením.
{
Opět ukládáme na stack, zde následuje přečtení ze stacku a ihned zase uložení, nicméně závorky zároveň používáme pro strukturování a tedy zlepšení čitelnosti.
%1:x22,%2:xF1,#Read Data By Identifier
Do šablony nastavujeme požadavek že DB1 musí mít hodnotu 0x22 (Read Data By Identifier ) a zároveň DB2 musí obsahovat hodnotu xF1.
>3:x80,#bootSoftwareIdentificationDataIdentifier
Vloženo pravidlo že DB3 obsahuje hodnotu 0x80. Tedy Read Data By Identifier (0x22) a bootSoftwareIdentificationDataIdentifier (0xF180). Více například v normě UDS.
>3:x81,#applicationSoftwareIdentificationDataIdentifier
Další pravidlo podobně jako předchozí.
>2:xFD:FE,3:x00:xFF,#SystemSupplierSpecific
Pravidlo při vložení přepisuje požadavek hodnoty datového bajtu DB2 z hodnoty 0xF1 na 0xFD až 0xFE. Je zde tak zadán rozsah hodnot bajtu DB2. Stejně tak je zadán rozsah pro DB3 a to 0x00 až 0xFF.
>2:xFF,3:x00:xFF,#ISOSAEReserved
Vloženo další pravidlo, DB2 musí mít hodnotu 0xFF a DB3 0x00 až 0xFF. Hodnoty DB3 se vkládají spíše pro přehlednost při přepisování dat z normy UDS. Rozsah (0až 255) je přes celý bajt a tak zadání rozsah nemá v tomto případě význam.
}
Opět návrat šablony na hodnotu ze stacku
>1:x22,#Unknown dataIdentifier
Vše ostatní co nevyhovuje předchozím pravidlům ve kterých je požadována hodnota 0x22 v DB1 dostane do názvu Unknown dataIdentifier.
>1:x7F,#Negative Response
DB1 s hodnotou 0x7F.
--
Reset šablony a smazání stacku.
%R:x7E0:x7E8,#OBD
Nastavíme rozsah identifikátorů neboť jsme šablonu vymazali. Pokud by jsme se tomuto chtěli vyhnout je potřeba u předchozího nastavení použít uložení šablony na stack a nepoužívat reset stacku.
%S:8:12:B
Indikaci velikosti nastavujeme na jiné hodnoty......
>m0:xF0,0:x10,#First Frame
...... neboť se tentokrát bude jednat o paket First frame multipaketového přenosu. Používáme opět masku, aby jsme rozlišili tento paket podle prvního datového bajtu.