--[[ Protocol : SAE-J1587 Author : IFTOOLS GmbH Version : 2017.02.15 Initial commit Version : 2020.04.29 Adapt renamed module names for cfg, bit and protocol Version : 2024.03.28 Replace bit32 function calls with native bit operators Brief: --]] -- function split is called every time a data byte is received -- with the following parameters: -- data : the data value (9 bit) (unused) -- intval : the time distance to the former data (unused) -- alter : is true when the data source (direction) was changed (unused) -- str : all received data bytes of the current telegram as a string -- returns the telegram state: UNCHANGED, STARTED, MODIFIED, COMPLETED function split( data, intval, alter, str ) if intval > transmission.bitpause( 11 ) then return STARTED end return MODIFIED end function out() -- fetch the current telegram local telegram = telegrams.this() -- number box.text{ caption="Trans", text=telegram:number(), bg= 0xf0f0f0, fg=0x444444 } local mid = telegram:data(1)..":"..Get_MID_Text( telegram:data(1) ) box.text{ caption="MID", text=mid, bg=0xf0f0f0, fg=0x444444 } -- iterate over all PIDs (meaning and value), we start with the first -- PID at position 2 (first after MID) local ppid = 2 while ppid < telegram:size() do ppid = ppid + Show_PID_Box( telegram:string():sub( ppid ) ) + 1 end -- checksum local must = Checksum( telegram:string():sub(1,-2) ) local is = telegram:data(-1) if must == is then box.text{ caption="CKS", text=string.format("%02X", is ), bg=0x90EE90 } else box.text{ caption="CKS", text=string.format("Is:%02X, Must:%02X", is, must ), bg=0xFF9A9A } end end function Checksum( data ) -- add all bytes local chksum = 0 for i=1,#data do chksum = chksum + data:byte(i) end -- bit inversion chksum = 255 - chksum + 1 return chksum & 0xFF end function Get_MID_Text( mid ) local txt = { [128] = "Engine #1", [171] = "Driver Information Center", [175] = "Engine #2" } if txt[ mid ] ~= nil then return txt[ mid ] else return "UNKNOWN" end end function Show_PID_Box( data ) local pid = data:byte(1) local paraLen = 1 -- draw the box local desc = "" local para = "" local msb = 2 local lsb = 3 local bg = nil local fg = nil if pid == 0 then elseif pid == 4 then desc,para,paraLen = Eval_PID_4( data:byte(2) ) --desc,para,paraLen = Eval_PID_0( data:byte(2) ) elseif pid == 18 then desc,para,paraLen = Eval_PID_18( data:byte(2) ) elseif pid == 19 then desc,para,paraLen = Eval_PID_19( data:byte(2) ) elseif pid == 92 then desc,para,paraLen, fg, bg = Eval_PID_92( data:byte(2) ) elseif pid == 94 then desc,para,paraLen = Eval_PID_94( data:byte(2) ) elseif pid == 44 then desc,para,paraLen = Eval_PID_44( data:byte(2) ) elseif pid == 100 then desc,para,paraLen = Eval_PID_100( data:byte(2) ) elseif pid == 103 then desc,para,paraLen = Eval_PID_103( data:byte(2) ) elseif pid == 106 then desc,para,paraLen = Eval_PID_106( data:byte(2) ) elseif pid == 109 then desc,para,paraLen = Eval_PID_109( data:byte(2) ) elseif pid == 110 then desc,para,paraLen = Eval_PID_110( data:byte(2) ) elseif pid == 127 then desc,para,paraLen = Eval_PID_127( data:byte(2) ) elseif pid == 164 then desc,para,paraLen = Eval_PID_164( data:byte(lsb) * 256 + data:byte(msb) ) elseif pid == 153 then desc,para,paraLen = Eval_PID_153( data:byte(lsb) * 256 + data:byte(msb) ) elseif pid == 167 then desc,para,paraLen = Eval_PID_167( data:byte(lsb) * 256 + data:byte(msb) ) elseif pid == 168 then desc,para,paraLen = Eval_PID_168( data:byte(lsb) * 256 + data:byte(msb) ) elseif pid == 173 then desc,para,paraLen = Eval_PID_173( data:byte(lsb) * 256 + data:byte(msb) ) elseif pid == 174 then desc,para,paraLen = Eval_PID_174( data:byte(lsb) * 256 + data:byte(msb) ) elseif pid == 175 then desc,para,paraLen = Eval_PID_175( data:byte(lsb) * 256 + data:byte(msb) ) elseif pid == 177 then desc,para,paraLen = Eval_PID_177( data:byte(lsb) * 256 + data:byte(msb) ) elseif pid == 182 then desc,para,paraLen = Eval_PID_182( data:byte(lsb) * 256 + data:byte(msb) ) elseif pid == 183 then desc,para,paraLen, fg, bg = Eval_PID_183( data:byte(lsb) * 256 + data:byte(msb) ) elseif pid == 187 then desc,para,paraLen = Eval_PID_187( data:byte(lsb) * 256 + data:byte(msb) ) elseif pid == 190 then desc,para,paraLen, fg, bg = Eval_PID_190( data:byte(lsb) * 256 + data:byte(msb) ) elseif pid == 194 then desc,para,paraLen = Eval_PID_194( data ) elseif pid == 247 then desc,para,paraLen = Eval_PID_247( data ) elseif pid == 250 then desc,para,paraLen = Eval_PID_250( data ) elseif pid == 254 then desc,para,paraLen = Eval_PID_254( data ) elseif pid == 255 then pid = 256 + data:byte( 2 ) desc,para,paraLen = Eval_PID_353( data ) end if fg == nil then fg = 0x000000 end if bg == nil then bg = 0xFFFFFF end if desc == "" then bg = 0xFFDEA2 end if pid == 0 or pid == 4 or pid == 194 or pid == 255 then bg = 0xFF8080 end box.text{ caption="PID:"..pid, text=desc..":"..para, bg=bg } return paraLen end -- A.0 Request Parameter function Eval_PID_0( value ) return "Request Parameter",value,1 end -- A.4 Reserved function Eval_PID_4( value ) return "RESERVED!",value,1 end -- A.18 Extended Range Fuel Pressure function Eval_PID_18( value ) -- bit resolution = 4 kPa return "Extended Range Fuel Pressure", ( value * 4 ).."kPa",1 end -- A.19 Extended Range Engine Oil Pressure function Eval_PID_19( value ) -- bit resolution = 4 kPa return "Extended Range Engine Oil Pressure", ( value * 4 ).."kPa",1 end -- A.21 Engine ECU Temperature function Eval_PID_21( value ) -- bit resolution = 2.5°F local result= 0 if value >= 127 then result = ( value - 255 ) * 2.5 else result = value * 2.5 end return "Engine ECU Temperature", result.."°F",1 end -- A.44 Attention/Warning Indicator Lamp Status function Eval_PID_44( value ) -- bits 8-7: Reserved, both bits set to 1 -- bits 6-5: Protect lamp status -- bits 4-3: Amber lamp status -- bits 2-1: Red lamp status -- Conditions for all: -- 00 : Off -- 01 : On -- 10 : Error condition -- 11 : Not available local cond = { [0] = "Off", [1] = "On", [2] = "Error", [3] = "nc" } local result = string.format( " Protect:%s, Amber:%s, Red:%s", cond[ ( value >> 4 ) & 3 ], cond[ ( value >> 2 ) & 3 ], cond[ value & 3 ] ) return "Indicator Lamp Status", result, 1 end -- A.92 Percent Engine Load function Eval_PID_92( value ) if val then value = val * 2 fg = 0x000000 bg = bgc[ n ] end return "Percent Engine Load", (value * 0.5).."%",1 end -- A.94 Fuel Delivery Pressure function Eval_PID_94( value ) -- bit resolution = 3.45kPa -- 101.325 kPa = 1.01325 bar local value = math.random( 101000, 110000 ) / 3450 return "Fuel Delivery Pressure", ( value * 3.45 ).."kPa",1 end -- A.100 Egine Oil Pressure function Eval_PID_100( value ) -- bit resolution = 3.45kPa -- 101.325 kPa = 1.01325 bar local value = math.random( 202000, 220000 ) / 3450 return "Engine Oil Pressure", ( value * 3.45 ).."kPa",1 end -- A.103 Turbo Speed function Eval_PID_103( value ) -- bit resolution = 500 rpm return "Turbo Speed", ( value * 500 ).."rpm",1 end -- A.106 Air Inlet Pressure function Eval_PID_106( value ) -- bit resolution = 1.724 kPa return "Air Inlet Pressure", ( value * 1.724 ).."kPa",1 end -- A.110 Engine Coolant Temperature function Eval_PID_110( value ) -- resolution 1°F local value = math.random( 70, 75 ) * 1.8 + 32 return "Engine Coolant Temperature", value.."°F",1 end -- A.109 Coolant Pressure function Eval_PID_109( value ) -- bit resolution = 0.862 kPa return "Coolant Pressure", (value * 0.862 ).."kPa",1 end -- A.127 Transmission Oil Pressure function Eval_PID_127( value ) -- resolution 13.8 kPa return "Transmission Oil Pressure", (value * 13.8).."kPa",1 end -- A.153 Crankcase Pressure function Eval_PID_153( value ) -- bit resolution = 0.0078125 kPa if value >= 0x7FFF then value = value - 0xFFFF end return "Crankcase Pressure", ( value * 0.0078125 ).."kPa",2 end -- A.164 Injection Control Pressure function Eval_PID_164( value ) -- bit resolution = 1/256 MPa return "Injection Control Pressure", ( value / 256 ).."MPa",2 end -- A.167 Alternator Potential function Eval_PID_167( value ) -- bit resolution = 0.05V return "Alternator Potential", (value * 0.05 ).."V",2 end -- A.168 Battery Potential function Eval_PID_168( value ) -- bit resolution = 0.05V return "Battery Potential", (value * 0.05 ).."V",2 end -- A.173 Exhaust Gas Temperature function Eval_PID_173( value ) -- bit resolution = 0.25°F local value = 4 * math.random( 200, 210 ) * 1.8 + 32 return "Exhaust Gas Temperature", (value * 0.25 ).."°F",2 end -- A.174 FuelTemperature function Eval_PID_174( value ) -- bit resolution = 0.25°F return "Fuel Temperature", (value * 0.25 ).."°F",2 end -- A.175 Engine Oil Temperature function Eval_PID_175( value ) -- bit resolution = 0.25°F return "Engine Oil Temperature", (value * 0.25 ).."°F",2 end -- A.177 Transmission#1 Oil Temperature function Eval_PID_177( value ) -- bit resolution = 0.25°F if value >= 0x7FFF then value = value - 0xFFFF end return "Transmission#1 Oil Temperature", (value * 0.25 ).."°F",2 end -- A.182 Trip Fuel function Eval_PID_182( value ) -- bit resolution = 0.473 L return "Trip Fuel", (value * 0.473 ).."L",2 end -- A.183 Fuel Rate function Eval_PID_183( value ) -- bit resolution = 1/64 gal/h (1 gal = 3.7854 l) if val then value = val * 64 end return "Fuel Rate", (value / 64 ).."gal/h",2 end -- A.187 Power Takeoff Speed function Eval_PID_187( value ) -- bit resolution = 0.25 rpm return "Power Takeoff Speed", (value * 0.25 ).."rpm",2 end -- A.190 Engine Speed function Eval_PID_190( value ) if val then value = val * 4 bg = bgc[ n ] end return "Engine Speed", (value*0.25).."rpm",2 end -- A.194 Transmitter System Diagnostic Code And Occurence Count Table function Eval_PID_194( data ) local len = data:byte(2) local result = "Len:"..len..", "..data:sub(3,-2):dump{} return "System Diagnostic",result,#data end -- A.247 Total Engine Hours function Eval_PID_247( data ) -- bit resolution = 0.05h local len = data:byte(2) local hours = data:byte(3) + 256*data:byte(4) + 65536*data:byte(5)+16777216*data:byte(6) return "Total Engine Hours", ( hours * 0.05 ).."h",5 end -- A.250 Total Fuel Used function Eval_PID_250( data ) -- bit resolution = 0.473L local len = data:byte(2) local fuel = data:byte(3) + 256*data:byte(4) + 65536*data:byte(5)+16777216*data:byte(6) return "Total Fuel Used", ( fuel * 0.473 ).."L",5 end -- A.254 Data Link Escape function Eval_PID_254( data ) return "Data Link Escape",data:sub(2,-2):dump{},#data end -- A.353 Reserved - To be assigned! function Eval_PID_353( data ) return "Reserved - To be assigned","?",#data end