Can someone help me understand this crc example.
T Chap
Posts: 4,223
Hey all, can someone help me interpret this example (unknown language?) that is used for crc8? I have been reading on the use of crc8 but still can't understand how to make use of the example.
Page 13 of the app note shows the example.
http://www.omron.com/ecb/products/sensor/special/mems/pdf/AN-D6T-01EN_r2.pdf
Page 13 of the app note shows the example.
http://www.omron.com/ecb/products/sensor/special/mems/pdf/AN-D6T-01EN_r2.pdf
[D6T-44L/D6T-8L] PEC check routine Example PEC is the data used for the error checki ng method using CRC-8. PEC and is appended to the end of the communication output. unsigned char calc_crc( unsigned char data ) { int index; unsigned char temp; for(index=0;index<8;index++){ temp = data; data <<= 1; if(temp & 0x80) data ^= 0x07; } return data; } int D6T_checkPEC( char buf , int pPEC ); { unsigned char crc; int i; crc = calc_crc( 0x14 ); crc = calc_crc( 0x4C ^ crc ); crc = calc_crc( 0x15 ^ crc ); for(i=0;i<pPEC;i++){ crc = calc_crc( readbuff[i] ^ crc ); } return (crc == readbuff[pPEC]); } Other case : Using Stop-Start conditi on without Repeat Start Condition, int D6T_checkPEC( char buf , int pPEC ); { unsigned char crc; int i; crc = calc_crc( 0x15 ); for(i=0;i<pPEC;i++){ crc = calc_crc( readbuff[i] ^ crc ); } return (crc == readbuff[pPEC]); }
Comments
The devices have either 11 bytes or 35 bytes of total data depending on the device type(including the final byte as the crc value). What I don't get is why are they also including I2C address and commands in the crc? What does the i2c address have to do with the returned data? Well since it appears that it does include I2C addresses, what I am trying to do is interpret this into SPIN. Any suggestions welcome.
Wiki: Char smallest addressable unit of the machine that can contain basic character set. It is an integer type. Actual type can be either signed or unsigned depending on the implementation.
Unsigned char same size as char, but guaranteed to be unsigned.
The result should be a single byte, masked, crc &= $000000FF.
This is a sample from the Omron device. The crc byte is decimal 175(AF). The applet shows 9E as the result based on the above. So, something is not adding up based on the Omron example in C based on Repeated start.
The Omron app note shows an example WITHOUT using Repeated start and it excludes the first 2 bytes 14 and 4C, and only uses 15 ( I2C address + read ).
15340118011a011e012101110115010d0110010801fd00fa00fd000601f700f800fa00 = AF
This does work on the applet. I thought I had tested this configuration earlier on the Propeller with the code shown and did not get the same answer. I will test again tomorrow now that I see what the formula really should be. I was testing with CRC as a long(local var) without any mask. I also tested with CRC as a byte, no masking obviously.
Thanks for the suggestions.
I will test this tomorrow:
030e0f5c4123594f2026
crc = $df
also the full for the full packet in your example. header (144c15) + 34 bytes data...
144c15340118011a011e012101110115010d0110010801fd00 fa00fd000601f700f800fa00
crc = $9e
That will indeed be puzzling if the D6T kicks out something different.
I'm not having joy with the bit-shift calculation. I'm still trying to make it come out the same as the table version. The table version has the advantage of being fast, the disadvantage of being big.
I think this is the correct example, and I just noticed that in this example that are not using XOR with CRC with $15, I never tried that combo today. I always had $15 ^ CRC even when I removed 14 and 4c.
The first value isn't XOR'ed because the value of crc is assumed to be zero at the beginning. I believe you initialize crc to zero, so it doesn't matter whether you XOR the first value or not.
Also attached, a version of the table version written without special treatment for the i2c header. Easier to test arbitrary strings. The table version and the bit-shift version give the same results, the former is quick but lots of memory for the table, the latter is a slow bitwise computation but easy on memory usage.
There are no carries in crc math and no effect from any of the bits that get shifted into a long. Just mask off the low byte at every step or at the end, it doesn't matter. What Dave said.
Randomly, about 30% are accurate comparisons with the crc value, doesn't matter which version shift/table using
$15 + 34 bytes of data. (scan 35 bytes)
I am clearly using repeated start, but their example for repeated start shows the additional i2c values at the top which we have removed from the test.
About 30% are accurate comparisons with the crc value, using the starting value as $14, $4c, $15 + 34 bytes of data. (scan 37 bytes)
It seems the crc values coming back are flipping back and forth randomly as if it thinks it is doing a stop/start method OR repeated start. It is completely random which method of calculation it is returning. The sensor may be confused thinking I am sending a repeated start on a loop, and a start sop method on another loop. Otherwise, the crc calculation is working on each read, depending on which method you need to apply to it's response.
The match as you noticed comes from starting at the $15. I think that is because the driver is not simply generating a repeated start; it is generating a stop/start combination.
Attaching an archive of my current code.
PS look in CON in the I2C object, raise del to get rid of any remaining errors. I forgot to edit the file name under OBJ.
I also tried the same test with the I2C object not slowed down. That is the one where I got to 0% error rate only when I reduced the clkfreq to 10MHz. At that point, the scl clock was running at 2.5kHz, and it asked for a clock hold only once, on the very first packet. Here is a summary at other clock rates. The numbers vary slightly from run to run.
clkfreq=80MHz scl frequency=20kHz, packet crc error rate=41%, hits on clock stretch=179
clkfreq=40MHz scl frequency=10kHz, packet crc error rate=39%, hits on clock stretch=49
clkfreq=20MHz scl frequency=5kHz, packet crc error rate=4%, hits on clock stretch=1
clkfreq=10MHz scl frequency=2.5kHz, packet crc error rate=0%, hits on clock stretch=1 never saw an error.
Funny, because the device is supposed to work at the original i2c scl speed, 100kHz. So why do we have to put it down to less than 5kHz? It's not a big problem, speed is not necessary, and the crc allows bad reads to be thrown away and retried. The data sheet does say that new data can be retrieved about 4 times per second. I tried interrogation at 1/2 second intervals, but that did not make a difference in the error rate.
The clock stretching comes into play at several points sporadically in the read sequence, during and after the Sr. The stretching events in this demo are counted and displayed. Also, the stretching is done with waitpne(), so it is not protected by a timeout.
Edit. Oh, I can see that this actually required the object to be tweaked, good eye.