After reading the specifications in TIA-102.BAAA-A, I see functions with GH(x) and IH(x) with a combined result of FH(x) but I still don't understand. Can anybody offer any help with understanding CRC-16 and CRC-32? I really want to understand CRC-16 first as most of the messages I'm dealing with are CRC-16. I am coding in C# (which is based on C/C++) so any code offered would be valuable (or even information so I can piece together).
I watched a video that showed how to calculate a CRC manually using a set of bits obtained from a polynomial but I don't know which polynomial to use when there are many.
Good luck understanding the math. I bought the book Error Correcting Codes 2e and ended up with a severe headache. If you're just trying to implement the CRC in code, there's a practical approach. Assuming that you're dealing with fixed-length messages, pre-calculate the CRC checksum for each bit position in your message and store those values in a lookup table. Create a message of all zeros and set the first message bit position to one and then calculate the CRC. Put that value in your CRC lookup table for bit position one. Repeat the process for all message bit positions. Your CRC-16, using the 17-bit polynomial should generate 16-bit CRC checksums. The wikipedia entry (Computation of CRC section) offers a pretty good explanation/example of how to calculate the CRC:
Cyclic redundancy check - Wikipedia, the free encyclopedia
When you want to check a message, start with a fill value of all zeros for your running checksum. For each bit in the message that is set to a one, XOR the corresponding checksum from your lookup table for that bit position to your running checksum. When you're done, the running checksum result should match the CRC value that was transmitted with the message.
A variation is to apply the lookup table checksum values against the original message checksum and at the end you should have all zeros. This approach helps when you're trying to figure out the initial fill value when they're using a non-zero fill value ...
Sometimes they use a non-zero initial fill value, instead of all zeros. LTR-Passport uses three initial fill values (0x0, 0x89 and 0x98) so that they can send trunking control messages for voice (0 value) and data messages like Fleetsync GPS with the other (0x89 value) to allow the receiving radio to distinguish between the traffic types. If the CRC checksum doesn't pass, the receiver throws away the message, thereby making it only listen for the correct message that it's interested in.
... but I don't know which polynomial to use when there are many.
You can reverse-engineer the polynomial if you have enough messages. Collect enough messages where you have lots of repeats so that you have a higher-confidence level that the messages are not just random messages. Find two messages that differ only in the final message bit like:
(48-bit message, 16-bit crc)
Message 1: 110001010011110010001001000101010011001100110011 1001100110000110
Message 2: 110001010011110010001001000101010011001100110010 1001100110100111
Difference: 000000000000000000000000000000000000000000000001 0001000000100001
The XOR difference value, including the final message bit, is the generator polynomial. You can then use the polynomial to recreate the entire lookup table.
Not all CRC algorithms are straight forward like this. LTR-Standard CRC checksums don't seem to follow a normal polynomial generated table. However, you can reverse-engineer the lookup table following the same approach. It's painful but, collect enough messages and you can use the same approach as above to find the CRC difference value for each bit position. Just use the XOR difference value (excluding the message bit) as the lookup value for that bit position, in your table.
I see GH(x) = x^16 + x^12 + x^5 +1. If I understand everything correctly that translates to 1000100000010000 or is that incorrect?
Don't forget the +1 at the end which represents the x^0 term (any number to zero power is 1). The binary polynomial representation should be one bit longer than your CRC type. Your CRC16 polynomial is 17-bits long.
10001000000100001
Denny