Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: R503_fingerprint_HelloWorldV4
Fingerprint.cpp
- Committer:
- cdupaty
- Date:
- 2021-03-21
- Revision:
- 3:394a5735eea0
- Parent:
- 2:6f273d942c43
- Child:
- 5:6fff11306a66
File content as of revision 3:394a5735eea0:
/*!
* @file Fingerprint.cpp
* @mainpage Adafruit Fingerprint Sensor Library
* @section intro_sec Introduction
* 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!
* @section author Author
* Written by Limor Fried/Ladyada for Adafruit Industries.
* @section license License
* BSD license, all text above must be included in any redistribution
*
* STM32 adaptation by Christian Dupaty 03/2021
*
*/
#include "Fingerprint.h"
#include "mbed.h"
/*!
* @brief Gets the command packet
*/
#define GET_CMD_PACKET(...) \
uint8_t data[] = {__VA_ARGS__}; \
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;
/*!
* @brief Sends the command packet
*/
#define SEND_CMD_PACKET(...) \
GET_CMD_PACKET(__VA_ARGS__); \
return packet.data[0];
/***************************************************************************
PUBLIC FUNCTIONS
***************************************************************************/
/**************************************************************************/
/*!
@brief Instantiates sensor with Software Serial
@param ss Pointer to SoftwareSerial object
@param password 32-bit integer password (default is 0)
*/
/**************************************************************************/
Fingerprint::Fingerprint(PinName serialTX, PinName serialRX, uint32_t password) : R503Serial(serialTX, serialRX)
{
thePassword = password;
theAddress = 0xFFFFFFFF;
status_reg = 0x0; ///< The status register (set by getParameters)
system_id = 0x0; ///< The system identifier (set by getParameters)
capacity = 64; ///< The fingerprint capacity (set by getParameters)
security_level = 0; ///< The security level (set by getParameters)
device_addr = 0xFFFFFFFF; ///< The device address (set by getParameters)
packet_len = 64; ///< The max packet length (set by getParameters)
baud_rate = 57600; ///< The UART baud rate (set by getParameters)
// Init buffer de reception, les deux pointeurs egaux
pe=buffUART;
pl=buffUART;
// active IT sur reception UART vers methode receiveUART
R503Serial.attach(callback(this,&Fingerprint::receiveUART),RawSerial::RxIrq);
}
/**************************************************************************/
/*!
@brief Initializes serial interface and baud rate
@param baudrate Sensor's UART baud rate (usually 57600, 9600 or 115200)
*/
/**************************************************************************/
void Fingerprint::begin(uint32_t baudrate) {
R503Serial.baud(baudrate);
}
/**************************************************************************/
/*!
@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
*/
/**************************************************************************/
bool Fingerprint::verifyPassword(void) {
return checkPassword() == FINGERPRINT_OK;
}
uint8_t 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 Get the sensors parameters, fills in the member variables
status_reg, system_id, capacity, security_level, device_addr, packet_len
and baud_rate
@returns True if password is correct
*/
/**************************************************************************/
uint8_t Fingerprint::getParameters(void) {
GET_CMD_PACKET(FINGERPRINT_READSYSPARAM);
status_reg = ((uint16_t)packet.data[1] << 8) | packet.data[2];
system_id = ((uint16_t)packet.data[3] << 8) | packet.data[4];
capacity = ((uint16_t)packet.data[5] << 8) | packet.data[6];
security_level = ((uint16_t)packet.data[7] << 8) | packet.data[8];
device_addr = ((uint32_t)packet.data[9] << 24) |
((uint32_t)packet.data[10] << 16) |
((uint32_t)packet.data[11] << 8) | (uint32_t)packet.data[12];
packet_len = ((uint16_t)packet.data[13] << 8) | packet.data[14];
if (packet_len == 0) {
packet_len = 32;
} else if (packet_len == 1) {
packet_len = 64;
} else if (packet_len == 2) {
packet_len = 128;
} else if (packet_len == 3) {
packet_len = 256;
}
baud_rate = (((uint16_t)packet.data[15] << 8) | packet.data[16]) * 9600;
return packet.data[0];
}
/**************************************************************************/
/*!
@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 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 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 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 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 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 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 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 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 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 Control the built in LED
@param on True if you want LED on, False to turn LED off
@returns <code>FINGERPRINT_OK</code> on success
*/
/**************************************************************************/
uint8_t Fingerprint::LEDcontrol(bool on) {
if (on) {
SEND_CMD_PACKET(FINGERPRINT_LEDON);
} else {
SEND_CMD_PACKET(FINGERPRINT_LEDOFF);
}
}
/**************************************************************************/
/*!
@brief Control the built in Aura LED (if exists). Check datasheet/manual
for different colors and control codes available
@param control The control code (e.g. breathing, full on)
@param speed How fast to go through the breathing/blinking cycles
@param coloridx What color to light the indicator
@param count How many repeats of blinks/breathing cycles
@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 Fingerprint::LEDcontrol(uint8_t control, uint8_t speed,
uint8_t coloridx, uint8_t count) {
SEND_CMD_PACKET(FINGERPRINT_AURALEDCONFIG, control, speed, coloridx, count);
}
/**************************************************************************/
/*!
@brief Ask the sensor to search the current slot fingerprint features to
match saved templates. The matching location is stored in <b>fingerID</b> and
the matching confidence in <b>confidence</b>
@param slot The slot to use for the print search, defaults to 1
@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 Fingerprint::fingerSearch(uint8_t slot) {
// search of slot starting thru the capacity
GET_CMD_PACKET(FINGERPRINT_SEARCH, slot, 0x00, 0x00, capacity >> 8,
capacity & 0xFF);
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 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 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 Fingerprint::writeStructuredPacket(const Fingerprint_Packet &packet)
{
R503Serial.putc((uint8_t)(packet.start_code >> 8));
R503Serial.putc((uint8_t)(packet.start_code & 0xFF));
R503Serial.putc(packet.address[0]);
R503Serial.putc(packet.address[1]);
R503Serial.putc(packet.address[2]);
R503Serial.putc(packet.address[3]);
R503Serial.putc(packet.type);
uint16_t wire_length = packet.length + 2;
R503Serial.putc((uint8_t)(wire_length >> 8));
R503Serial.putc((uint8_t)(wire_length & 0xFF));
#ifdef FINGERPRINT_DEBUG
printf("-> Send packet \n-> ");
printf("0x%02X%02X ",(uint8_t)(packet.start_code >> 8),(uint8_t)(packet.start_code & 0xFF));
printf(", 0x%02X ",packet.address[0]);
printf(", 0x%02X ",packet.address[1]);
printf(", 0x%02X ",packet.address[2]);
printf(", 0x%02X ",packet.address[3]);
printf(", 0x%02X ",packet.type);
printf(", 0x%02X ",(uint8_t)(wire_length >> 8));
printf(", 0x%02X \n-> Data ",(uint8_t)(wire_length & 0xFF));
#endif
uint16_t sum = ((wire_length) >> 8) + ((wire_length)&0xFF) + packet.type;
for (uint8_t i = 0; i < packet.length; i++)
{
R503Serial.putc(packet.data[i]);
sum += packet.data[i];
#ifdef FINGERPRINT_DEBUG
printf(", 0x%02X ",packet.data[i]);
#endif
}
// #ifdef FINGERPRINT_DEBUG
// printf("\n-\n");
// #endif
R503Serial.putc((uint8_t)(sum >> 8));
R503Serial.putc((uint8_t)(sum & 0xFF));
#ifdef FINGERPRINT_DEBUG
printf("-> chksum = 0x%02X%02X \n",(uint8_t)(sum >> 8),(uint8_t)(sum & 0xFF));
#endif
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 Fingerprint::getStructuredPacket(Fingerprint_Packet *packet, uint16_t timeout)
{
uint8_t byte;
uint16_t idx = 0, timer = 0;
#ifdef FINGERPRINT_DEBUG
printf("\n<----------------------packet reception\n<- ");
#endif
while (true)
{
while (pl==pe) // rien n'est arrivé
{
wait_ms(1);
timer++;
if (timer >= timeout)
{
#ifdef FINGERPRINT_DEBUG
printf("Timed out\n");
#endif
return FINGERPRINT_TIMEOUT;
}
}
byte = readUARTbuff();
#ifdef FINGERPRINT_DEBUG
printf("0x%02X, ",byte);
#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: // 4 bytes for adress
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;
#ifdef FINGERPRINT_DEBUG
printf("\n<- Data ");
#endif
break;
default:
packet->data[idx - 9] = byte;
if ((idx - 8) == packet->length)
{
#ifdef FINGERPRINT_DEBUG
printf("\n<--------------------packet reception OK \n\n");
#endif
return FINGERPRINT_OK;
}
break;
}
idx++;
}
// Shouldn't get here so...
// return FINGERPRINT_BADPACKET;
}
/*
Added by Christian Dupaty, STM32 adaptation
*/
/***************************************************************************
PRIVATE FUNCTIONS
***************************************************************************/
void Fingerprint::receiveUART(void) {
uint8_t c;
while(!R503Serial.readable());
c=R503Serial.getc();
*pe=c;
pe++;
if (pe>buffUART+sizeof(buffUART)) pe=buffUART;
}
uint8_t Fingerprint::readUARTbuff(void) {
uint8_t c;
c=*pl;
pl++;
if (pl>buffUART+sizeof(buffUART)) pl=buffUART;
return c;
}