Project

General

Profile

Statistics
| Branch: | Revision:

root / toolbox / rfid.c @ master

History | View | Annotate | Download (2.03 KB)

1
#include <string.h>
2
#include <stdint.h>
3
#include <util/delay.h>
4
#include "rfid.h"
5
#include "serial.h"
6

    
7
#define MF_SELECT_CMD 0x83
8

    
9
static uint8_t select_cmd[] = {0xFF, 0, 1, MF_SELECT_CMD, MF_SELECT_CMD + 1};
10

    
11
#define FRAME_SIZE(data_size) ((data_size)+4)
12
#define RFID_DATA_SIZE (RFID_SERNO_SIZE+2)
13
#define MAX_FRAME_SIZE FRAME_SIZE(RFID_DATA_SIZE)
14

    
15
#define RESP_START    0
16
#define RESP_RESERVED 1
17
#define RESP_LENGTH   2
18
#define RESP_CMD      3
19
#define RESP_DATA     4
20
static uint8_t response[MAX_FRAME_SIZE];
21
static uint8_t resp_idx;
22

    
23
static uint8_t serno[RFID_SERNO_SIZE];
24

    
25
static void zero_serno() {
26
  int i;
27
  for (i = 0; i < RFID_SERNO_SIZE; i++) {
28
    serno[i] = 0;
29
  }
30
}
31

    
32
void rfid_init() {
33
  serial_init();
34
}
35

    
36
void rfid_start_read() {
37
  resp_idx = 0;
38
  serial_flush();
39
  serial_write(select_cmd, sizeof(select_cmd));
40
}
41

    
42
char parse_response() {
43
  uint8_t sum;
44
  int resp_csum, i;
45

    
46
  if (response[RESP_CMD] != MF_SELECT_CMD) {
47
    // invalid response, ignore
48
    zero_serno();
49
    return 0;
50
  }
51

    
52
  if (response[RESP_LENGTH] != RFID_DATA_SIZE) {
53
    // wrong response length, assume there's no card
54
    zero_serno();
55
    return 1;
56
  }
57

    
58
  resp_csum = response[RESP_LENGTH] + RESP_CMD;
59
  sum = 0;
60
  for (i = RESP_LENGTH; i < resp_csum; i++) {
61
    sum += response[i];
62
  }
63
  if (response[resp_csum] != sum) {
64
    zero_serno();
65
    return 0;
66
  }
67

    
68
  memcpy(serno, &response[RESP_DATA+1], RFID_SERNO_SIZE);
69
  return 1;
70
}
71

    
72
char rfid_poll() {
73
  int c;
74

    
75
  while ((c = serial_read()) >= 0) {
76

    
77
    if (resp_idx < sizeof(response)) {
78
      response[resp_idx] = c;
79
    }
80
    resp_idx++;
81

    
82
    if (resp_idx == 1) {
83

    
84
      // restart if the frame start is invalid
85
      if (response[RESP_START] != 0xFF) {
86
        resp_idx = 0;
87
      }
88

    
89
    } else if (resp_idx > RESP_LENGTH) {
90

    
91
      // check if we're done with current packet
92
      if (resp_idx >= FRAME_SIZE(response[RESP_LENGTH])) {
93
        rfid_start_read();
94
        if (parse_response()) {
95
          return 1;
96
        }
97
      }
98

    
99
    }
100
  }
101

    
102
  return 0;
103
}
104

    
105
void rfid_get_serno(uint8_t *buf) {
106
  memcpy(buf, serno, sizeof(serno));
107
}