So I am working on a project, and I am unfortunately too new to see the path to complete my current task. Any advice on where (or how conceptually to look for the solution to my task is appreciated.
This application is to simulate a RFID card read using an Arduino. I have a sketch that can crete the card number (and the code is kinda ugly but works), but I have to disable parity checking in order for the whole thing to work.
The data looks like this:
P[data]P
…where P is a single bit and data is 35 bits (35 bits plus two parity is 37 bits total). Beginning parity bit is Even and covers the first nineteen bits inclusive, ending parity bit is Odd and covers the last nineteen bits inclusive.
(See parity pic)
While I am not 100% there yet, I believe I can construct the 35 bits of data reliably. What I cannot do is come up with a good method to sum a group of bits up, decide if it is an even or odd number, and then decide how to set the Parity bit.
I am using a long to store this value because an int is too short.
I can do this manually via the following process (i.e. leading Parity bit):
Walk thru each of the “E” bits counting the one bits (18bits total).
Decide if the number is odd or even.
If odd, then set the Parity bit to 1, thus making the sum even.
Else set Parity bit to 0.
I think I can:
-Walk thru the data and bitRead each bit
-Increment an int variable by 1 for each bit that is a 1.
-When finished, read the lsb of the int variable to determine if the int is even or odd.
-bitWrite the Parity bit position in the long
Can anyone suggest a better way or am I going to code up my method of doing this calculation with pen and paper??
Ok, this is kind of tricky, as the overlapping nature makes it hard to craft structs and/or unions for it.
Fist though, a long is only 32 bits, so you can't store your whole packet in it. You need something bigger. Let's look at how we could craft a struct to store the raw data. We'll probably be best off using an "unsigned long long" value for the basic data storage, as that's 64 bits. Over that, using a union, we can place a pair of structs, one for odd and one for even parity calculation. To that we should then also add another struct to get at the packet portion of the long long. We might end up with something like:
struct packet {
union {
// Raw storage area - 64 bits
unsigned long long data;
// Split even area, with 1:18:45 split.
struct {
unsigned long long evenPar:1; // Set the parity here
unsigned long long evenData:18; // Count the bits here
};
// Split odd area
struct {
unsigned long oddPad1:18;
unsigned long oddData:18; // Count the bits here
unsigned long oddPar:1; // Set the parity here
};
// Access area for 37 bit packet data
struct {
unsigned long long packetData:37; // This is the full result
};
// Area for manipulating the data content
struct {
unsigned long long ePar:1;
unsigned long long pData:35; // Set this to the raw data value
unsigned long long oPar:1;
};
};
} __attribute__((packed));
struct packet p;
// Count the number of set bits in a value. Pass it the value and the
// total number of bits in the value.
byte countBits(unsigned long long val, byte bits) {
byte bcount = 0;
while(bits > 0) {
bcount += (val & 1 ? 1 : 0);
val >>= 1;
bits--;
}
return bcount;
}
// Print a 37-bit value as binary with information
// lines wrapping it.
void printBin(unsigned long long v) {
Serial.println();
Serial.println("Edddddddddddddddddd");
for (int i = 0; i < 37; i++) {
Serial.print(v & (1LLU << (36-i)) ? 1 : 0);
}
Serial.println();
Serial.println(" ddddddddddddddddddO");
}
void setup() {
Serial.begin(9600);
// This is your data value. Note the use of the ULL suffix to make it an Unsigned Long Long
p.pData = 0b11001010110101011100010101101011100ULL;
// Calculate the two parity bits.
p.evenPar = (countBits(p.evenData, 18) & 1) ? 0 : 1;
p.oddPar = (countBits(p.oddData, 18) & 1) ? 1 : 0;
// Print the results.
printBin(p.packetData);
}
void loop() {
}