Yes, here it is: LINK
Here is the datasheet:
SYSTEM_THREAD(ENABLED) wasn't meant to cure the blocking of the library and the D7 blinking does not get affected by the library blocking since it runs in a seperate thread.
The D7 blink test was meant to illustrate that in fact your code got flashed even when you assumed it didn't due to the missing publish event.
SYSTEM_THREAD(ENABLED) was meant to cure this
with it your code will still stall, but you should still be able to flash OTA.
So are you using the GT-511C1R or the GT511C3?
My fingerprint scanner is the “economy version”: GT-511C1R
It worked about 2 years with the library you ported…
Thanks for looking into it!

For a strange reason, my Photon could not be reflashed in case a sketch with any of the three FPS libraries was running. I had to bring it first into safe mode before it accepted to be flashed again.
![]()
@FiDel, can you give more details on how you have things hooked up. If it worked for two years then stopped working, what changed needs to be identified.
- Did you change any hardware connections?
- Did you change the power source for your project?
- How is the scanner powered?
- Did you change any of the code?
- Which version of firmware are you targeting?
Can you post a picture of your setup?
Indeed, it always helps to spend some time to check the basics:
Did you change any hardware connections?
No.
Did you change the power source for your project?
No.
How is the scanner powered?
Directly from my home’s 5V DC power line.
Did you change any of the code?
No. Actually, I test with just the FPS_Blink.ino example.
Even that sketch does not work anymore with the on-line libraries, but it does with your old (off-line) library.
Which version of firmware are you targeting?
System firmware target: : 0.6.3
On the device: 0.6.3
Confusing things happened in the previous days when suddenly also your “old” library stopped working… That was weird!
Today, I tried my FPS module again with the Windows demo program and my FPS module came back to life. I was glad to see it’s blue light working. 
When I then tried my FPS module again with your (old) library and with Particle Dev, all my previous sketches worked again!!!
I suppose the frequent trouble with the on-line libraries had confused my FPS module… 
When I try any sketch in the Web IDE, nothing works and the RGB LED consistently turns green every time again after about 10-15"…
I can still continue to use my FPS and update my sketches off-line, but probably others who try with the available on-line libraries can’t anymore…
It would be nice if you could make your library available again in the Web IDE.
Thanks on beforehand!
I wish i would have known there was a lib out there before I wrote my own 
Congratulations @seulater if you wrote the necessary library yourself!
Q:
Which FPS scanner are you using?
Can you share your library and sketch with the community?

I used the GT-511C3.
I cannot share the sketch because its tied into allot of other source files, which I am not willing to share at this time.
Since this forum does not allot you to upload files other than images I tried putting it here but the forum only allows 32k.
So i’ll have to do it in 2 steps.
GT-511C3.cpp
#include "application.h"
#include "headers.h"
#include "MI0283QT-9A.h"
#include "sx8654.h"
#include "SST25VF016B.h"
#include "SX1509.h"
#include "GT-511C3.h"
int fds=0;
SB_OEM_PKT* Command_Packet;
uint16_t total_downloaded;
//uint8_t FingerImg[240*320/4];
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int CheckPacket(uint8_t *ucData, uint8_t rtn)
{
uint8_t x;
if(rtn == SB_OEM_PKT_SIZE)
{
Serial.println("OK Packet");
if(Command_Packet->wCmd0 == ACK)
{
Serial.println("OK ACK");
if(CheckChkSumOfRpsAckPkt(Command_Packet) == OK)
{
Serial.println("OK Packet");
}
else
{
Serial.println("Bad Packet");
}
}
else
{
Serial.println("Bad ACK");
}
}
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int GT_511C3_Init( void )
{
int rt;
Command_Packet =(SB_OEM_PKT*) malloc(sizeof(SB_OEM_PKT));
// Serial1.begin(9600); // open serial over USB
GT_511C3_PurgeRX();
rt = GT_511C3_Terminate();
sprintf(lcdstring,"Terminate=%d",rt);
Serial.println(lcdstring);
rt = GT_511C3_ChangeBaudRate(115200);
sprintf(lcdstring,"Change Baud=%d",rt);
Serial.println(lcdstring);
Serial1.begin(115200); // open serial over USB
// Serial1.write("\r");
// Serial1.write("\n");
GT_511C3_PurgeRX();
rt = GT_511C3_Open(115200);
sprintf(lcdstring,"Init GT_511C3=%d",rt);
Serial.println(lcdstring);
return rt;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int GT_511C3_Terminate(void)
{
/*********Open Command***********/
Command_Packet->Head1 = COMMAND_START_CODE1;
Command_Packet->Head2 = COMMAND_START_CODE2;
Command_Packet->wDevId0 = DEVICE_ID;
Command_Packet->wDevId1 = DEVICE_ID>>8;
Command_Packet->nParam0 = ZERO;
Command_Packet->nParam1 = ZERO;
Command_Packet->nParam2 = ZERO;
Command_Packet->nParam3 = ZERO;
Command_Packet->wCmd0 = CLOSE;
Command_Packet->wCmd1 = ZERO;
uint16_t tmp = CalcChkSumOfCmdAckPkt(Command_Packet);
Command_Packet->wChkSum0 = tmp % 256;
Command_Packet->wChkSum1 = tmp >> 8;
/*********Open Command***********/
GT_511C3_SendCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
int rtn = GT_511C3_ReceiveCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
// CheckPacket((uint8_t *)Command_Packet, rtn);
if( (rtn == SB_OEM_PKT_SIZE) && (Command_Packet->wCmd0 == ACK) && (CheckChkSumOfRpsAckPkt(Command_Packet) == OK) )
{
return OK;
}
return FAIL;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
void GT_511C3_SendCommand(uint8_t *ucData, uint8_t length)
{
uint8_t x;
uint8_t *uc;
if(0)
{
uc = ucData;
Serial.print("Sending Packet:");
for(x=0;x<length;x++)
{
Serial.print(*uc);
Serial.print(",");
uc++;
}
Serial.println("");
}
// If we are sending something, then we will be receiving something So make sure
// the rx is clean before we start. Just to be safe.
GT_511C3_PurgeRX();
for(x=0;x<length;x++)
{
Serial1.write(*ucData);
ucData++;
}
// Serial1.write(0);
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int GT_511C3_ReceiveCommand(uint8_t *ucData, uint16_t length)
{
uint8_t total=0;
uint8_t x;
uint8_t *uc;
uint32_t t=0;
uc = ucData;
do
{
while(Serial1.available())
{
*ucData = Serial1.read();
ucData++;
total++;
}
}while( (total < length) && (++t < 2000000) );
if(0)
{
Serial.print("Received Packet:");
for(x=0;x<length;x++)
{
Serial.print(*uc);
Serial.print(",");
uc++;
}
Serial.println("");
}
return total;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
void GT_511C3_PurgeRX(void)
{
while(Serial1.available())
{
Serial1.read();
}
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int CalcChkSumOfCmdAckPkt( SB_OEM_PKT* pPkt )
{
uint16_t wChkSum = 0;
uint8_t * pBuf = (uint8_t*)pPkt;
uint16_t i;
for(i=0;i<(sizeof(SB_OEM_PKT) - SB_OEM_CHK_SUM_SIZE);i++)
{
wChkSum += pBuf[i];
}
return wChkSum;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int CheckChkSumOfRpsAckPkt( SB_OEM_PKT* pPkt )
{
unsigned short wChkSum = 0;
uint8_t * pBuf = (uint8_t*)pPkt;
uint16_t i;
if(pPkt->Head1 != RESPONSE_START_CODE1 || pPkt->Head2 != RESPONSE_START_CODE2)
{
return PKT_HDR_ERR;
}
if(pPkt->wDevId0 != DEVICE_ID || pPkt->wDevId1 != ZERO)
{
return PKT_DEV_ID_ERR;
}
for(i=0;i<(sizeof(SB_OEM_PKT) - SB_OEM_CHK_SUM_SIZE);i++)
wChkSum += pBuf[i];
if(pPkt->wChkSum0 != (wChkSum & 0xFF) || pPkt->wChkSum1 != (wChkSum & 0xFF00)>>8)
{
return PKT_CHK_SUM_ERR;
}
return OK;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int CalcChkSumOfDataPkt( unsigned char* pDataPkt, int nSize )
{
int i;
unsigned short wChkSum = 0;
unsigned char* pBuf = (unsigned char*)pDataPkt;
if(*pBuf != DATA_START_CODE1 || *(pBuf + 1) != DATA_START_CODE2)
return PKT_HDR_ERR;
if(*(pBuf + 2) != DEVICE_ID || *(pBuf + 3) != ZERO)
return PKT_DEV_ID_ERR;
for(i=0;i< nSize - SB_OEM_CHK_SUM_SIZE;i++)
wChkSum += pBuf[i];
if(*(pBuf + nSize - SB_OEM_CHK_SUM_SIZE) != (wChkSum & 0xFF) || *(pBuf + nSize - SB_OEM_CHK_SUM_SIZE + 1) != (wChkSum & 0xFF00)>>8)
return PKT_CHK_SUM_ERR;
return OK;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int GT_511C3_Open(unsigned long BAUDRATE)
{
/*********Open Command***********/
Command_Packet->Head1 = COMMAND_START_CODE1;
Command_Packet->Head2 = COMMAND_START_CODE2;
Command_Packet->wDevId0 = DEVICE_ID;
Command_Packet->wDevId1 = DEVICE_ID>>8;
Command_Packet->nParam0 = ZERO;
Command_Packet->nParam1 = ZERO;
Command_Packet->nParam2 = ZERO;
Command_Packet->nParam3 = ZERO;
Command_Packet->wCmd0 = OPEN;
Command_Packet->wCmd1 = ZERO;
uint16_t tmp = CalcChkSumOfCmdAckPkt(Command_Packet);
Command_Packet->wChkSum0 = tmp % 256;
Command_Packet->wChkSum1 = tmp >> 8;
/*********Open Command***********/
GT_511C3_SendCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
int rtn = GT_511C3_ReceiveCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
// CheckPacket((uint8_t *)Command_Packet, rtn);
if( (rtn == SB_OEM_PKT_SIZE) && (Command_Packet->wCmd0 == ACK) && (CheckChkSumOfRpsAckPkt(Command_Packet) == OK) )
{
return OK;
}
return FAIL;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int GT_511C3_ChangeBaudRate(unsigned long BAUDRATE)
{
/*********Change Baudrate Command***********/
Command_Packet->Head1 = COMMAND_START_CODE1;
Command_Packet->Head2 = COMMAND_START_CODE2;
Command_Packet->wDevId0 = DEVICE_ID;
Command_Packet->wDevId1 = DEVICE_ID>>8;
Command_Packet->nParam0 = BAUDRATE & 0xFF;
Command_Packet->nParam1 = (BAUDRATE & 0xFF00) >> 8 ;
Command_Packet->nParam2 = (BAUDRATE & 0xFF0000) >> 16;
Command_Packet->nParam3 = (BAUDRATE & 0xFF000000) >> 24;
Command_Packet->wCmd0 = CHANGBAUDRATE;
Command_Packet->wCmd1 = ZERO;
uint16_t tmp = CalcChkSumOfCmdAckPkt(Command_Packet);
Command_Packet->wChkSum0 = tmp % 256;
Command_Packet->wChkSum1 = tmp >> 8;
/*********Change Baudrate Command***********/
GT_511C3_SendCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
int rtn = GT_511C3_ReceiveCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
// CheckPacket((uint8_t *)Command_Packet, rtn);
if( (rtn == SB_OEM_PKT_SIZE) && (Command_Packet->wCmd0 == ACK) && (CheckChkSumOfRpsAckPkt(Command_Packet) == OK) )
{
return OK;
}
return FAIL;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int GT_511C3_LED(boolean State)
{
/*********Change Baudrate Command***********/
Command_Packet->Head1 = COMMAND_START_CODE1;
Command_Packet->Head2 = COMMAND_START_CODE2;
Command_Packet->wDevId0 = DEVICE_ID;
Command_Packet->wDevId1 = DEVICE_ID>>8;
Command_Packet->nParam0 = State & 0xFF;
Command_Packet->nParam1 = 0x00; //(State & 0xFF00) >> 8 ;
Command_Packet->nParam2 = 0x00; //(State & 0xFF0000) >> 16;
Command_Packet->nParam3 = 0x00; //(State & 0xFF000000) >> 24;
Command_Packet->wCmd0 = CMOSLED;
Command_Packet->wCmd1 = ZERO;
uint16_t tmp = CalcChkSumOfCmdAckPkt(Command_Packet);
Command_Packet->wChkSum0 = tmp % 256;
Command_Packet->wChkSum1 = tmp >> 8;
/*********Change Baudrate Command***********/
GT_511C3_SendCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
int rtn = GT_511C3_ReceiveCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
if( (rtn == SB_OEM_PKT_SIZE) && (Command_Packet->wCmd0 == ACK) && (CheckChkSumOfRpsAckPkt(Command_Packet) == OK) )
{
return OK;
}
// iprintf("Led Fail\r\n");
return FAIL;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int GT_511C3_IsFingerPressed(void)
{
/*********Change Baudrate Command***********/
Command_Packet->Head1 = COMMAND_START_CODE1;
Command_Packet->Head2 = COMMAND_START_CODE2;
Command_Packet->wDevId0 = DEVICE_ID;
Command_Packet->wDevId1 = DEVICE_ID>>8;
Command_Packet->nParam0 = ZERO;
Command_Packet->nParam1 = ZERO;
Command_Packet->nParam2 = ZERO;
Command_Packet->nParam3 = ZERO;
Command_Packet->wCmd0 = ISPRESSFINGER;
Command_Packet->wCmd1 = ZERO;
uint16_t tmp = CalcChkSumOfCmdAckPkt(Command_Packet);
Command_Packet->wChkSum0 = tmp % 256;
Command_Packet->wChkSum1 = tmp >> 8;
/*********Change Baudrate Command***********/
GT_511C3_SendCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
int rtn = GT_511C3_ReceiveCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
if( (rtn == SB_OEM_PKT_SIZE) && (Command_Packet->wCmd0 == ACK) && (CheckChkSumOfRpsAckPkt(Command_Packet) == OK) )
{
if(Command_Packet->nParam0 == 0)
{
return FINGER_PRESSED;
}
else
{
return FINGER_NOT_PRESSED;
}
}
// iprintf("IsFingerPressed Fail\r\n");
return FAIL;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int GT_511C3_GetEnrollment(void)
{
/*********Change Baudrate Command***********/
Command_Packet->Head1 = COMMAND_START_CODE1;
Command_Packet->Head2 = COMMAND_START_CODE2;
Command_Packet->wDevId0 = DEVICE_ID;
Command_Packet->wDevId1 = DEVICE_ID>>8;
Command_Packet->nParam0 = ZERO;
Command_Packet->nParam1 = ZERO;
Command_Packet->nParam2 = ZERO;
Command_Packet->nParam3 = ZERO;
Command_Packet->wCmd0 = GETENROLLCOUNT;
Command_Packet->wCmd1 = ZERO;
uint16_t tmp = CalcChkSumOfCmdAckPkt(Command_Packet);
Command_Packet->wChkSum0 = tmp % 256;
Command_Packet->wChkSum1 = tmp >> 8;
/*********Change Baudrate Command***********/
GT_511C3_SendCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
int rtn = GT_511C3_ReceiveCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
if( (rtn == SB_OEM_PKT_SIZE) && (Command_Packet->wCmd0 == ACK) && (CheckChkSumOfRpsAckPkt(Command_Packet) == OK) )
{
return Command_Packet->nParam0;
}
// iprintf("GetEnrollment Fail\r\n");
return FAIL;
}
/*********************************************************************
*
* Function: Identify( Param 1 )
* Description: Identify
*
* Copyright: Versamodule
* Author: JP
* Creation Date: 4.13.2013
*
*
* Function Passers: Param 1: data to send to the Command Register
*
*
* NOTE: CaptureFinger must be called first before this for it to be valid
*
*
*
* Returns: Identity good, -1 if not
*
**********************************************************************/
int GT_511C3_Identify(void)
{
/*********Change Baudrate Command***********/
Command_Packet->Head1 = COMMAND_START_CODE1;
Command_Packet->Head2 = COMMAND_START_CODE2;
Command_Packet->wDevId0 = DEVICE_ID;
Command_Packet->wDevId1 = DEVICE_ID>>8;
Command_Packet->nParam0 = ZERO;
Command_Packet->nParam1 = ZERO;
Command_Packet->nParam2 = ZERO;
Command_Packet->nParam3 = ZERO;
Command_Packet->wCmd0 = IDENTIFY;
Command_Packet->wCmd1 = ZERO;
uint16_t tmp = CalcChkSumOfCmdAckPkt(Command_Packet);
Command_Packet->wChkSum0 = tmp % 256;
Command_Packet->wChkSum1 = tmp >> 8;
/*********Change Baudrate Command***********/
GT_511C3_SendCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
int rtn = GT_511C3_ReceiveCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
if( (rtn == SB_OEM_PKT_SIZE) && (Command_Packet->wCmd0 == ACK) && (CheckChkSumOfRpsAckPkt(Command_Packet) == OK) )
{
return (Command_Packet->nParam1<<8) + Command_Packet->nParam0;
}
// iprintf("Identify Fail\r\n");
return FAIL;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int GT_511C3_CaptureFinger(uint8_t cFlag)
{
/*********Change Baudrate Command***********/
Command_Packet->Head1 = COMMAND_START_CODE1;
Command_Packet->Head2 = COMMAND_START_CODE2;
Command_Packet->wDevId0 = DEVICE_ID;
Command_Packet->wDevId1 = DEVICE_ID>>8;
Command_Packet->nParam0 = cFlag & 0xFF;
Command_Packet->nParam1 = 0x00; //(cFlag & 0xFF00) >> 8 ;
Command_Packet->nParam2 = 0x00; //(cFlag & 0xFF0000) >> 16;
Command_Packet->nParam3 = 0x00; //(cFlag & 0xFF000000) >> 24;
Command_Packet->wCmd0 = CAPTURE_FINGER;
Command_Packet->wCmd1 = ZERO;
uint16_t tmp = CalcChkSumOfCmdAckPkt(Command_Packet);
Command_Packet->wChkSum0 = tmp % 256;
Command_Packet->wChkSum1 = tmp >> 8;
/*********Change Baudrate Command***********/
GT_511C3_SendCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
int rtn = GT_511C3_ReceiveCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
if( (rtn == SB_OEM_PKT_SIZE) && (Command_Packet->wCmd0 == ACK) && (CheckChkSumOfRpsAckPkt(Command_Packet) == OK) )
{
return OK;
}
return FAIL;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int GT_511C3_DeleteAll(void)
{
/*********Change Baudrate Command***********/
Command_Packet->Head1 = COMMAND_START_CODE1;
Command_Packet->Head2 = COMMAND_START_CODE2;
Command_Packet->wDevId0 = DEVICE_ID;
Command_Packet->wDevId1 = DEVICE_ID>>8;
Command_Packet->nParam0 = ZERO;
Command_Packet->nParam1 = ZERO;
Command_Packet->nParam2 = ZERO;
Command_Packet->nParam3 = ZERO;
Command_Packet->wCmd0 = DELETEALL;
Command_Packet->wCmd1 = ZERO;
uint16_t tmp = CalcChkSumOfCmdAckPkt(Command_Packet);
Command_Packet->wChkSum0 = tmp % 256;
Command_Packet->wChkSum1 = tmp >> 8;
/*********Change Baudrate Command***********/
GT_511C3_SendCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
int rtn = GT_511C3_ReceiveCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
if( (rtn == SB_OEM_PKT_SIZE) && (Command_Packet->wCmd0 == NACK) && (CheckChkSumOfRpsAckPkt(Command_Packet) == OK) )
{
return OK;
}
// iprintf("DeleteAll Fail\r\n");
return FAIL;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int GT_511C3_Delete_ID(uint16_t id)
{
/*********Change Baudrate Command***********/
Command_Packet->Head1 = COMMAND_START_CODE1;
Command_Packet->Head2 = COMMAND_START_CODE2;
Command_Packet->wDevId0 = DEVICE_ID;
Command_Packet->wDevId1 = DEVICE_ID>>8;
Command_Packet->nParam0 = id & 0xFF;
Command_Packet->nParam1 = (id & 0xFF00) >> 8 ;
Command_Packet->nParam2 = 0x00; //(id & 0xFF0000) >> 16;
Command_Packet->nParam3 = 0x00; //(id & 0xFF000000) >> 24;
Command_Packet->wCmd0 = DELETEID;
Command_Packet->wCmd1 = ZERO;
uint16_t tmp = CalcChkSumOfCmdAckPkt(Command_Packet);
Command_Packet->wChkSum0 = tmp % 256;
Command_Packet->wChkSum1 = tmp >> 8;
/*********Change Baudrate Command***********/
GT_511C3_SendCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
int rtn = GT_511C3_ReceiveCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
if( (rtn == SB_OEM_PKT_SIZE) && (Command_Packet->wCmd0 == ACK) && (CheckChkSumOfRpsAckPkt(Command_Packet) == OK) )
{
return OK;
}
// iprintf("Delete_ID Fail\r\n");
return FAIL;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int GT_511C3_GetRawImage(int valid)
{
// uint8_t gbyImgRaw[240*320/4];
uint8_t pixel;
// uint8_t gbyImgRaw[240];
int x, y;
int j=0;
//*********Change Baudrate Command***********
Command_Packet->Head1 = COMMAND_START_CODE1;
Command_Packet->Head2 = COMMAND_START_CODE2;
Command_Packet->wDevId0 = DEVICE_ID;
Command_Packet->wDevId1 = DEVICE_ID>>8;
Command_Packet->nParam0 = ZERO;
Command_Packet->nParam1 = ZERO;
Command_Packet->nParam2 = ZERO;
Command_Packet->nParam3 = ZERO;
Command_Packet->wCmd0 = GETRAWIMAGE;
Command_Packet->wCmd1 = ZERO;
uint16_t tmp = CalcChkSumOfCmdAckPkt(Command_Packet);
Command_Packet->wChkSum0 = tmp % 256;
Command_Packet->wChkSum1 = tmp >> 8;
//*********Change Baudrate Command***********
GT_511C3_SendCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
int rtn = GT_511C3_ReceiveCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
if( (rtn == SB_OEM_PKT_SIZE) && (Command_Packet->wCmd0 == ACK) && (CheckChkSumOfRpsAckPkt(Command_Packet) == OK) )
{
Serial.print("Downloading Image\r\n");
for( x=0; x<120; x++)
{
for( y=0; y<160; y++)
{
while(!Serial1.available());
pixel = Serial1.read();
if(valid == VALID)
{
LCD_PixelPut(x + 5, y + 45 , pixel << 5 ); //Shift up 4 or 5
}
else
{
LCD_PixelPut(x + 5, y + 45 , (pixel << 5) | 0xf800 ); //Shift up 4 or 5
}
}
}
GT_511C3_PurgeRX();
return OK;
}
Serial.print("GetRawImage Fail\r\n");
// Wipe Bargraph Off screen
// LCD_Fill(1,41,129,220,0x0000);
// sprintf(lcdstring,"Image Error");
// LCD_String(lcdstring,Comic_Sans_MS20x27,5,120,4,0x07e0,0x0000);
return FAIL;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int GT_511C3_EnrollStart(uint16_t id)
{
/*********Change Baudrate Command***********/
Command_Packet->Head1 = COMMAND_START_CODE1;
Command_Packet->Head2 = COMMAND_START_CODE2;
Command_Packet->wDevId0 = DEVICE_ID;
Command_Packet->wDevId1 = DEVICE_ID>>8;
Command_Packet->nParam0 = id & 0xFF;
Command_Packet->nParam1 = (id & 0xFF00) >> 8 ;
Command_Packet->nParam2 = 0x00; //(id & 0xFF0000) >> 16;
Command_Packet->nParam3 = 0x00; //(id & 0xFF000000) >> 24;
Command_Packet->wCmd0 = ENROLLSTART;
Command_Packet->wCmd1 = ZERO;
uint16_t tmp = CalcChkSumOfCmdAckPkt(Command_Packet);
Command_Packet->wChkSum0 = tmp % 256;
Command_Packet->wChkSum1 = tmp >> 8;
/*********Change Baudrate Command***********/
GT_511C3_SendCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
int rtn = GT_511C3_ReceiveCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
if( (rtn == SB_OEM_PKT_SIZE) && (Command_Packet->wCmd0 == ACK) && (CheckChkSumOfRpsAckPkt(Command_Packet) == OK) )
{
return Command_Packet->nParam0;
}
// iprintf("GetEnrollment Fail\r\n");
return FAIL;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int GT_511C3_Enrollnth(uint8_t count)
{
/*********Change Baudrate Command***********/
Command_Packet->Head1 = COMMAND_START_CODE1;
Command_Packet->Head2 = COMMAND_START_CODE2;
Command_Packet->wDevId0 = DEVICE_ID;
Command_Packet->wDevId1 = DEVICE_ID>>8;
Command_Packet->nParam0 = ZERO;
Command_Packet->nParam1 = ZERO;
Command_Packet->nParam2 = ZERO;
Command_Packet->nParam3 = ZERO;
Command_Packet->wCmd0 = ENROLLSTART + count;
Command_Packet->wCmd1 = ZERO;
uint16_t tmp = CalcChkSumOfCmdAckPkt(Command_Packet);
Command_Packet->wChkSum0 = tmp % 256;
Command_Packet->wChkSum1 = tmp >> 8;
/*********Change Baudrate Command***********/
GT_511C3_SendCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
int rtn = GT_511C3_ReceiveCommand((uint8_t *)Command_Packet,SB_OEM_PKT_SIZE);
if( (rtn == SB_OEM_PKT_SIZE) && (Command_Packet->wCmd0 == ACK) && (CheckChkSumOfRpsAckPkt(Command_Packet) == OK) )
{
return Command_Packet->nParam0;
}
// iprintf("Enroll nth Fail\r\n");
return FAIL;
}
//*********************************************************************
//**************************** TASK 1 *******************************
//*********************************************************************
int GT_511C3_PerformEnrollment(uint16_t id)
{
uint8_t x;
if(GT_511C3_EnrollStart(id) == OK)
{
// iprintf("Start Enrollment for ID:%d\r\n",id);
// Turn LCD on so module can see finger
GT_511C3_LED(1);
for(x=1;x<4;x++)
{
// iprintf("Enrollment #%u of 3, Press Finger\r\n",x);
// Wait for finger press
while(GT_511C3_IsFingerPressed() != FINGER_PRESSED)
{
//OSTimeDly( 1 );
}
// while finger pressed and capture not ready
while( (GT_511C3_IsFingerPressed() == FINGER_PRESSED) && (GT_511C3_CaptureFinger(1)!=OK) )
{
//OSTimeDly( 5 );
}
if(GT_511C3_Enrollnth(x)==OK)
{
// iprintf("Enroll Complete, Remove Finger\r\n");
while(GT_511C3_IsFingerPressed() == FINGER_PRESSED)
{
//OSTimeDly( 1 );
}
}
else
{
// iprintf("Enroll %u Failed\r\n",x);
return FAIL;
}
}
GT_511C3_LED(0);
// iprintf("Enrollment of ID[%d] Successful\r\n",id);
return OK;
}
else
{
// iprintf("!!! Start Enrollment Fail for ID:%d !!!\r\n",id);
}
return FAIL;
}
GT-511C3.h
/*
* GT-511C3.h
*
* Created on: Apr 12, 2013
* Author: Jim
*/
#ifndef GT_511C3_H_
#define GT_511C3_H_
#define ERROR 0
#define VALID 1
#define FINGER_PRESSED 1
#define FINGER_NOT_PRESSED 0
#define OK 0
#define FAIL (char) -1
#define MAX_ENTRY_LEN 64
#define VSIZE 224
#define HSIZE 216
#define CAP_OK 1
#define GET_USB_MESSAGE 2
#define PROCESSING 3
#define QUILITY_BAD 4
#define LOGIN_PASS 5
#define LOGIN_FAIL 6
#define RECOVER 7
#define ID_EMPTY 8
#define ENROLLING 0x30
#define GET_IMAGE_DATA 0x33
#define IMAGE_PROTOCOLl_START 0x33
#define NO_PUT_FINGER 9
#define REMOVE_FINGER 10
#define REMOVE_OK 11
#define UNDETECT_AGAIN 12
#define ENROLL_FAIL 13
#define ENROLL_OK 14
#define ERASEID_OK 15
#define ERASE_PROTECT 0xFB
#define FLASH_FAIL 0xFC
#define CAP_FAIL 0xFF
#define EVEN_BREAK 0xFF
#define INFO_EXISTED -1000
#define PROCESSING_FAIL -1001
#define COMMAND_FAIL -1002
#define COMMAND_START_CODE1 0x55
#define COMMAND_START_CODE2 0xAA
#define DEVICE_ID 0x0001
#define RESPONSE_START_CODE1 0x55
#define RESPONSE_START_CODE2 0xAA
#define DATA_START_CODE1 0x5A
#define DATA_START_CODE2 0xA5
#define OPEN 0x01
#define CLOSE 0x02
#define USBINTERNALCHECK 0x03
#define CHANGBAUDRATE 0x04
#define IAPMODE 0x05
#define CMOSLED 0x12
#define GETENROLLCOUNT 0x20
#define CHECKENROLLED 0x21
#define ENROLLSTART 0x22
#define ENROLL1 0x23
#define ENROLL2 0x24
#define ENROLL3 0x25
#define ISPRESSFINGER 0x26
#define DELETEID 0x40
#define DELETEALL 0x41
#define VERIFY 0x50
#define IDENTIFY 0x51
#define VERIFY_TEMPLATE 0x52
#define IDENTIFY_TEMPLATE 0x53
#define CAPTURE_FINGER 0x60
#define GETIMAGE 0x62
#define GETRAWIMAGE 0x63
#define GETTEMPLATE 0x70
#define SETTEMPLATE 0x71
#define GETDATABASESTART 0x72
#define GETDATABASEEND 0x73
#define UPGRADEFIRMWARE 0x80
#define ACK 0x30
#define NACK 0x31
#define NACK_NONE 0x1000
#define NACK_TIMEOUT 0x1001
#define NACK_INVALID_BAUDRATE 0x1002
#define NACK_INVALID_POS 0x1003
#define NACK_IS_NOT_USED 0x1004
#define NACK_IS_ALREADY_USED 0x1005
#define NACK_COMM_ERR 0x1006
#define NACK_VERIFY_FAILED 0x1007
#define NACK_IDENTIFY_FAILED 0x1008
#define NACK_DB_IS_FULL 0x1009
#define NACK_DB_IS_EMPTY 0x100A
#define NACK_TURN_ERR 0x100B
#define NACK_BAD_FINGER 0x100C
#define NACK_ENROLL_FAILED 0x100D
#define NACK_IS_NOT_SUPPORTED 0x100E
#define NACK_DEV_ERR 0x100F
#define NACK_CAPTURE_CANCELED 0x1010
#define NACK_INVALID_PARAM 0x1011
#define NACK_FINGER_IS_NOT_PRESSED 0x1012
#define COMMAND_PACKET 0x00
#define RESPONSE_PACKET 0x01
#define DATA_PACKET 0x02
#define SB_OEM_PKT_SIZE 12
#define SB_OEM_HEADER_SIZE 2
#define SB_OEM_DEV_ID_SIZE 2
#define SB_OEM_CHK_SUM_SIZE 2
#define NONZERO 0x01
#define ZERO 0x00
#define DEVUCE_SERIAL_NUMBER_ERROR 0xFF
#define PKT_ERR_START -500
#define PKT_COMM_ERR PKT_ERR_START+1
#define PKT_HDR_ERR PKT_ERR_START+2
#define PKT_DEV_ID_ERR PKT_ERR_START+3
#define PKT_CHK_SUM_ERR PKT_ERR_START+4
#define PKT_PARAM_ERR PKT_ERR_START+5
#define FP_MAX_USERS 20
typedef struct _devinfo
{
long FirmwareVersion;
unsigned char DeviceSerialNumber[16];
} devinfo;
typedef struct {
unsigned char Head1;
unsigned char Head2;
unsigned char wDevId0;
unsigned char wDevId1;
unsigned char nParam0;
unsigned char nParam1;
unsigned char nParam2;
unsigned char nParam3;
unsigned char wCmd0;// or nAck
unsigned char wCmd1;
unsigned char wChkSum0;
unsigned char wChkSum1;
} SB_OEM_PKT;
extern uint16_t total_downloaded;
//extern uint8_t FingerImg[240*320/4];
int GT_511C3_Init( void );
int GT_511C3_Terminate(void);
void GT_511C3_SendCommand(uint8_t * ucData, uint8_t length);
int GT_511C3_ReceiveCommand(uint8_t *ucData, uint16_t length);
int GT_511C3_ReceiveCommandLCD(char *ucData, uint16_t length);
void GT_511C3_PurgeRX(void);
int CalcChkSumOfCmdAckPkt( SB_OEM_PKT* pPkt );
int CheckChkSumOfRpsAckPkt( SB_OEM_PKT* pPkt );
int CalcChkSumOfDataPkt( unsigned char* pDataPkt, int nSize );
int GT_511C3_Open(unsigned long BAUDRATE);
int GT_511C3_ChangeBaudRate(unsigned long BAUDRATE);
int GT_511C3_LED(boolean State);
int GT_511C3_IsFingerPressed(void);
int GT_511C3_GetEnrollment(void);
int GT_511C3_Identify(void);
int GT_511C3_CaptureFinger(uint8_t cFlag);
int GT_511C3_DeleteAll(void);
int GT_511C3_Delete_ID(uint16_t id);
int GT_511C3_GetImage(void);
int GT_511C3_GetRawImage(int valid);
int GT_511C3_EnrollStart(uint16_t id);
int GT_511C3_Enrollnth(uint8_t count);
int GT_511C3_PerformEnrollment(uint16_t id);
#endif /* GT_511C3_H_ */
main.ino
#include "application.h"
#include "headers.h"
#include "MI0283QT-9A.h"
#include "sx8654.h"
#include "SST25VF016B.h"
#include "SX1509.h"
#include "GT-511C3.h"
#include "menus.h"
// SX1509 Pin definition:
#define SX1509_LED_PIN 15 // LED to SX1509's pin 15
#define SX1509_PWM_PIN 14 // LED PWM Breathe output
//https://docs.particle.io/reference/firmware/photon/#semi-automatic-mode
// This is done so we initialize the LCD quickly so user does not think its
// dead while it waiting to register, or it it has not been registered yet.
SYSTEM_MODE(SEMI_AUTOMATIC);
//*********************************************************************
//****************** INITALIZE THE CHIP SELECT PIN ******************
//*********************************************************************
void setup()
{
pinMode(FLASH_CS_PIN, OUTPUT);
digitalWrite(FLASH_CS_PIN, HIGH);
pinMode(LCD_CS_PIN, OUTPUT);
digitalWrite(LCD_CS_PIN, HIGH);
pinMode(LCD_DC_PIN, OUTPUT);
digitalWrite(LCD_DC_PIN, HIGH);
pinMode(LCD_IRQ_PIN, INPUT_PULLUP);
Serial1.begin(9600); // open serial over USB
Serial1.write("\r");
Serial1.write("\n");
Serial.begin(115200); // open serial over USB
// Initialize the I2C bus if not already enabled
if ( !Wire.isEnabled() )
{
Wire.setSpeed(CLOCK_SPEED_100KHZ);
Wire.begin();
}
SPI1.begin();
SPI1.setBitOrder(MSBFIRST);
SPI1.setClockDivider(SPI_CLOCK_DIV2);
SPI1.setDataMode(SPI_MODE0);
// Init LCD
LCD_InitLandscape();
// Verify the sFLASH, Touch Screen, GPIO Expander
if( (sFLASH_Init() == true) && (SX8654_Init() == true) && (io.begin(SX1509_ADDRESS)==true) )
{
LCD_Fill(0,0,320,81,0xF800);
LCD_Fill(0,81,320,81,0x07e0);
LCD_Fill(0,160,320,80,0x001f);
// Set up the SX1509's clock to use the internal 2MHz
// oscillator. The second parameter divides the oscillator
// clock to generate a slower LED clock. 4 divides the 2MHz
// clock by 2 ^ (4-1) (8, ie. 250kHz). The divider parameter
// can be anywhere between 1-7.
io.clock(INTERNAL_CLOCK_2MHZ, 4);
io.pinMode(SX1509_LED_PIN, OUTPUT); // Set LED pin to OUTPUT
// Blink the LED pin -- ~1000 ms LOW, ~500 ms HIGH:
io.blink(SX1509_LED_PIN, 1000, 500);
// To breathe an LED, make sure you set it as an
// ANALOG_OUTPUT, so we can PWM the pin:
io.pinMode(SX1509_PWM_PIN, ANALOG_OUTPUT);
// Breathe an LED: 1000ms LOW, 500ms HIGH,
// 500ms to rise from low to high
// 250ms to fall from high to low
io.breathe(SX1509_PWM_PIN, 1000, 500, 500, 250);
}
else
{
LCD_CLS(0xF800);
}
// Wi-Fi connect...
Particle.connect();
// delay(1000);
LCD_CLS(0x0000);
sprintf(lcdstring,"Open Terminal");
LCD_StringFram(lcdstring,Comic_Sans_20x27,100,100,3,0xF81f,0x0000);
// Now open your Serial Terminal, and hit any key to continue!
// while(!Serial.available()) Particle.process();
LCD_CLS(0x0000);
GT_511C3_Init();
GT_511C3_LED(true);
sprintf(lcdstring,"Biometric Scanner");
LCD_StringFram(lcdstring,Comic_Sans_20x27,25,0,4,0xffe0,0x0000);
LCD_Box(0,40,130,210,0xffe0);
DisplayFRAMImage(PressYellow,190,60);
CreateTouchContainer(190,60,PressYellow,HAND_ICON);
CreateTouchBox(0,40,130,210,SETTINGS_ICON,0);
CreateTouchContainer(10,20,UserAdd,USER_ADD_ICON);
CreateTouchContainer(115,20,UserDelete,USER_DELETE_ICON);
CreateTouchContainer(220,20,RecycleBin,RECYCLEBIN_ICON);
CreateTouchContainer(10,125,UserProfile,USER_PROFILE_ICON);
CreateTouchContainer(220,125,Previous,PREVIOUS_ICON);
GT_511C3_LED(false);
//Show how many fingers are enrolled
int enroll = GT_511C3_GetEnrollment();
Serial.print("Total Enrolled:");
Serial.println(enroll);
}
//*********************************************************************
//****************** INITALIZE THE CHIP SELECT PIN ******************
//*********************************************************************
void loop()
{
// WaitForFingerScan();
if(IsScreenPressed() == true)
{
if( GetPenLocation() == true)
{
Crosshairs(sx8654_touch.pen_x, sx8654_touch.pen_y,5, 0x07e0);
// See if the area we touched was within the "Touch Me" location container
if(CheckTouchBox(sx8654_touch.pen_x,sx8654_touch.pen_y,HAND_ICON) == true)
{
// Wipe fingerprint Off screen
LCD_Fill(1,51,129,154,0x0000);
DisplayFRAMImage(PressGreen,190,60);
WaitForFingerScan();
}
else if(CheckContainer(sx8654_touch.pen_x,sx8654_touch.pen_y,SETTINGS_ICON) == true)
{
SetupMenu();
LCD_CLS(0x0000);
sprintf(lcdstring,"Biometric Scanner");
LCD_StringFram(lcdstring,Comic_Sans_20x27,25,0,4,0xffe0,0x0000);
LCD_Box(0,40,130,210,0xffe0);
DisplayFRAMImage(PressYellow,190,60);
WaitForTouchRelease(2000);
}
}
}
delay(5);
}
Is there an update to this that doesn’t require application.h? application.h has 40 other header files.
Yes, application.h was superseded by Particle.h but what’s the issue with the nested header files?
If the respective modules are not used in your code they won’t be linked into the binary but chances are that you will need at least a dozen of them anyway.
The alternative would be that everybody else would potentially have to include dozends of headers manually 
Oh sweet, I will include Particle.h thanks.