This mail is longer than I expected. I'm sorry for that. The basic
issue is about the IOC feature, specifically trying to read a wiegand
package.
I'm trying to read a card number using a wiegand output reader.
I'm using a PIC16F88x so I'm using the full portb interrupt on
change. The IOC is properly set on by setting ICB<1:0> bits, since I'm using
RB0 and RB1.
On the interrupt, when IOC is detected I have the following code:
if( RBIF && RBIE )
{
RX_TEMP = PORTB; // Read PORTB
RX_TEMP &= 0x03; // Leave only the necesary bits
if( (RX_TEMP != 0x03) && RX_TEMP ) // Both bits can't
be 1 or 0 at the same time *ERROR CONDITION*
{
if( RX_TEMP & 0x01 ) // If RB0 is 1
{
getCardData( 1 );
}
else
{
getCardData( 0 );
}
wait = 2; // Wait for
500 uS
RBIE = 0; // Disable
IOC for the above time
timeout = 200; // Timeout end of
card (50 ms)
}
RBIF=0; //Clear IOC bit
}
Well, that's the basic code. It's working mostly, except that every
once in a while, an interrupt generates but the code reads a bit
incorrectly.
The "wait" is used to avoid the IOC to interrupt when the wiegand
signals return to high level. Since the wiegand LOW pulse is aprox. 40-50 uS
and the space between bits is 2mS, the 500uS should be fine.
Once the 500uS have finished the IOC interrupt is enabled:
RX_TEMP = PORTB;
RBIF = 0;
RBIE = 1;
This procedure is to ensure that any interrupt is clear before
re-enabling the IOC.
Problems:
Once a read is finished, the firmware outputs a stream of data
trough the serial port (see attached file). The correct number of the card
should be FC 081 and Card No. 00695. As you can see, the number is read ok
most of the time, but the parity is not.
Page 2 here explains how the parity should be.
http://www.hidcorp.com/documents/understandCardDataFormats_wp_en.pdf
In the beginning I was using the internal oscillator, but that lead to
aprox. 4 to 6 *ERROR CONDITIONS* detected, when I change the oscillator to
20 MHz external, that count went down to 0 to 1. That makes me wonder if
there should be something I'm missing about the whole IOC feature.
Regards,
Mauricio
If you use the interrupt on change feature, make sure you disable the
interrupt as soon as one occurs, and reset only once the data line has
returned to high before resetting the interrupt again (or it may result in
an incorrect interrupt as the line returns back to its high state). Your
method of waiting is risky. The timing of the reader is too "loose".
> if( (RX_TEMP != 0x03) && RX_TEMP ) // Both bits can't
> be 1 or 0 at the same time *ERROR CONDITION*
I'm not a C guy, but both output bits of the reader WILL be 1 in the normal
rest state. They can never be both 0 though. Testing for this condition is
redundant IMHO though.
Your attachment reads:
The parity is calculated as follow:
Even parity: using bits 1 to 12
Odd parity: using bits 12 to 25
That is not exactly correct, the leading parity bit (0), includes itself, 0
- 12. The trailing parity bit (26) includes bits 13 - 26 inclusive. Checking
the parity is actually surprisingly simple. In the even parity, count all
the 1's (of the proper bits), and check the LSB of the register containing
the count to be 0. For the odd parity it should be 1.
I run mine of the internal RC oscillator, no problem at all. I also decode
and do parity check, and drive an LCD all off that one PIC (16F628A)
I hope this helps,
Bill van Dijk
--
http://www.piclist.com PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist
Regarding the IF that you mentioned. It's to provide additional security
when reading the card. It's just some way to make sure you are not reading
garbage.
Regards,