Compare commits

15 Commits

Author SHA1 Message Date
ace6c49c8c Switched to mfrc522 driver fork. 2024-06-03 22:11:17 +02:00
501cfcb03a Improved readability of SPI related debug messages. 2024-06-02 10:27:42 +02:00
42cab6dcc3 Attempt to replicate the initialization sequence of an arduino project. 2024-06-02 10:27:06 +02:00
0fd71c101c WIP: Reuse logic from arduino project wo make mfrc522 work.
Hint: https://github.com/miguelbalboa/rfid.git
2024-06-01 00:33:54 +02:00
561b6d7ff7 Probably (!) fixed problem with spurious interrupts.
After turning on the analog section of the mfrc522, a lot of spurious
interrupts could be observed. Debugging revealed that the mfrc522 did not
give consistent information about an interrupt source.

A closer look into the chip documentation (chapter 9.3.1.4) revealed that
the interrupt pin is open drain by default, but can be set to CMOS.

Switched to CMOS, deactivated internal and external pull down resistors.
No more spurious interrupts.
2024-05-31 15:20:11 +02:00
2b98beab3a Initialization seems to work now: reading/writing requires a-/prepending a byte. 2024-05-20 23:13:09 +02:00
8ac8726904 Initial SPI integration. Known issue: RC522 reports invalid version id. 2024-05-16 21:44:29 +02:00
32c0865e32 Workaround: don't stop timer during debugging to prevent lockup while sleeping. 2024-05-16 21:43:43 +02:00
bf0f63032e Enable stdio on uart for debugging. 2024-05-16 21:41:51 +02:00
dbb566a2ae SPI setup will not yield the exact selected speed. 2024-05-09 15:56:57 +02:00
e4b0c9ee6f GPIO setup, IRQ handler setup, blink keepalive LED, delay serial usb setup. 2024-05-09 15:55:09 +02:00
c5153421b1 Turned I2C and UART related functions to duds. 2024-05-08 21:35:53 +02:00
f8d602ca6a WIP: Added gpio for reset pin. Rolled dice - it's gpio 5. 2024-05-06 22:01:27 +02:00
bf53194a1d WIP: Added debug and delay code. 2024-05-06 21:01:37 +02:00
f389cd5506 WIP: began implementing experimental integration skeleton. 2024-05-06 19:30:54 +02:00
5 changed files with 712 additions and 4 deletions

2
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "third_party/mfrc522"]
path = third_party/mfrc522_integration/mfrc522
url = https://github.com/libdriver/mfrc522.git
url = https://github.com/hoedur/mfrc522.git

View File

@@ -23,4 +23,4 @@ target_link_libraries(${PROJECT} mfrc522)
pico_add_extra_outputs(${PROJECT})
pico_enable_stdio_usb(${PROJECT} 1)
pico_enable_stdio_uart(${PROJECT} 0)
pico_enable_stdio_uart(${PROJECT} 1)

230
main.c
View File

@@ -1,6 +1,234 @@
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "driver_mfrc522_interface.h"
#define MFRC522_CFG_IRQ_GPIO 14
static mfrc522_handle_t ctx = {0};
static void mfrc522_integration_irq_handler(uint gpio, uint32_t event_mask)
{
(void) gpio;
(void) event_mask;
// Dump return value for now, we cannot do anything at the moment.
(void) mfrc522_irq_handler(&ctx);
}
static void mfrc522_integration_irq_init(mfrc522_handle_t* const ctx)
{
bool pu = gpio_is_pulled_up(MFRC522_CFG_IRQ_GPIO);
bool pd = gpio_is_pulled_down(MFRC522_CFG_IRQ_GPIO);
ctx->debug_print("GPIO PU: %d PD: %d\n", (int) pu, (int) pd);
gpio_set_pulls(MFRC522_CFG_IRQ_GPIO, false, false);
pu = gpio_is_pulled_up(MFRC522_CFG_IRQ_GPIO);
pd = gpio_is_pulled_down(MFRC522_CFG_IRQ_GPIO);
ctx->debug_print("GPIO PU: %d PD: %d\n", (int) pu, (int) pd);
gpio_set_irq_enabled_with_callback(MFRC522_CFG_IRQ_GPIO, GPIO_IRQ_EDGE_RISE, true,
mfrc522_integration_irq_handler);
}
void setup_attempt_1(void)
{
// Set rf uart to 106000 baud (tx/rx)
uint8_t set_tx_speed_ret = mfrc522_set_tx_speed(&ctx, MFRC522_SPEED_106_KBD);
if (set_tx_speed_ret != 0) {
mfrc522_interface_debug_print("ERR: could not set rf tx speed\n");
}
uint8_t set_rx_speed_ret = mfrc522_set_rx_speed(&ctx, MFRC522_SPEED_106_KBD);
if (set_rx_speed_ret != 0) {
mfrc522_interface_debug_print("ERR: could not set rf rx speed\n");
}
// Set modulation width to initial default value (datasheet section 9.3.3.4)
uint8_t set_modw_ret = mfrc522_set_modulation_width(&ctx, 0x26);
if (set_modw_ret != 0) {
mfrc522_interface_debug_print("ERR: could not set modulation width register\n");
}
// Timer setup. First set timer to auto, then set prescaler to 0xA9
uint8_t set_tauto_ret = mfrc522_set_timer_auto(&ctx, MFRC522_BOOL_TRUE);
if (set_tauto_ret != 0) {
mfrc522_interface_debug_print("ERR: Could not set timer to auto\n");
}
uint8_t set_tprescaler = mfrc522_set_timer_prescaler(&ctx, (uint16_t) 0xA9);
if (set_tprescaler != 0) {
mfrc522_interface_debug_print("ERR: Could not set timer prescaler\n");
}
// Timer setup. Configure reload registers (hi and lo)
uint8_t set_treload = mfrc522_set_timer_reload(&ctx, (uint16_t) 0x3E8);
if (set_treload != 0) {
mfrc522_interface_debug_print("ERR: Could not set timer reload value");
}
// A magic modulation setting: force ASK 100% - whatever that is..
uint8_t force_100ask_ret = mfrc522_set_force_100_ask(&ctx, MFRC522_BOOL_TRUE);
if (force_100ask_ret != 0) {
mfrc522_interface_debug_print("ERR: Could not force 100\% ASK modulation\n");
}
// More settings for the mode register (crc setup, wait for rf field)
uint8_t set_modereg_msbfirst_ret = mfrc522_set_crc_msb_first(&ctx, MFRC522_BOOL_FALSE);
if (set_modereg_msbfirst_ret != 0) {
mfrc522_interface_debug_print("ERR: Could not set crc to msb first\n");
}
uint8_t set_modereg_txwaitrf_ret = mfrc522_set_tx_wait_rf(&ctx, MFRC522_BOOL_TRUE);
if (set_modereg_txwaitrf_ret != 0) {
mfrc522_interface_debug_print("ERR: Could not make transmitter wait for rf field\n");
}
uint8_t set_modereg_polmfin_ret = mfrc522_set_mfin_polarity(&ctx, MFRC522_MFIN_POLARITY_HIGH);
if (set_modereg_polmfin_ret != 0)
{
mfrc522_interface_debug_print("ERR: Could not set mfin polarity\n");
}
uint8_t set_modereg_crcpres_ret = mfrc522_set_crc_preset(&ctx, MFRC522_CRC_PRESET_6363);
if (set_modereg_crcpres_ret != 0) {
mfrc522_interface_debug_print("ERR: Could not set crc preset value\n");
}
// Enable antenna
uint8_t set_ant_invrx2_ret = mfrc522_set_antenna_driver(&ctx, MFRC522_ANTENNA_DRIVER_INV_TX2_RF_ON, MFRC522_BOOL_TRUE);
if (set_ant_invrx2_ret != 0)
{
mfrc522_interface_debug_print("ERR: Could not enable tx2 invert\n");
}
uint8_t enable_ant_tx2rf_ret = mfrc522_set_antenna_driver(&ctx, MFRC522_ANTENNA_DRIVER_TX2_RF, MFRC522_BOOL_TRUE);
if (enable_ant_tx2rf_ret != 0)
{
mfrc522_interface_debug_print("ERR: Could not enable tx2 rf\n");
}
uint8_t enable_ant_tx1rf_ret = mfrc522_set_antenna_driver(&ctx, MFRC522_ANTENNA_DRIVER_TX1_RF, MFRC522_BOOL_TRUE);
if (enable_ant_tx1rf_ret != 0)
{
mfrc522_interface_debug_print("ERR: Could not enable tx1 rf\n");
}
// Enable RX interrupt on rf side XXX Are we doing the right thing?!?
uint8_t set_irq_invert_ret = mfrc522_set_interrupt1_pin_invert(&ctx, MFRC522_BOOL_TRUE);
if (set_irq_invert_ret != 0)
{
mfrc522_interface_debug_print("ERR: Could not invert irq pin\n");
}
// Enable RX interrupt
uint8_t en_rx_irq = mfrc522_set_interrupt1(&ctx, MFRC522_INTERRUPT1_RX , MFRC522_BOOL_TRUE);
if (en_rx_irq != 0)
{
mfrc522_interface_debug_print("ERR: Could not enable rx interrupt on rf side\n");
}
// Enable analog section of the reader
uint8_t analog_enable_retval = mfrc522_set_receiver_analog(&ctx, MFRC522_BOOL_TRUE);
if (analog_enable_retval != 0) {
mfrc522_interface_debug_print("ERR: Enabling analog receiver failed: %d\n", analog_enable_retval);
}
}
// follows setup strategy of arduino lib
void setup_attempt_2(void)
{
/*
_dev->PCD_WriteRegister(TModeReg, 0x80); // TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
_dev->PCD_WriteRegister(TPrescalerReg, 0xA9); // TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25μs.
_dev->PCD_WriteRegister(TReloadRegH, 0x03); // Reload timer with 0x3E8 = 1000, ie 25ms before timeout.
_dev->PCD_WriteRegister(TReloadRegL, 0xE8);
_dev->PCD_WriteRegister(TxASKReg, 0x40); // Default 0x00. Force a 100 % ASK modulation independent of the ModGsPReg register setting
_dev->PCD_WriteRegister(ModeReg, 0x3D); // Default 0x3F. Set the preset value for the CRC coprocessor for the CalcCRC command to 0x6363 (ISO 14443-3 part 6.2.4)
*/
// PCD Setup part
uint8_t new_tmodereg = 0x80;
(void) mfrc522_set_reg(&ctx, 0x2A, &new_tmodereg, sizeof(new_tmodereg));
uint8_t new_tprescalerreg = 0xA9;
(void) mfrc522_set_reg(&ctx, 0x2B, &new_tprescalerreg, sizeof(new_tprescalerreg));
uint8_t new_treloadregh = 0x03;
(void) mfrc522_set_reg(&ctx, 0x2C, &new_treloadregh, sizeof(new_treloadregh));
uint8_t new_treloadregl = 0xE8;
(void) mfrc522_set_reg(&ctx, 0x2D, &new_treloadregl, sizeof(new_treloadregl));
uint8_t new_txaskreg = 0x40;
(void) mfrc522_set_reg(&ctx, 0x15, &new_txaskreg, sizeof(new_txaskreg));
uint8_t new_modereg = 0x3D;
(void) mfrc522_set_reg(&ctx, 0x11, &new_modereg, sizeof(new_modereg));
// Enable antenna
uint8_t current_txcontrolreg = 0;
(void) mfrc522_get_reg(&ctx, 0x14, &current_txcontrolreg, sizeof(current_txcontrolreg));
if ((current_txcontrolreg & 0x03) != 0x03) {
uint8_t new_txcontrolreg = current_txcontrolreg | 0x03;
(void) mfrc522_set_reg(&ctx, 0x14, &new_txcontrolreg, sizeof(new_txcontrolreg));
}
// Allow ... irq to be propagated
uint8_t new_comienreg = 0xA0;
(void) mfrc522_set_reg(&ctx, 0x02, &new_comienreg, sizeof(new_comienreg));
}
void mfrc522_integration_init(void)
{
DRIVER_MFRC522_LINK_INIT(&ctx, mfrc522_handle_t);
DRIVER_MFRC522_LINK_RESET_GPIO_INIT(&ctx, mfrc522_interface_reset_gpio_init);
DRIVER_MFRC522_LINK_RESET_GPIO_DEINIT(&ctx, mfrc522_interface_reset_gpio_deinit);
DRIVER_MFRC522_LINK_RESET_GPIO_WRITE(&ctx, mfrc522_interface_reset_gpio_write);
DRIVER_MFRC522_LINK_IIC_INIT(&ctx, mfrc522_interface_iic_init);
DRIVER_MFRC522_LINK_IIC_DEINIT(&ctx, mfrc522_interface_iic_deinit);
DRIVER_MFRC522_LINK_IIC_WRITE(&ctx, mfrc522_interface_iic_write);
DRIVER_MFRC522_LINK_IIC_READ(&ctx, mfrc522_interface_iic_read);
DRIVER_MFRC522_LINK_UART_INIT(&ctx, mfrc522_interface_uart_init);
DRIVER_MFRC522_LINK_UART_DEINIT(&ctx, mfrc522_interface_uart_deinit);
DRIVER_MFRC522_LINK_UART_READ(&ctx, mfrc522_interface_uart_read);
DRIVER_MFRC522_LINK_UART_WRITE(&ctx, mfrc522_interface_uart_write);
DRIVER_MFRC522_LINK_UART_FLUSH(&ctx, mfrc522_interface_uart_flush);
DRIVER_MFRC522_LINK_SPI_INIT(&ctx, mfrc522_interface_spi_init);
DRIVER_MFRC522_LINK_SPI_DEINIT(&ctx, mfrc522_interface_spi_deinit);
DRIVER_MFRC522_LINK_SPI_READ(&ctx, mfrc522_interface_spi_read);
DRIVER_MFRC522_LINK_SPI_WRITE(&ctx, mfrc522_interface_spi_write);
DRIVER_MFRC522_LINK_DELAY_MS(&ctx, mfrc522_interface_delay_ms);
DRIVER_MFRC522_LINK_DEBUG_PRINT(&ctx, mfrc522_interface_debug_print);
DRIVER_MFRC522_LINK_RECEIVE_CALLBACK(&ctx, mfrc522_interface_receive_callback);
mfrc522_set_interface(&ctx, MFRC522_INTERFACE_SPI);
uint8_t init_retval = mfrc522_init(&ctx);
if (init_retval != 0) {
mfrc522_interface_debug_print("ERR: %s failed: %d\n", __FUNCTION__, init_retval);
}
// Set IRQ pin of MFRC522 to CMOS, enable irq on pico on success
uint8_t irq_pin_type_ret = mfrc522_set_interrupt_pin_type(&ctx, MFRC522_INTERRUPT_PIN_TYPE_STANDARD_CMOS);
if (irq_pin_type_ret != 0) {
mfrc522_interface_debug_print("ERR: Could not set interrupt pin type.\n");
}
else
{
mfrc522_integration_irq_init(&ctx);
}
// replicate arduino behavior
setup_attempt_2();
}
int main(void)
{
timer_hw->dbgpause = 0;
stdio_init_all();
printf("Hello World!\n");
mfrc522_integration_init();
const uint LED_PIN = PICO_DEFAULT_LED_PIN;
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
while (true) {
gpio_put(LED_PIN, 1);
sleep_ms(250);
gpio_put(LED_PIN, 0);
sleep_ms(250);
}
}

View File

@@ -1,4 +1,17 @@
set(SRC ${CMAKE_CURRENT_SOURCE_DIR}/mfrc522/src)
set(INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/mfrc522/interface)
add_library(mfrc522 STATIC
mfrc522_rp2040_integration.c
${SRC}/driver_mfrc522.c
)
target_link_libraries(mfrc522
pico_stdlib
pico_time
hardware_gpio
hardware_spi
)
add_library(mfrc522 STATIC ${SRC}/driver_mfrc522.c)
target_include_directories(mfrc522 PUBLIC ${SRC})
target_include_directories(mfrc522 PUBLIC ${INTERFACE})

View File

@@ -0,0 +1,467 @@
/**
* Copyright (c) 2015 - present LibDriver All rights reserved
*
* The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file driver_mfrc522_interface_template.c
* @brief driver mfrc522 interface template source file
* @version 1.0.0
* @author Shifeng Li
* @date 2022-05-31
*
* <h3>history</h3>
* <table>
* <tr><th>Date <th>Version <th>Author <th>Description
* <tr><td>2022/05/31 <td>1.0 <td>Shifeng Li <td>first upload
* </table>
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "hardware/sync.h"
#ifndef NO_DEBUG
#include <stdarg.h>
#endif
#include "driver_mfrc522_interface.h"
#define MFRC522_CFG_RST_GPIO 9
#define MFRC522_CFG_SPI_INSTANCE spi1
#define MFRC522_CFG_SPI_MISO_GPIO 12
#define MFRC522_CFG_SPI_MOSI_GPIO 11
#define MFRC522_CFG_SPI_CLK_GPIO 10
#define MFRC522_CFG_SPI_SS_GPIO 13
#define MFRC522_CFG_SPI_SPEED_MHZ (1000 * 1000)
static inline void print_hex(uint8_t *bytes, size_t len)
{
for (size_t idx = 0; idx < len; ++idx) {
mfrc522_interface_debug_print("%x", bytes[idx]);
}
mfrc522_interface_debug_print("\n");
}
static uint32_t irq_status = 0;
/**
* @brief Helper function to pull the CS line low
*
* Taken from pico-examples, bme280_spi.c
*/
static inline void cs_select() {
// irq_status = save_and_disable_interrupts();
asm volatile("nop \n nop \n nop");
gpio_put(MFRC522_CFG_SPI_SS_GPIO, 0); // Active low
asm volatile("nop \n nop \n nop");
}
/**
* @brief Helper function to release the CS line low
*
* Taken from pico-examples, bme280_spi.c
*/
static inline void cs_deselect() {
asm volatile("nop \n nop \n nop");
gpio_put(MFRC522_CFG_SPI_SS_GPIO, 1);
asm volatile("nop \n nop \n nop");
// restore_interrupts(irq_status);
}
/**
* @brief interface reset gpio init
* @return status code
* - 0 success
* - 1 reset gpio init failed
* @note none
*/
uint8_t mfrc522_interface_reset_gpio_init(void)
{
gpio_init(MFRC522_CFG_RST_GPIO);
gpio_set_dir(MFRC522_CFG_RST_GPIO, GPIO_OUT);
return 0;
}
/**
* @brief interface reset gpio deinit
* @return status code
* - 0 success
* - 1 reset gpio deinit failed
* @note none
*/
uint8_t mfrc522_interface_reset_gpio_deinit(void)
{
gpio_deinit(MFRC522_CFG_RST_GPIO);
return 0;
}
/**
* @brief interface reset gpio write
* @param[in] value is the written value
* @return status code
* - 0 success
* - 1 reset gpio write failed
* @note none
*/
uint8_t mfrc522_interface_reset_gpio_write(uint8_t value)
{
gpio_put(MFRC522_CFG_RST_GPIO, !!value);
return 0;
}
/**
* @brief interface iic bus init
* @return status code
* - 0 success
* - 1 iic init failed
* @note none
*/
uint8_t mfrc522_interface_iic_init(void)
{
mfrc522_interface_debug_print("WARN: %s not implemented!\n", __FUNCTION__);
return 0;
}
/**
* @brief interface iic bus deinit
* @return status code
* - 0 success
* - 1 iic deinit failed
* @note none
*/
uint8_t mfrc522_interface_iic_deinit(void)
{
mfrc522_interface_debug_print("WARN: %s not implemented!\n", __FUNCTION__);
return 0;
}
/**
* @brief interface iic bus read
* @param[in] addr is the iic device write address
* @param[in] reg is the iic register address
* @param[out] *buf points to a data buffer
* @param[in] len is the length of the data buffer
* @return status code
* - 0 success
* - 1 read failed
* @note none
*/
uint8_t mfrc522_interface_iic_read(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len)
{
mfrc522_interface_debug_print("WARN: %s not implemented!\n", __FUNCTION__);
return 0;
}
/**
* @brief interface iic bus write
* @param[in] addr is the iic device write address
* @param[in] reg is the iic register address
* @param[in] *buf points to a data buffer
* @param[in] len is the length of the data buffer
* @return status code
* - 0 success
* - 1 write failed
* @note none
*/
uint8_t mfrc522_interface_iic_write(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len)
{
mfrc522_interface_debug_print("WARN: %s not implemented!\n", __FUNCTION__);
return 0;
}
/**
* @brief interface spi bus init
* @return status code
* - 0 success
* - 1 spi init failed
* @note none
*/
uint8_t mfrc522_interface_spi_init(void)
{
gpio_set_function(MFRC522_CFG_SPI_MISO_GPIO, GPIO_FUNC_SPI);
gpio_set_function(MFRC522_CFG_SPI_MOSI_GPIO, GPIO_FUNC_SPI);
gpio_set_function(MFRC522_CFG_SPI_CLK_GPIO, GPIO_FUNC_SPI);
//gpio_set_function(MFRC522_CFG_SPI_SS_GPIO, GPIO_FUNC_SPI);
//gpio_set_dir(MFRC522_CFG_SPI_CLK_GPIO, GPIO_OUT);
gpio_init(MFRC522_CFG_SPI_SS_GPIO);
gpio_set_dir(MFRC522_CFG_SPI_SS_GPIO, GPIO_OUT);
gpio_put(MFRC522_CFG_SPI_SS_GPIO, 1);
/*
* From the manual:
* "There is no guarantee that the baudrate requested can be achieved exactly;
* the nearest will be chosen and returned"
*/
return !spi_init(MFRC522_CFG_SPI_INSTANCE, MFRC522_CFG_SPI_SPEED_MHZ);
}
/**
* @brief interface spi bus deinit
* @return status code
* - 0 success
* - 1 spi deinit failed
* @note none
*/
uint8_t mfrc522_interface_spi_deinit(void)
{
mfrc522_interface_debug_print("WARN: %s not implemented!\n", __FUNCTION__);
return 0;
}
/**
* @brief interface spi bus read
* @param[in] reg is the register address
* @param[out] *buf points to a data buffer
* @param[in] len is the length of data buffer
* @return status code
* - 0 success
* - 1 read failed
* @note none
*/
uint8_t mfrc522_interface_spi_read(uint8_t reg, uint8_t *buf, uint16_t len)
{
if (len == UINT16_MAX)
return 1;
// We need to read len + 1 bytes...
const size_t local_buf_len = len + 1;
uint8_t local_buf[local_buf_len];
memset(local_buf, 0, local_buf_len);
cs_select();
uint16_t n_bytes_read = spi_read_blocking(MFRC522_CFG_SPI_INSTANCE, reg, local_buf, local_buf_len);
cs_deselect();
// ...and ignore the first byte we received.
memcpy(buf, local_buf + 1, len);
// XXX Debug - remove me
mfrc522_interface_debug_print("[SPI-RX REG 0x%x] ", (uint8_t) ((reg & 0x7f) >> 1));
print_hex(buf, len);
return (uint8_t) (n_bytes_read == local_buf_len) ? 0 : 1;
}
/**
* @brief interface spi bus write
* @param[in] reg is the register address
* @param[in] *buf points to a data buffer
* @param[in] len is the length of data buffer
* @return status code
* - 0 success
* - 1 write failed
* @note none
*/
uint8_t mfrc522_interface_spi_write(uint8_t reg, uint8_t *buf, uint16_t len)
{
if (len == UINT16_MAX)
return 1;
// We need to send the address byte (reg) as part of the payload.
const size_t local_buf_len = len + 1;
uint8_t local_buf[local_buf_len];
local_buf[0] = reg;
memcpy(&local_buf[1], buf, len);
// XXX Debug - remove me
mfrc522_interface_debug_print("[SPI-TX REG 0x%x] ", (uint8_t) ((reg & 0x7f) >> 1));
print_hex(buf, len);
cs_select();
uint16_t n_bytes_written = spi_write_blocking(MFRC522_CFG_SPI_INSTANCE, local_buf, local_buf_len);
cs_deselect();
return (uint8_t) (n_bytes_written == local_buf_len) ? 0 : 1;
}
/**
* @brief interface uart init
* @return status code
* - 0 success
* - 1 uart init failed
* @note none
*/
uint8_t mfrc522_interface_uart_init(void)
{
mfrc522_interface_debug_print("WARN: %s not implemented!\n", __FUNCTION__);
return 0;
}
/**
* @brief interface uart deinit
* @return status code
* - 0 success
* - 1 uart deinit failed
* @note none
*/
uint8_t mfrc522_interface_uart_deinit(void)
{
mfrc522_interface_debug_print("WARN: %s not implemented!\n", __FUNCTION__);
return 0;
}
/**
* @brief interface uart read
* @param[out] *buf points to a data buffer
* @param[in] len is the length of the data buffer
* @return status code
* - 0 success
* - 1 read failed
* @note none
*/
uint16_t mfrc522_interface_uart_read(uint8_t *buf, uint16_t len)
{
mfrc522_interface_debug_print("WARN: %s not implemented!\n", __FUNCTION__);
return 0;
}
/**
* @brief interface uart write
* @param[in] *buf points to a data buffer
* @param[in] len is the length of the data buffer
* @return status code
* - 0 success
* - 1 write failed
* @note none
*/
uint8_t mfrc522_interface_uart_write(uint8_t *buf, uint16_t len)
{
mfrc522_interface_debug_print("WARN: %s not implemented!\n", __FUNCTION__);
return 0;
}
/**
* @brief interface uart flush
* @return status code
* - 0 success
* - 1 uart flush failed
* @note none
*/
uint8_t mfrc522_interface_uart_flush(void)
{
mfrc522_interface_debug_print("WARN: %s not implemented!\n", __FUNCTION__);
return 0;
}
/**
* @brief interface delay ms
* @param[in] ms
* @note none
*/
void mfrc522_interface_delay_ms(uint32_t ms)
{
sleep_ms(ms);
}
/**
* @brief interface print format data
* @param[in] fmt is the format data
* @note none
*/
void mfrc522_interface_debug_print(const char *const fmt, ...)
{
#ifndef NO_DEBUG
char str[256];
uint16_t len;
va_list args;
memset((char *)str, 0, sizeof(char) * 256);
va_start(args, fmt);
vsnprintf((char *)str, 255, (char const *)fmt, args);
va_end(args);
len = strlen((char *)str);
(void)printf((uint8_t *)str, len);
#endif
}
/**
* @brief interface receive callback
* @param[in] type is the irq type
* @note none
*/
void mfrc522_interface_receive_callback(uint16_t type)
{
switch (type)
{
case MFRC522_INTERRUPT_MFIN_ACT :
{
mfrc522_interface_debug_print("mfrc522: irq mfin act.\n");
break;
}
case MFRC522_INTERRUPT_CRC :
{
mfrc522_interface_debug_print("mfrc522: irq crc.\n");
break;
}
case MFRC522_INTERRUPT_TX :
{
mfrc522_interface_debug_print("mfrc522: irq tx.\n");
break;
}
case MFRC522_INTERRUPT_RX :
{
mfrc522_interface_debug_print("mfrc522: irq rx.\n");
break;
}
case MFRC522_INTERRUPT_IDLE :
{
mfrc522_interface_debug_print("mfrc522: irq idle.\n");
break;
}
case MFRC522_INTERRUPT_HI_ALERT :
{
mfrc522_interface_debug_print("mfrc522: irq hi alert.\n");
break;
}
case MFRC522_INTERRUPT_LO_ALERT :
{
mfrc522_interface_debug_print("mfrc522: irq lo alert.\n");
break;
}
case MFRC522_INTERRUPT_ERR :
{
mfrc522_interface_debug_print("mfrc522: irq err.\n");
break;
}
case MFRC522_INTERRUPT_TIMER :
{
mfrc522_interface_debug_print("mfrc522: irq timer.\n");
break;
}
default :
{
mfrc522_interface_debug_print("mfrc522: irq unknown code.\n");
break;
}
}
}