Permalink
Browse files

Implement RFID reader for doorduino.

A read RFID tag will result in a hash sent in similar way to a swipe card.
  • Loading branch information...
1 parent 56a9e5b commit 1750ea58d7f65ba4d14044fb0beeb29f4299533f @knielsen knielsen committed Oct 31, 2011
Showing with 171 additions and 2 deletions.
  1. +1 −1 Makefile
  2. +43 −1 doorduino.c
  3. +127 −0 softserial.c
View
@@ -1,6 +1,6 @@
## Name your project
NAME = doorduino
-FILES = doorduino.c sha1.c serial.c
+FILES = doorduino.c sha1.c serial.c softserial.c
## Point this to the directory where you did
## git clone git://github.com/esmil/oniudra-headers.git arduino
View
@@ -54,6 +54,8 @@ volatile uint8_t events = EV_NONE;
#undef SERIAL_INBUF
#undef SERIAL_OUTBUF
+#include "softserial.c"
+
#define SHA1_SHORTCODE
#include "sha1.c"
#undef SHA1_SHORTCODE
@@ -163,6 +165,40 @@ handle_serial_input(void)
}
}
+static void
+handle_rfid_input(void)
+{
+ static char buf[10];
+ static uint8_t idx = 0;
+ int c;
+ uint8_t i;
+ for (;;) {
+ c = softserial_getchar();
+ switch (c) {
+ case SOFTSERIAL_EOF:
+ return;
+ case 10:
+ idx = 0;
+ break;
+ case 13:
+ if (idx == 10) {
+ /*
+ We got an RFID tag.
+ Copy it into the card reader buffer to
+ emulate a read card data string.
+ */
+ data_reset();
+ for (i = 0; i < 10 && cnt < 255; ++i, ++cnt)
+ data[cnt] = buf[i];
+ }
+ default:
+ if (idx < 10)
+ buf[idx++] = c;
+ break;
+ }
+ }
+}
+
int
main(void)
{
@@ -196,6 +232,8 @@ main(void)
timer1_clock_d64();
timer1_interrupt_a_enable();
+ softserial_init();
+
sleep_mode_idle();
while (1) {
@@ -205,7 +243,7 @@ main(void)
* http://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html
*/
cli();
- if (events == EV_NONE) {
+ if (events == EV_NONE && !ev_softserial) {
sleep_enable();
sei();
sleep_cpu();
@@ -219,6 +257,10 @@ main(void)
continue;
}
+ if (ev_softserial) {
+ handle_rfid_input();
+ }
+
events &= ~EV_DATA;
if (cnt > 0 && data[cnt - 1] == 0xB4) {
if (cnt >= 10) {
View
@@ -0,0 +1,127 @@
+#include <arduino/timer0.h>
+
+/* Also need to change the interrupt references if changing pin */
+#define SOFTSERIAL_RX_PIN 12
+
+static uint8_t ev_softserial = 0;
+static uint8_t softserial_pin_oldstate;
+static uint8_t softserial_state = 0;
+static uint8_t softserial_data;
+static uint8_t softserial_bit_count = 0;
+static uint8_t softserial_startbit_time;
+
+#define SOFTSERIAL_EOF -256
+static volatile struct {
+ uint8_t buf[16];
+ uint8_t start;
+ uint8_t end;
+} softserial_input;
+
+static void
+softserial_put_in_fifo(void)
+{
+ uint8_t end = softserial_input.end;
+ softserial_input.buf[end] = softserial_data;
+ softserial_input.end = (end + 1) % sizeof(softserial_input.buf);
+ ev_softserial = 1;
+}
+
+static int
+softserial_getchar(void)
+{
+ uint8_t start = softserial_input.start;
+ int r;
+
+ cli();
+ if (start == softserial_input.end)
+ {
+ ev_softserial = 0;
+ sei();
+ return SOFTSERIAL_EOF;
+ }
+ sei();
+
+ r = (char)softserial_input.buf[start];
+ softserial_input.start = (start + 1) % sizeof(softserial_input.buf);
+
+ return r;
+}
+
+pin_8to13_interrupt()
+{
+ uint8_t state;
+ uint8_t current, delta;
+ state = pin_is_high(SOFTSERIAL_RX_PIN);
+ if (state == softserial_pin_oldstate)
+ return; /* Not for us... */
+ softserial_pin_oldstate = state;
+
+ switch (softserial_state) {
+ case 0: /* Waiting for start bit. */
+ start_bit:
+ if (state)
+ return;
+ softserial_startbit_time = timer0_count();
+ /* Trigger a timeout interrupt in 11 bits -> 11/9600/16usec -> 72 */
+ timer0_compare_a_set(softserial_startbit_time + 72);
+ timer0_flags_clear();
+ timer0_interrupt_a_enable();
+ softserial_bit_count = 0;
+ softserial_data = 0;
+ softserial_state = 1;
+ break;
+
+ case 1: /* Collecting bits */
+ current = timer0_count();
+ delta = current - softserial_startbit_time;
+ while (softserial_bit_count < 8)
+ {
+ if ((uint16_t)delta * 154 <= (uint16_t)softserial_bit_count*1000 + 1500)
+ break;
+ /*
+ Add any bits since last; note that those bits had the reverse state of
+ what we currently have.
+ */
+ if (!state)
+ softserial_data |= (1 << softserial_bit_count);
+ ++softserial_bit_count;
+ }
+ if (softserial_bit_count >= 8)
+ {
+ timer0_interrupt_a_disable();
+ softserial_state = 0;
+ softserial_put_in_fifo();
+ goto start_bit;
+ }
+ break;
+ }
+}
+
+timer0_interrupt_a()
+{
+ /*
+ Handle the timeout we get if the last bit(s) are zero (so we do not get a
+ transition on the stop bit) and there is no immediately following new
+ start bit.
+ */
+ timer0_interrupt_a_disable();
+ while (softserial_bit_count < 8)
+ softserial_data |= (1 << softserial_bit_count++);
+ softserial_state = 0;
+ softserial_bit_count = 8;
+ softserial_put_in_fifo();
+}
+
+static void
+softserial_init(void)
+{
+ timer0_clock_off();
+ timer0_interrupt_a_disable();
+ timer0_mode_normal();
+ timer0_clock_d1024(); /* 16MHz / 256 -> 16usec / tick. */
+
+ pin_mode_input(SOFTSERIAL_RX_PIN);
+ softserial_pin_oldstate = pin_is_high(SOFTSERIAL_RX_PIN);
+ pin12_interrupt_mask();
+ pin_8to13_interrupt_enable();
+}

0 comments on commit 1750ea5

Please sign in to comment.