/***************************************************
  Пример работы оптического датчика отпечатков пальцев
  Разработанный для работы с Adafruit BMP085 Breakout Http://www.adafruit.com/products/751
  Автор Limor Fried/Ladyada для Adafruit Industries.

  Код модифицирован и откомментирован  http://iarduino.ru
  Сканер отпечатков пальцев для Arduino http://iarduino.ru/shop/Expansion-payments/skaner-otpechakov-palcev.html
  
  ### РЕГСТРАЦИЯ ОТПЕЧАТКОВ ПАЛЬЦЕВ В БАЗЕ МОДУЛЯ ###
 ****************************************************/

// Линия RX (Receive)  arduino (вывод 2), подключается к ЗЕЛЁНОМУ проводу датчика T (Transmit)
// Линия TX (Transmit) arduino (вывод 3), подключается к БЕЛОМУ   проводу датчика R (Receive)

#include <Adafruit_Fingerprint.h>                               // подключаем библиотеку для работы с модулем отпечатков пальцев
#include <SoftwareSerial.h>                                     // подключаем библиотеку для работы с программным UART

uint8_t              id;                                        // идентификационный номер, под которым будет сохранён шаблон отпечатка пальца
SoftwareSerial       mySerial(2, 3);                            // объявляем объект mySerial для работы с библиотекой SoftwareSerial ИМЯ_ОБЪЕКТА( RX, TX ); // Можно указывать любые выводы, поддерживающие прерывание PCINTx
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);  // объявляем объект finger   для работы с библиотекой Adafruit_Fingerprint ИМЯ_ОБЪЕКТА = Adafruit_Fingerprint(ПАРАМЕТР); // ПАРАМЕТР - ссылка на объект для работы с UART к которому подключен модуль, например: &Serial1

void setup(){
  while(!Serial);                                               // Ожидание инициализации аппаратного UART
  delay(500);                                                   // Ожидание инициализации модуля отпечатков пальцев
  Serial.begin(9600);                                           // Инициализация аппаратного UART на скорости 9600
  Serial.println("Scan sensor...");                             // Вывод сообщения "Поиск сенсора"
  finger.begin(57600);                                          // Инициализация программного UART на скорости 57600 (скорость модуля по умолчанию)
  if(finger.verifyPassword()){Serial.println("Found sensor!");} // Если модуль отпечатков    обнаружен, выводим сообщение "сенсор обнаружен"
  else{Serial.println("Did not find sensor :("); while(1);    } // Если модуль отпечатков не обнаружен, выводим сообщение "сенсор не обнаружен" и входим в бесконечный цикл: while(1);
}

void loop(){
  Serial.println("----------------------------------");
  Serial.print  ("Please enter ID number You want save ... ");  // Вывод сообщения "Пожалуйста введите идентификационный номер который Вы хотите сохранить"
  id = readnumber();                                            // Ожидание получения цифры, введённой с COM-порта
  Serial.print("Ok! ID="); Serial.println(id);                  // Вывод сообщения "Введён идентификационный номер" цифра
  while(!getFingerprintEnroll());
}

// функция возвращает номер, введённый с COM-порта
uint8_t readnumber(void){
  int num = -1;                                                 // Переменная с номером, который требуется вернуть
  while(num<0){                                                 // Вход в цикл, пока переменная num не станет >= 0
    while(!Serial.available());                                 // Ожидание пока в буфере COM-порта нет появятся данные
    while(Serial.available()){                                  // Цикл пока в буфере COM-порта не закончатся данные
      char c = Serial.read();                                   // Присваиваем очередной символ из COM-порта в переменную c
      if(isdigit(c)){                                           // Если значение переменной с - цифра, то ...
        if(num<0){num=0;}else{num *= 10;}                       // Увеличиваем значение num на один порядок
        num += c - '0';                                         // Прибавляем к значению num цифру из переменной c
      } delay(5);                                               // Задержка на 5мс, чтоб в буфер COM-порта успели догрузиться следующие символы (если таковые имеются)
    }
  }
  return num;                                                   // Возвращение введённого числа
}

uint8_t getFingerprintEnroll(){
  int p;                                                                                                             // Переменная для получения результатов выполнения функций
//Загрузка первого изображения отпечатка пальца
  p = -1;                                Serial.print  ("Please put your finger on the scanner .");                  // Вывод сообщения "Пожалуйста положите Ваш палец на сканер"
  while(p != FINGERPRINT_OK){                                                                                        // Вход в цикл, пока переменная p не станет равна константе FINGERPRINT_OK (корректная загрузка изображения)
    p = finger.getImage();                                                                                           // Захватываем изображение и возвращаем результат выполнения данной операции в переменную p
    switch(p){                                                                                                       // Проверка ответа ...
      case FINGERPRINT_OK:               Serial.println(" Ok!");                                      break;         // Изображение отпечатка пальца корректно загрузилось
      case FINGERPRINT_NOFINGER:         Serial.print  (".");                                         break;         // Сканер не обнаружил отпечаток пальца
      case FINGERPRINT_PACKETRECIEVEERR: Serial.println(" Communication error :(\nPlease try again ");break;         // Ошибка соединения
      case FINGERPRINT_IMAGEFAIL:        Serial.println(" Imaging error :(\nPlease try again ");      break;         // Ошибка изображения
      default:                           Serial.println(" Unknown error :(\nPlease try again ");      break;         // Неизвестная ошибка
    }
  }
//Конвертирование изображения первого отпечатка пальца
  p = finger.image2Tz(1);                Serial.print  ("Image converting: ");                                       // Конвертируем первое изображение и возвращаем результат выполнения данной операции в переменную p
  switch(p){                                                                                                         // Проверка ответа ...
    case FINGERPRINT_OK:                 Serial.println("Ok!");                                       break;         // Изображение сконвертировано
    case FINGERPRINT_IMAGEMESS:          Serial.println("Image too messy :(");                        return p;      // Изображение слишком нечеткое
    case FINGERPRINT_PACKETRECIEVEERR:   Serial.println("Communication error :(");                    return p;      // Ошибка соединения
    case FINGERPRINT_FEATUREFAIL:        Serial.println("No fingerprint on image :(");                return p;      // Ошибка конвертирования
    case FINGERPRINT_INVALIDIMAGE:       Serial.println("No fingerprint on image :(");                return p;      // Ошибка изображения
    default:                             Serial.println("Unknown error :(");                          return p;      // Неизвестная ошибка
  }
//Просим убрать палец от сканера
  p = 0;                                 Serial.print  ("Please remove your finger from the scanner ...");           // Вывод сообщения "Пожалуйста уберите Ваш палец со сканера"
  delay(2000);
  while(p != FINGERPRINT_NOFINGER){                                                                                  // Вход в цикл, пока переменная p не станет равна константе FINGERPRINT_NOFINGER (сканер не обнаружил отпечаток пальца)
    p=finger.getImage();                                                                                             // Захватываем изображение и возвращаем результат выполнения данной операции в переменную p
  }                                      Serial.println(" Ok!");
//Загрузка второго изображения отпечатка пальца
  p = -1;                                Serial.print  ("Place same finger again .");                                // Вывод сообщения "Пожалуйста положите тот же палец еще раз"
  while(p != FINGERPRINT_OK){                                                                                        // Вход в цикл, пока переменная p не станет равна константе FINGERPRINT_OK (корректная загрузка изображения)
    p = finger.getImage();                                                                                           // Захватываем изображение и возвращаем результат выполнения данной операции в переменную p
    switch(p){                                                                                                       // Проверка ответа ...
      case FINGERPRINT_OK:               Serial.println(" Ok!");                                      break;         // Изображение отпечатка пальца корректно загрузилось
      case FINGERPRINT_NOFINGER:         Serial.print  (".");                                         break;         // Сканер не обнаружил отпечаток пальца
      case FINGERPRINT_PACKETRECIEVEERR: Serial.println(" Communication error :(\nPlease try again ");break;         // Ошибка соединения
      case FINGERPRINT_IMAGEFAIL:        Serial.println(" Imaging error :(\nPlease try again ");      break;         // Ошибка изображения
      default:                           Serial.println(" Unknown error :(\nPlease try again ");      break;         // Неизвестная ошибка
    }
  }
//Конвертирование изображения второго отпечатка пальца
  p = finger.image2Tz(2);                Serial.print  ("Image converting: ");                                       // Конвертируем второе изображение и возвращаем результат выполнения данной операции в переменную p
  switch(p){                                                                                                         // Проверка ответа ...
    case FINGERPRINT_OK:                 Serial.println("Ok!");                                       break;         // Изображение сконвертировано
    case FINGERPRINT_IMAGEMESS:          Serial.println("Image too messy :(");                        return p;      // Изображение слишком нечеткое
    case FINGERPRINT_PACKETRECIEVEERR:   Serial.println("Communication error :(");                    return p;      // Ошибка соединения
    case FINGERPRINT_FEATUREFAIL:        Serial.println("No fingerprint on image :(");                return p;      // Ошибка конвертирования
    case FINGERPRINT_INVALIDIMAGE:       Serial.println("No fingerprint on image :(");                return p;      // Ошибка изображения
    default:                             Serial.println("Unknown error :(");                          return p;      // Неизвестная ошибка
  }
//Создание модели (шаблона) отпечатка пальца, по двум изображениям
  p = finger.createModel();              Serial.print  ("Creating model: ");                                         // Создание модели (шаблона) отпечатка пальца, по двум изображениям
  if(p == FINGERPRINT_OK              ){ Serial.println("Ok!");                                                }else // Модель (шаблон) отпечатка пальца создана
  if(p == FINGERPRINT_PACKETRECIEVEERR){ Serial.println("Communication error :(");                    return p;}else // Ошибка соединения
  if(p == FINGERPRINT_ENROLLMISMATCH  ){ Serial.println("Fingerprints did not match :(");             return p;}else // Отпечатки пальцев не совпадают
                                       { Serial.println("Unknown error :(");                          return p;}     // Неизвестная ошибка
//Сохранение, ранее созданной, модели (шаблона) отпечатка пальца, под определённым ранее, идентификационным номером
  p = finger.storeModel(id);             Serial.print  ("Saving model in ID="); Serial.print(id); Serial.print(": ");// Сохранение модели (шаблона) отпечатка пальца, по двум изображениям
  if(p == FINGERPRINT_OK              ){ Serial.println("Ok!");                                                }else // Модель (шаблон) отпечатка пальца сохранена
  if(p == FINGERPRINT_PACKETRECIEVEERR){ Serial.println("Communication error");                       return p;}else // Ошибка соединения
  if(p == FINGERPRINT_BADLOCATION     ){ Serial.println("Could not store in that location");          return p;}else // Не удалось сохранить в этом месте
  if(p == FINGERPRINT_FLASHERR        ){ Serial.println("Error writing to flash");                    return p;}else // Ошибка записи в flash память
                                       { Serial.println("Unknown error");                             return p;}     // Неизвестная ошибка
}