#![no_std]
#![no_main]
use a608_embedded::{
ENROLLMISMATCH, FingerprintSensor, IMAGEMESS, LedColor, LedMode, NOFINGER, NOMATCH, NOTFOUND,
OK, PACKETRECIEVEERR, SensorBuffer, SystemParam,
};
use cortex_m_rt::entry;
use panic_halt as _;
use stm32_hal2::{
clocks::Clocks,
gpio::{Pin, PinMode, Port},
pac,
usart::{Usart, UsartConfig, UsartDevice},
};
fn delay_ms(ms: u32) {
let iterations = ms * 10_000;
for _ in 0..iterations {
cortex_m::asm::nop();
}
}
macro_rules! debug_print {
($($arg:tt)*) => {
let _ = ($($arg)*);
};
}
#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let cp = cortex_m::Peripherals::take().unwrap();
let clock_cfg = Clocks::default();
clock_cfg.setup().unwrap();
let _tx_pin = Pin::new(Port::A, 9, PinMode::Alt(7));
let _rx_pin = Pin::new(Port::A, 10, PinMode::Alt(7));
let usart_cfg = UsartConfig {
baud_rate: 57600,
..Default::default()
};
let usart1 = Usart::new(dp.USART1, usart_cfg, &clock_cfg);
let mut sensor = FingerprintSensor::new(usart1, [0, 0, 0, 0]);
debug_print!("Initializing fingerprint sensor...");
match sensor.init() {
Ok(()) => {
debug_print!("Sensor initialized successfully!");
}
Err(e) => {
debug_print!("Failed to initialize sensor: {:?}", e);
loop {
cortex_m::asm::wfi();
}
}
}
if let Some(params) = sensor.system_parameters() {
debug_print!("=== System Parameters ===");
debug_print!("Library size: {}", params.library_size);
debug_print!("Security level: {}", params.security_level);
debug_print!("Baud rate: {} * 9600", params.baudrate);
debug_print!(
"Data packet size: {} bytes",
params.data_packet_size.byte_count()
);
}
match sensor.count_templates() {
Ok(OK) => {
debug_print!("Stored templates: {}", sensor.template_count);
}
Ok(err) => {
debug_print!("Count templates error: 0x{:02X}", err);
}
Err(e) => {
debug_print!("Count templates failed: {:?}", e);
}
}
let _ = sensor.set_led(LedColor::Blue, LedMode::Breathe, 100, 0);
debug_print!("=== Fingerprint Demo Started ===");
debug_print!("Place your finger on the sensor...");
let mut state = DemoState::Identifying;
let mut loop_count: u32 = 0;
let mut enrollment_slot: u16 = 0;
loop {
match state {
DemoState::Identifying => {
match try_identify(&mut sensor) {
Ok(Some((finger_id, confidence))) => {
debug_print!("*** MATCH FOUND ***");
debug_print!("Finger ID: {}, Confidence: {}", finger_id, confidence);
let _ = sensor.set_led(LedColor::Blue, LedMode::Flash, 50, 3);
delay_ms(1500);
let _ = sensor.set_led(LedColor::Blue, LedMode::Breathe, 100, 0);
}
Ok(None) => {
}
Err(_) => {
debug_print!("Identification error");
}
}
loop_count += 1;
if loop_count > 100 {
state = DemoState::WaitingForFirstCapture;
enrollment_slot = find_empty_slot(&mut sensor).unwrap_or(0);
debug_print!("=== ENROLLMENT MODE ===");
debug_print!("Will enroll to slot {}", enrollment_slot);
debug_print!("Place your finger (1st capture)...");
let _ = sensor.set_led(LedColor::Purple, LedMode::Breathe, 100, 0);
}
}
DemoState::WaitingForFirstCapture => {
match sensor.get_image() {
Ok(OK) => {
match sensor.image_2_tz(1) {
Ok(OK) => {
debug_print!("First capture OK. Remove finger...");
let _ = sensor.set_led(LedColor::Blue, LedMode::On, 0, 0);
state = DemoState::WaitingForRemoval;
}
_ => {
debug_print!("Failed to convert first image");
state = DemoState::EnrollmentFailed;
}
}
}
Ok(NOFINGER) => {}
_ => {}
}
}
DemoState::WaitingForRemoval => match sensor.get_image() {
Ok(NOFINGER) => {
delay_ms(500);
debug_print!("Place same finger (2nd capture)...");
let _ = sensor.set_led(LedColor::Purple, LedMode::Breathe, 100, 0);
state = DemoState::WaitingForSecondCapture;
}
_ => {}
},
DemoState::WaitingForSecondCapture => {
match sensor.get_image() {
Ok(OK) => {
match sensor.image_2_tz(2) {
Ok(OK) => {
debug_print!("Second capture OK. Creating model...");
state = DemoState::CreatingModel;
}
_ => {
debug_print!("Failed to convert second image");
state = DemoState::EnrollmentFailed;
}
}
}
Ok(NOFINGER) => {}
_ => {}
}
}
DemoState::CreatingModel => {
match sensor.create_model() {
Ok(OK) => {
match sensor.store_model(enrollment_slot, 1) {
Ok(OK) => {
debug_print!("*** ENROLLMENT SUCCESSFUL ***");
debug_print!("Stored at slot {}", enrollment_slot);
let _ = sensor.set_led(LedColor::Purple, LedMode::Flash, 50, 5);
delay_ms(2000);
loop_count = 0;
state = DemoState::Identifying;
let _ = sensor.set_led(LedColor::Blue, LedMode::Breathe, 100, 0);
}
_ => {
debug_print!("Failed to store model");
state = DemoState::EnrollmentFailed;
}
}
}
Ok(ENROLLMISMATCH) => {
debug_print!("Fingerprints don't match");
state = DemoState::EnrollmentFailed;
}
_ => {
debug_print!("Failed to create model");
state = DemoState::EnrollmentFailed;
}
}
}
DemoState::EnrollmentFailed => {
let _ = sensor.set_led(LedColor::Red, LedMode::Flash, 50, 3);
delay_ms(1500);
debug_print!("Retrying enrollment...");
state = DemoState::WaitingForFirstCapture;
let _ = sensor.set_led(LedColor::Purple, LedMode::Breathe, 100, 0);
}
}
delay_ms(100);
}
}
#[derive(Clone, Copy)]
enum DemoState {
Identifying,
WaitingForFirstCapture,
WaitingForRemoval,
WaitingForSecondCapture,
CreatingModel,
EnrollmentFailed,
}
fn try_identify<UART, E>(
sensor: &mut FingerprintSensor<UART>,
) -> Result<Option<(u16, u16)>, a608_embedded::Error<E>>
where
UART: embedded_io::Write<Error = E> + embedded_io::Read<Error = E>,
{
match sensor.get_image()? {
OK => {}
NOFINGER => return Ok(None),
IMAGEMESS => return Ok(None),
_ => return Ok(None),
}
match sensor.image_2_tz(1)? {
OK => {}
_ => return Ok(None),
}
match sensor.finger_fast_search()? {
OK => Ok(Some((sensor.finger_id, sensor.confidence))),
NOTFOUND => Ok(None),
_ => Ok(None),
}
}
fn find_empty_slot<UART, E>(sensor: &mut FingerprintSensor<UART>) -> Option<u16>
where
UART: embedded_io::Write<Error = E> + embedded_io::Read<Error = E>,
{
let library_size = sensor.library_size().unwrap_or(200);
let num_pages = ((library_size + 255) / 256) as u8;
for page in 0..num_pages {
let mut bitmap = [0u8; 32];
if sensor.read_template_page(page, &mut bitmap).ok()? == OK {
for byte_idx in 0..32 {
if bitmap[byte_idx] != 0xFF {
for bit_idx in 0..8 {
if (bitmap[byte_idx] & (1 << bit_idx)) == 0 {
let slot = (page as u16 * 256) + (byte_idx as u16 * 8) + bit_idx as u16;
if slot < library_size {
return Some(slot);
}
}
}
}
}
}
}
Some(sensor.template_count)
}
#[allow(dead_code)]
fn delete_fingerprint<UART, E>(
sensor: &mut FingerprintSensor<UART>,
slot: u16,
) -> Result<bool, a608_embedded::Error<E>>
where
UART: embedded_io::Write<Error = E> + embedded_io::Read<Error = E>,
{
match sensor.delete_model(slot)? {
OK => Ok(true),
_ => Ok(false),
}
}
#[allow(dead_code)]
fn clear_all_fingerprints<UART, E>(
sensor: &mut FingerprintSensor<UART>,
) -> Result<bool, a608_embedded::Error<E>>
where
UART: embedded_io::Write<Error = E> + embedded_io::Read<Error = E>,
{
match sensor.empty_library()? {
OK => Ok(true),
_ => Ok(false),
}
}
#[allow(dead_code)]
fn set_security_level<UART, E>(
sensor: &mut FingerprintSensor<UART>,
level: u8,
) -> Result<bool, a608_embedded::Error<E>>
where
UART: embedded_io::Write<Error = E> + embedded_io::Read<Error = E>,
{
let level = level.clamp(1, 5);
match sensor.set_sysparam(SystemParam::SecurityLevel, level)? {
OK => Ok(true),
_ => Ok(false),
}
}
#[allow(dead_code)]
fn download_template<UART, E>(
sensor: &mut FingerprintSensor<UART>,
slot: u16,
buffer: &mut [u8],
) -> Result<usize, a608_embedded::Error<E>>
where
UART: embedded_io::Write<Error = E> + embedded_io::Read<Error = E>,
{
match sensor.load_model(slot, 1)? {
OK => {}
err => return Err(a608_embedded::Error::CommandFailed(err)),
}
sensor.get_fpdata(SensorBuffer::Char { slot: 1 }, buffer)
}
#[allow(dead_code)]
fn upload_template<UART, E>(
sensor: &mut FingerprintSensor<UART>,
slot: u16,
data: &[u8],
) -> Result<bool, a608_embedded::Error<E>>
where
UART: embedded_io::Write<Error = E> + embedded_io::Read<Error = E>,
{
sensor.send_fpdata(data, SensorBuffer::Char { slot: 1 })?;
match sensor.store_model(slot, 1)? {
OK => Ok(true),
_ => Ok(false),
}
}