Skip to content

Instantly share code, notes, and snippets.

@flaviotoribio
Forked from kosenko-max/racecapture3.lua
Created June 1, 2024 00:46
Show Gist options
  • Save flaviotoribio/f3ab1248d0bf6e596e41957ba95a0b30 to your computer and use it in GitHub Desktop.
Save flaviotoribio/f3ab1248d0bf6e596e41957ba95a0b30 to your computer and use it in GitHub Desktop.
Improved version with CAN mapping in the config string
-- Copyright 2016 Mash at boostedforums.net
-- Minify before use by https://mothereff.in/lua-minifier
-- Editor https://ace.c9.io/build/kitchen-sink.html
-- don't remove excessive commas or comments - minify will deal with it
-- ========================= CAN CONFIG =======================================
local canCon ="0x7E1,0x33,10;8,SstTemp,-50,205,C@0x7E1,0x34,10;8,SstMode,1,3@0x7E1,0x36,3;8,Gear,0,11@0x7E1,0xA6;16,SstSlip1,-8500,8500,RPM,1/2,0,1;16,SstSlip2,-8500,8500,RPM,1/2,0,1@0x7E1,0xAA;16,SstPress1,0,30,Bar,1/500,0,1;16,SstPress2,0,30,Bar,1/500,0,1@0x7E1,0xA5;16,SstTemp1,-40,215,C,1/4,0,1;16,SstTemp2,-40,215,C,1/4,0,1@0x7E1,0x38;8,GearTarget,0,11@0x7E1,0xAB;16,SstPosF1,-128,128,mm,1/256,0,1;16,SstPosF2,-128,128,mm,1/256,0,1@0x7E1,0xAC;16,SstPosF3,-128,128,mm,1/256,0,1;16,SstPosF4,-128,128,mm,1/256,0,1@0x7E1,0xAD;16,SstCurF1,0,2048,mA,1/16,0,1;16,SstCurF2,0,2048,mA,1/16,0,1@0x7E1,0xAE;16,SstCurCool,0,2048,mA,1/16,0,1@0x7E1,0xAF;16,SstCurLPS,0,2048,mA,1/16,0,1@0x7E1,0xB0;16,SstShaft1,0,8500,RPM,1/2,0,1;16,SstShaft2,0,8500,RPM,1/2,0,1@0x7E1,0xB2;16,SstDamper,0,8500,RPM,1/2,0,1@0x7E1,0x1B;16,WheelFR,0,3000,RPM,1/2;16,WheelRR,0,3000,RPM,1/2;16,WheelFL,0,3000,RPM,1/2;16,WheelRL,0,3000,RPM,1/2@0x784,0x02;16,Steering,-420,420,deg,1/22.885,0,1;32;16,BrakeMC,0,120,bar,1/100,0,1;16,BrakeFL,0,120,bar,1/100,0,1;16,BrakeFR,0,120,bar,1/100,0,1;16,BrakeRL,0,120,bar,1/100,0,1;16,BrakeRR,0,120,bar,1/100,0,1@0x7E0,0x805100;16,Load,0,1000,load,10/32;16,RPM,0,10000,rpm,1000/256;16,MAP,0,60,psi,19.3383650667/300;16,MivecIn,-2.5,37.5,deg,-10/512,80;16,MivecEx,-37.5,2.5,deg,-10/512,80;16,IPW,0,32,ms,0.001;8,AFR,8,18,afr,0.046872,7.3125;8,Speed,0,255,kph;8,Timing,-20,107,deg,1,-20;8,KnockSum,0,255;8,TPS,0,100,%,100/255;8,WGDC,0,100,%,1/2;8,ECT,-40,215,C,1,-40;8,MAT,-40,215,C,1,-40;8,IAT,-40,215,C,1,-40;8,STFT,-25,25,%,100/512,-25;8,LTFT,-25,25,%,100/512,-25;8,MAF,0,5,V,5/255;16,LoadMAP,0,1000,load,100/16384;16,LoadMAF,0,1000,load,100/16384;8,KnockBase,0,255;8,KnockFilter,0,255@0x7E0,0x805100;8,Load,0,398,load,100/64;8,IPW,0,25.5,ms,1/10;8,AfrMap,8,20,afr,1/14.7/128;24;8,LtftIdle,-25,25,%,100/512,-25;8,LtftCruise,-25,25,%,100/512,-25;8,LoadTiming,0,398,load,100/64;33;7,Baro,0.45*14.5037738,1.725*14.5037738,psi,14.5037738/200,0.45*14.5037738;16;8,MivecInTar,-2.5,37.5,deg,10/64,-2.5;8,MivecExTar,-37.5,2.5,deg,-10/64,2.5;24;8,APP,0,100,%,1/2,-16;8;8,WgdcCorr,-64,128,%,1/2;8,SpeedH,0,330,kph,2;8,EcuVolt,0,18.7,V,18.7/255;24;8,LoadImap,0,398,load,100/64;8;8,LoadChosen,0,398,load,100/64@0x7E0,0x808661,2;8,FrontO2,0,1,V,5/255@"
local canMap = {}
local sb,sl,sm = string.byte,string.len,string.match
function readOne(pos)
local c = sb(canCon,pos)
if c==nil then return nil,pos+1 end
if (c > 47 and c < 58) or c==45 then -- read number
local nums = sm(canCon,"[-.%xxX]+",pos)
local num = tonumber(nums)
local pos2 = pos+sl(nums)
c=sb(canCon,pos2)
if c==42 or c==47 then -- MULTIPLY or DIVIDE
pos2=pos2+1
local nums2=sm(canCon,"[-.%xxX]+",pos2)
local num2=tonumber(nums2)
pos2 = pos2+sl(nums2)
if c==42 then num=num*num2 else num=num/num2 end
end
return num,pos2
end
-- Read string
local st = sm(canCon,"[^,;@]+",pos)
if st==nil then return nil,pos+1
else return st, pos+sl(st) end
end
function ss(pos)
return string.sub(canCon,pos,pos)
end
function canRDmap()
local cmi,res,pos = 1,nil,1
while pos <= sl(canCon) do
canMap[cmi]=nil -- separator of requests
canMap[cmi+1],pos=readOne(pos) -- address
canMap[cmi+2],pos=readOne(pos+1) -- pid
if ss(pos) =="," then
canMap[cmi+3],pos=readOne(pos+1) -- priority
else canMap[cmi+3]=1 end
--print("REQUEST Address: "..canMap[cmi+1].." PID: "..canMap[cmi+2].." Priority: "..canMap[cmi+3])
local cmi_len = cmi+4
canMap[cmi_len]=0
cmi=cmi+5
while ss(pos)~="@" do
-- Address,PID,Priority (1)
-- ;Bits,Name,Min,Max,Unit,Mult(1),Add(0),Signed(0/1 - default 0)
-- ;Bits - skip number of bits forward
-- @
-- nil, address, pid, priority, length - request
-- bits, nil - skip
-- bits, channelId, mult, add, signed - channel
--print(" start char "..ss(pos))
local name,minv,maxv,precision,unit,mult = "",0,0,0,"",1
canMap[cmi],pos=readOne(pos+1) --bits
--print(" bits: "..canMap[cmi])
canMap[cmi_len]=canMap[cmi_len]+canMap[cmi] -- count length
if ss(pos)~="," then
--print(" skip "..ss(pos))
canMap[cmi+1]=nil -- Skip
cmi=cmi+2
else
name,pos = readOne(pos+1)
minv,pos = readOne(pos+1)
maxv,pos = readOne(pos+1)
if ss(pos)=="," then unit,pos = readOne(pos+1) --unit
else unit = "" end
if ss(pos)=="," then mult,pos = readOne(pos+1) --mult
else mult=1 end
canMap[cmi+2]=mult
if ss(pos)=="," then canMap[cmi+3],pos = readOne(pos+1) --add
else canMap[cmi+3]=0 end
if ss(pos)=="," then canMap[cmi+4],pos = readOne(pos+1) --sign
else canMap[cmi+4]=0 end
while mult < 1 do
precision=precision+1
mult=mult*10
end
canMap[cmi+1]=addChannel(name,1000,precision,minv,maxv,unit)
cmi=cmi+5
end
end
pos=pos+1
end
canCon = nil -- Clean memory from large string we won't use anymore
end
function canRDall(count)
-- nil, address, pid, priority, length - request
-- bits, nil - skip
-- bits, channelId, mult, add, signed - channel
local i = 1
while canMap[i+1]~=nil do
if (count % canMap[i+3]) == 0 then -- Priority implement
local data = canRD(canMap[i+1],canMap[i+2],canMap[i+4])
if data ~= nil then
i=i+5
local bit = 1
while canMap[i]~=nil do -- Set Channels
if canMap[i+1]~=nil then
local val = bitsToN(data,bit,canMap[i],canMap[i+4])
val=val*canMap[i+2]+canMap[i+3]
setChannel(canMap[i+1],val)
bit=bit+canMap[i]
i=i+5
else -- skip bits
bit=bit+canMap[i]
i=i+2
end
end
end
end
end
end
-- =========== UP TO 24 BIT NUMBER EXTRACTION FROM BYTE ARRAY ==================
local band, bxor, bnot = bit.band, bit.bxor, bit.bnot
local lshift, rshift = bit.lshift, bit.rshift
function bitsToN(d,startBit,length,signed)
local shift = (8 - ((startBit+length-1) % 8)) % 8
local startByte = 1 + (startBit - 1 - ((startBit-1) % 8)) / 8--TODO: to //
local bnumb = d[startByte]
if (length+shift) > 8 then
bnumb = d[startByte+1] + lshift(bnumb,8)
if (length+shift) > 16 then
bnumb = d[startByte+2] + lshift(bnumb,8)
end
end
bnumb = rshift(bnumb,shift)
bnumb = band(bnumb,2^length-1)
if signed and bnumb > 0x7FFF then
bnumb = 0 - lshift(band(-bnot(0x1000+rshift(number,8)),0xFF),8)
- band(-bxor(0x1000+band(number,0xFF),0),0xFF) - 1
end
return bnumb
end
--============================ READ CAN DATA AND RETURN DATA BYTE ARRAY ========
function canRD(address,pid,reqLength) -- TODO: Check it works without padding
local req
if pid > 255 then -- MODE 23
req = {5,0x23,rshift(pid,16),rshift(pid,8),band(pid,0xFF),reqLength}
else -- MODE21
req={2,0x21,pid}
end
res = txCAN(0, address, 0, req, 100) -- Send request
if res ~= 1 then return nil end
local data = {}
local id, ext, d1 = rxCAN(0,100) -- Read Response
if id == nil then return nil end
-- for r,d in ipairs(d1) do print(d..",") end
-- println(" ")
local i = 1
local s = 3
if d1[1] == 0x10 then s=s+1 end -- Multimessaging
if pid < 256 then s=s+1 end -- Mode23 has more data
while s<9 do
data[i]=d1[s]
i=i+1
s=s+1
end
if d1[1] ~= 0x10 then return data end -- Not multimessaging, so quit
-- Read multi messages
res = txCAN(0, address, 0, {48,8,0},100)
if res ~= 1 then return nil end
local messages = (d1[2] + 1) / 7
for m=1,messages do
local id, ext, d1 = rxCAN(0,100)
if id == nil then return nil end
-- print(m..": ")
-- for r,d in ipairs(d1) do print(d..",") end
-- println(" ")
local s=2
while s<9 and i<reqLength+1 do
data[i]=d1[s]
i=i+1
s=s+1
end
end
return data
end
-- ========================= MAIN CYCLE =======================================
local fpChan,tgtFP,chCANHz = 3,43.5,addChannel("CAN", 1, 0, 0, 300, "Hz")
initCAN(0, 500000)
setTickRate(1000)
for i=1,10 do rxCAN(0,5) end -- Clear CAN buffer
canRDmap()
collectgarbage()
function onTick()
local started,mc = getUptime(),0
print("START")
while getUptime()-started < 1000 do -- Release Tick every second
canRDall(mc)
collectgarbage()
mc = mc + 1
end
setChannel(chCANHz, mc)
--TODO: Calculated channels:
-- SSTLoadSlip,SSTMaxPressure,SSTShiftTime,
-- AfrDiff,LtftStft,IDC,Boost,FuelPressError,MivecIn/ExError,
-- MatVsIat
-- GenStatus = 0 - cold,1 - wait warming,2 - warming,3 - full on,
-- 4 - warning check later,5 - warning slow down,6 - stop now
-- 5 and 6 go to safe map triggering in ECU
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment