Gracias por toda la ayuda.
Después de hacer una investigación con un osciloscopio, he descubierto lo que está pasando:
Muestra datos puros del lector (LSB primero, espacios agregados para mayor claridad):
10 0000 11000 10 0000 00000 10 0100 01110 10 1011 00001 10 0101 00000 10
^s 0 ^3 ^p^s ^0 ^0 ^p^s ^2 ^E ^p^s ^D ^0 ^p^s ^A ^0 ^s
Para un valor de datos de
0 3 0 0 2 E D 0 A 0 -> 30 00 E2 0D 0A
s es el indicador de parada, p es el bit de paridad y otros son los datos hexadecimales.
Lo que está sucediendo en mi arduino es que el bit de paridad se lee como el bit más significativo para la segunda mitad del byte, luego se usa el bit menos significativo anterior para sobrescribir el nuevo bit menos significativo de ese medio byte.
Aplicado al ejemplo anterior:
11000 -> 1000
00000 -> 0000
01110 -> 0110
00001 -> 0001
00000 -> 0000
que produce:
0 1 0 0 2 6 D 8 A 0 -> 10 00 62 8D 0A
explicando la conversión que ves en mi ejemplo original en los bytes de inicio y fin:
30 00 E2 0D 0A -> 10 00 62 8D 0A
Si por alguna razón alguien más se encuentra con este problema increíblemente específico, he convertido los datos de nuevo en la lógica arduino con estas funciones (no son óptimas):
byte fixBits(byte rc) {
byte five = rc & 0x10;
byte six = getParity(rc) << 5;
byte hex1 = (rc & 0xF0) << 1;
byte hex2 = rc & 0x0F;
return ((hex2 | hex1) & 0xCF) | five | six; // bit masking
}
byte getParity(byte rc) {
int sum = 0;
byte test = rc;
for (int i = 0; i < 8; i++) {
sum += test & 1;
test >> 1;
}
return sum & 1;
}
Si alguien puede describir exactamente por qué sucede esto, me gustaría saberlo, pero de lo contrario este problema se solucionó.