HID reader.pde

From ATXHackerspace

Jump to: navigation, search

#include <avr/interrupt.h>
#include <avr/io.h>
#include <stdint.h>
#include <util/delay.h>

#define CARRIERPOS_PIN 10
#define CARRIERPOS_REG PORTC6
#define CARRIERNEG_PIN 9
#define CARRIERPOS_REG PORTC7

#define LED_PIN 11
#define LED_PORT PORTD
#define LED_REG PORTD6

// AIN0 = PE6 = threshold
// ADC0 = PF0 = antenna - detect

#define DEBUG_PORT PORTB
#define DEBUG_REG PORTB3
#define DEBUG2_REG PORTD0

#define LED_ON() (LED_PORT |= _BV(LED_REG))
#define LED_OFF() (LED_PORT &= ~_BV(LED_REG))
#define TOGGLE_LED() (LED_PORT ^= _BV(LED_REG))

#define DEBUG_ON() (DEBUG_PORT |= _BV(DEBUG_REG))
#define DEBUG_OFF() (DEBUG_PORT &= ~_BV(DEBUG_REG))
#define DEBUG2_ON() (PORTD |= _BV(PORTD0))
#define DEBUG2_OFF() (PORTD &= ~_BV(PORTD0))

#define TOGGLE_DEBUG2() (PORTD ^= _BV(DEBUG2_REG))
#define TOGGLE_DEBUG() (PORTB ^= _BV(DEBUG_REG))

void initTimer4()
{
// pwm with dead time generator
TCCR4A = _BV(PWM4A) | _BV(COM4A0);//
// phase & frequency correct pwm
TCCR4D = _BV(WGM40);
TCCR4E = _BV(ENHC4);

//duty cycle for oscillator toggle
OCR4A = 64;
//OCR4B = 64;
// 125k would be no prescaler, period = 128
OCR4C = 64;

// no prescaler (CK/1)
TCCR4B = _BV(CS40);
}

void initTimer1()
{
TCCR1A = 0;
TCCR1B &= ~_BV(WGM13); // NORMAL mode
TCCR1B |= _BV(ICNC1); // enable noise cancellation
TCCR1B &= ~_BV(ICES1); // falling edge detect

TCNT1 = 0;
OCR1A = 200; // upper bound of single-bit length

// input capture interrupt triggered by analog comparator
// enable Timer/Countern Output Compare A Match interrupt
TIMSK1 |= _BV(ICIE1) | _BV(OCIE1A);
TCCR1B = _BV(CS11); // PS = 8
}

void initAnalogComparator()
{

// AIN0 = PE6 = detect
// ADC0 = PF0 = threshold

// disable adc
ADCSRA &= ~_BV(ADEN);
// enable analog comparator mux
ADCSRB |= _BV(ACME);
// clear analog comparator interrupt flag
ACSR |= _BV(ACI) | _BV(ACIS1) | _BV(ACIC);
// interrupt on falling edge
ACSR &= ~_BV(ACIS0) & ~_BV(ACBG);
// enable analog comparator input capture, AIN0 connected to AC+

// ADC0 connected to AC- input
ADMUX &= ~_BV(MUX2) & ~_BV(MUX1) & ~_BV(MUX0);

// disable digital input buffer
DIDR1 |= _BV(AIN0D);

}

#define BUFSIZE 256
#define wrapI() if (i > BUFSIZE) {i=0;}
#define write1() { {wrapI(); buf[i++] = 1; }; }
#define write0() { {wrapI(); buf[i++] = 0; }; }

//#define wrapT() {if (t > BUFSIZE) {t=0;}}
//#define writeT(n) {wrapT(); timebuf[t++] = n; }

volatile int buf[BUFSIZE]; // stores raw signal, still manchester encoded (01 is a 0, 10 is a 1)
volatile int decoded[45]; // stores the actual decoded bits

//volatile uint16_t timebuf[BUFSIZE]; //stores timings between up-edges
volatile int i = 0;
//volatile int t = 0;
volatile int bitcount = 0;
volatile int logging = 0;
volatile int msglen = 0;
volatile int lastlen = 0;
volatile int isReading = 0;

volatile int isSync;

void countbits()
{
isReading = 1;

if (bitcount > 3 && bitcount < 7)
{
write1();
}
else if (bitcount > 8 && bitcount <11)
{
msglen++;
write1();
write1();
}
else if (bitcount > 12)
{
// triple long high as part of the header
write1();
write1();
write1();
DEBUG2_OFF();
LED_OFF();
if (isSync != 1)
{
isSync=0;
}
else
{
i=0;
// t=0;
msglen=0;
isSync=2;
}
}
bitcount = 0;
}

// this timer will fire and turn off the debug pin if a capture doesn't happen within 2/8T.
ISR(TIMER1_COMPA_vect)
{
if (bitcount > 0)
{
countbits();
DEBUG_OFF();
// turn off the pin as soon as possible at the beginning of low periods.
}
LED_OFF();
}

ISR(TIMER1_CAPT_vect)
{
if (1)
{

uint16_t timer1val = ICR1;

TCNT1 = 0;

// log timing infos separately from bit values
// wrapT();
// writeT(timer1val);

if (timer1val > 100 && timer1val < 200)
{
if (bitcount==0)
{
DEBUG_ON();
}
bitcount++;
}
else
{

if (timer1val > 800 && timer1val < 1150)
{
msglen++;
//DEBUG_OFF();
//countbits();
write0();
}
else if (timer1val > 1600 && timer1val < 1900)
{
msglen++;
write0();
write0();
}
else if (timer1val > 2400 && timer1val < 2700)
{
// header bits, triple long low
lastlen = msglen;
write0();
write0();
write0();
// sync pulse
isSync = 1;
LED_ON();
DEBUG2_ON();
}
}
}

//TOGGLE_LED();
// TOGGLE_DEBUG();

}

void setup()
{
memset((void*)buf, sizeof(uint8_t)*BUFSIZE, 0);
//memset((void*)timebuf, sizeof(uint8_t)*BUFSIZE, 0);
cli();

// debug pin out / OC4B pin out, OCOA (PB7) output
DDRB = _BV(PORTB3) | _BV(PORTB7);
DDRD = ~_BV(PORTD4) | _BV(PORTD0) | _BV(PORTD6);
// enable pull-up resistor
PORTD = _BV(PORTD4);

// 125khz carrier oscillator pins 8&9, OC4A/~OC4A
pinMode(CARRIERPOS_PIN, OUTPUT);
pinMode(CARRIERNEG_PIN, OUTPUT);

// threshold voltage out
pinMode(12, OUTPUT);

LED_OFF();

// input ddr regs, enable pull-up resistors
DDRE = ~_BV(DDE6);
PORTE = ~_BV(PORTE6);
DDRF = ~_BV(DDF0);
PORTF = ~_BV(PORTF0);

//initTimer0();
initTimer1();
initTimer4();
initAnalogComparator();

sei();
analogWrite(12, 6);
Serial.begin(57600);
}

int manchesterToBit(int m1, int m2)
{
if (m1 && ~m2) return 1;
if (~m1 && m2) return 0;
}

// write out the rfid's digits to the serial port
void decodeManchesterMessage()
{
int inputIndex;
int tmp1, tmp2;
for (int a=0; a<45; a++)
{
inputIndex = (2*a)%BUFSIZE;
tmp1 = buf[inputIndex];
tmp2 = buf[inputIndex+1];
decoded[a] = manchesterToBit(tmp1, tmp2);
}
}

void decodeHID()
{
// decoded buffer should be filled at this point with the decoded bits of the 45 bit message.
// this method will convert the 20, 8, and 16-bit sections into their respective decimal values
// and print them to the Serial port.

long mfgCode=0;
int siteCode=0;
long cardCode=0;

int z=0;

for (;z<20;z++)
{
// Serial.print(z);
// Serial.print(":");
mfgCode |= decoded[z]<<(19-z);
// Serial.print(decoded[z]);
// Serial.print(",");
// Serial.print(decoded[z]<<(19-z));
// Serial.print(",");
// Serial.print(mfgCode);
// Serial.print(".");
}
Serial.println();

for (;z<29;z++)
{
siteCode |= decoded[z]<<(28-z);
}

for (;z<44;z++)
{
cardCode |= decoded[z]<<(43-z);
}

Serial.println();
Serial.print(mfgCode);
Serial.print(":");
Serial.print(siteCode);
Serial.print(":");
Serial.println(cardCode);
}

void printbuf()
{
isReading = 0;
logging = 1;

decodeManchesterMessage();
Serial.println();
for (int r=0; r<lastlen; r++)
{
Serial.print(decoded[r]);
//Serial.print(",");
}
decodeHID();

logging=0;
}

void loop()
{
if (isReading && lastlen ==45)
{
printbuf();
}
_delay_ms(1000);
}