forked from adafruit/Adafruit-Fingerprint-Sensor-Library
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Adafruit_Fingerprint.cpp
executable file
·363 lines (319 loc) · 13.6 KB
/
Adafruit_Fingerprint.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
/***************************************************
This is a library for our optical Fingerprint sensor
Designed specifically to work with the Adafruit Fingerprint sensor
----> http://www.adafruit.com/products/751
These displays use TTL Serial to communicate, 2 pins are required to
interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
#include "Adafruit_Fingerprint.h"
#if defined(__AVR__) || defined(ESP8266)
#include <SoftwareSerial.h>
#endif
//#define FINGERPRINT_DEBUG
#if ARDUINO >= 100
#define SERIAL_WRITE(...) mySerial->write(__VA_ARGS__)
#else
#define SERIAL_WRITE(...) mySerial->write(__VA_ARGS__, BYTE)
#endif
#define SERIAL_WRITE_U16(v) SERIAL_WRITE((uint8_t)(v>>8)); SERIAL_WRITE((uint8_t)(v & 0xFF));
#define GET_CMD_PACKET(...) \
uint8_t data[] = {__VA_ARGS__}; \
Adafruit_Fingerprint_Packet packet(FINGERPRINT_COMMANDPACKET, sizeof(data), data); \
writeStructuredPacket(packet); \
if (getStructuredPacket(&packet) != FINGERPRINT_OK) return FINGERPRINT_PACKETRECIEVEERR; \
if (packet.type != FINGERPRINT_ACKPACKET) return FINGERPRINT_PACKETRECIEVEERR;
#define SEND_CMD_PACKET(...) GET_CMD_PACKET(__VA_ARGS__); return packet.data[0];
/***************************************************************************
PUBLIC FUNCTIONS
***************************************************************************/
#if defined(__AVR__) || defined(ESP8266)
/**************************************************************************/
/*!
@brief Instantiates sensor with Software Serial
@param ss Pointer to SoftwareSerial object
@param password 32-bit integer password (default is 0)
*/
/**************************************************************************/
Adafruit_Fingerprint::Adafruit_Fingerprint(SoftwareSerial *ss, uint32_t password) {
thePassword = password;
theAddress = 0xFFFFFFFF;
hwSerial = NULL;
swSerial = ss;
mySerial = swSerial;
}
#endif
/**************************************************************************/
/*!
@brief Instantiates sensor with Hardware Serial
@param hs Pointer to HardwareSerial object
@param password 32-bit integer password (default is 0)
*/
/**************************************************************************/
Adafruit_Fingerprint::Adafruit_Fingerprint(HardwareSerial *hs, uint32_t password) {
thePassword = password;
theAddress = 0xFFFFFFFF;
#if defined(__AVR__) || defined(ESP8266)
swSerial = NULL;
#endif
hwSerial = hs;
mySerial = hwSerial;
}
/**************************************************************************/
/*!
@brief Initializes serial interface and baud rate
@param baudrate Sensor's UART baud rate (usually 57600, 9600 or 115200)
*/
/**************************************************************************/
void Adafruit_Fingerprint::begin(uint32_t baudrate) {
delay(1000); // one second delay to let the sensor 'boot up'
if (hwSerial) hwSerial->begin(baudrate);
#if defined(__AVR__) || defined(ESP8266)
if (swSerial) swSerial->begin(baudrate);
#endif
}
/**************************************************************************/
/*!
@brief Verifies the sensors' access password (default password is 0x0000000). A good way to also check if the sensors is active and responding
@returns True if password is correct
*/
/**************************************************************************/
boolean Adafruit_Fingerprint::verifyPassword(void) {
return checkPassword() == FINGERPRINT_OK;
}
uint8_t Adafruit_Fingerprint::checkPassword(void) {
GET_CMD_PACKET(FINGERPRINT_VERIFYPASSWORD,
(uint8_t)(thePassword >> 24), (uint8_t)(thePassword >> 16),
(uint8_t)(thePassword >> 8), (uint8_t)(thePassword & 0xFF));
if (packet.data[0] == FINGERPRINT_OK)
return FINGERPRINT_OK;
else
return FINGERPRINT_PACKETRECIEVEERR;
}
/**************************************************************************/
/*!
@brief Ask the sensor to take an image of the finger pressed on surface
@returns <code>FINGERPRINT_OK</code> on success
@returns <code>FINGERPRINT_NOFINGER</code> if no finger detected
@returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
@returns <code>FINGERPRINT_IMAGEFAIL</code> on imaging error
*/
/**************************************************************************/
uint8_t Adafruit_Fingerprint::getImage(void) {
SEND_CMD_PACKET(FINGERPRINT_GETIMAGE);
}
/**************************************************************************/
/*!
@brief Ask the sensor to convert image to feature template
@param slot Location to place feature template (put one in 1 and another in 2 for verification to create model)
@returns <code>FINGERPRINT_OK</code> on success
@returns <code>FINGERPRINT_IMAGEMESS</code> if image is too messy
@returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
@returns <code>FINGERPRINT_FEATUREFAIL</code> on failure to identify fingerprint features
@returns <code>FINGERPRINT_INVALIDIMAGE</code> on failure to identify fingerprint features
*/
uint8_t Adafruit_Fingerprint::image2Tz(uint8_t slot) {
SEND_CMD_PACKET(FINGERPRINT_IMAGE2TZ,slot);
}
/**************************************************************************/
/*!
@brief Ask the sensor to take two print feature template and create a model
@returns <code>FINGERPRINT_OK</code> on success
@returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
@returns <code>FINGERPRINT_ENROLLMISMATCH</code> on mismatch of fingerprints
*/
uint8_t Adafruit_Fingerprint::createModel(void) {
SEND_CMD_PACKET(FINGERPRINT_REGMODEL);
}
/**************************************************************************/
/*!
@brief Ask the sensor to store the calculated model for later matching
@param location The model location #
@returns <code>FINGERPRINT_OK</code> on success
@returns <code>FINGERPRINT_BADLOCATION</code> if the location is invalid
@returns <code>FINGERPRINT_FLASHERR</code> if the model couldn't be written to flash memory
@returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
uint8_t Adafruit_Fingerprint::storeModel(uint16_t location) {
SEND_CMD_PACKET(FINGERPRINT_STORE, 0x01, (uint8_t)(location >> 8), (uint8_t)(location & 0xFF));
}
/**************************************************************************/
/*!
@brief Ask the sensor to load a fingerprint model from flash into buffer 1
@param location The model location #
@returns <code>FINGERPRINT_OK</code> on success
@returns <code>FINGERPRINT_BADLOCATION</code> if the location is invalid
@returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
uint8_t Adafruit_Fingerprint::loadModel(uint16_t location) {
SEND_CMD_PACKET(FINGERPRINT_LOAD, 0x01, (uint8_t)(location >> 8), (uint8_t)(location & 0xFF));
}
/**************************************************************************/
/*!
@brief Ask the sensor to transfer 256-byte fingerprint template from the buffer to the UART
@returns <code>FINGERPRINT_OK</code> on success
@returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
uint8_t Adafruit_Fingerprint::getModel(void) {
SEND_CMD_PACKET(FINGERPRINT_UPLOAD, 0x01);
}
/**************************************************************************/
/*!
@brief Ask the sensor to delete a model in memory
@param location The model location #
@returns <code>FINGERPRINT_OK</code> on success
@returns <code>FINGERPRINT_BADLOCATION</code> if the location is invalid
@returns <code>FINGERPRINT_FLASHERR</code> if the model couldn't be written to flash memory
@returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
uint8_t Adafruit_Fingerprint::deleteModel(uint16_t location) {
SEND_CMD_PACKET(FINGERPRINT_DELETE, (uint8_t)(location >> 8), (uint8_t)(location & 0xFF), 0x00, 0x01);
}
/**************************************************************************/
/*!
@brief Ask the sensor to delete ALL models in memory
@returns <code>FINGERPRINT_OK</code> on success
@returns <code>FINGERPRINT_BADLOCATION</code> if the location is invalid
@returns <code>FINGERPRINT_FLASHERR</code> if the model couldn't be written to flash memory
@returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
uint8_t Adafruit_Fingerprint::emptyDatabase(void) {
SEND_CMD_PACKET(FINGERPRINT_EMPTY);
}
/**************************************************************************/
/*!
@brief Ask the sensor to search the current slot 1 fingerprint features to match saved templates. The matching location is stored in <b>fingerID</b> and the matching confidence in <b>confidence</b>
@returns <code>FINGERPRINT_OK</code> on fingerprint match success
@returns <code>FINGERPRINT_NOTFOUND</code> no match made
@returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
/**************************************************************************/
uint8_t Adafruit_Fingerprint::fingerFastSearch(void) {
// high speed search of slot #1 starting at page 0x0000 and page #0x00A3
GET_CMD_PACKET(FINGERPRINT_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x00, 0xA3);
fingerID = 0xFFFF;
confidence = 0xFFFF;
fingerID = packet.data[1];
fingerID <<= 8;
fingerID |= packet.data[2];
confidence = packet.data[3];
confidence <<= 8;
confidence |= packet.data[4];
return packet.data[0];
}
/**************************************************************************/
/*!
@brief Ask the sensor for the number of templates stored in memory. The number is stored in <b>templateCount</b> on success.
@returns <code>FINGERPRINT_OK</code> on success
@returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
/**************************************************************************/
uint8_t Adafruit_Fingerprint::getTemplateCount(void) {
GET_CMD_PACKET(FINGERPRINT_TEMPLATECOUNT);
templateCount = packet.data[1];
templateCount <<= 8;
templateCount |= packet.data[2];
return packet.data[0];
}
/**************************************************************************/
/*!
@brief Set the password on the sensor (future communication will require password verification so don't forget it!!!)
@param password 32-bit password code
@returns <code>FINGERPRINT_OK</code> on success
@returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
/**************************************************************************/
uint8_t Adafruit_Fingerprint::setPassword(uint32_t password) {
SEND_CMD_PACKET(FINGERPRINT_SETPASSWORD, (password >> 24), (password >> 16), (password >> 8), password);
}
/**************************************************************************/
/*!
@brief Helper function to process a packet and send it over UART to the sensor
@param packet A structure containing the bytes to transmit
*/
/**************************************************************************/
void Adafruit_Fingerprint::writeStructuredPacket(const Adafruit_Fingerprint_Packet & packet) {
SERIAL_WRITE_U16(packet.start_code);
SERIAL_WRITE(packet.address[0]);
SERIAL_WRITE(packet.address[1]);
SERIAL_WRITE(packet.address[2]);
SERIAL_WRITE(packet.address[3]);
SERIAL_WRITE(packet.type);
uint16_t wire_length = packet.length + 2;
SERIAL_WRITE_U16(wire_length);
uint16_t sum = ((wire_length)>>8) + ((wire_length)&0xFF) + packet.type;
for (uint8_t i=0; i< packet.length; i++) {
SERIAL_WRITE(packet.data[i]);
sum += packet.data[i];
}
SERIAL_WRITE_U16(sum);
return;
}
/**************************************************************************/
/*!
@brief Helper function to receive data over UART from the sensor and process it into a packet
@param packet A structure containing the bytes received
@param timeout how many milliseconds we're willing to wait
@returns <code>FINGERPRINT_OK</code> on success
@returns <code>FINGERPRINT_TIMEOUT</code> or <code>FINGERPRINT_BADPACKET</code> on failure
*/
/**************************************************************************/
uint8_t Adafruit_Fingerprint::getStructuredPacket(Adafruit_Fingerprint_Packet * packet, uint16_t timeout) {
uint8_t byte;
uint16_t idx=0, timer=0;
while(true) {
while(!mySerial->available()) {
delay(1);
timer++;
if( timer >= timeout) {
#ifdef FINGERPRINT_DEBUG
Serial.println("Timed out");
#endif
return FINGERPRINT_TIMEOUT;
}
}
byte = mySerial->read();
#ifdef FINGERPRINT_DEBUG
Serial.print("<- 0x"); Serial.println(byte, HEX);
#endif
switch (idx) {
case 0:
if (byte != (FINGERPRINT_STARTCODE >> 8))
continue;
packet->start_code = (uint16_t)byte << 8;
break;
case 1:
packet->start_code |= byte;
if (packet->start_code != FINGERPRINT_STARTCODE)
return FINGERPRINT_BADPACKET;
break;
case 2:
case 3:
case 4:
case 5:
packet->address[idx-2] = byte;
break;
case 6:
packet->type = byte;
break;
case 7:
packet->length = (uint16_t)byte << 8;
break;
case 8:
packet->length |= byte;
break;
default:
packet->data[idx-9] = byte;
if((idx-8) == packet->length)
return FINGERPRINT_OK;
break;
}
idx++;
}
// Shouldn't get here so...
return FINGERPRINT_BADPACKET;
}