For my current application, I'm writing up a plugin that will allow a device to speak to a slave device. The slave device has two checksums, a header and a data checksum. The header checksum was producing some erratic results which was fine tuned and corrected by members here: Odd Checksum Result(s) - Not Receiving Expected Results
Now I'm unsure if my data checksum is correct. I believe it is because of a thread that I had created here to help understand and build it which I did here: Converting a C Checksum Function to Lua
Now, I do not think that it is the data checksum functions. But I believe it is the way I am trying to implement it. I'm at the point where I'm now just trying to duplicate example code and send it to my slave device in hopes that I receive the appropriate response(s). Problem is that I am receiving nACK's in return. I've tried every permutation and combination I could think of and I'm not receiving an accepted value. The input
is a representation of the string I need to send to the function databuild(str)
function below.
input = "010032380000000000000000000000000000000000000000" -- title must be a specific length so it is filled with NUL's to meet that criteria
function CRC(data, length)
sum = 65535
local d
for i = 1, length do
d = string.byte(data, i)
sum = ByteCRC(sum, d)
end
return sum
end
function ByteCRC(sum, data)
sum = sum ~ data
for i = 0, 7 do
if ((sum & 1) == 0) then
sum = sum >> 1
else
sum = (sum >> 1) ~ 0xA001
end
end
return sum
end
function databuild(str) -- I know I should not be doing what's inside here but don't fully understand why not to and better ways of approaching it.
local dataSum = ""
local dataSumReslt = ""
local dataConv = ""
for char in str:gmatch("..") do
dataConv = dataConv..string.char("0x"..char)
end
dataSum = string.format("%04X", CRC(dataConv, #dataConv))
for char in dataSum:gmatch("..") do
dataSumReslt = dataSumReslt..string.char("0x"..char)
end
return dataConv..dataSumReslt
end
print(databuild(input))
I'm supposed to be getting the data checksum based on those byte values in my print statement. I send the entire string to the function databuild(str)
function. From there I turn the result to hex format and then concatenate that result (after turning the two-byte value to hex via string.char
) and then return the entire hex string.
Right now, as it is, I get the result 170B
. Unfortunately, I'm not advanced enough in programming to debug or test out properly whether what I'm receiving is true or not.
Should I be turning the data string into hex first prior to doing the function CRC(data, length)
or should I leave it the decimal representation first, or does it even matter???
Since all 2-byte and 4-byte words within my files are needed to be little-endian, does it mean that my checksum should also be little-endian? Or are checksums left untouched? (the checksum functions were provided in C in the slave device's manual.
Finally, what is a better way to approach the function databuild(str)
so that I'm not breaking up each byte, translating it, then concatenating it so much? I am very appreciative when my code is corrected. But can someone help me understand exactly why it is just not a good thing to do?
Since I'm fairly new to programming in general, most of the time I'm not trying to work at this low-level (bit manipulation). I haven't reached this point in any of my classes since it has been all higher-level programming (Java and self-taught what I know in Lua). This is my first work project where it is truly "baptism by fire" concerning bytes, hex conversions, etc. Needless to say I'm barely keeping my head above water here. So all the constructive criticism I get is DEFINITELY wanted.
You can replace
for char in str:gmatch("..") do
dataConv = dataConv..string.char("0x"..char)
end
with
dataConv = str:gsub("..",function (x) return string.char(tonumber(x,16)) end)
You can simplify this to
dataConv = str:gsub("..",HEX)
after doing
HEX={}
for c=0,255 do
HEX[string.format("%02x",c)] = string.char(c)
end
This will avoid the concatenations.