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.
Diff: FPScanner.cpp
- Revision:
- 2:1b1c0502bb08
diff -r 0e5e9821d89d -r 1b1c0502bb08 FPScanner.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FPScanner.cpp Mon Apr 25 00:36:32 2016 +0000
@@ -0,0 +1,601 @@
+/*
+ FPScanner.h v1.0 - Library for controlling the GT-511C3 Finger Print Scanner (FPS)
+ Created by Josh Hawley, July 23rd 2013
+ Licensed for non-commercial use, must include this license message
+ basically, Feel free to hack away at it, but just give me credit for my work =)
+ TLDR; Wil Wheaton's Law
+*/
+
+#include "FPScanner.h"
+
+
+// returns the 12 bytes of the generated command packet
+// remember to call delete on the returned array
+byte* Command_Packet::GetPacketBytes()
+{
+ byte* packetbytes= new byte[12];
+
+ // update command before calculating checksum (important!)
+ word cmd = Command;
+ command[0] = GetLowByte(cmd);
+ command[1] = GetHighByte(cmd);
+
+ word checksum = _CalculateChecksum();
+
+ packetbytes[0] = COMMAND_START_CODE_1;
+ packetbytes[1] = COMMAND_START_CODE_2;
+ packetbytes[2] = COMMAND_DEVICE_ID_1;
+ packetbytes[3] = COMMAND_DEVICE_ID_2;
+ packetbytes[4] = Parameter[0];
+ packetbytes[5] = Parameter[1];
+ packetbytes[6] = Parameter[2];
+ packetbytes[7] = Parameter[3];
+ packetbytes[8] = command[0];
+ packetbytes[9] = command[1];
+ packetbytes[10] = GetLowByte(checksum);
+ packetbytes[11] = GetHighByte(checksum);
+
+ return packetbytes;
+}
+
+// Converts the int to bytes and puts them into the paramter array
+void Command_Packet::ParameterFromInt(int i)
+{
+ Parameter[0] = (i & 0x000000ff);
+ Parameter[1] = (i & 0x0000ff00) >> 8;
+ Parameter[2] = (i & 0x00ff0000) >> 16;
+ Parameter[3] = (i & 0xff000000) >> 24;
+}
+
+// Returns the high byte from a word
+byte Command_Packet::GetHighByte(word w)
+{
+ return (byte)(w>>8)&0x00FF;
+}
+
+// Returns the low byte from a word
+byte Command_Packet::GetLowByte(word w)
+{
+ return (byte)w&0x00FF;
+}
+
+word Command_Packet::_CalculateChecksum()
+{
+ word w = 0;
+ w += COMMAND_START_CODE_1;
+ w += COMMAND_START_CODE_2;
+ w += COMMAND_DEVICE_ID_1;
+ w += COMMAND_DEVICE_ID_2;
+ w += Parameter[0];
+ w += Parameter[1];
+ w += Parameter[2];
+ w += Parameter[3];
+ w += command[0];
+ w += command[1];
+
+ return w;
+}
+
+Command_Packet::Command_Packet()
+{
+};
+
+// creates and parses a response packet from the finger print scanner
+Response_Packet::Response_Packet(byte* buffer)
+{
+ // CheckParsing(buffer[0], COMMAND_START_CODE_1, COMMAND_START_CODE_1);
+ // CheckParsing(buffer[1], COMMAND_START_CODE_2, COMMAND_START_CODE_2);
+ // CheckParsing(buffer[2], COMMAND_DEVICE_ID_1, COMMAND_DEVICE_ID_1);
+ // CheckParsing(buffer[3], COMMAND_DEVICE_ID_2, COMMAND_DEVICE_ID_2);
+ // CheckParsing(buffer[8], 0x30, 0x31);
+ if (buffer[8] == 0x30) ACK = true; else ACK = false;
+ // CheckParsing(buffer[9], 0x00, 0x00);
+
+ word checksum = CalculateChecksum(buffer, 10);
+ byte checksum_low = GetLowByte(checksum);
+ byte checksum_high = GetHighByte(checksum);
+ // CheckParsing(buffer[10], checksum_low, checksum_low);
+ // CheckParsing(buffer[11], checksum_high, checksum_high);
+
+ Error = ErrorCodes::ParseFromBytes(buffer[5], buffer[4]);
+
+ ParameterBytes[0] = buffer[4];
+ ParameterBytes[1] = buffer[5];
+ ParameterBytes[2] = buffer[6];
+ ParameterBytes[3] = buffer[7];
+ ResponseBytes[0]=buffer[8];
+ ResponseBytes[1]=buffer[9];
+ for (int i=0; i < 12; i++)
+ {
+ RawBytes[i]=buffer[i];
+ }
+}
+
+// parses bytes into one of the possible errors from the finger print scanner
+Response_Packet::ErrorCodes::Errors_Enum Response_Packet::ErrorCodes::ParseFromBytes(byte high, byte low)
+{
+ Errors_Enum e = INVALID;
+ if (high == 0x00)
+ {
+ }
+ if (high == 0x01)
+ {
+ switch(low)
+ {
+ case 0x00: e = NO_ERROR; break;
+ case 0x01: e = NACK_TIMEOUT; break;
+ case 0x02: e = NACK_INVALID_BAUDRATE; break;
+ case 0x03: e = NACK_INVALID_POS; break;
+ case 0x04: e = NACK_IS_NOT_USED; break;
+ case 0x05: e = NACK_IS_ALREADY_USED; break;
+ case 0x06: e = NACK_COMM_ERR; break;
+ case 0x07: e = NACK_VERIFY_FAILED; break;
+ case 0x08: e = NACK_IDENTIFY_FAILED; break;
+ case 0x09: e = NACK_DB_IS_FULL; break;
+ case 0x0A: e = NACK_DB_IS_EMPTY; break;
+ case 0x0B: e = NACK_TURN_ERR; break;
+ case 0x0C: e = NACK_BAD_FINGER; break;
+ case 0x0D: e = NACK_ENROLL_FAILED; break;
+ case 0x0E: e = NACK_IS_NOT_SUPPORTED; break;
+ case 0x0F: e = NACK_DEV_ERR; break;
+ case 0x10: e = NACK_CAPTURE_CANCELED; break;
+ case 0x11: e = NACK_INVALID_PARAM; break;
+ case 0x12: e = NACK_FINGER_IS_NOT_PRESSED; break;
+ }
+ }
+ return e;
+}
+
+// Gets an int from the parameter bytes
+int Response_Packet::IntFromParameter()
+{
+ int retval = 0;
+ retval = (retval << 8) + ParameterBytes[3];
+ retval = (retval << 8) + ParameterBytes[2];
+ retval = (retval << 8) + ParameterBytes[1];
+ retval = (retval << 8) + ParameterBytes[0];
+ return retval;
+}
+
+// calculates the checksum from the bytes in the packet
+word Response_Packet::CalculateChecksum(byte* buffer, int length)
+{
+ word checksum = 0;
+ for (int i=0; i<length; i++)
+ {
+ checksum +=buffer[i];
+ }
+ return checksum;
+}
+
+// Returns the high byte from a word
+byte Response_Packet::GetHighByte(word w)
+{
+ return (byte)(w>>8)&0x00FF;
+}
+
+// Returns the low byte from a word
+byte Response_Packet::GetLowByte(word w)
+{
+ return (byte)w&0x00FF;
+}
+
+// checks to see if the byte is the proper value, and logs it to the serial channel if not
+bool Response_Packet::CheckParsing(byte b, byte propervalue, byte alternatevalue)
+{
+ bool retval = (b == propervalue) || (b == alternatevalue);
+ return retval;
+
+}
+
+
+// Creates a new object to interface with the fingerprint scanner
+FPScanner::FPScanner(PinName tx, PinName rx)
+ : _serial(tx,rx)
+{
+ pin_TX = tx;
+ pin_RX = rx;
+ _serial.baud(9600);
+};
+
+
+//Initialises the device and gets ready for commands
+void FPScanner::Open()
+{
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::Open;
+ cp->Parameter[0] = 0x00;
+ cp->Parameter[1] = 0x00;
+ cp->Parameter[2] = 0x00;
+ cp->Parameter[3] = 0x00;
+ byte* packetbytes = cp->GetPacketBytes();
+ SendCommand(packetbytes, 12);
+ Response_Packet* rp = GetResponse();
+ delete cp;
+ delete rp;
+ delete [] packetbytes;
+}
+
+// According to the DataSheet, this does nothing...
+// Implemented it for completeness.
+void FPScanner::Close()
+{
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::Close;
+ cp->Parameter[0] = 0x00;
+ cp->Parameter[1] = 0x00;
+ cp->Parameter[2] = 0x00;
+ cp->Parameter[3] = 0x00;
+ byte* packetbytes = cp->GetPacketBytes();
+ SendCommand(packetbytes, 12);
+ Response_Packet* rp = GetResponse();
+ delete cp;
+ delete rp;
+ delete [] packetbytes;
+};
+
+// Turns on or off the LED backlight
+// Parameter: true turns on the backlight, false turns it off
+// Returns: True if successful, false if not
+bool FPScanner::SetLED(bool on)
+{
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::CmosLed;
+ if (on)
+ {
+ cp->Parameter[0] = 0x01;
+ }
+ else
+ {
+ cp->Parameter[0] = 0x00;
+ }
+ cp->Parameter[1] = 0x00;
+ cp->Parameter[2] = 0x00;
+ cp->Parameter[3] = 0x00;
+ byte* packetbytes = cp->GetPacketBytes();
+ SendCommand(packetbytes, 12);
+ Response_Packet* rp = GetResponse();
+ bool retval = true;
+ if (rp->ACK == false) retval = false;
+ delete rp;
+ delete [] packetbytes;
+ delete cp;
+ return retval;
+};
+
+// Changes the baud rate of the connection
+// Parameter: 9600, 19200, 38400, 57600, 115200
+// Returns: True if success, false if invalid baud
+// NOTE: Untested (don't have a logic level changer and a voltage divider is too slow)
+bool FPScanner::ChangeBaudRate(int baud)
+{
+ if ((baud == 9600) || (baud == 19200) || (baud == 38400) || (baud == 57600) || (baud == 115200))
+ {
+
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::Open;
+ cp->ParameterFromInt(baud);
+ byte* packetbytes = cp->GetPacketBytes();
+ SendCommand(packetbytes, 12);
+ Response_Packet* rp = GetResponse();
+ bool retval = rp->ACK;
+ if (retval)
+ {
+ _serial.baud(baud);
+ }
+ delete cp;
+ delete rp;
+ delete [] packetbytes;
+ return retval;
+ }
+ return false;
+}
+
+// Gets the number of enrolled fingerprints
+// Return: The total number of enrolled fingerprints
+int FPScanner::GetEnrollCount()
+{
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::GetEnrollCount;
+ cp->Parameter[0] = 0x00;
+ cp->Parameter[1] = 0x00;
+ cp->Parameter[2] = 0x00;
+ cp->Parameter[3] = 0x00;
+ byte* packetbytes = cp->GetPacketBytes();
+ SendCommand(packetbytes, 12);
+ Response_Packet* rp = GetResponse();
+
+ int retval = rp->IntFromParameter();
+ delete cp;
+ delete rp;
+ delete [] packetbytes;
+ return retval;
+}
+
+// checks to see if the ID number is in use or not
+// Parameter: 0-199
+// Return: True if the ID number is enrolled, false if not
+bool FPScanner::CheckEnrolled(int id)
+{
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::CheckEnrolled;
+ cp->ParameterFromInt(id);
+ byte* packetbytes = cp->GetPacketBytes();
+ SendCommand(packetbytes, 12);
+ Response_Packet* rp = GetResponse();
+ bool retval = false;
+ retval = rp->ACK;
+ delete cp;
+ delete rp;
+ delete [] packetbytes;
+ return retval;
+}
+
+// Starts the Enrollment Process
+// Parameter: 0-199
+// Return:
+// 0 - ACK
+// 1 - Database is full
+// 2 - Invalid Position
+// 3 - Position(ID) is already used
+int FPScanner::EnrollStart(int id)
+{
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::EnrollStart;
+ cp->ParameterFromInt(id);
+ byte* packetbytes = cp->GetPacketBytes();
+ delete cp;
+ SendCommand(packetbytes, 12);
+ delete [] packetbytes;
+ Response_Packet* rp = GetResponse();
+ int retval = 0;
+ if (rp->ACK == false)
+ {
+ if (rp->Error == Response_Packet::ErrorCodes::NACK_DB_IS_FULL) retval = 1;
+ if (rp->Error == Response_Packet::ErrorCodes::NACK_INVALID_POS) retval = 2;
+ if (rp->Error == Response_Packet::ErrorCodes::NACK_IS_ALREADY_USED) retval = 3;
+ }
+ delete rp;
+ return retval;
+}
+
+// Gets the first scan of an enrollment
+// Return:
+// 0 - ACK
+// 1 - Enroll Failed
+// 2 - Bad finger
+// 3 - ID in use
+int FPScanner::Enroll1()
+{
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::Enroll1;
+ byte* packetbytes = cp->GetPacketBytes();
+ delete cp;
+ SendCommand(packetbytes, 12);
+ delete [] packetbytes;
+ Response_Packet* rp = GetResponse();
+ int retval = rp->IntFromParameter();
+ if (retval < 200) retval = 3; else retval = 0;
+ if (rp->ACK == false)
+ {
+ if (rp->Error == Response_Packet::ErrorCodes::NACK_ENROLL_FAILED) retval = 1;
+ if (rp->Error == Response_Packet::ErrorCodes::NACK_BAD_FINGER) retval = 2;
+ }
+ delete rp;
+ if (rp->ACK) return 0; else return retval;
+}
+
+// Gets the Second scan of an enrollment
+// Return:
+// 0 - ACK
+// 1 - Enroll Failed
+// 2 - Bad finger
+// 3 - ID in use
+int FPScanner::Enroll2()
+{
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::Enroll2;
+ byte* packetbytes = cp->GetPacketBytes();
+ delete cp;
+ SendCommand(packetbytes, 12);
+ delete [] packetbytes;
+ Response_Packet* rp = GetResponse();
+ int retval = rp->IntFromParameter();
+ if (retval < 200) retval = 3; else retval = 0;
+ if (rp->ACK == false)
+ {
+ if (rp->Error == Response_Packet::ErrorCodes::NACK_ENROLL_FAILED) retval = 1;
+ if (rp->Error == Response_Packet::ErrorCodes::NACK_BAD_FINGER) retval = 2;
+ }
+ delete rp;
+ if (rp->ACK) return 0; else return retval;
+}
+
+// Gets the Third scan of an enrollment
+// Finishes Enrollment
+// Return:
+// 0 - ACK
+// 1 - Enroll Failed
+// 2 - Bad finger
+// 3 - ID in use
+int FPScanner::Enroll3()
+{
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::Enroll3;
+ byte* packetbytes = cp->GetPacketBytes();
+ delete cp;
+ SendCommand(packetbytes, 12);
+ delete [] packetbytes;
+ Response_Packet* rp = GetResponse();
+ int retval = rp->IntFromParameter();
+ if (retval < 200) retval = 3; else retval = 0;
+ if (rp->ACK == false)
+ {
+ if (rp->Error == Response_Packet::ErrorCodes::NACK_ENROLL_FAILED) retval = 1;
+ if (rp->Error == Response_Packet::ErrorCodes::NACK_BAD_FINGER) retval = 2;
+ }
+ delete rp;
+ if (rp->ACK) return 0; else return retval;
+}
+
+// Checks to see if a finger is pressed on the FPS
+// Return: true if finger pressed, false if not
+bool FPScanner::IsPressFinger()
+{
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::IsPressFinger;
+ byte* packetbytes = cp->GetPacketBytes();
+ SendCommand(packetbytes, 12);
+ Response_Packet* rp = GetResponse();
+ bool retval = false;
+ int pval = rp->ParameterBytes[0];
+ pval += rp->ParameterBytes[1];
+ pval += rp->ParameterBytes[2];
+ pval += rp->ParameterBytes[3];
+ if (pval == 0) retval = true;
+ delete rp;
+ delete [] packetbytes;
+ delete cp;
+ return retval;
+}
+
+// Deletes the specified ID (enrollment) from the database
+// Parameter: 0-199 (id number to be deleted)
+// Returns: true if successful, false if position invalid
+bool FPScanner::DeleteID(int id)
+{
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::DeleteID;
+ cp->ParameterFromInt(id);
+ byte* packetbytes = cp->GetPacketBytes();
+ SendCommand(packetbytes, 12);
+ Response_Packet* rp = GetResponse();
+ bool retval = rp->ACK;
+ delete rp;
+ delete [] packetbytes;
+ delete cp;
+ return retval;
+}
+
+// Deletes all IDs (enrollments) from the database
+// Returns: true if successful, false if db is empty
+bool FPScanner::DeleteAll()
+{
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::DeleteAll;
+ byte* packetbytes = cp->GetPacketBytes();
+ SendCommand(packetbytes, 12);
+ Response_Packet* rp = GetResponse();
+ bool retval = rp->ACK;
+ delete rp;
+ delete [] packetbytes;
+ delete cp;
+ return retval;
+}
+
+// Checks the currently pressed finger against a specific ID
+// Parameter: 0-199 (id number to be checked)
+// Returns:
+// 0 - Verified OK (the correct finger)
+// 1 - Invalid Position
+// 2 - ID is not in use
+// 3 - Verified FALSE (not the correct finger)
+int FPScanner::Verify1_1(int id)
+{
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::Verify1_1;
+ cp->ParameterFromInt(id);
+ byte* packetbytes = cp->GetPacketBytes();
+ SendCommand(packetbytes, 12);
+ Response_Packet* rp = GetResponse();
+ int retval = 0;
+ if (rp->ACK == false)
+ {
+ if (rp->Error == Response_Packet::ErrorCodes::NACK_INVALID_POS) retval = 1;
+ if (rp->Error == Response_Packet::ErrorCodes::NACK_IS_NOT_USED) retval = 2;
+ if (rp->Error == Response_Packet::ErrorCodes::NACK_VERIFY_FAILED) retval = 3;
+ }
+ delete rp;
+ delete [] packetbytes;
+ delete cp;
+ return retval;
+}
+
+// Checks the currently pressed finger against all enrolled fingerprints
+// Returns:
+// 0-199: Verified against the specified ID (found, and here is the ID number)
+// 200: Failed to find the fingerprint in the database
+int FPScanner::Identify1_N()
+{
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::Identify1_N;
+ byte* packetbytes = cp->GetPacketBytes();
+ SendCommand(packetbytes, 12);
+ Response_Packet* rp = GetResponse();
+ int retval = rp->IntFromParameter();
+ if (retval > 200) retval = 200;
+ delete rp;
+ delete [] packetbytes;
+ delete cp;
+ return retval;
+}
+
+// Captures the currently pressed finger into onboard ram use this prior to other commands
+// Parameter: true for high quality image(slower), false for low quality image (faster)
+// Generally, use high quality for enrollment, and low quality for verification/identification
+// Returns: True if ok, false if no finger pressed
+bool FPScanner::CaptureFinger(bool highquality)
+{
+ Command_Packet* cp = new Command_Packet();
+ cp->Command = Command_Packet::Commands::CaptureFinger;
+ if (highquality)
+ {
+ cp->ParameterFromInt(1);
+ }
+ else
+ {
+ cp->ParameterFromInt(0);
+ }
+ byte* packetbytes = cp->GetPacketBytes();
+ SendCommand(packetbytes, 12);
+ Response_Packet* rp = GetResponse();
+ bool retval = rp->ACK;
+ delete rp;
+ delete [] packetbytes;
+ delete cp;
+ return retval;
+
+}
+
+
+// Sends the command to the software serial channel
+void FPScanner::SendCommand(byte cmd[], int length)
+{
+ for (int i = 0; i < length; i++) {
+ _serial.putc(cmd[i]);
+ }
+};
+
+// Gets the response to the command from the software serial channel (and waits for it)
+Response_Packet* FPScanner::GetResponse()
+{
+ byte firstbyte = 0;
+ bool done = false;
+ while (done == false)
+ {
+ firstbyte = (byte)_serial.getc();
+ if (firstbyte == Response_Packet::COMMAND_START_CODE_1)
+ {
+ done = true;
+ }
+ }
+ byte* resp = new byte[12];
+ resp[0] = firstbyte;
+ for (int i=1; i < 12; i++)
+ {
+ resp[i]= (byte) _serial.getc();
+ }
+ Response_Packet* rp = new Response_Packet(resp);
+ delete [] resp;
+ return rp;
+};