Trung Nguyen
/
FINAL_PROJECT_4180
asdasdasd
Fork of FINAL_PROJECT_4180 by
Diff: FPScanner.cpp
- Revision:
- 2:1b1c0502bb08
--- /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; +};