Files
rpi_pico_mfrc522/main.c

235 lines
9.6 KiB
C

#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);
}
}