diff --git a/tests/driver_mfrc522/Makefile b/tests/driver_mfrc522/Makefile new file mode 100644 index 000000000000..aa7119194378 --- /dev/null +++ b/tests/driver_mfrc522/Makefile @@ -0,0 +1,10 @@ +include ../Makefile.tests_common + +USEMODULE += mfrc522 +USEMODULE += xtimer +USEMODULE += shell + +CFLAGS += -DMFRC522_SELF_TEST_FUNCTION +CFLAGS += -DMFRC522_DUMP_FUNCTIONS + +include $(RIOTBASE)/Makefile.include diff --git a/tests/driver_mfrc522/Makefile.ci b/tests/driver_mfrc522/Makefile.ci new file mode 100644 index 000000000000..02b0eb5c3609 --- /dev/null +++ b/tests/driver_mfrc522/Makefile.ci @@ -0,0 +1,8 @@ +BOARD_INSUFFICIENT_MEMORY := \ + arduino-duemilanove \ + arduino-leonardo \ + arduino-nano \ + arduino-uno \ + atmega328p \ + atmega32u4 \ + # diff --git a/tests/driver_mfrc522/README.md b/tests/driver_mfrc522/README.md new file mode 100644 index 000000000000..b908fde505a4 --- /dev/null +++ b/tests/driver_mfrc522/README.md @@ -0,0 +1,28 @@ +# MFRC522 RFID Card Reader + +## Overview + +This test application demonstrates the usage of the MFRC522 driver interface +and can be used to test a MFRC522 RFID card reader with shell commands. + +## Optional features + +Add `CFLAGS += -DMFRC522_SELF_TEST_FUNCTION` to your Makefile to also compile +the self-test function into the driver. + +Add `CFLAGS += -DMFRC522_DUMP_FUNCTIONS` to your Makefile to also compile +the dump functions into the driver. + +## Usage + +The following shell commands are available: +* **reset** Reset the device. +* **antenna_on** Turn the antenna on. +* **antenna_off** Turn the antenna off. +* **set_antenna_gain** Set antenna gain. +* **get_antenna_gain** Get antenna gain. +* **firmware_version** Print the firmware version. +* **picc_dump** Dumps debug info about a scanned PICC. +* **scan_uid** Scan repeatedly until a PICC's UID is scanned. +* **set_uid** Set the UID of a scanned PICC. +* **self_test** Run the self test. diff --git a/tests/driver_mfrc522/main.c b/tests/driver_mfrc522/main.c new file mode 100644 index 000000000000..c6dce6d6d076 --- /dev/null +++ b/tests/driver_mfrc522/main.c @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2021 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup tests + * @brief Test application for the MFRC522 controller + * @author Hendrik van Essen + * @file + * + */ + +#include +#include +#include + +#include "xtimer.h" +#include "shell.h" + +#include "mfrc522.h" +#include "mfrc522_params.h" + +static mfrc522_t mfrc522_dev; + +/* Stores scanned ID read from RFID Module */ +static uint8_t read_card[4]; + +int get_uid(mfrc522_uid_t *uid, bool stop_read) +{ + int rc = 0; + + /* Getting ready for Reading PICCs + * If a new PICC placed to RFID reader continue + */ + if ( ! (rc = mfrc522_picc_is_new_card_present(&mfrc522_dev))) { + puts("No card detected ..."); + return 0; + } + + puts("Card detected. Read card serial ..."); + + /* Since a PICC placed get Serial and continue */ + mfrc522_status_code_t status = mfrc522_picc_read_card_serial(&mfrc522_dev, uid); + if (status != MFRC522_STATUS_OK) { + return 0; + } + + printf("Scanned PICC's UID: "); + for ( uint8_t i = 0; i < uid->size; i++) { + read_card[i] = uid->uid_byte[i]; + printf("%x", read_card[i]); + } + printf("\n"); + + /* Stop reading */ + if (stop_read) { + mfrc522_picc_halt_a(&mfrc522_dev); + } + + return 1; +} + +int scan_uid(int argc, char **argv) +{ + (void) argc; + (void) argv; + + mfrc522_uid_t uid; + uint8_t success_read; + + int i = 0; + do { + if (i >= 1) { + printf("Repeat scan (%d/20) ...\n", i + 1); + } + success_read = get_uid(&uid, true); + xtimer_usleep(500 * 1000); + i++; + } while (!success_read && i < 20); + + return 0; +} + +int self_test(int argc, char **argv) +{ + (void) argc; + (void) argv; + + bool success = mfrc522_pcd_perform_self_test(&mfrc522_dev); + + success ? printf("SUCCESS\n") : printf("FAILED\n"); + + /* After self-test the device is unusable => repeat the initialization routine */ + int rc = 0; + if ((rc = mfrc522_pcd_init(&mfrc522_dev, &mfrc522_params[0])) != 0) { + printf("Initialization failed! rc = %d", rc); + return 1; + } + + return 0; +} + +int reset(int argc, char **argv) +{ + (void) argc; + (void) argv; + + mfrc522_pcd_reset(&mfrc522_dev); + + return 0; +} + +int antenna_on(int argc, char **argv) +{ + (void) argc; + (void) argv; + + mfrc522_pcd_antenna_on(&mfrc522_dev); + + return 0; +} + +int antenna_off(int argc, char **argv) +{ + (void) argc; + (void) argv; + + mfrc522_pcd_antenna_off(&mfrc522_dev); + + return 0; +} + +int set_antenna_gain(int argc, char **argv) +{ + (void) argc; + (void) argv; + + if (argc != 2) { + puts("usage: set_antenna_gain "); + puts(" 0: 18db, 1: 23db, 2: 33db, 3: 38db, 4: 43db, 5: 48db"); + return 1; + } + else { + uint8_t input = atoi(argv[1]); + mfrc522_pcd_rx_gain_t gain; + + switch (input) { + case 0: + gain = MFRC522_RXGAIN_18_DB; + break; + case 1: + gain = MFRC522_RXGAIN_23_DB; + break; + case 2: + gain = MFRC522_RXGAIN_33_DB; + break; + case 3: + gain = MFRC522_RXGAIN_38_DB; + break; + case 4: + gain = MFRC522_RXGAIN_43_DB; + break; + case 5: + gain = MFRC522_RXGAIN_48_DB; + break; + default: + puts("gain needs to be one of [0-5]"); + puts("0: 18db, 1: 23db, 2: 33db, 3: 38db, 4: 43db, 5: 48db"); + return 1; + } + + mfrc522_pcd_set_antenna_gain(&mfrc522_dev, gain); + } + + return 0; +} + +int get_antenna_gain(int argc, char **argv) +{ + (void) argc; + (void) argv; + + mfrc522_pcd_rx_gain_t gain = mfrc522_pcd_get_antenna_gain(&mfrc522_dev); + + switch (gain) { + case MFRC522_RXGAIN_18_DB: + /* fall-through */ + case MFRC522_RXGAIN_18_DB_2: + printf("gain = MFRC522_RXGAIN_18_DB\n"); + break; + case MFRC522_RXGAIN_23_DB: + /* fall-through */ + case MFRC522_RXGAIN_23_DB_2: + printf("gain = MFRC522_RXGAIN_23_DB\n"); + break; + case MFRC522_RXGAIN_33_DB: + printf("gain = MFRC522_RXGAIN_33_DB\n"); + break; + case MFRC522_RXGAIN_38_DB: + printf("gain = MFRC522_RXGAIN_38_DB\n"); + break; + case MFRC522_RXGAIN_43_DB: + printf("gain = MFRC522_RXGAIN_43_DB\n"); + break; + case MFRC522_RXGAIN_48_DB: + printf("gain = MFRC522_RXGAIN_48_DB\n"); + break; + default: + printf("gain = UNKNOWN\n"); + break; + } + + return 0; +} + +int firmware_version(int argc, char **argv) +{ + (void) argc; + (void) argv; + + mfrc522_pcd_dump_version_to_serial(&mfrc522_dev); + + return 0; +} + +int picc_dump(int argc, char **argv) +{ + (void) argc; + (void) argv; + + mfrc522_uid_t uid; + if (get_uid(&uid, false) != 1) { + return 1; + } + + mfrc522_picc_dump_to_serial(&mfrc522_dev, &uid); + + return 0; +} + +int set_uid(int argc, char **argv) +{ + (void) argc; + (void) argv; + + if (argc != 5) { + puts("usage: set_uid "); + puts(" as hex value (e.g. 0xA9 or A9)"); + return 1; + } + else { + mfrc522_uid_t uid; + if (get_uid(&uid, false) != 1) { + return 1; + } + + uint8_t byte_1 = (uint8_t) strtol(argv[1], NULL, 16); + uint8_t byte_2 = (uint8_t) strtol(argv[2], NULL, 16); + uint8_t byte_3 = (uint8_t) strtol(argv[3], NULL, 16); + uint8_t byte_4 = (uint8_t) strtol(argv[4], NULL, 16); + + uint8_t uid_buf[4] = { byte_1, byte_2, byte_3, byte_4 }; + + mfrc522_status_code_t status = mfrc522_mifare_set_uid(&mfrc522_dev, &uid, uid_buf, 4); + printf("status = %s\n", mfrc522_get_status_code_string(status)); + } + + return 0; +} + +static const shell_command_t shell_commands[] = { + { "reset", "Reset the device.", reset }, + { "antenna_on", "Turn the antenna on.", antenna_on }, + { "antenna_off", "Turn the antenna off.", antenna_off }, + { "set_antenna_gain", "Set antenna gain.", set_antenna_gain }, + { "get_antenna_gain", "Get antenna gain.", get_antenna_gain }, + { "firmware_version", "Print the firmware version.", firmware_version }, + { "picc_dump", "Dumps debug info about a scanned PICC.", picc_dump }, + { "scan_uid", "Scan repeatedly until a PICC's UID is scanned.", scan_uid }, + { "set_uid", "Set the UID of a scanned PICC.", set_uid }, + { "self_test", "Run the self test.", self_test }, + { NULL, NULL, NULL } +}; + +int main(void) +{ + int rc = 0; + if ((rc = mfrc522_pcd_init(&mfrc522_dev, &mfrc522_params[0])) != 0) { + printf("Initialization failed! rc = %d", rc); + return 1; + } + + char line_buf[SHELL_DEFAULT_BUFSIZE]; + shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + + return 0; +}