Revision 1085ef77
Made rfid.c more robust against false negatives
Also changed LED code to be more generally usable, and changed mainbox
to grant access to a particular user id instead of randomly choosing
mainbox/tool.c | ||
---|---|---|
102 | 102 |
if (status[MB_COIL_NEW]) { |
103 | 103 |
tool_read_user(tool); |
104 | 104 |
// TODO check actual credentials |
105 |
if (rand() & 1) {
|
|
105 |
if (tool->user == 0x023acbf6) {
|
|
106 | 106 |
tool_grant_access(tool); |
107 | 107 |
} else { |
108 | 108 |
tool_deny_access(tool); |
toolbox/led.c | ||
---|---|---|
9 | 9 |
#define OCR (F_CPU / PRESCALE / 1000UL) |
10 | 10 |
#define ERROR (F_CPU / PRESCALE - OCR * 1000UL) |
11 | 11 |
|
12 |
char count; |
|
13 |
uint16_t period; |
|
12 |
char blink_count; |
|
13 |
enum color_t blink_color; |
|
14 |
uint16_t blink_period; |
|
14 | 15 |
|
15 | 16 |
uint16_t ms; |
16 | 17 |
uint16_t error; |
17 | 18 |
|
19 |
static void led_color(enum color_t color) { |
|
20 |
switch (color) { |
|
21 |
case OFF: |
|
22 |
led_off(); |
|
23 |
break; |
|
24 |
case RED: |
|
25 |
led_red(); |
|
26 |
break; |
|
27 |
case YELLOW: |
|
28 |
led_yellow(); |
|
29 |
break; |
|
30 |
case GREEN: |
|
31 |
led_green(); |
|
32 |
break; |
|
33 |
} |
|
34 |
} |
|
35 |
|
|
18 | 36 |
static void blink() { |
19 |
count--; |
|
20 |
if (count % 2) { |
|
21 |
led_yellow();
|
|
37 |
blink_count--;
|
|
38 |
if (blink_count % 2) {
|
|
39 |
led_color(blink_color);
|
|
22 | 40 |
} else { |
23 | 41 |
led_off(); |
24 | 42 |
} |
... | ... | |
30 | 48 |
error -= 1000; |
31 | 49 |
} else { |
32 | 50 |
ms++; |
33 |
if (ms == period) { |
|
51 |
if (ms == blink_period) {
|
|
34 | 52 |
blink(); |
35 |
if (count == 0) { |
|
53 |
if (blink_count == 0) {
|
|
36 | 54 |
TCCR0B = 0; |
37 | 55 |
} |
38 | 56 |
ms = 0; |
... | ... | |
40 | 58 |
} |
41 | 59 |
} |
42 | 60 |
|
43 |
void led_blink_start(unsigned int period_ms, char n_times) { |
|
44 |
led_yellow(); |
|
61 |
void led_blink_start(unsigned int period_ms, char n_times, enum color_t color) {
|
|
62 |
|
|
45 | 63 |
ms = 0; |
46 | 64 |
error = 0; |
47 |
count = n_times*2-1; |
|
48 |
period = period_ms/2; |
|
65 |
|
|
66 |
blink_count = n_times*2-1; |
|
67 |
blink_period = period_ms/2; |
|
68 |
blink_color = color; |
|
69 |
led_color(color); |
|
70 |
|
|
49 | 71 |
OCR0A = OCR; |
50 | 72 |
TIMSK = _BV(OCIE0A); |
51 | 73 |
TCCR0A = _BV(WGM01); |
52 | 74 |
TCCR0B = CLOCK_SEL; |
75 |
|
|
53 | 76 |
} |
54 | 77 |
|
55 | 78 |
char led_blink_done() { |
56 |
return count == 0; |
|
79 |
return blink_count == 0;
|
|
57 | 80 |
} |
toolbox/led.h | ||
---|---|---|
3 | 3 |
|
4 | 4 |
#include <avr/io.h> |
5 | 5 |
|
6 |
enum color_t { |
|
7 |
OFF, RED, YELLOW, GREEN |
|
8 |
}; |
|
9 |
|
|
6 | 10 |
static inline void led_init() {DDRC |= _BV(DDC1) | _BV(DDC0);} |
7 | 11 |
static inline void led_off() {PORTC &= ~(_BV(PC1) | _BV(PC0));} |
8 | 12 |
static inline void led_red() {PORTC = (PORTC & ~_BV(PC0)) | _BV(PC1);} |
... | ... | |
10 | 14 |
static inline void led_green() {PORTC = (PORTC & ~_BV(PC1)) | _BV(PC0);} |
11 | 15 |
|
12 | 16 |
/* Starts LED blinking */ |
13 |
void led_blink_start(unsigned int period_ms, char n_times); |
|
17 |
void led_blink_start(unsigned int period_ms, char n_times, enum color_t color);
|
|
14 | 18 |
|
15 | 19 |
/* Returns nonzero if blinking has finished */ |
16 | 20 |
char led_blink_done(); |
toolbox/main.c | ||
---|---|---|
33 | 33 |
static inline void tool_enable() {PORTA |= _BV(PA1);} |
34 | 34 |
static inline void tool_disable() {PORTA &= ~ _BV(PA1);} |
35 | 35 |
|
36 |
static char serno_zero(uint8_t *serno) {
|
|
36 |
static inline void serno_zero(uint8_t *serno) {
|
|
37 | 37 |
memset(serno, 0, RFID_SERNO_SIZE); |
38 | 38 |
} |
39 | 39 |
|
... | ... | |
131 | 131 |
toolstate = TS_REQ_DIS; |
132 | 132 |
} else if (!serno_equal(current_user, latest_reading)) { |
133 | 133 |
toolstate = TS_MISSING_ID; |
134 |
led_blink_start(666, 6);
|
|
134 |
led_blink_start(666, 15, YELLOW);
|
|
135 | 135 |
} |
136 | 136 |
break; |
137 | 137 |
|
toolbox/rfid.c | ||
---|---|---|
4 | 4 |
#include "rfid.h" |
5 | 5 |
#include "serial.h" |
6 | 6 |
|
7 |
#define RFID_OK 1 |
|
7 | 8 |
static uint8_t read_cmd[] = {'!', 'R', 'W', 1, 32}; |
8 | 9 |
|
9 | 10 |
static int serno_idx; |
11 |
static char n_failures; |
|
10 | 12 |
static uint8_t serno[RFID_SERNO_SIZE]; |
11 | 13 |
|
12 | 14 |
static void zero_serno() { |
... | ... | |
20 | 22 |
serial_init(); |
21 | 23 |
} |
22 | 24 |
|
23 |
void rfid_start_read() {
|
|
25 |
static void restart_read() {
|
|
24 | 26 |
serno_idx = -1; |
25 |
serial_flush(); |
|
26 | 27 |
serial_write(read_cmd, sizeof(read_cmd)); |
27 | 28 |
} |
28 | 29 |
|
30 |
void rfid_start_read() { |
|
31 |
n_failures = 0; |
|
32 |
restart_read(); |
|
33 |
} |
|
34 |
|
|
29 | 35 |
char rfid_poll() { |
30 | 36 |
int c; |
31 | 37 |
|
... | ... | |
33 | 39 |
|
34 | 40 |
if (serno_idx < 0) { |
35 | 41 |
if (c != RFID_OK) { |
36 |
zero_serno(); |
|
37 |
return 1; |
|
42 |
n_failures++; |
|
43 |
if (n_failures >= RFID_N_FAILURES) { |
|
44 |
zero_serno(); |
|
45 |
return 1; |
|
46 |
} else { |
|
47 |
restart_read(); |
|
48 |
return 0; |
|
49 |
} |
|
38 | 50 |
} |
39 | 51 |
} else { |
40 | 52 |
serno[serno_idx] = c; |
toolbox/rfid.h | ||
---|---|---|
1 | 1 |
#ifndef RFID_H |
2 | 2 |
#define RFID_H |
3 | 3 |
|
4 |
/* First byte back from rfid reader */ |
|
5 |
#define RFID_OK 1 |
|
6 |
|
|
7 | 4 |
/* Bytes in serial number on rfid tags */ |
8 | 5 |
#define RFID_SERNO_SIZE 4 |
9 | 6 |
|
10 |
/* In rfid_read_safe, it must read the same value RFID_MIN_OK times. If it |
|
11 |
* encounters RFID_MAX_ERRS read errors first, it will output all 0's. */ |
|
12 |
#define RFID_MAX_ERRS 10 |
|
13 |
#define RFID_MIN_OK 5 |
|
7 |
/* Number of consective read failures before giving up and returning all 0s */ |
|
8 |
#define RFID_N_FAILURES 5 |
|
14 | 9 |
|
15 | 10 |
/* Should be called before anything else */ |
16 | 11 |
void rfid_init(); |
... | ... | |
24 | 19 |
* rfid_get_serno can be called */ |
25 | 20 |
char rfid_poll(); |
26 | 21 |
|
27 |
/* Attempts to read the serial number multiple times, and only accepts it if it |
|
28 |
* is the same every time. Don't use it */ |
|
29 |
void rfid_read_safe(); |
|
30 |
|
|
31 | 22 |
/* Call this only after rfid_poll returns nonzero. This will copy the value it |
32 | 23 |
* read into serno, which should be at least RFID_SERNO_SIZE bytes */ |
33 | 24 |
void rfid_get_serno(uint8_t *serno); |
34 | 25 |
|
35 |
/* Call this only after rfid_poll returns nonzero. Returns 1 if serno matches |
|
36 |
* the internal buffer of the most recently read serial number */ |
|
37 |
char rfid_check_serno(uint8_t *serno); |
|
38 |
|
|
39 | 26 |
/* Call this only after rfid_poll returns nonzero. Returns 1 if the internal |
40 | 27 |
* buffer is nonzero, meaning a serial number was successfully read from an |
41 | 28 |
* rfid tag */ |
Also available in: Unified diff