0

I'm working with esp-idf and I found this repository that has implemented the Adafruit driver for the PN532 in "plain" esp-idf. This library works very well if I use it as is.

I'm trying to improve the code by changing the SPI functions to use directly the one provided by esp-idf.

I found this documentation (see section 6.1.1.1) and this other documentation (section 2.4.1) that slightly helped me in order to understand how to configure the SPI device, but I'm still missing something because I don't have the right response from PN532 when I use the settings shown below, nor in any other configuration.

So I'm searching for someone that can help me understand better what I'm missing here.

The original functions are:

void pn532_spi_init(pn532_t *obj, uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t ss)
{
    obj->_clk = clk;
    obj->_miso = miso;
    obj->_mosi = mosi;
    obj->_ss = ss;

    gpio_pad_select_gpio(obj->_clk);
    gpio_pad_select_gpio(obj->_miso);
    gpio_pad_select_gpio(obj->_mosi);
    gpio_pad_select_gpio(obj->_ss);

    gpio_set_direction(obj->_ss, GPIO_MODE_OUTPUT);
    gpio_set_level(obj->_ss, 1);
    gpio_set_direction(obj->_clk, GPIO_MODE_OUTPUT);
    gpio_set_direction(obj->_mosi, GPIO_MODE_OUTPUT);
    gpio_set_direction(obj->_miso, GPIO_MODE_INPUT);
}

/**************************************************************************/
/*!
    @brief  Low-level SPI write wrapper

    @param  c       8-bit command to write to the SPI bus
*/
/**************************************************************************/
void pn532_spi_write(pn532_t *obj, uint8_t c)
{
    int8_t i;
    gpio_set_level(obj->_clk, 1);

    for (i = 0; i < 8; i++)
    {
        gpio_set_level(obj->_clk, 0);
        if (c & _BV(i))
        {
            gpio_set_level(obj->_mosi, 1);
        }
        else
        {
            gpio_set_level(obj->_mosi, 0);
        }
        gpio_set_level(obj->_clk, 1);
    }
}

/**************************************************************************/
/*!
    @brief  Low-level SPI read wrapper

    @returns The 8-bit value that was read from the SPI bus
*/
/**************************************************************************/
uint8_t pn532_spi_read(pn532_t *obj)
{
    int8_t i, x;
    x = 0;

    gpio_set_level(obj->_clk, 1);

    for (i = 0; i < 8; i++)
    {
        if (gpio_get_level(obj->_miso))
        {
            x |= _BV(i);
        }
        gpio_set_level(obj->_clk, 0);
        gpio_set_level(obj->_clk, 1);
    }

    return x;
}

And my changes are:


void pn532_spi_init(pn532_t *obj, spi_host_device_t spiHostDevice, uint8_t ss) {

    gpio_set_direction((gpio_num_t) ss, GPIO_MODE_OUTPUT);
    gpio_set_level((gpio_num_t) ss, 1);


    //Config Frequency and SS GPIO
    spi_device_interface_config_t deviceInterfaceConfig = {
            .mode = 0,  //SPI mode 0
            .clock_speed_hz= 1200000,  // Uusually 1.2 Mhz
            .input_delay_ns = 0,
            .spics_io_num = ss,
            .flags = (SPI_DEVICE_BIT_LSBFIRST),
            .queue_size = 1
    };

    spi_device_handle_t spiDeviceHandle;

    //Attach the pn532 to the SPI bus
    ESP_ERROR_CHECK(spi_bus_add_device(spiHostDevice, &deviceInterfaceConfig, &spiDeviceHandle));

    obj->spi = spiDeviceHandle;
    obj->_ss = ss;

}


void pn532_spi_write(pn532_t *obj, uint8_t data) {
    spi_transaction_t t;
    memset(&t, 0, sizeof(t));       //Zero out the transaction
    t.length = 8;
    t.tx_buffer = &data;
    //t.flags = SPI_TRANS_CS_KEEP_ACTIVE;

    ESP_LOGI(TAG, "send data: 0b%s", toBinary(data,8));

    //t.flags = (SPI_TRANS_MODE_OCT | SPI_TRANS_MODE_QIO);

    ESP_ERROR_CHECK(spi_device_polling_transmit(obj->spi, &t));

}


uint8_t pn532_spi_read(pn532_t *obj) {

    uint8_t data = 1;
    spi_transaction_t t;
    memset(&t, 0, sizeof(t));       //Zero out the transaction
    t.length = 8;
    t.rxlength = 8;
    t.tx_buffer = NULL;
    t.rx_buffer = &data;
    //t.flags = SPI_TRANS_CS_KEEP_ACTIVE;

    //t.flags = (SPI_TRANS_MODE_OCT);

    ESP_ERROR_CHECK(spi_device_polling_transmit(obj->spi, &t));

    ESP_LOGI(TAG, "read data: 0b%s", toBinary(data,8));

    return data;

}

Externally from this function I'm initializing the SPI bus and then calling the pn532 init and begin functions.

     spi_bus_config_t spi_config = {
            .mosi_io_num= PIN_NUM_MOSI,
            .miso_io_num= PIN_NUM_MISO,
            .sclk_io_num= PIN_NUM_CLK,
            .quadwp_io_num= -1,
            .quadhd_io_num= -1,
            .max_transfer_sz= 4092
    };

    //Initialize the SPI bus
    ESP_ERROR_CHECK(spi_bus_initialize(HSPI_HOST, &spi_config, SPI_DMA_CH_AUTO));
    
    static pn532_t nfc;
    pn532_spi_init(&nfc, HSPI_HOST, GPIO_NUM_25);
    pn532_begin(&nfc);
    

With this configuration, when I try to read from the SPI, the hex that return the PN532 is 0x08, were expecting 0x01 or 0x00. Seem that is a padding problem? The 1 is shifted in the wrong place?

I'm really lost! :(

jbernavaprah
  • 593
  • 1
  • 5
  • 11

0 Answers0